Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Apr 2014 18:00:07 +0000 (11:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Apr 2014 18:00:07 +0000 (11:00 -0700)
Pull timer changes from Thomas Gleixner:
 "This assorted collection provides:

   - A new timer based timer broadcast feature for systems which do not
     provide a global accessible timer device.  That allows those
     systems to put CPUs into deep idle states where the per cpu timer
     device stops.

   - A few NOHZ_FULL related improvements to the timer wheel

   - The usual updates to timer devices found in ARM SoCs

   - Small improvements and updates all over the place"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits)
  tick: Remove code duplication in tick_handle_periodic()
  tick: Fix spelling mistake in tick_handle_periodic()
  x86: hpet: Use proper destructor for delayed work
  workqueue: Provide destroy_delayed_work_on_stack()
  clocksource: CMT, MTU2, TMU and STI should depend on GENERIC_CLOCKEVENTS
  timer: Remove code redundancy while calling get_nohz_timer_target()
  hrtimer: Rearrange comments in the order struct members are declared
  timer: Use variable head instead of &work_list in __run_timers()
  clocksource: exynos_mct: silence a static checker warning
  arm: zynq: Add support for cpufreq
  arm: zynq: Don't use arm_global_timer with cpufreq
  clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
  clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled
  clocksource: Add Kconfig entries for CMT, MTU2, TMU and STI
  sh: Remove Kconfig entries for TMU, CMT and MTU2
  ARM: shmobile: Remove CMT, TMU and STI Kconfig entries
  clocksource: armada-370-xp: Use atomic access for shared registers
  clocksource: orion: Use atomic access for shared registers
  clocksource: timer-keystone: Delete unnecessary variable
  clocksource: timer-keystone: introduce clocksource driver for Keystone
  ...

2368 files changed:
.gitignore
Documentation/00-INDEX
Documentation/PCI/MSI-HOWTO.txt
Documentation/RCU/00-INDEX
Documentation/RCU/RTFP.txt
Documentation/RCU/checklist.txt
Documentation/arm/00-INDEX
Documentation/arm64/memory.txt
Documentation/blackfin/00-INDEX
Documentation/block/00-INDEX
Documentation/device-mapper/cache.txt
Documentation/device-mapper/thin-provisioning.txt
Documentation/devicetree/00-INDEX
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/ata/ahci-platform.txt
Documentation/devicetree/bindings/ata/apm-xgene.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt
Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt
Documentation/devicetree/bindings/net/micrel-ks8851.txt
Documentation/devicetree/bindings/net/opencores-ethoc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/sti-dwmac.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/brcm,capri-pinctrl.txt [deleted file]
Documentation/devicetree/bindings/power/bq2415x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi_atmel.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/dvb/contributors.txt
Documentation/fb/00-INDEX
Documentation/filesystems/00-INDEX
Documentation/filesystems/nfs/00-INDEX
Documentation/i2c/instantiating-devices
Documentation/ide/00-INDEX
Documentation/kernel-parameters.txt
Documentation/kernel-per-CPU-kthreads.txt
Documentation/laptops/00-INDEX
Documentation/leds/00-INDEX
Documentation/m68k/00-INDEX
Documentation/memory-barriers.txt
Documentation/networking/00-INDEX
Documentation/networking/3c505.txt [deleted file]
Documentation/networking/can.txt
Documentation/networking/netlink_mmap.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/timestamping.txt
Documentation/phy.txt
Documentation/power/00-INDEX
Documentation/ptp/testptp.c
Documentation/s390/00-INDEX
Documentation/scheduler/00-INDEX
Documentation/scsi/00-INDEX
Documentation/serial/00-INDEX
Documentation/spi/00-INDEX [new file with mode: 0644]
Documentation/spi/spi-summary
Documentation/sysctl/kernel.txt
Documentation/timers/00-INDEX
Documentation/virtual/kvm/00-INDEX
Documentation/vm/00-INDEX
Documentation/w1/masters/00-INDEX
Documentation/w1/slaves/00-INDEX
Documentation/x86/00-INDEX
Documentation/x86/boot.txt
Documentation/zh_CN/arm64/booting.txt
Documentation/zh_CN/arm64/memory.txt
Documentation/zh_CN/arm64/tagged-pointers.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/Kbuild
arch/alpha/include/asm/cputime.h [deleted file]
arch/arc/include/asm/Kbuild
arch/arc/mm/cache_arc700.c
arch/arm/Kconfig
arch/arm/boot/compressed/.gitignore
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/at91-sama5d3_xplained.dts [new file with mode: 0644]
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/bcm11351.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/imx6dl-hummingboard.dts
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
arch/arm/boot/dts/keystone-clocks.dtsi
arch/arm/boot/dts/omap3-gta04.dts
arch/arm/boot/dts/omap3-igep0020.dts
arch/arm/boot/dts/omap3-igep0030.dts
arch/arm/boot/dts/omap3-n9.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950.dts
arch/arm/boot/dts/omap3-overo-storm-tobi.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-overo-tobi-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap3-overo-tobi.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-overo.dtsi
arch/arm/boot/dts/omap3-tobi.dts [deleted file]
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sama5d36.dtsi
arch/arm/boot/dts/ste-href.dtsi
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/testcases/tests-interrupts.dtsi [deleted file]
arch/arm/boot/dts/testcases/tests-phandle.dtsi [deleted file]
arch/arm/boot/dts/testcases/tests.dtsi [deleted file]
arch/arm/boot/dts/versatile-pb.dts
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/include/asm/Kbuild
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/spinlock.h
arch/arm/include/asm/topology.h
arch/arm/kernel/head-common.S
arch/arm/kernel/head.S
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kvm/arm.c
arch/arm/kvm/interrupts.S
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-hisi/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-imx6sl.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/pm-imx6q.c
arch/arm/mach-moxart/Kconfig
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/cclock3xxx_data.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/prminst44xx.c
arch/arm/mach-pxa/am300epd.c
arch/arm/mach-pxa/include/mach/balloon3.h
arch/arm/mach-pxa/include/mach/corgi.h
arch/arm/mach-pxa/include/mach/csb726.h
arch/arm/mach-pxa/include/mach/gumstix.h
arch/arm/mach-pxa/include/mach/idp.h
arch/arm/mach-pxa/include/mach/palmld.h
arch/arm/mach-pxa/include/mach/palmt5.h
arch/arm/mach-pxa/include/mach/palmtc.h
arch/arm/mach-pxa/include/mach/palmtx.h
arch/arm/mach-pxa/include/mach/pcm027.h
arch/arm/mach-pxa/include/mach/pcm990_baseboard.h
arch/arm/mach-pxa/include/mach/poodle.h
arch/arm/mach-pxa/include/mach/spitz.h
arch/arm/mach-pxa/include/mach/tosa.h
arch/arm/mach-pxa/include/mach/trizeps4.h
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-sa1100/include/mach/collie.h
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/tegra.c
arch/arm/mach-zynq/common.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/dump.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm64/Kconfig
arch/arm64/boot/dts/apm-storm.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/atomic.h
arch/arm64/include/asm/barrier.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cmpxchg.h
arch/arm64/include/asm/compat.h
arch/arm64/include/asm/cpufeature.h [new file with mode: 0644]
arch/arm64/include/asm/debug-monitors.h
arch/arm64/include/asm/dma-mapping.h
arch/arm64/include/asm/esr.h
arch/arm64/include/asm/futex.h
arch/arm64/include/asm/hwcap.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/irqflags.h
arch/arm64/include/asm/kgdb.h [new file with mode: 0644]
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/percpu.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/psci.h
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/spinlock.h
arch/arm64/include/asm/tlb.h
arch/arm64/include/asm/topology.h [new file with mode: 0644]
arch/arm64/include/asm/uaccess.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/include/uapi/asm/Kbuild
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/include/uapi/asm/perf_regs.h [new file with mode: 0644]
arch/arm64/kernel/Makefile
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/head.S
arch/arm64/kernel/kgdb.c [new file with mode: 0644]
arch/arm64/kernel/kuser32.S
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/perf_regs.c [new file with mode: 0644]
arch/arm64/kernel/process.c
arch/arm64/kernel/psci.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/smp_spin_table.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/topology.c [new file with mode: 0644]
arch/arm64/kernel/vdso.c
arch/arm64/kernel/vdso/Makefile
arch/arm64/kernel/vdso/gettimeofday.S
arch/arm64/kvm/hyp-init.S
arch/arm64/kvm/hyp.S
arch/arm64/lib/bitops.S
arch/arm64/mm/cache.S
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/init.c
arch/arm64/mm/mmu.c
arch/arm64/mm/pgd.c
arch/arm64/mm/proc.S
arch/avr32/Makefile
arch/avr32/boards/mimc200/fram.c
arch/avr32/include/asm/Kbuild
arch/avr32/include/asm/bugs.h
arch/avr32/include/asm/io.h
arch/avr32/include/asm/processor.h
arch/avr32/kernel/cpu.c
arch/avr32/mm/cache.c
arch/blackfin/include/asm/Kbuild
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/cache.h
arch/cris/include/asm/Kbuild
arch/cris/include/asm/bitops.h
arch/cris/include/asm/cputime.h [deleted file]
arch/frv/include/asm/Kbuild
arch/frv/include/asm/cputime.h [deleted file]
arch/hexagon/include/asm/Kbuild
arch/ia64/configs/generic_defconfig
arch/ia64/hp/common/sba_iommu.c
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/topology.h
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/efi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/mca.c
arch/ia64/kernel/uncached.c
arch/m32r/include/asm/Kbuild
arch/m32r/include/asm/cputime.h [deleted file]
arch/m68k/Kconfig
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/barrier.h [deleted file]
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/head.S
arch/m68k/kernel/syscalltable.S
arch/metag/include/asm/Kbuild
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/asm/cputime.h [deleted file]
arch/microblaze/include/asm/delay.h
arch/microblaze/include/asm/io.h
arch/microblaze/kernel/head.S
arch/mips/Kconfig
arch/mips/alchemy/board-gpr.c
arch/mips/alchemy/board-mtx1.c
arch/mips/alchemy/devboards/db1000.c
arch/mips/bcm47xx/board.c
arch/mips/bcm47xx/nvram.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/include/asm/Kbuild
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/ftrace.h
arch/mips/include/asm/syscall.h
arch/mips/include/asm/topology.h
arch/mips/include/asm/unistd.h
arch/mips/include/uapi/asm/inst.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/kernel/ftrace.c
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/rtlx-cmp.c
arch/mips/kernel/rtlx-mt.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/math-emu/cp1emu.c
arch/mips/mti-malta/malta-amon.c
arch/mips/mti-malta/malta-int.c
arch/mips/pci/msi-octeon.c
arch/mn10300/include/asm/Kbuild
arch/mn10300/include/asm/cputime.h [deleted file]
arch/openrisc/include/asm/Kbuild
arch/parisc/hpux/fs.c
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/page.h
arch/parisc/include/asm/spinlock.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/include/asm/Kbuild
arch/powerpc/include/asm/compat.h
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/vdso.h
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/ftrace.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/reloc_64.S
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/vdso32/vdso32_wrapper.S
arch/powerpc/kernel/vdso64/vdso64_wrapper.S
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/subpage-prot.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power8-pmu.c
arch/powerpc/platforms/cell/ras.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/powernv/powernv.h
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/pci.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/s390/appldata/appldata_base.c
arch/s390/appldata/appldata_os.c
arch/s390/configs/default_defconfig
arch/s390/configs/gcov_defconfig
arch/s390/configs/performance_defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/crypto/aes_s390.c
arch/s390/crypto/des_s390.c
arch/s390/defconfig
arch/s390/hypfs/hypfs_vm.c
arch/s390/include/asm/Kbuild
arch/s390/include/asm/airq.h
arch/s390/include/asm/bitops.h
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/checksum.h
arch/s390/include/asm/compat.h
arch/s390/include/asm/futex.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/sclp.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/uaccess.h
arch/s390/include/uapi/asm/ptrace.h
arch/s390/kernel/Makefile
arch/s390/kernel/compat_exec_domain.c [deleted file]
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_linux.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.S [deleted file]
arch/s390/kernel/compat_wrapper.c [new file with mode: 0644]
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head64.S
arch/s390/kernel/perf_event.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/topology.c
arch/s390/kvm/diag.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/lib/Makefile
arch/s390/lib/find.c
arch/s390/lib/uaccess.h
arch/s390/lib/uaccess_mvcos.c
arch/s390/lib/uaccess_pt.c
arch/s390/mm/maccess.c
arch/s390/mm/page-states.c
arch/s390/mm/pgtable.c
arch/s390/pci/pci_debug.c
arch/s390/pci/pci_dma.c
arch/score/include/asm/Kbuild
arch/score/include/asm/cputime.h [deleted file]
arch/sh/include/asm/Kbuild
arch/sh/include/cpu-sh2/cpu/cache.h
arch/sh/include/cpu-sh2a/cpu/cache.h
arch/sh/include/cpu-sh3/cpu/cache.h
arch/sh/include/cpu-sh4/cpu/cache.h
arch/sh/kernel/cpu/init.c
arch/sh/kernel/idle.c
arch/sh/mm/cache-debugfs.c
arch/sh/mm/cache-sh2.c
arch/sh/mm/cache-sh2a.c
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-shx3.c
arch/sh/mm/cache.c
arch/sparc/Kconfig
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/smp_64.h
arch/sparc/include/asm/topology_64.h
arch/sparc/kernel/mdesc.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/prom_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/syscalls.S
arch/sparc/mm/srmmu.c
arch/sparc/mm/tsb.c
arch/tile/include/asm/Kbuild
arch/um/include/asm/Kbuild
arch/unicore32/include/asm/Kbuild
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/Kconfig.debug
arch/x86/Makefile
arch/x86/boot/Makefile
arch/x86/boot/compressed/aslr.c
arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/eboot.h
arch/x86/boot/compressed/efi_stub_64.S
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/cpucheck.c
arch/x86/boot/header.S
arch/x86/boot/tools/build.c
arch/x86/include/asm/Kbuild
arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/barrier.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/cputime.h [deleted file]
arch/x86/include/asm/efi.h
arch/x86/include/asm/io.h
arch/x86/include/asm/msr.h
arch/x86/include/asm/nmi.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/special_insns.h
arch/x86/include/asm/spinlock.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/topology.h
arch/x86/include/asm/tsc.h
arch/x86/include/asm/unistd.h
arch/x86/include/asm/xen/page.h
arch/x86/include/asm/xsave.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/amd_nb.c
arch/x86/kernel/aperture_64.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/apic_noop.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/apic/summit_32.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/centaur.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/microcode/amd_early.c
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_intel_uncore.h
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/crash.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/early-quirks.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/head_32.S
arch/x86/kernel/head_64.S
arch/x86/kernel/i387.c
arch/x86/kernel/irq.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/module.c
arch/x86/kernel/nmi.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/quirks.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/time.c
arch/x86/kernel/tsc.c
arch/x86/kernel/tsc_msr.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/hash.c
arch/x86/lib/memcpy_32.c
arch/x86/lib/msr.c
arch/x86/mm/dump_pagetables.c
arch/x86/mm/fault.c
arch/x86/mm/numa.c
arch/x86/mm/numa_32.c
arch/x86/mm/pageattr.c
arch/x86/mm/srat.c
arch/x86/mm/tlb.c
arch/x86/net/bpf_jit.S
arch/x86/platform/efi/Makefile
arch/x86/platform/efi/efi-bgrt.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/efi_stub_64.S
arch/x86/platform/efi/efi_thunk_64.S [new file with mode: 0644]
arch/x86/platform/ts5500/ts5500.c
arch/x86/um/asm/barrier.h
arch/x86/vdso/Makefile
arch/x86/xen/enlighten.c
arch/x86/xen/p2m.c
arch/xtensa/Kconfig
arch/xtensa/boot/dts/xtfpga.dtsi
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/io.h
arch/xtensa/include/asm/traps.h
arch/xtensa/include/asm/vectors.h
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/time.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/mm/init.c
arch/xtensa/mm/mmu.c
arch/xtensa/platforms/xtfpga/setup.c
arch/xtensa/variants/fsf/include/variant/tie.h
block/blk-core.c
block/blk-exec.c
block/blk-flush.c
block/blk-lib.c
block/blk-merge.c
block/blk-mq-cpu.c
block/blk-mq-tag.c
block/blk-mq.c
block/blk-mq.h
block/blk-sysfs.c
block/blk-timeout.c
block/blk.h
drivers/acpi/ac.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/button.c
drivers/acpi/container.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/fan.c
drivers/acpi/pci_irq.c
drivers/acpi/proc.c
drivers/acpi/processor_throttling.c
drivers/acpi/resource.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/acard-ahci.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_da850.c [new file with mode: 0644]
drivers/ata/ahci_imx.c
drivers/ata/ahci_platform.c
drivers/ata/ahci_st.c [new file with mode: 0644]
drivers/ata/ahci_sunxi.c [new file with mode: 0644]
drivers/ata/ahci_xgene.c [new file with mode: 0644]
drivers/ata/ata_generic.c
drivers/ata/libahci.c
drivers/ata/libahci_platform.c [new file with mode: 0644]
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-zpodd.c
drivers/ata/pata_acpi.c
drivers/ata/pata_amd.c
drivers/ata/pata_arasan_cf.c
drivers/ata/pata_artop.c
drivers/ata/pata_at91.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_atp867x.c
drivers/ata/pata_cmd640.c
drivers/ata/pata_cmd64x.c
drivers/ata/pata_cs5520.c
drivers/ata/pata_cs5530.c
drivers/ata/pata_cs5535.c
drivers/ata/pata_cs5536.c
drivers/ata/pata_cypress.c
drivers/ata/pata_efar.c
drivers/ata/pata_ep93xx.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c
drivers/ata/pata_hpt3x3.c
drivers/ata/pata_imx.c
drivers/ata/pata_it8213.c
drivers/ata/pata_it821x.c
drivers/ata/pata_jmicron.c
drivers/ata/pata_legacy.c
drivers/ata/pata_marvell.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_netcell.c
drivers/ata/pata_ninja32.c
drivers/ata/pata_ns87410.c
drivers/ata/pata_ns87415.c
drivers/ata/pata_oldpiix.c
drivers/ata/pata_opti.c
drivers/ata/pata_optidma.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_pdc2027x.c
drivers/ata/pata_pdc202xx_old.c
drivers/ata/pata_piccolo.c
drivers/ata/pata_platform.c
drivers/ata/pata_pxa.c
drivers/ata/pata_radisys.c
drivers/ata/pata_rdc.c
drivers/ata/pata_rz1000.c
drivers/ata/pata_sc1200.c
drivers/ata/pata_scc.c
drivers/ata/pata_sch.c
drivers/ata/pata_serverworks.c
drivers/ata/pata_sil680.c
drivers/ata/pata_sis.c
drivers/ata/pata_sl82c105.c
drivers/ata/pata_triflex.c
drivers/ata/pata_via.c
drivers/ata/pdc_adma.c
drivers/ata/sata_dwc_460ex.c
drivers/ata/sata_highbank.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sil.c
drivers/ata/sata_sis.c
drivers/ata/sata_svw.c
drivers/ata/sata_sx4.c
drivers/ata/sata_uli.c
drivers/ata/sata_via.c
drivers/ata/sata_vsc.c
drivers/base/component.c
drivers/base/dma-buf.c
drivers/base/firmware_class.c
drivers/block/aoe/aoecmd.c
drivers/block/floppy.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/null_blk.c
drivers/block/nvme-core.c
drivers/block/nvme-scsi.c
drivers/block/rbd.c
drivers/block/virtio_blk.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/block/zram/zram_drv.c
drivers/char/Kconfig
drivers/char/raw.c
drivers/char/virtio_console.c
drivers/clk/at91/clk-master.c
drivers/clk/clk-nomadik.c
drivers/clk/clk.c
drivers/clk/keystone/gate.c
drivers/clk/mvebu/armada-370.c
drivers/clk/mvebu/armada-xp.c
drivers/clk/mvebu/dove.c
drivers/clk/mvebu/kirkwood.c
drivers/clk/shmobile/clk-rcar-gen2.c
drivers/clk/tegra/clk-divider.c
drivers/clk/tegra/clk-id.h
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-super-gen4.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra20.c
drivers/clocksource/bcm_kona_timer.c
drivers/clocksource/vf_pit_timer.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/powernow-k8.c
drivers/cpuidle/cpuidle-powernv.c
drivers/cpuidle/cpuidle-pseries.c
drivers/crypto/nx/nx-842.c
drivers/dma/Kconfig
drivers/dma/imx-sdma.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v3.c
drivers/dma/mv_xor.c
drivers/dma/ste_dma40.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_module.h
drivers/edac/i7300_edac.c
drivers/edac/i7core_edac.c
drivers/extcon/extcon-arizona.c
drivers/firewire/core-device.c
drivers/firewire/net.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/firmware/dcdbas.c
drivers/firmware/efi/efi-stub-helper.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/efivars.c
drivers/fmc/fmc-write-eeprom.c
drivers/gpio/Kconfig
drivers/gpio/gpio-bcm-kona.c
drivers/gpio/gpio-clps711x.c
drivers/gpio/gpio-intel-mid.c
drivers/gpio/gpio-xtensa.c
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/ast/ast_fb.c
drivers/gpu/drm/bochs/Kconfig
drivers/gpu/drm/cirrus/cirrus_fbdev.c
drivers/gpu/drm/drm_cache.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/gma500/mmu.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/engine/device/nv40.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/mc.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h
drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_vga.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/btcd.h
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/evergreen_smc.h
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_audio.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_semaphore.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/trinity_dpm.c
drivers/gpu/drm/radeon/uvd_v2_2.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/ttm/ttm_agp_backend.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/drm/vmwgfx/svga3d_reg.h
drivers/gpu/drm/vmwgfx/svga3d_surfacedefs.h
drivers/gpu/drm/vmwgfx/svga_reg.h
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/gpu/host1x/job.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hv/connection.c
drivers/hwmon/da9055-hwmon.c
drivers/hwmon/max1668.c
drivers/hwmon/ntc_thermistor.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/iio/accel/bma180.c
drivers/iio/adc/max1363.c
drivers/iio/gyro/Kconfig
drivers/iio/gyro/st_gyro.h
drivers/iio/gyro/st_gyro_core.c
drivers/iio/gyro/st_gyro_i2c.c
drivers/iio/gyro/st_gyro_spi.c
drivers/iio/imu/adis16400.h
drivers/iio/imu/adis16400_core.c
drivers/iio/light/cm32181.c
drivers/iio/light/cm36651.c
drivers/iio/light/tsl2563.c
drivers/iio/magnetometer/ak8975.c
drivers/iio/magnetometer/mag3110.c
drivers/infiniband/hw/amso1100/c2.c
drivers/infiniband/hw/amso1100/c2_rnic.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx5/Kconfig
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mlx5/user.h
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/ocrdma/ocrdma_main.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/evdev.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/misc/arizona-haptics.c
drivers/input/misc/da9052_onkey.c
drivers/input/mouse/cypress_ps2.c
drivers/input/mouse/synaptics.c
drivers/input/mousedev.c
drivers/iommu/arm-smmu.c
drivers/iommu/omap-iommu-debug.c
drivers/irqchip/Makefile
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-metag-ext.c
drivers/irqchip/irq-metag.c
drivers/irqchip/irq-orion.c
drivers/irqchip/irq-zevio.c [new file with mode: 0644]
drivers/isdn/capi/Kconfig
drivers/isdn/hisax/q931.c
drivers/md/Kconfig
drivers/md/bcache/bcache.h
drivers/md/bcache/bset.c
drivers/md/bcache/btree.c
drivers/md/bcache/extents.c
drivers/md/bcache/request.c
drivers/md/bcache/sysfs.c
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-target.c
drivers/md/dm-io.c
drivers/md/dm-mpath.c
drivers/md/dm-raid1.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/persistent-data/Kconfig
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/persistent-data/dm-space-map-metadata.h
drivers/md/raid1.c
drivers/md/raid5.c
drivers/media/dvb-frontends/cx24117.c
drivers/media/dvb-frontends/nxt200x.c
drivers/media/i2c/adv7842.c
drivers/media/i2c/s5k5baf.c
drivers/media/pci/bt8xx/bttv-cards.c
drivers/media/pci/bt8xx/bttv-gpio.c
drivers/media/pci/saa7134/saa7134-cards.c
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/platform/exynos4-is/fimc-lite.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c
drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h
drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c
drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h
drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c
drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h
drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h
drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h
drivers/media/usb/dvb-usb-v2/mxl111sf.c
drivers/media/usb/dvb-usb-v2/mxl111sf.h
drivers/media/usb/hdpvr/hdpvr-core.c
drivers/media/v4l2-core/v4l2-dv-timings.c
drivers/media/v4l2-core/videobuf-dma-contig.c
drivers/media/v4l2-core/videobuf-dma-sg.c
drivers/media/v4l2-core/videobuf-vmalloc.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/message/i2o/i2o_config.c
drivers/mfd/da9055-i2c.c
drivers/mfd/max14577.c
drivers/mfd/max8997.c
drivers/mfd/max8998.c
drivers/mfd/sec-core.c
drivers/mfd/tps65217.c
drivers/mfd/wm8994-core.c
drivers/misc/genwqe/card_dev.c
drivers/misc/mei/client.c
drivers/misc/mic/host/mic_virtio.c
drivers/misc/sgi-gru/grukdump.c
drivers/misc/sgi-xp/xpc_uv.c
drivers/mmc/card/queue.c
drivers/mmc/host/dw_mmc.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/omap2.c
drivers/mtd/ubi/fastmap.c
drivers/net/Kconfig
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_3ad.h
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bonding.h
drivers/net/can/Kconfig
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/janz-ican3.c
drivers/net/can/usb/kvaser_usb.c
drivers/net/can/vcan.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/cnic.h
drivers/net/ethernet/broadcom/cnic_defs.h
drivers/net/ethernet/broadcom/cnic_if.h
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bfa_ioc.c
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmveth.h
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/Kconfig
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/ethernet/stmicro/stmmac/Makefile
drivers/net/ethernet/stmicro/stmmac/chain_mode.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c [new file with mode: 0644]
drivers/net/ethernet/stmicro/stmmac/ring_mode.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_cpdma.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ifb.c
drivers/net/irda/Kconfig
drivers/net/irda/Makefile
drivers/net/irda/ep7211-sir.c [deleted file]
drivers/net/irda/irtty-sir.c
drivers/net/macvlan.c
drivers/net/phy/dp83640.c
drivers/net/phy/mdio-sun4i.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/gl620a.c
drivers/net/usb/hso.c
drivers/net/usb/mcs7830.c
drivers/net/usb/net1080.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/r815x.c [deleted file]
drivers/net/usb/rndis_host.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/sr9800.c [new file with mode: 0644]
drivers/net/usb/sr9800.h [new file with mode: 0644]
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/dlci.c
drivers/net/wireless/ath/ar5523/ar5523.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_proc.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/mwifiex/11ac.c
drivers/net/wireless/mwifiex/11n.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rtl818x/rtl8180/dev.c
drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/ti/wl1251/rx.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netfront.c
drivers/of/address.c
drivers/of/base.c
drivers/of/of_mdio.c
drivers/of/selftest.c
drivers/of/testcase-data/testcases.dtsi [new file with mode: 0644]
drivers/of/testcase-data/tests-interrupts.dtsi [new file with mode: 0644]
drivers/of/testcase-data/tests-match.dtsi [new file with mode: 0644]
drivers/of/testcase-data/tests-phandle.dtsi [new file with mode: 0644]
drivers/pci/bus.c
drivers/pci/host/pci-mvebu.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/phy/phy-exynos-dp-video.c
drivers/phy/phy-exynos-mipi-video.c
drivers/phy/phy-mvebu-sata.c
drivers/phy/phy-omap-usb2.c
drivers/phy/phy-twl4030-usb.c
drivers/pinctrl/Kconfig
drivers/pinctrl/core.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-capri.c
drivers/pinctrl/pinctrl-imx1-core.c
drivers/pinctrl/pinctrl-sunxi.c
drivers/pinctrl/pinctrl-sunxi.h
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/sh-pfc/pfc-r8a7791.c
drivers/pinctrl/sirf/pinctrl-prima2.c
drivers/pinctrl/sirf/pinctrl-sirf.c
drivers/pinctrl/vt8500/pinctrl-wmt.c
drivers/pnp/pnpacpi/rsparser.c
drivers/pnp/pnpbios/bioscalls.c
drivers/power/ds2782_battery.c
drivers/power/isp1704_charger.c
drivers/power/max17040_battery.c
drivers/ps3/ps3-vuart.c
drivers/pwm/pwm-lp3943.c
drivers/rapidio/devices/tsi721.h
drivers/rapidio/devices/tsi721_dma.c
drivers/regulator/ab3100.c
drivers/regulator/core.c
drivers/regulator/da9055-regulator.c
drivers/regulator/da9063-regulator.c
drivers/regulator/max14577.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/rtc/rtc-s3c.c
drivers/s390/char/con3215.c
drivers/s390/char/con3270.c
drivers/s390/char/raw3270.c
drivers/s390/char/raw3270.h
drivers/s390/char/sclp_early.c
drivers/s390/cio/airq.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc_sch.c
drivers/s390/cio/cio.c
drivers/s390/cio/device.c
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_main.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/sbus/char/jsflash.c
drivers/scsi/atari_scsi.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/isci/host.h
drivers/scsi/isci/port_config.c
drivers/scsi/isci/task.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_isr.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/scsi_lib.c
drivers/scsi/storvsc_drv.c
drivers/spi/Kconfig
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-imx.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi.c
drivers/staging/android/ashmem.c
drivers/staging/android/binder.c
drivers/staging/android/ion/compat_ion.c
drivers/staging/android/ion/ion_dummy_driver.c
drivers/staging/android/ion/ion_heap.c
drivers/staging/android/ion/ion_priv.h
drivers/staging/android/ion/ion_system_heap.c
drivers/staging/android/sw_sync.h
drivers/staging/android/sync.c
drivers/staging/bcm/Bcmnet.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/comedi/drivers/usbduxsigma.c
drivers/staging/cxt1e1/linux.c
drivers/staging/dgrp/dgrp_net_ops.c
drivers/staging/fwserial/fwserial.c
drivers/staging/fwserial/fwserial.h
drivers/staging/gdm72xx/gdm_usb.c
drivers/staging/iio/Documentation/iio_utils.h
drivers/staging/iio/adc/ad799x_core.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-hdmi.c
drivers/staging/lustre/TODO
drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h
drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
drivers/staging/lustre/lustre/include/lustre/lustre_user.h
drivers/staging/lustre/lustre/llite/dir.c
drivers/staging/lustre/lustre/mdc/mdc_request.c
drivers/staging/media/go7007/go7007-loader.c
drivers/staging/netlogic/xlr_net.c
drivers/staging/octeon-usb/octeon-hcd.c
drivers/staging/ozwpan/ozproto.c
drivers/staging/rtl8188eu/core/rtw_wlan_util.c
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8188eu/os_dep/os_intfs.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8821ae/Kconfig
drivers/staging/rtl8821ae/wifi.h
drivers/staging/usbip/userspace/libsrc/names.c
drivers/staging/usbip/vhci_sysfs.c
drivers/staging/wlags49_h2/wl_wext.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_erl2.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/target_core_alua.c
drivers/target/target_core_pr.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_transport.c
drivers/thermal/Kconfig
drivers/thermal/thermal_core.c
drivers/thermal/x86_pkg_temp_thermal.c
drivers/tty/hvc/hvc_opal.c
drivers/tty/hvc/hvc_rtas.c
drivers/tty/hvc/hvc_udbg.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/n_gsm.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/sirfsoc_uart.c
drivers/tty/serial/sunhv.c
drivers/tty/serial/sunsab.c
drivers/tty/serial/sunsu.c
drivers/tty/serial/sunzilog.c
drivers/tty/tty_ldsem.c
drivers/tty/vt/vt.c
drivers/usb/chipidea/udc.c
drivers/usb/core/config.c
drivers/usb/core/driver.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.h
drivers/usb/dwc2/core.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/platform.c
drivers/usb/gadget/bcm63xx_udc.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_virthub.c
drivers/usb/musb/omap2430.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/phy/phy.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/usb-serial-simple.c
drivers/usb/storage/Kconfig
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_cypress.h
drivers/usb/storage/unusual_devs.h
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/video/Kconfig
drivers/video/exynos/Kconfig
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dpi.c
drivers/video/omap2/dss/sdi.c
drivers/vme/bridges/vme_ca91cx42.c
drivers/vme/bridges/vme_tsi148.c
drivers/watchdog/Kconfig
drivers/watchdog/w83697hf_wdt.c
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/events/events_base.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/xencomm.c [deleted file]
fs/afs/internal.h
fs/afs/rxrpc.c
fs/anon_inodes.c
fs/bio-integrity.c
fs/bio.c
fs/btrfs/check-integrity.c
fs/btrfs/compression.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/sysfs.c
fs/buffer.c
fs/ceph/acl.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifsacl.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb1ops.c
fs/cifs/smb2glob.h
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2proto.h
fs/cifs/transport.c
fs/cifs/xattr.c
fs/compat.c
fs/compat_binfmt_elf.c
fs/compat_ioctl.c
fs/dcache.c
fs/efivarfs/file.c
fs/exec.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/resize.c
fs/ext4/super.c
fs/file.c
fs/file_table.c
fs/fs-writeback.c
fs/fscache/object-list.c
fs/fscache/object.c
fs/hfsplus/catalog.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/hfsplus_raw.h
fs/hfsplus/inode.c
fs/hfsplus/options.c
fs/jbd2/transaction.c
fs/jfs/acl.c
fs/jfs/xattr.c
fs/kernfs/dir.c
fs/kernfs/mount.c
fs/lockd/svclock.c
fs/mount.h
fs/namei.c
fs/namespace.c
fs/nfs/delegation.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4client.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4session.c
fs/nfs/nfs4session.h
fs/nfs/nfs4state.c
fs/nfsd/nfs4acl.c
fs/nfsd/vfs.c
fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.c
fs/notify/group.c
fs/notify/inotify/inotify.h
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/notification.c
fs/ntfs/file.c
fs/ocfs2/alloc.c
fs/ocfs2/file.c
fs/ocfs2/localalloc.c
fs/ocfs2/localalloc.h
fs/ocfs2/namei.c
fs/ocfs2/quota_global.c
fs/ocfs2/quota_local.c
fs/ocfs2/stackglue.c
fs/open.c
fs/pnode.c
fs/pnode.h
fs/posix_acl.c
fs/proc/base.c
fs/proc/page.c
fs/proc/stat.c
fs/proc/uptime.c
fs/proc/vmcore.c
fs/quota/dquot.c
fs/read_write.c
fs/reiserfs/do_balan.c
fs/sync.c
fs/sysfs/mount.c
fs/udf/file.c
fs/udf/inode.c
fs/xfs/xfs_file.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_sb.c
fs/xfs/xfs_super.c
include/asm-generic/bitops/const_hweight.h
include/asm-generic/cputime_jiffies.h
include/asm-generic/cputime_nsecs.h
include/asm-generic/mcs_spinlock.h [new file with mode: 0644]
include/asm-generic/pgtable.h
include/asm-generic/rwsem.h
include/drm/drmP.h
include/drm/drm_crtc.h
include/drm/ttm/ttm_page_alloc.h
include/dt-bindings/clock/tegra124-car.h
include/kvm/arm_vgic.h
include/linux/ahci_platform.h
include/linux/audit.h
include/linux/binfmts.h
include/linux/bio.h
include/linux/bitops.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/can/skb.h
include/linux/ceph/ceph_fs.h
include/linux/cgroup.h
include/linux/clk/ti.h
include/linux/compat.h
include/linux/compiler-gcc4.h
include/linux/cputime.h [new file with mode: 0644]
include/linux/dma-buf.h
include/linux/efi.h
include/linux/file.h
include/linux/firewire.h
include/linux/fs.h
include/linux/fsnotify_backend.h
include/linux/ftrace_event.h
include/linux/futex.h
include/linux/gfp.h
include/linux/gpio/consumer.h
include/linux/huge_mm.h
include/linux/hyperv.h
include/linux/init.h
include/linux/interrupt.h
include/linux/io.h
include/linux/ipc_namespace.h
include/linux/irq_work.h
include/linux/kernel.h
include/linux/kernel_stat.h
include/linux/kernfs.h
include/linux/kexec.h
include/linux/libata.h
include/linux/linkage.h
include/linux/lockdep.h
include/linux/mfd/max8997-private.h
include/linux/mfd/max8998-private.h
include/linux/mfd/tps65217.h
include/linux/mlx5/driver.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/mutex.h
include/linux/netdev_features.h
include/linux/netdevice.h
include/linux/nfs_xdr.h
include/linux/nvme.h
include/linux/of.h
include/linux/of_device.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/phy/phy.h
include/linux/rculist.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/rmap.h
include/linux/sched.h
include/linux/sched/prio.h [new file with mode: 0644]
include/linux/sched/rt.h
include/linux/security.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/smp.h
include/linux/spi/spi.h
include/linux/srcu.h
include/linux/syscalls.h
include/linux/torture.h [new file with mode: 0644]
include/linux/tracepoint.h
include/linux/usb.h
include/linux/usb/cdc_ncm.h
include/linux/usb/usbnet.h
include/linux/vm_event_item.h
include/linux/vmstat.h
include/linux/workqueue.h
include/linux/writeback.h
include/net/datalink.h
include/net/dn.h
include/net/dn_route.h
include/net/ethoc.h
include/net/if_inet6.h
include/net/ip_tunnels.h
include/net/ipx.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nft_reject.h [new file with mode: 0644]
include/net/sctp/structs.h
include/net/sock.h
include/net/tcp.h
include/net/xfrm.h
include/rdma/ib_verbs.h
include/scsi/libsas.h
include/sound/soc-dapm.h
include/target/iscsi/iscsi_transport.h
include/target/target_core_base.h
include/trace/events/power.h
include/trace/events/sunrpc.h
include/trace/events/writeback.h
include/trace/ftrace.h
include/uapi/asm-generic/unistd.h
include/uapi/drm/drm.h
include/uapi/drm/vmwgfx_drm.h
include/uapi/linux/btrfs.h
include/uapi/linux/in6.h
include/uapi/linux/mic_ioctl.h
include/uapi/linux/nvme.h
include/uapi/xen/Kbuild
include/uapi/xen/gntalloc.h [new file with mode: 0644]
include/uapi/xen/gntdev.h [new file with mode: 0644]
include/xen/gntalloc.h [deleted file]
include/xen/gntdev.h [deleted file]
include/xen/grant_table.h
include/xen/interface/io/blkif.h
include/xen/interface/xencomm.h [deleted file]
include/xen/xencomm.h [deleted file]
init/Kconfig
init/main.c
ipc/compat.c
ipc/compat_mq.c
ipc/mq_sysctl.c
ipc/mqueue.c
ipc/msg.c
kernel/Makefile
kernel/audit.c
kernel/audit.h
kernel/audit_tree.c
kernel/audit_watch.c
kernel/auditfilter.c
kernel/auditsc.c
kernel/cgroup.c
kernel/compat.c
kernel/cpu/Makefile [deleted file]
kernel/cpu/idle.c [deleted file]
kernel/cpuset.c
kernel/debug/debug_core.c
kernel/events/core.c
kernel/extable.c
kernel/fork.c
kernel/futex.c
kernel/irq/Kconfig
kernel/irq/devres.c
kernel/irq/irqdesc.c
kernel/irq/irqdomain.c
kernel/irq/manage.c
kernel/irq_work.c
kernel/kexec.c
kernel/kmod.c
kernel/ksysfs.c
kernel/locking/Makefile
kernel/locking/lockdep.c
kernel/locking/locktorture.c [new file with mode: 0644]
kernel/locking/mcs_spinlock.c [new file with mode: 0644]
kernel/locking/mcs_spinlock.h [new file with mode: 0644]
kernel/locking/mutex-debug.c
kernel/locking/mutex.c
kernel/locking/rtmutex.c
kernel/locking/rwsem-xadd.c
kernel/module.c
kernel/notifier.c
kernel/panic.c
kernel/power/console.c
kernel/printk/printk.c
kernel/profile.c
kernel/ptrace.c
kernel/rcu/Makefile
kernel/rcu/rcu.h
kernel/rcu/rcutorture.c [new file with mode: 0644]
kernel/rcu/srcu.c
kernel/rcu/tiny.c
kernel/rcu/tiny_plugin.h
kernel/rcu/torture.c [deleted file]
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/rcu/tree_trace.c
kernel/rcu/update.c
kernel/sched/Makefile
kernel/sched/auto_group.c
kernel/sched/clock.c
kernel/sched/core.c
kernel/sched/cpudeadline.c
kernel/sched/cputime.c
kernel/sched/deadline.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/idle.c [new file with mode: 0644]
kernel/sched/idle_task.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/sched/stop_task.c
kernel/stop_machine.c
kernel/sys.c
kernel/sysctl.c
kernel/time/jiffies.c
kernel/time/sched_clock.c
kernel/time/tick-broadcast.c
kernel/time/timekeeping.c
kernel/timer.c
kernel/torture.c [new file with mode: 0644]
kernel/trace/ring_buffer.c
kernel/trace/ring_buffer_benchmark.c
kernel/trace/trace.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_events.c
kernel/trace/trace_export.c
kernel/trace/trace_irqsoff.c
kernel/tracepoint.c
kernel/user_namespace.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Makefile
lib/dma-debug.c
lib/fonts/Kconfig
lib/percpu_ida.c
lib/radix-tree.c
lib/random32.c
lib/string.c
mm/Kconfig
mm/compaction.c
mm/filemap.c
mm/fremap.c
mm/huge_memory.c
mm/ksm.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mmu_context.c
mm/mprotect.c
mm/page-writeback.c
mm/page_alloc.c
mm/percpu.c
mm/process_vm_access.c
mm/rmap.c
mm/slub.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/vmpressure.c
mm/vmstat.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/9p/client.c
net/9p/trans_virtio.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/hard-interface.c
net/batman-adv/originator.c
net/batman-adv/originator.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/translation-table.c
net/bluetooth/hidp/core.c
net/bluetooth/hidp/hidp.h
net/bridge/br_device.c
net/bridge/br_fdb.c
net/bridge/br_if.c
net/bridge/br_input.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_stp_if.c
net/bridge/br_vlan.c
net/caif/caif_dev.c
net/caif/cfsrvl.c
net/can/af_can.c
net/can/bcm.c
net/can/raw.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/compat.c
net/core/dev.c
net/core/fib_rules.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/netpoll.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ccids/lib/tfrc.c
net/dccp/ccids/lib/tfrc.h
net/decnet/af_decnet.c
net/hsr/hsr_framereg.c
net/ieee802154/6lowpan.c
net/ipv4/af_inet.c
net/ipv4/devinet.c
net/ipv4/gre_demux.c
net/ipv4/inet_fragment.c
net/ipv4/ip_forward.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ipconfig.c
net/ipv4/ipmr.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/nf_nat_h323.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/netfilter/nft_reject_ipv4.c [new file with mode: 0644]
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp_offload.c
net/ipv6/Kconfig
net/ipv6/addrconf.c
net/ipv6/exthdrs_core.c
net/ipv6/exthdrs_offload.c
net/ipv6/icmp.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6mr.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/Makefile
net/ipv6/netfilter/nft_reject_ipv6.c [new file with mode: 0644]
net/ipv6/ping.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/udp_offload.c
net/ipx/af_ipx.c
net/ipx/ipx_route.c
net/key/af_key.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_netlink.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mesh_ps.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wme.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_core.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/nft_ct.c
net/netfilter/nft_log.c
net/netfilter/nft_lookup.c
net/netfilter/nft_meta.c
net/netfilter/nft_payload.c
net/netfilter/nft_queue.c
net/netfilter/nft_rbtree.c
net/netfilter/nft_reject.c
net/netfilter/nft_reject_inet.c [new file with mode: 0644]
net/netfilter/xt_CT.c
net/netlink/af_netlink.c
net/nfc/nci/core.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/openvswitch/flow_table.c
net/openvswitch/flow_table.h
net/packet/af_packet.c
net/sched/sch_api.c
net/sched/sch_fq.c
net/sched/sch_pie.c
net/sched/sch_tbf.c
net/sctp/associola.c
net/sctp/ipv6.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/ulpevent.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/svc_xprt.c
net/sunrpc/xprtsock.c
net/tipc/bearer.c
net/tipc/config.c
net/tipc/core.c
net/tipc/core.h
net/tipc/handler.c
net/tipc/link.c
net/tipc/name_table.c
net/tipc/netlink.c
net/tipc/ref.c
net/tipc/server.c
net/tipc/server.h
net/tipc/socket.c
net/tipc/subscr.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/reg.c
net/wireless/scan.c
net/wireless/sme.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/checkpatch.pl
scripts/gcc-ld [new file with mode: 0644]
scripts/gen_initramfs_list.sh
scripts/get_maintainer.pl
scripts/ld-version.sh [new file with mode: 0755]
scripts/mod/file2alias.c
scripts/mod/modpost.c
scripts/mod/modpost.h
security/Kconfig
security/capability.c
security/keys/compat.c
security/keys/keyring.c
security/security.c
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/include/xfrm.h
security/selinux/nlmsgtab.c
security/selinux/selinuxfs.c
security/selinux/ss/policydb.c
security/selinux/ss/services.c
security/selinux/xfrm.c
sound/core/compress_offload.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/thinkpad_helper.c
sound/pci/oxygen/xonar_dg.c
sound/soc/blackfin/Kconfig
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/da732x.c
sound/soc/codecs/da9055.c
sound/soc/codecs/isabelle.c
sound/soc/codecs/max98090.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/si476x.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/fsl_esai.c
sound/soc/fsl/fsl_esai.h
sound/soc/fsl/imx-mc13783.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/fsl/imx-wm8962.c
sound/soc/omap/n810.c
sound/soc/samsung/Kconfig
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/soc/txx9/txx9aclc-ac97.c
sound/usb/Kconfig
sound/usb/mixer.c
sound/usb/mixer_maps.c
tools/include/linux/hash.h [new file with mode: 0644]
tools/lib/api/Makefile
tools/lib/api/fs/fs.c [new file with mode: 0644]
tools/lib/api/fs/fs.h [new file with mode: 0644]
tools/lib/lockdep/Makefile
tools/lib/lockdep/preload.c
tools/lib/lockdep/run_tests.sh [changed mode: 0644->0755]
tools/lib/lockdep/uinclude/asm/hash.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rcu.h
tools/net/Makefile
tools/perf/Documentation/perf-mem.txt
tools/perf/Documentation/perf-probe.txt
tools/perf/MANIFEST
tools/perf/Makefile.perf
tools/perf/arch/arm/Makefile
tools/perf/arch/arm/util/unwind-libunwind.c [new file with mode: 0644]
tools/perf/arch/arm/util/unwind.c [deleted file]
tools/perf/arch/x86/Makefile
tools/perf/arch/x86/include/perf_regs.h
tools/perf/arch/x86/tests/dwarf-unwind.c [new file with mode: 0644]
tools/perf/arch/x86/tests/regs_load.S [new file with mode: 0644]
tools/perf/arch/x86/util/unwind-libdw.c [new file with mode: 0644]
tools/perf/arch/x86/util/unwind-libunwind.c [new file with mode: 0644]
tools/perf/arch/x86/util/unwind.c [deleted file]
tools/perf/bench/bench.h
tools/perf/bench/futex-hash.c [new file with mode: 0644]
tools/perf/bench/futex-requeue.c [new file with mode: 0644]
tools/perf/bench/futex-wake.c [new file with mode: 0644]
tools/perf/bench/futex.h [new file with mode: 0644]
tools/perf/bench/numa.c
tools/perf/builtin-bench.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
tools/perf/builtin-kvm.c
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/Makefile
tools/perf/config/feature-checks/Makefile
tools/perf/config/feature-checks/test-all.c
tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c [new file with mode: 0644]
tools/perf/design.txt
tools/perf/perf-completion.sh
tools/perf/perf.h
tools/perf/tests/builtin-test.c
tools/perf/tests/dwarf-unwind.c [new file with mode: 0644]
tools/perf/tests/hists_link.c
tools/perf/tests/make
tools/perf/tests/parse-events.c
tools/perf/tests/sample-parsing.c
tools/perf/tests/tests.h
tools/perf/tests/vmlinux-kallsyms.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/hist.c
tools/perf/ui/stdio/hist.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/cpumap.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/fs.c [deleted file]
tools/perf/util/fs.h [deleted file]
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/include/asm/hash.h [new file with mode: 0644]
tools/perf/util/include/linux/bitops.h
tools/perf/util/include/linux/hash.h [deleted file]
tools/perf/util/include/linux/kernel.h
tools/perf/util/include/linux/list.h
tools/perf/util/include/linux/magic.h [deleted file]
tools/perf/util/include/linux/prefetch.h [deleted file]
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/parse-events.c
tools/perf/util/parse-options.c
tools/perf/util/parse-options.h
tools/perf/util/perf_regs.c [new file with mode: 0644]
tools/perf/util/perf_regs.h
tools/perf/util/pmu.c
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/python-ext-sources
tools/perf/util/record.c
tools/perf/util/session.c
tools/perf/util/symbol-elf.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/trace-event-parse.c
tools/perf/util/unwind-libdw.c [new file with mode: 0644]
tools/perf/util/unwind-libdw.h [new file with mode: 0644]
tools/perf/util/unwind-libunwind.c [new file with mode: 0644]
tools/perf/util/unwind.c [deleted file]
tools/perf/util/unwind.h
tools/perf/util/util.c
tools/testing/selftests/ipc/msgque.c
tools/testing/selftests/rcutorture/bin/functions.sh
tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh [deleted file]
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/kvm.sh
tools/testing/selftests/rcutorture/configs/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/SRCU-N [deleted file]
tools/testing/selftests/rcutorture/configs/SRCU-N.boot [deleted file]
tools/testing/selftests/rcutorture/configs/SRCU-P [deleted file]
tools/testing/selftests/rcutorture/configs/SRCU-P.boot [deleted file]
tools/testing/selftests/rcutorture/configs/TINY01 [deleted file]
tools/testing/selftests/rcutorture/configs/TINY02 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE01 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE01.boot [deleted file]
tools/testing/selftests/rcutorture/configs/TREE02 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE03 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE04 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE04.boot [deleted file]
tools/testing/selftests/rcutorture/configs/TREE05 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE05.boot [deleted file]
tools/testing/selftests/rcutorture/configs/TREE06 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE07 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE08 [deleted file]
tools/testing/selftests/rcutorture/configs/TREE08-T [deleted file]
tools/testing/selftests/rcutorture/configs/TREE09 [deleted file]
tools/testing/selftests/rcutorture/configs/lock/BUSTED [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/CFcommon [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/LOCK01 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/BUSTED [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/CFcommon [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/SRCU-N [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/SRCU-P [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TINY01 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TINY02 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE01 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE02 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE03 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE04 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE05 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE06 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE07 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE08 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE08-T [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE09 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/configs/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt [deleted file]
tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt [new file with mode: 0644]
virt/kvm/arm/vgic.c
virt/kvm/coalesced_mmio.c
virt/kvm/kvm_main.c

index 7e9932e55475cef2891a790e391011b77b9ff666..42fa0d5626a9560d74d16b2df5250b300543b67e 100644 (file)
@@ -92,3 +92,6 @@ extra_certificates
 signing_key.priv
 signing_key.x509
 x509.genkey
+
+# Kconfig presets
+all.config
index 38f8444bdd0e2b6df55d5643f5ac73319e2663ad..07de7e19b4ce4b2255c5ddf0c046fa5515733203 100644 (file)
@@ -29,6 +29,8 @@ DMA-ISA-LPC.txt
        - How to do DMA with ISA (and LPC) devices.
 DMA-attributes.txt
        - listing of the various possible attributes a DMA region can have
+dmatest.txt
+       - how to compile, configure and use the dmatest system.
 DocBook/
        - directory with DocBook templates etc. for kernel documentation.
 EDID/
@@ -77,6 +79,8 @@ arm/
        - directory with info about Linux on the ARM architecture.
 arm64/
        - directory with info about Linux on the 64 bit ARM architecture.
+assoc_array.txt
+       - generic associative array intro.
 atomic_ops.txt
        - semantics and behavior of atomic and bitmask operations.
 auxdisplay/
@@ -87,6 +91,8 @@ bad_memory.txt
        - how to use kernel parameters to exclude bad RAM regions.
 basic_profiling.txt
        - basic instructions for those who wants to profile Linux kernel.
+bcache.txt
+       - Block-layer cache on fast SSDs to improve slow (raid) I/O performance.
 binfmt_misc.txt
        - info on the kernel support for extra binary formats.
 blackfin/
@@ -171,6 +177,8 @@ early-userspace/
        - info about initramfs, klibc, and userspace early during boot.
 edac.txt
        - information on EDAC - Error Detection And Correction
+efi-stub.txt
+       - How to use the EFI boot stub to bypass GRUB or elilo on EFI systems.
 eisa.txt
        - info on EISA bus support.
 email-clients.txt
@@ -195,8 +203,8 @@ futex-requeue-pi.txt
        - info on requeueing of tasks from a non-PI futex to a PI futex
 gcov.txt
        - use of GCC's coverage testing tool "gcov" with the Linux kernel
-gpio.txt
-       - overview of GPIO (General Purpose Input/Output) access conventions.
+gpio/
+       - gpio related documentation
 hid/
        - directory with information on human interface devices
 highuid.txt
@@ -255,6 +263,8 @@ kernel-docs.txt
        - listing of various WWW + books that document kernel internals.
 kernel-parameters.txt
        - summary listing of command line / boot prompt args for the kernel.
+kernel-per-CPU-kthreads.txt
+       - List of all per-CPU kthreads and how they introduce jitter.
 kmemcheck.txt
        - info on dynamic checker that detects uses of uninitialized memory.
 kmemleak.txt
@@ -299,8 +309,6 @@ memory-devices/
        - directory with info on parts like the Texas Instruments EMIF driver
 memory-hotplug.txt
        - Hotpluggable memory support, how to use and current status.
-memory.txt
-       - info on typical Linux memory problems.
 metag/
        - directory with info about Linux on Meta architecture.
 mips/
@@ -311,6 +319,8 @@ mmc/
        - directory with info about the MMC subsystem
 mn10300/
        - directory with info about the mn10300 architecture port
+module-signing.txt
+       - Kernel module signing for increased security when loading modules.
 mtd/
        - directory with info about memory technology devices (flash)
 mono.txt
@@ -343,6 +353,8 @@ pcmcia/
        - info on the Linux PCMCIA driver.
 percpu-rw-semaphore.txt
        - RCU based read-write semaphore optimized for locking for reading
+phy.txt
+       - Description of the generic PHY framework.
 pi-futex.txt
        - documentation on lightweight priority inheritance futexes.
 pinctrl.txt
@@ -431,6 +443,8 @@ sysrq.txt
        - info on the magic SysRq key.
 target/
        - directory with info on generating TCM v4 fabric .ko modules
+this_cpu_ops.txt
+       - List rationale behind and the way to use this_cpu operations.
 thermal/
        - directory with information on managing thermal issues (CPU/temp)
 trace/
@@ -469,6 +483,8 @@ wimax/
        - directory with info about Intel Wireless Wimax Connections
 workqueue.txt
        - information on the Concurrency Managed Workqueue implementation
+ww-mutex-design.txt
+       - Intro to Mutex wait/would deadlock handling.s
 x86/x86_64/
        - directory with info on Linux support for AMD x86-64 (Hammer) machines.
 xtensa/
index a8d01005f480ad6be4c86f187665e9ef3d75d08e..10a93696e55ad33c821a5466ed813a07e9fb9930 100644 (file)
@@ -82,7 +82,19 @@ Most of the hard work is done for the driver in the PCI layer.  It simply
 has to request that the PCI layer set up the MSI capability for this
 device.
 
-4.2.1 pci_enable_msi_range
+4.2.1 pci_enable_msi
+
+int pci_enable_msi(struct pci_dev *dev)
+
+A successful call allocates ONE interrupt to the device, regardless
+of how many MSIs the device supports.  The device is switched from
+pin-based interrupt mode to MSI mode.  The dev->irq number is changed
+to a new number which represents the message signaled interrupt;
+consequently, this function should be called before the driver calls
+request_irq(), because an MSI is delivered via a vector that is
+different from the vector of a pin-based interrupt.
+
+4.2.2 pci_enable_msi_range
 
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
 
@@ -147,6 +159,11 @@ static int foo_driver_enable_msi(struct pci_dev *pdev, int nvec)
        return pci_enable_msi_range(pdev, nvec, nvec);
 }
 
+Note, unlike pci_enable_msi_exact() function, which could be also used to
+enable a particular number of MSI-X interrupts, pci_enable_msi_range()
+returns either a negative errno or 'nvec' (not negative errno or 0 - as
+pci_enable_msi_exact() does).
+
 4.2.1.3 Single MSI mode
 
 The most notorious example of the request type described above is
@@ -158,7 +175,27 @@ static int foo_driver_enable_single_msi(struct pci_dev *pdev)
        return pci_enable_msi_range(pdev, 1, 1);
 }
 
-4.2.2 pci_disable_msi
+Note, unlike pci_enable_msi() function, which could be also used to
+enable the single MSI mode, pci_enable_msi_range() returns either a
+negative errno or 1 (not negative errno or 0 - as pci_enable_msi()
+does).
+
+4.2.3 pci_enable_msi_exact
+
+int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+
+This variation on pci_enable_msi_range() call allows a device driver to
+request exactly 'nvec' MSIs.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to request any more MSI interrupts for
+this device.
+
+By contrast with pci_enable_msi_range() function, pci_enable_msi_exact()
+returns zero in case of success, which indicates MSI interrupts have been
+successfully allocated.
+
+4.2.4 pci_disable_msi
 
 void pci_disable_msi(struct pci_dev *dev)
 
@@ -172,7 +209,7 @@ on any interrupt for which it previously called request_irq().
 Failure to do so results in a BUG_ON(), leaving the device with
 MSI enabled and thus leaking its vector.
 
-4.2.3 pci_msi_vec_count
+4.2.4 pci_msi_vec_count
 
 int pci_msi_vec_count(struct pci_dev *dev)
 
@@ -257,8 +294,8 @@ possible, likely up to the limit returned by pci_msix_vec_count() function:
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-       return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-                                   1, nvec);
+       return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                    1, nvec);
 }
 
 Note the value of 'minvec' parameter is 1.  As 'minvec' is inclusive,
@@ -269,8 +306,8 @@ In this case the function could look like this:
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-       return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-                                   FOO_DRIVER_MINIMUM_NVEC, nvec);
+       return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                    FOO_DRIVER_MINIMUM_NVEC, nvec);
 }
 
 4.3.1.2 Exact number of MSI-X interrupts
@@ -282,10 +319,15 @@ parameters:
 
 static int foo_driver_enable_msix(struct foo_adapter *adapter, int nvec)
 {
-       return pci_enable_msi_range(adapter->pdev, adapter->msix_entries,
-                                   nvec, nvec);
+       return pci_enable_msix_range(adapter->pdev, adapter->msix_entries,
+                                    nvec, nvec);
 }
 
+Note, unlike pci_enable_msix_exact() function, which could be also used to
+enable a particular number of MSI-X interrupts, pci_enable_msix_range()
+returns either a negative errno or 'nvec' (not negative errno or 0 - as
+pci_enable_msix_exact() does).
+
 4.3.1.3 Specific requirements to the number of MSI-X interrupts
 
 As noted above, there could be devices that can not operate with just any
@@ -332,7 +374,64 @@ Note how pci_enable_msix_range() return value is analized for a fallback -
 any error code other than -ENOSPC indicates a fatal error and should not
 be retried.
 
-4.3.2 pci_disable_msix
+4.3.2 pci_enable_msix_exact
+
+int pci_enable_msix_exact(struct pci_dev *dev,
+                         struct msix_entry *entries, int nvec)
+
+This variation on pci_enable_msix_range() call allows a device driver to
+request exactly 'nvec' MSI-Xs.
+
+If this function returns a negative number, it indicates an error and
+the driver should not attempt to allocate any more MSI-X interrupts for
+this device.
+
+By contrast with pci_enable_msix_range() function, pci_enable_msix_exact()
+returns zero in case of success, which indicates MSI-X interrupts have been
+successfully allocated.
+
+Another version of a routine that enables MSI-X mode for a device with
+specific requirements described in chapter 4.3.1.3 might look like this:
+
+/*
+ * Assume 'minvec' and 'maxvec' are non-zero
+ */
+static int foo_driver_enable_msix(struct foo_adapter *adapter,
+                                 int minvec, int maxvec)
+{
+       int rc;
+
+       minvec = roundup_pow_of_two(minvec);
+       maxvec = rounddown_pow_of_two(maxvec);
+
+       if (minvec > maxvec)
+               return -ERANGE;
+
+retry:
+       rc = pci_enable_msix_exact(adapter->pdev,
+                                  adapter->msix_entries, maxvec);
+
+       /*
+        * -ENOSPC is the only error code allowed to be analyzed
+        */
+       if (rc == -ENOSPC) {
+               if (maxvec == 1)
+                       return -ENOSPC;
+
+               maxvec /= 2;
+
+               if (minvec > maxvec)
+                       return -ENOSPC;
+
+               goto retry;
+       } else if (rc < 0) {
+               return rc;
+       }
+
+       return maxvec;
+}
+
+4.3.3 pci_disable_msix
 
 void pci_disable_msix(struct pci_dev *dev)
 
index 1d7a885761f51f07a8e46be9199ac67d5939f946..fa57139f50bf771b0aeacafaa4a5c4836a847f43 100644 (file)
@@ -8,6 +8,8 @@ listRCU.txt
        - Using RCU to Protect Read-Mostly Linked Lists
 lockdep.txt
        - RCU and lockdep checking
+lockdep-splat.txt
+       - RCU Lockdep splats explained.
 NMI-RCU.txt
        - Using RCU to Protect Dynamic NMI Handlers
 rcubarrier.txt
index 273e654d7d086531ae958e16af780d7a0d1404d1..2f0fcb2112d271b01ba74b16a4c65c82caebb009 100644 (file)
@@ -31,6 +31,14 @@ has lapsed, so this approach may be used in non-GPL software, if desired.
 (In contrast, implementation of RCU is permitted only in software licensed
 under either GPL or LGPL.  Sorry!!!)
 
+In 1987, Rashid et al. described lazy TLB-flush [RichardRashid87a].
+At first glance, this has nothing to do with RCU, but nevertheless
+this paper helped inspire the update-side batching used in the later
+RCU implementation in DYNIX/ptx.  In 1988, Barbara Liskov published
+a description of Argus that noted that use of out-of-date values can
+be tolerated in some situations.  Thus, this paper provides some early
+theoretical justification for use of stale data.
+
 In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
 were reading a given data structure permitted deferred free to operate
 in the presence of non-terminating threads.  However, this explicit
@@ -41,11 +49,11 @@ providing a fine-grained locking design, however, it would be interesting
 to see how much of the performance advantage reported in 1990 remains
 today.
 
-At about this same time, Adams [Adams91] described ``chaotic relaxation'',
-where the normal barriers between successive iterations of convergent
-numerical algorithms are relaxed, so that iteration $n$ might use
-data from iteration $n-1$ or even $n-2$.  This introduces error,
-which typically slows convergence and thus increases the number of
+At about this same time, Andrews [Andrews91textbook] described ``chaotic
+relaxation'', where the normal barriers between successive iterations
+of convergent numerical algorithms are relaxed, so that iteration $n$
+might use data from iteration $n-1$ or even $n-2$.  This introduces
+error, which typically slows convergence and thus increases the number of
 iterations required.  However, this increase is sometimes more than made
 up for by a reduction in the number of expensive barrier operations,
 which are otherwise required to synchronize the threads at the end
@@ -55,7 +63,8 @@ is thus inapplicable to most data structures in operating-system kernels.
 
 In 1992, Henry (now Alexia) Massalin completed a dissertation advising
 parallel programmers to defer processing when feasible to simplify
-synchronization.  RCU makes extremely heavy use of this advice.
+synchronization [HMassalinPhD].  RCU makes extremely heavy use of
+this advice.
 
 In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
 simplest deferred-free technique: simply waiting a fixed amount of time
@@ -90,27 +99,29 @@ mechanism, which is quite similar to RCU [Gamsa99].  These operating
 systems made pervasive use of RCU in place of "existence locks", which
 greatly simplifies locking hierarchies and helps avoid deadlocks.
 
-2001 saw the first RCU presentation involving Linux [McKenney01a]
-at OLS.  The resulting abundance of RCU patches was presented the
-following year [McKenney02a], and use of RCU in dcache was first
-described that same year [Linder02a].
+The year 2000 saw an email exchange that would likely have
+led to yet another independent invention of something like RCU
+[RustyRussell2000a,RustyRussell2000b].  Instead, 2001 saw the first
+RCU presentation involving Linux [McKenney01a] at OLS.  The resulting
+abundance of RCU patches was presented the following year [McKenney02a],
+and use of RCU in dcache was first described that same year [Linder02a].
 
 Also in 2002, Michael [Michael02b,Michael02a] presented "hazard-pointer"
 techniques that defer the destruction of data structures to simplify
 non-blocking synchronization (wait-free synchronization, lock-free
 synchronization, and obstruction-free synchronization are all examples of
-non-blocking synchronization).  In particular, this technique eliminates
-locking, reduces contention, reduces memory latency for readers, and
-parallelizes pipeline stalls and memory latency for writers.  However,
-these techniques still impose significant read-side overhead in the
-form of memory barriers.  Researchers at Sun worked along similar lines
-in the same timeframe [HerlihyLM02].  These techniques can be thought
-of as inside-out reference counts, where the count is represented by the
-number of hazard pointers referencing a given data structure rather than
-the more conventional counter field within the data structure itself.
-The key advantage of inside-out reference counts is that they can be
-stored in immortal variables, thus allowing races between access and
-deletion to be avoided.
+non-blocking synchronization).  The corresponding journal article appeared
+in 2004 [MagedMichael04a].  This technique eliminates locking, reduces
+contention, reduces memory latency for readers, and parallelizes pipeline
+stalls and memory latency for writers.  However, these techniques still
+impose significant read-side overhead in the form of memory barriers.
+Researchers at Sun worked along similar lines in the same timeframe
+[HerlihyLM02].  These techniques can be thought of as inside-out reference
+counts, where the count is represented by the number of hazard pointers
+referencing a given data structure rather than the more conventional
+counter field within the data structure itself.  The key advantage
+of inside-out reference counts is that they can be stored in immortal
+variables, thus allowing races between access and deletion to be avoided.
 
 By the same token, RCU can be thought of as a "bulk reference count",
 where some form of reference counter covers all reference by a given CPU
@@ -123,8 +134,10 @@ can be thought of in other terms as well.
 
 In 2003, the K42 group described how RCU could be used to create
 hot-pluggable implementations of operating-system functions [Appavoo03a].
-Later that year saw a paper describing an RCU implementation of System
-V IPC [Arcangeli03], and an introduction to RCU in Linux Journal
+Later that year saw a paper describing an RCU implementation
+of System V IPC [Arcangeli03] (following up on a suggestion by
+Hugh Dickins [Dickins02a] and an implementation by Mingming Cao
+[MingmingCao2002IPCRCU]), and an introduction to RCU in Linux Journal
 [McKenney03a].
 
 2004 has seen a Linux-Journal article on use of RCU in dcache
@@ -383,6 +396,21 @@ for Programming Languages and Operating Systems}"
 }
 }
 
+@phdthesis{HMassalinPhD
+,author="H. Massalin"
+,title="Synthesis: An Efficient Implementation of Fundamental Operating
+System Services"
+,school="Columbia University"
+,address="New York, NY"
+,year="1992"
+,annotation={
+       Mondo optimizing compiler.
+       Wait-free stuff.
+       Good advice: defer work to avoid synchronization.  See page 90
+               (PDF page 106), Section 5.4, fourth bullet point.
+}
+}
+
 @unpublished{Jacobson93
 ,author="Van Jacobson"
 ,title="Avoid Read-Side Locking Via Delayed Free"
@@ -671,6 +699,20 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 [Viewed October 18, 2004]"
 }
 
+@conference{Michael02b
+,author="Maged M. Michael"
+,title="High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
+,Year="2002"
+,Month="August"
+,booktitle="{Proceedings of the 14\textsuperscript{th} Annual ACM
+Symposium on Parallel
+Algorithms and Architecture}"
+,pages="73-82"
+,annotation={
+Like the title says...
+}
+}
+
 @Conference{Linder02a
 ,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
 ,Title="Scalability of the Directory Entry Cache"
@@ -727,6 +769,24 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 }
 }
 
+@conference{Michael02a
+,author="Maged M. Michael"
+,title="Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic
+Reads and Writes"
+,Year="2002"
+,Month="August"
+,booktitle="{Proceedings of the 21\textsuperscript{st} Annual ACM
+Symposium on Principles of Distributed Computing}"
+,pages="21-30"
+,annotation={
+       Each thread keeps an array of pointers to items that it is
+       currently referencing.  Sort of an inside-out garbage collection
+       mechanism, but one that requires the accessing code to explicitly
+       state its needs.  Also requires read-side memory barriers on
+       most architectures.
+}
+}
+
 @unpublished{Dickins02a
 ,author="Hugh Dickins"
 ,title="Use RCU for System-V IPC"
@@ -735,6 +795,17 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 ,note="private communication"
 }
 
+@InProceedings{HerlihyLM02
+,author={Maurice Herlihy and Victor Luchangco and Mark Moir}
+,title="The Repeat Offender Problem: A Mechanism for Supporting Dynamic-Sized,
+Lock-Free Data Structures"
+,booktitle={Proceedings of 16\textsuperscript{th} International
+Symposium on Distributed Computing}
+,year=2002
+,month="October"
+,pages="339-353"
+}
+
 @unpublished{Sarma02b
 ,Author="Dipankar Sarma"
 ,Title="Some dcache\_rcu benchmark numbers"
@@ -749,6 +820,19 @@ Andrea Arcangeli and Andi Kleen and Orran Krieger and Rusty Russell"
 }
 }
 
+@unpublished{MingmingCao2002IPCRCU
+,Author="Mingming Cao"
+,Title="[PATCH]updated ipc lock patch"
+,month="October"
+,year="2002"
+,note="Available:
+\url{https://lkml.org/lkml/2002/10/24/262}
+[Viewed February 15, 2014]"
+,annotation={
+       Mingming Cao's patch to introduce RCU to SysV IPC.
+}
+}
+
 @unpublished{LinusTorvalds2003a
 ,Author="Linus Torvalds"
 ,Title="Re: {[PATCH]} small fixes in brlock.h"
@@ -982,6 +1066,23 @@ Realtime Applications"
 }
 }
 
+@article{MagedMichael04a
+,author="Maged M. Michael"
+,title="Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects"
+,Year="2004"
+,Month="June"
+,journal="IEEE Transactions on Parallel and Distributed Systems"
+,volume="15"
+,number="6"
+,pages="491-504"
+,url="Available:
+\url{http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf}
+[Viewed March 1, 2005]"
+,annotation={
+       New canonical hazard-pointer citation.
+}
+}
+
 @phdthesis{PaulEdwardMcKenneyPhD
 ,author="Paul E. McKenney"
 ,title="Exploiting Deferred Destruction:
index 91266193b8f49e840709db77d75f8357428b2806..9d10d1db16a53ffc464c484cc7fe1b7ef2a1e864 100644 (file)
@@ -256,10 +256,10 @@ over a rather long period of time, but improvements are always welcome!
                variations on this theme.
 
        b.      Limiting update rate.  For example, if updates occur only
-               once per hour, then no explicit rate limiting is required,
-               unless your system is already badly broken.  The dcache
-               subsystem takes this approach -- updates are guarded
-               by a global lock, limiting their rate.
+               once per hour, then no explicit rate limiting is
+               required, unless your system is already badly broken.
+               Older versions of the dcache subsystem take this approach,
+               guarding updates with a global lock, limiting their rate.
 
        c.      Trusted update -- if updates can only be done manually by
                superuser or some other trusted user, then it might not
@@ -268,7 +268,8 @@ over a rather long period of time, but improvements are always welcome!
                the machine.
 
        d.      Use call_rcu_bh() rather than call_rcu(), in order to take
-               advantage of call_rcu_bh()'s faster grace periods.
+               advantage of call_rcu_bh()'s faster grace periods.  (This
+               is only a partial solution, though.)
 
        e.      Periodically invoke synchronize_rcu(), permitting a limited
                number of updates per grace period.
@@ -276,6 +277,13 @@ over a rather long period of time, but improvements are always welcome!
        The same cautions apply to call_rcu_bh(), call_rcu_sched(),
        call_srcu(), and kfree_rcu().
 
+       Note that although these primitives do take action to avoid memory
+       exhaustion when any given CPU has too many callbacks, a determined
+       user could still exhaust memory.  This is especially the case
+       if a system with a large number of CPUs has been configured to
+       offload all of its RCU callbacks onto a single CPU, or if the
+       system has relatively little free memory.
+
 9.     All RCU list-traversal primitives, which include
        rcu_dereference(), list_for_each_entry_rcu(), and
        list_for_each_safe_rcu(), must be either within an RCU read-side
index 36420e116c908bc7fd6dea9bd3b55081c0addad1..a94090cc785d06eee25e0daa8150157f2125b9a8 100644 (file)
@@ -4,6 +4,8 @@ Booting
        - requirements for booting
 Interrupts
        - ARM Interrupt subsystem documentation
+IXP4xx
+       - Intel IXP4xx Network processor.
 msm
        - MSM specific documentation
 Netwinder
@@ -24,8 +26,16 @@ SPEAr
        - ST SPEAr platform Linux Overview
 VFP/
        - Release notes for Linux Kernel Vector Floating Point support code
+cluster-pm-race-avoidance.txt
+       - Algorithm for CPU and Cluster setup/teardown
 empeg/
        - Ltd's Empeg MP3 Car Audio Player
+firmware.txt
+       - Secure firmware registration and calling.
+kernel_mode_neon.txt
+       - How to use NEON instructions in kernel mode
+kernel_user_helpers.txt
+       - Helper functions in kernel space made available for userspace.
 mem_alignment
        - alignment abort handler documentation
 memory.txt
@@ -34,3 +44,7 @@ nwfpe/
        - NWFPE floating point emulator documentation
 swp_emulation
        - SWP/SWPB emulation handler/logging description
+tcm.txt
+       - ARM Tightly Coupled Memory
+vlocks.txt
+       - Voting locks, low-level mechanism relying on memory system atomic writes.
index 5e054bfe4dde8e30e178c073d19c8c2b520a7e0f..85e24c4f215c45136eb3393763dc802b007ac408 100644 (file)
@@ -35,11 +35,13 @@ ffffffbc00000000    ffffffbdffffffff           8GB          vmemmap
 
 ffffffbe00000000       ffffffbffbbfffff          ~8GB          [guard, future vmmemap]
 
-ffffffbffbc00000       ffffffbffbdfffff           2MB          earlyprintk device
+ffffffbffa000000       ffffffbffaffffff          16MB          PCI I/O space
+
+ffffffbffb000000       ffffffbffbbfffff          12MB          [guard]
 
-ffffffbffbe00000       ffffffbffbe0ffff          64KB          PCI I/O space
+ffffffbffbc00000       ffffffbffbdfffff           2MB          earlyprintk device
 
-ffffffbffbe10000       ffffffbcffffffff          ~2MB          [guard]
+ffffffbffbe00000       ffffffbffbffffff           2MB          [guard]
 
 ffffffbffc000000       ffffffbfffffffff          64MB          modules
 
@@ -60,11 +62,13 @@ fffffdfc00000000    fffffdfdffffffff           8GB          vmemmap
 
 fffffdfe00000000       fffffdfffbbfffff          ~8GB          [guard, future vmmemap]
 
-fffffdfffbc00000       fffffdfffbdfffff           2MB          earlyprintk device
+fffffdfffa000000       fffffdfffaffffff          16MB          PCI I/O space
+
+fffffdfffb000000       fffffdfffbbfffff          12MB          [guard]
 
-fffffdfffbe00000       fffffdfffbe0ffff          64KB          PCI I/O space
+fffffdfffbc00000       fffffdfffbdfffff           2MB          earlyprintk device
 
-fffffdfffbe10000       fffffdfffbffffff          ~2MB          [guard]
+fffffdfffbe00000       fffffdfffbffffff           2MB          [guard]
 
 fffffdfffc000000       fffffdffffffffff          64MB          modules
 
index 2df0365f2dff0ec2a02fd35025f0565ae31648fa..c54fcdd4ae9f68ce6ee439722c0bfac494651406 100644 (file)
@@ -1,8 +1,10 @@
 00-INDEX
        - This file
-
+Makefile
+       - Makefile for gptimers example file.
 bfin-gpio-notes.txt
        - Notes in developing/using bfin-gpio driver.
-
 bfin-spi-notes.txt
        - Notes for using bfin spi bus driver.
+gptimers-example.c
+       - gptimers example
index 929d9904f74b7eb94bac71e81308b0bf335c3108..e840b47613f78f9f9efa6843cc90c997a36ccdce 100644 (file)
@@ -14,6 +14,8 @@ deadline-iosched.txt
        - Deadline IO scheduler tunables
 ioprio.txt
        - Block io priorities (in CFQ scheduler)
+null_blk.txt
+       - Null block for block-layer benchmarking.
 queue-sysfs.txt
        - Queue's sysfs entries
 request.txt
index e6b72d35515123ad0aff423999aeef359183bb3d..68c0f517c60edb1ab7a61e990720c7c8f097bb16 100644 (file)
@@ -124,12 +124,11 @@ the default being 204800 sectors (or 100MB).
 Updating on-disk metadata
 -------------------------
 
-On-disk metadata is committed every time a REQ_SYNC or REQ_FUA bio is
-written.  If no such requests are made then commits will occur every
-second.  This means the cache behaves like a physical disk that has a
-write cache (the same is true of the thin-provisioning target).  If
-power is lost you may lose some recent writes.  The metadata should
-always be consistent in spite of any crash.
+On-disk metadata is committed every time a FLUSH or FUA bio is written.
+If no such requests are made then commits will occur every second.  This
+means the cache behaves like a physical disk that has a volatile write
+cache.  If power is lost you may lose some recent writes.  The metadata
+should always be consistent in spite of any crash.
 
 The 'dirty' state for a cache block changes far too frequently for us
 to keep updating it on the fly.  So we treat it as a hint.  In normal
index 8a7a3d46e0daa00d6f87315648b7cb292e8c05b4..05a27e9442bd4e5c4d3e618a6a0594e55466b192 100644 (file)
@@ -116,6 +116,35 @@ Resuming a device with a new table itself triggers an event so the
 userspace daemon can use this to detect a situation where a new table
 already exceeds the threshold.
 
+A low water mark for the metadata device is maintained in the kernel and
+will trigger a dm event if free space on the metadata device drops below
+it.
+
+Updating on-disk metadata
+-------------------------
+
+On-disk metadata is committed every time a FLUSH or FUA bio is written.
+If no such requests are made then commits will occur every second.  This
+means the thin-provisioning target behaves like a physical disk that has
+a volatile write cache.  If power is lost you may lose some recent
+writes.  The metadata should always be consistent in spite of any crash.
+
+If data space is exhausted the pool will either error or queue IO
+according to the configuration (see: error_if_no_space).  If metadata
+space is exhausted or a metadata operation fails: the pool will error IO
+until the pool is taken offline and repair is performed to 1) fix any
+potential inconsistencies and 2) clear the flag that imposes repair.
+Once the pool's metadata device is repaired it may be resized, which
+will allow the pool to return to normal operation.  Note that if a pool
+is flagged as needing repair, the pool's data and metadata devices
+cannot be resized until repair is performed.  It should also be noted
+that when the pool's metadata space is exhausted the current metadata
+transaction is aborted.  Given that the pool will cache IO whose
+completion may have already been acknowledged to upper IO layers
+(e.g. filesystem) it is strongly suggested that consistency checks
+(e.g. fsck) be performed on those layers when repair of the pool is
+required.
+
 Thin provisioning
 -----------------
 
@@ -258,10 +287,9 @@ ii) Status
        should register for the event and then check the target's status.
 
     held metadata root:
-       The location, in sectors, of the metadata root that has been
+       The location, in blocks, of the metadata root that has been
        'held' for userspace read access.  '-' indicates there is no
-       held root.  This feature is not yet implemented so '-' is
-       always returned.
+       held root.
 
     discard_passdown|no_discard_passdown
        Whether or not discards are actually being passed down to the
index b78f691fd84705d0e557ae540732445bde7dbf62..8c4102c6a5e77b108522a00d40274ea6bcc03126 100644 (file)
@@ -8,3 +8,5 @@ https://lists.ozlabs.org/listinfo/devicetree-discuss
        - this file
 booting-without-of.txt
        - Booting Linux without Open Firmware, describes history and format of device trees.
+usage-model.txt
+       - How Linux uses DT and what DT aims to solve.
\ No newline at end of file
index 34dc40cffdfd8bfa316d55c2db5cc7a49fc1e999..af9b4a0d902b3f7a182864b02dbfec13fb6c2cba 100644 (file)
@@ -91,7 +91,7 @@ Boards:
   compatible = "ti,omap3-beagle", "ti,omap3"
 
 - OMAP3 Tobi with Overo : Commercial expansion board with daughter board
-  compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
+  compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3"
 
 - OMAP4 SDP : Software Development Board
   compatible = "ti,omap4-sdp", "ti,omap4430"
index 89de1564950ce64cf2bdb1e087da04e2043a0db6..48b285ffa3a650e7d0adb028e7f577617b2dff9c 100644 (file)
@@ -4,17 +4,33 @@ SATA nodes are defined to describe on-chip Serial ATA controllers.
 Each SATA controller should have its own node.
 
 Required properties:
-- compatible        : compatible list, contains "snps,spear-ahci"
+- compatible        : compatible list, one of "snps,spear-ahci",
+                      "snps,exynos5440-ahci", "ibm,476gtr-ahci",
+                      "allwinner,sun4i-a10-ahci", "fsl,imx53-ahci"
+                      "fsl,imx6q-ahci" or "snps,dwc-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
+- clocks            : a list of phandle + clock specifier pairs
+- target-supply     : regulator for SATA target power
 
-Example:
+"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties:
+- clocks            : must contain the sata, sata_ref and ahb clocks
+- clock-names       : must contain "ahb" for the ahb clock
+
+Examples:
         sata@ffe08000 {
                compatible = "snps,spear-ahci";
                reg = <0xffe08000 0x1000>;
                interrupts = <115>;
-
         };
+
+       ahci: sata@01c18000 {
+               compatible = "allwinner,sun4i-a10-ahci";
+               reg = <0x01c18000 0x1000>;
+               interrupts = <56>;
+               clocks = <&pll6 0>, <&ahb_gates 25>;
+               target-supply = <&reg_ahci_5v>;
+       };
diff --git a/Documentation/devicetree/bindings/ata/apm-xgene.txt b/Documentation/devicetree/bindings/ata/apm-xgene.txt
new file mode 100644 (file)
index 0000000..7bcfbf5
--- /dev/null
@@ -0,0 +1,76 @@
+* APM X-Gene 6.0 Gb/s SATA host controller nodes
+
+SATA host controller nodes are defined to describe on-chip Serial ATA
+controllers. Each SATA controller (pair of ports) have its own node.
+
+Required properties:
+- compatible           : Shall contain:
+  * "apm,xgene-ahci"
+- reg                  : First memory resource shall be the AHCI memory
+                         resource.
+                         Second memory resource shall be the host controller
+                         core memory resource.
+                         Third memory resource shall be the host controller
+                         diagnostic memory resource.
+                         4th memory resource shall be the host controller
+                         AXI memory resource.
+                         5th optional memory resource shall be the host
+                         controller MUX memory resource if required.
+- interrupts           : Interrupt-specifier for SATA host controller IRQ.
+- clocks               : Reference to the clock entry.
+- phys                 : A list of phandles + phy-specifiers, one for each
+                         entry in phy-names.
+- phy-names            : Should contain:
+  * "sata-phy" for the SATA 6.0Gbps PHY
+
+Optional properties:
+- status               : Shall be "ok" if enabled or "disabled" if disabled.
+                         Default is "ok".
+
+Example:
+               sataclk: sataclk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <1>;
+                       clock-frequency = <100000000>;
+                       clock-output-names = "sataclk";
+               };
+
+               phy2: phy@1f22a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f22a000 0x0 0x100>;
+                       #phy-cells = <1>;
+               };
+
+               phy3: phy@1f23a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f23a000 0x0 0x100>;
+                       #phy-cells = <1>;
+               };
+
+               sata2: sata@1a400000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a400000 0x0 0x1000>,
+                             <0x0 0x1f220000 0x0 0x1000>,
+                             <0x0 0x1f22d000 0x0 0x1000>,
+                             <0x0 0x1f22e000 0x0 0x1000>,
+                             <0x0 0x1f227000 0x0 0x1000>;
+                       interrupts = <0x0 0x87 0x4>;
+                       status = "ok";
+                       clocks = <&sataclk 0>;
+                       phys = <&phy2 0>;
+                       phy-names = "sata-phy";
+               };
+
+               sata3: sata@1a800000 {
+                       compatible = "apm,xgene-ahci-pcie";
+                       reg = <0x0 0x1a800000 0x0 0x1000>,
+                             <0x0 0x1f230000 0x0 0x1000>,
+                             <0x0 0x1f23d000 0x0 0x1000>,
+                             <0x0 0x1f23e000 0x0 0x1000>,
+                             <0x0 0x1f237000 0x0 0x1000>;
+                       interrupts = <0x0 0x88 0x4>;
+                       status = "ok";
+                       clocks = <&sataclk 0>;
+                       phys = <&phy3 0>;
+                       phy-names = "sata-phy";
+               };
index a6a352c2771e74da0064ec9ce93a87c44ce2fe07..5992dceec7af7d1e9d1ac8f329b831d48e409d87 100644 (file)
@@ -21,9 +21,9 @@ Required Properties:
     must appear in the same order as the output clocks.
   - #clock-cells: Must be 1
   - clock-output-names: The name of the clocks as free-form strings
-  - renesas,indices: Indices of the gate clocks into the group (0 to 31)
+  - renesas,clock-indices: Indices of the gate clocks into the group (0 to 31)
 
-The clocks, clock-output-names and renesas,indices properties contain one
+The clocks, clock-output-names and renesas,clock-indices properties contain one
 entry per gate clock. The MSTP groups are sparsely populated. Unimplemented
 gate clocks must not be declared.
 
index 68b83ecc385007216d391f1a0edf06527dad5fb9..ee9be9961524cdcb45a0c43890064e8483702323 100644 (file)
@@ -1,12 +1,16 @@
 * Freescale Smart Direct Memory Access (SDMA) Controller for i.MX
 
 Required properties:
-- compatible : Should be "fsl,imx31-sdma", "fsl,imx31-to1-sdma",
-  "fsl,imx31-to2-sdma", "fsl,imx35-sdma", "fsl,imx35-to1-sdma",
-  "fsl,imx35-to2-sdma", "fsl,imx51-sdma", "fsl,imx53-sdma" or
-  "fsl,imx6q-sdma". The -to variants should be preferred since they
-  allow to determnine the correct ROM script addresses needed for
-  the driver to work without additional firmware.
+- compatible : Should be one of
+      "fsl,imx25-sdma"
+      "fsl,imx31-sdma", "fsl,imx31-to1-sdma", "fsl,imx31-to2-sdma"
+      "fsl,imx35-sdma", "fsl,imx35-to1-sdma", "fsl,imx35-to2-sdma"
+      "fsl,imx51-sdma"
+      "fsl,imx53-sdma"
+      "fsl,imx6q-sdma"
+  The -to variants should be preferred since they allow to determnine the
+  correct ROM script addresses needed for the driver to work without additional
+  firmware.
 - reg : Should contain SDMA registers location and length
 - interrupts : Should contain SDMA interrupt
 - #dma-cells : Must be <3>.
diff --git a/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
new file mode 100644 (file)
index 0000000..aee38e7
--- /dev/null
@@ -0,0 +1,18 @@
+TI-NSPIRE interrupt controller
+
+Required properties:
+- compatible: Compatible property value should be "lsi,zevio-intc".
+
+- reg: Physical base address of the controller and length of memory mapped
+       region.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+
+Example:
+
+interrupt-controller {
+       compatible = "lsi,zevio-intc";
+       interrupt-controller;
+       reg = <0xDC000000 0x1000>;
+       #interrupt-cells = <1>;
+};
index 0a85c70cd30a6eed9196f20c3a7eda14db71a9ae..07ad02075a935455387f684c4b94435a68c70255 100644 (file)
@@ -13,6 +13,9 @@ Required properties:
 - #address-cells: should be one. The cell is the slot id.
 - #size-cells: should be zero.
 - at least one slot node
+- clock-names: tuple listing input clock names.
+       Required elements: "mci_clk"
+- clocks: phandles to input clocks.
 
 The node contains child nodes for each slot that the platform uses
 
@@ -24,6 +27,8 @@ mmc0: mmc@f0008000 {
        interrupts = <12 4>;
        #address-cells = <1>;
        #size-cells = <0>;
+       clock-names = "mci_clk";
+       clocks = <&mci0_clk>;
 
        [ child node definitions...]
 };
index b90bfcd138fff1ab7b92f97b2323afcac60bdca0..863d5b8155c70db91e1eb2a121467fa40284c701 100644 (file)
@@ -1,7 +1,8 @@
 * Allwinner EMAC ethernet controller
 
 Required properties:
-- compatible: should be "allwinner,sun4i-emac".
+- compatible: should be "allwinner,sun4i-a10-emac" (Deprecated:
+              "allwinner,sun4i-emac")
 - reg: address and length of the register set for the device.
 - interrupts: interrupt for the device
 - phy: A phandle to a phy node defining the PHY address (as the reg
@@ -14,7 +15,7 @@ Optional properties:
 Example:
 
 emac: ethernet@01c0b000 {
-       compatible = "allwinner,sun4i-emac";
+       compatible = "allwinner,sun4i-a10-emac";
        reg = <0x01c0b000 0x1000>;
        interrupts = <55>;
        clocks = <&ahb_gates 17>;
index 00b9f9a3ec1d8bcce665a5c31645456de7e012a3..4ec56413779d3af28b60b3b647d4134d7f3e42bb 100644 (file)
@@ -1,7 +1,8 @@
 * Allwinner A10 MDIO Ethernet Controller interface
 
 Required properties:
-- compatible: should be "allwinner,sun4i-mdio".
+- compatible: should be "allwinner,sun4i-a10-mdio"
+              (Deprecated: "allwinner,sun4i-mdio").
 - reg: address and length of the register set for the device.
 
 Optional properties:
@@ -9,7 +10,7 @@ Optional properties:
 
 Example at the SoC level:
 mdio@01c0b080 {
-       compatible = "allwinner,sun4i-mdio";
+       compatible = "allwinner,sun4i-a10-mdio";
        reg = <0x01c0b080 0x14>;
        #address-cells = <1>;
        #size-cells = <0>;
index 11ace3c3d805f872990ad82f721af2d7c8bd86b7..4fc39276361132fe7450248e0ceb5216c151bf25 100644 (file)
@@ -7,3 +7,4 @@ Required properties:
 
 Optional properties:
 - local-mac-address : Ethernet mac address to use
+- vdd-supply:  supply for Ethernet mac
diff --git a/Documentation/devicetree/bindings/net/opencores-ethoc.txt b/Documentation/devicetree/bindings/net/opencores-ethoc.txt
new file mode 100644 (file)
index 0000000..2dc127c
--- /dev/null
@@ -0,0 +1,22 @@
+* OpenCores MAC 10/100 Mbps
+
+Required properties:
+- compatible: Should be "opencores,ethoc".
+- reg: two memory regions (address and length),
+  first region is for the device registers and descriptor rings,
+  second is for the device packet memory.
+- interrupts: interrupt for the device.
+
+Optional properties:
+- clocks: phandle to refer to the clk used as per
+  Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Examples:
+
+       enet0: ethoc@fd030000 {
+               compatible = "opencores,ethoc";
+               reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
+               interrupts = <1>;
+               local-mac-address = [00 50 c2 13 6f 00];
+               clocks = <&osc>;
+        };
diff --git a/Documentation/devicetree/bindings/net/sti-dwmac.txt b/Documentation/devicetree/bindings/net/sti-dwmac.txt
new file mode 100644 (file)
index 0000000..3dd3d0b
--- /dev/null
@@ -0,0 +1,58 @@
+STMicroelectronics SoC DWMAC glue layer controller
+
+The device node has following properties.
+
+Required properties:
+ - compatible  : Can be "st,stih415-dwmac", "st,stih416-dwmac" or
+   "st,stid127-dwmac".
+ - reg         : Offset of the glue configuration register map in system
+   configuration regmap pointed by st,syscon property and size.
+
+ - reg-names   : Should be "sti-ethconf".
+
+ - st,syscon   : Should be phandle to system configuration node which
+   encompases this glue registers.
+
+ - st,tx-retime-src: On STi Parts for Giga bit speeds, 125Mhz clocks can be
+   wired up in from different sources. One via TXCLK pin and other via CLK_125
+   pin. This wiring is totally board dependent. However the retiming glue
+   logic should be configured accordingly. Possible values for this property
+
+          "txclk" - if 125Mhz clock is wired up via txclk line.
+          "clk_125" - if 125Mhz clock is wired up via clk_125 line.
+
+   This property is only valid for Giga bit setup( GMII, RGMII), and it is
+   un-used for non-giga bit (MII and RMII) setups. Also note that internal
+   clockgen can not generate stable 125Mhz clock.
+
+ - st,ext-phyclk: This boolean property indicates who is generating the clock
+  for tx and rx. This property is only valid for RMII case where the clock can
+  be generated from the MAC or PHY.
+
+ - clock-names: should be "sti-ethclk".
+ - clocks: Should point to ethernet clockgen which can generate phyclk.
+
+
+Example:
+
+ethernet0: dwmac@fe810000 {
+       device_type     = "network";
+       compatible      = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710";
+       reg             = <0xfe810000 0x8000>, <0x8bc 0x4>;
+       reg-names       = "stmmaceth", "sti-ethconf";
+       interrupts      = <0 133 0>, <0 134 0>, <0 135 0>;
+       interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+       phy-mode        = "mii";
+
+       st,syscon       = <&syscfg_rear>;
+
+       snps,pbl        = <32>;
+       snps,mixed-burst;
+
+       resets          = <&softreset STIH416_ETH0_SOFTRESET>;
+       reset-names     = "stmmaceth";
+       pinctrl-0       = <&pinctrl_mii0>;
+       pinctrl-names   = "default";
+       clocks          = <&CLK_S_GMAC0_PHY>;
+       clock-names     = "stmmaceth";
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,bcm11351-pinctrl.txt
new file mode 100644 (file)
index 0000000..c119deb
--- /dev/null
@@ -0,0 +1,461 @@
+Broadcom BCM281xx Pin Controller
+
+This is a pin controller for the Broadcom BCM281xx SoC family, which includes
+BCM11130, BCM11140, BCM11351, BCM28145, and BCM28155 SoCs.
+
+=== Pin Controller Node ===
+
+Required Properties:
+
+- compatible:  Must be "brcm,bcm11351-pinctrl"
+- reg:         Base address of the PAD Controller register block and the size
+               of the block.
+
+For example, the following is the bare minimum node:
+
+       pinctrl@35004800 {
+               compatible = "brcm,bcm11351-pinctrl";
+               reg = <0x35004800 0x430>;
+       };
+
+As a pin controller device, in addition to the required properties, this node
+should also contain the pin configuration nodes that client devices reference,
+if any.
+
+=== Pin Configuration Node ===
+
+Each pin configuration node is a sub-node of the pin controller node and is a
+container of an arbitrary number of subnodes, called pin group nodes in this
+document.
+
+Please refer to the pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the definition of a
+"pin configuration node".
+
+=== Pin Group Node ===
+
+A pin group node specifies the desired pin mux and/or pin configuration for an
+arbitrary number of pins.  The name of the pin group node is optional and not
+used.
+
+A pin group node only affects the properties specified in the node, and has no
+effect on any properties that are omitted.
+
+The pin group node accepts a subset of the generic pin config properties. For
+details generic pin config properties, please refer to pinctrl-bindings.txt
+and <include/linux/pinctrl/pinconfig-generic.h>.
+
+Each pin controlled by this pin controller belong to one of three types:
+Standard, I2C, and HDMI.  Each type accepts a different set of pin config
+properties.  A list of pins and their types is provided below.
+
+Required Properties (applicable to all pins):
+
+- pins:                Multiple strings.  Specifies the name(s) of one or more pins to
+               be configured by this node.
+
+Optional Properties (for standard pins):
+
+- function:                    String. Specifies the pin mux selection. Values
+                               must be one of: "alt1", "alt2", "alt3", "alt4"
+- input-schmitt-enable:                No arguments. Enable schmitt-trigger mode.
+- input-schmitt-disable:       No arguments. Disable schmitt-trigger mode.
+- bias-pull-up:                        No arguments. Pull up on pin.
+- bias-pull-down:              No arguments. Pull down on pin.
+- bias-disable:                        No arguments. Disable pin bias.
+- slew-rate:                   Integer. Meaning depends on configured pin mux:
+                               *_SCL or *_SDA:
+                                       0: Standard(100kbps)& Fast(400kbps) mode
+                                       1: Highspeed (3.4Mbps) mode
+                               IC_DM or IC_DP:
+                                       0: normal slew rate
+                                       1: fast slew rate
+                               Otherwise:
+                                       0: fast slew rate
+                                       1: normal slew rate
+- input-enable:                        No arguements. Enable input (does not affect
+                               output.)
+- input-disable:               No arguements. Disable input (does not affect
+                               output.)
+- drive-strength:              Integer. Drive strength in mA.  Valid values are
+                               2, 4, 6, 8, 10, 12, 14, 16 mA.
+
+Optional Properties (for I2C pins):
+
+- function:                    String. Specifies the pin mux selection. Values
+                               must be one of: "alt1", "alt2", "alt3", "alt4"
+- bias-pull-up:                        Integer. Pull up strength in Ohm. There are 3
+                               pull-up resisitors (1.2k, 1.8k, 2.7k) available
+                               in parallel for I2C pins, so the valid values
+                               are: 568, 720, 831, 1080, 1200, 1800, 2700 Ohm.
+- bias-disable:                        No arguments. Disable pin bias.
+- slew-rate:                   Integer. Meaning depends on configured pin mux:
+                               *_SCL or *_SDA:
+                                       0: Standard(100kbps)& Fast(400kbps) mode
+                                       1: Highspeed (3.4Mbps) mode
+                               IC_DM or IC_DP:
+                                       0: normal slew rate
+                                       1: fast slew rate
+                               Otherwise:
+                                       0: fast slew rate
+                                       1: normal slew rate
+- input-enable:                        No arguements. Enable input (does not affect
+                               output.)
+- input-disable:               No arguements. Disable input (does not affect
+                               output.)
+
+Optional Properties (for HDMI pins):
+
+- function:                    String. Specifies the pin mux selection. Values
+                               must be one of: "alt1", "alt2", "alt3", "alt4"
+- slew-rate:                   Integer. Controls slew rate.
+                                       0: Standard(100kbps)& Fast(400kbps) mode
+                                       1: Highspeed (3.4Mbps) mode
+- input-enable:                        No arguements. Enable input (does not affect
+                               output.)
+- input-disable:               No arguements. Disable input (does not affect
+                               output.)
+
+Example:
+// pin controller node
+pinctrl@35004800 {
+       compatible = "brcmbcm11351-pinctrl";
+       reg = <0x35004800 0x430>;
+
+       // pin configuration node
+       dev_a_default: dev_a_active {
+               //group node defining 1 standard pin
+               grp_1 {
+                       pins            = "std_pin1";
+                       function        = "alt1";
+                       input-schmitt-enable;
+                       bias-disable;
+                       slew-rate       = <1>;
+                       drive-strength  = <4>;
+               };
+
+               // group node defining 2 I2C pins
+               grp_2 {
+                       pins            = "i2c_pin1", "i2c_pin2";
+                       function        = "alt2";
+                       bias-pull-up    = <720>;
+                       input-enable;
+               };
+
+               // group node defining 2 HDMI pins
+               grp_3 {
+                       pins            = "hdmi_pin1", "hdmi_pin2";
+                       function        = "alt3";
+                       slew-rate       = <1>;
+               };
+
+               // other pin group nodes
+               ...
+       };
+
+       // other pin configuration nodes
+       ...
+};
+
+In the example above, "dev_a_active" is a pin configuration node with a number
+of sub-nodes.  In the pin group node "grp_1", one pin, "std_pin1", is defined in
+the "pins" property.  Thus, the remaining properties in the "grp_1" node applies
+only to this pin, including the following settings:
+ - setting pinmux to "alt1"
+ - enabling schmitt-trigger (hystersis) mode
+ - disabling pin bias
+ - setting the slew-rate to 1
+ - setting the drive strength to 4 mA
+Note that neither "input-enable" nor "input-disable" was specified - the pinctrl
+subsystem will therefore leave this property unchanged from whatever state it
+was in before applying these changes.
+
+The "pins" property in the pin group node "grp_2" specifies two pins -
+"i2c_pin1" and "i2c_pin2"; the remaining properties in this pin group node,
+therefore, applies to both of these pins.  The properties include:
+ - setting pinmux to "alt2"
+ - setting pull-up resistance to 720 Ohm (ie. enabling 1.2k and 1.8k resistors
+   in parallel)
+ - enabling both pins' input
+"slew-rate" is not specified in this pin group node, so the slew-rate for these
+pins are left as-is.
+
+Finally, "grp_3" defines two HDMI pins.  The following properties are applied to
+both pins:
+ - setting pinmux to "alt3"
+ - setting slew-rate to 1; for HDMI pins, this corresponds to the 3.4 Mbps
+   Highspeed mode
+The input is neither enabled or disabled, and is left untouched.
+
+=== Pin Names and Type ===
+
+The following are valid pin names and their pin types:
+
+       "adcsync",              Standard
+       "bat_rm",               Standard
+       "bsc1_scl",             I2C
+       "bsc1_sda",             I2C
+       "bsc2_scl",             I2C
+       "bsc2_sda",             I2C
+       "classgpwr",            Standard
+       "clk_cx8",              Standard
+       "clkout_0",             Standard
+       "clkout_1",             Standard
+       "clkout_2",             Standard
+       "clkout_3",             Standard
+       "clkreq_in_0",          Standard
+       "clkreq_in_1",          Standard
+       "cws_sys_req1",         Standard
+       "cws_sys_req2",         Standard
+       "cws_sys_req3",         Standard
+       "digmic1_clk",          Standard
+       "digmic1_dq",           Standard
+       "digmic2_clk",          Standard
+       "digmic2_dq",           Standard
+       "gpen13",               Standard
+       "gpen14",               Standard
+       "gpen15",               Standard
+       "gpio00",               Standard
+       "gpio01",               Standard
+       "gpio02",               Standard
+       "gpio03",               Standard
+       "gpio04",               Standard
+       "gpio05",               Standard
+       "gpio06",               Standard
+       "gpio07",               Standard
+       "gpio08",               Standard
+       "gpio09",               Standard
+       "gpio10",               Standard
+       "gpio11",               Standard
+       "gpio12",               Standard
+       "gpio13",               Standard
+       "gpio14",               Standard
+       "gps_pablank",          Standard
+       "gps_tmark",            Standard
+       "hdmi_scl",             HDMI
+       "hdmi_sda",             HDMI
+       "ic_dm",                Standard
+       "ic_dp",                Standard
+       "kp_col_ip_0",          Standard
+       "kp_col_ip_1",          Standard
+       "kp_col_ip_2",          Standard
+       "kp_col_ip_3",          Standard
+       "kp_row_op_0",          Standard
+       "kp_row_op_1",          Standard
+       "kp_row_op_2",          Standard
+       "kp_row_op_3",          Standard
+       "lcd_b_0",              Standard
+       "lcd_b_1",              Standard
+       "lcd_b_2",              Standard
+       "lcd_b_3",              Standard
+       "lcd_b_4",              Standard
+       "lcd_b_5",              Standard
+       "lcd_b_6",              Standard
+       "lcd_b_7",              Standard
+       "lcd_g_0",              Standard
+       "lcd_g_1",              Standard
+       "lcd_g_2",              Standard
+       "lcd_g_3",              Standard
+       "lcd_g_4",              Standard
+       "lcd_g_5",              Standard
+       "lcd_g_6",              Standard
+       "lcd_g_7",              Standard
+       "lcd_hsync",            Standard
+       "lcd_oe",               Standard
+       "lcd_pclk",             Standard
+       "lcd_r_0",              Standard
+       "lcd_r_1",              Standard
+       "lcd_r_2",              Standard
+       "lcd_r_3",              Standard
+       "lcd_r_4",              Standard
+       "lcd_r_5",              Standard
+       "lcd_r_6",              Standard
+       "lcd_r_7",              Standard
+       "lcd_vsync",            Standard
+       "mdmgpio0",             Standard
+       "mdmgpio1",             Standard
+       "mdmgpio2",             Standard
+       "mdmgpio3",             Standard
+       "mdmgpio4",             Standard
+       "mdmgpio5",             Standard
+       "mdmgpio6",             Standard
+       "mdmgpio7",             Standard
+       "mdmgpio8",             Standard
+       "mphi_data_0",          Standard
+       "mphi_data_1",          Standard
+       "mphi_data_2",          Standard
+       "mphi_data_3",          Standard
+       "mphi_data_4",          Standard
+       "mphi_data_5",          Standard
+       "mphi_data_6",          Standard
+       "mphi_data_7",          Standard
+       "mphi_data_8",          Standard
+       "mphi_data_9",          Standard
+       "mphi_data_10",         Standard
+       "mphi_data_11",         Standard
+       "mphi_data_12",         Standard
+       "mphi_data_13",         Standard
+       "mphi_data_14",         Standard
+       "mphi_data_15",         Standard
+       "mphi_ha0",             Standard
+       "mphi_hat0",            Standard
+       "mphi_hat1",            Standard
+       "mphi_hce0_n",          Standard
+       "mphi_hce1_n",          Standard
+       "mphi_hrd_n",           Standard
+       "mphi_hwr_n",           Standard
+       "mphi_run0",            Standard
+       "mphi_run1",            Standard
+       "mtx_scan_clk",         Standard
+       "mtx_scan_data",        Standard
+       "nand_ad_0",            Standard
+       "nand_ad_1",            Standard
+       "nand_ad_2",            Standard
+       "nand_ad_3",            Standard
+       "nand_ad_4",            Standard
+       "nand_ad_5",            Standard
+       "nand_ad_6",            Standard
+       "nand_ad_7",            Standard
+       "nand_ale",             Standard
+       "nand_cen_0",           Standard
+       "nand_cen_1",           Standard
+       "nand_cle",             Standard
+       "nand_oen",             Standard
+       "nand_rdy_0",           Standard
+       "nand_rdy_1",           Standard
+       "nand_wen",             Standard
+       "nand_wp",              Standard
+       "pc1",                  Standard
+       "pc2",                  Standard
+       "pmu_int",              Standard
+       "pmu_scl",              I2C
+       "pmu_sda",              I2C
+       "rfst2g_mtsloten3g",    Standard
+       "rgmii_0_rx_ctl",       Standard
+       "rgmii_0_rxc",          Standard
+       "rgmii_0_rxd_0",        Standard
+       "rgmii_0_rxd_1",        Standard
+       "rgmii_0_rxd_2",        Standard
+       "rgmii_0_rxd_3",        Standard
+       "rgmii_0_tx_ctl",       Standard
+       "rgmii_0_txc",          Standard
+       "rgmii_0_txd_0",        Standard
+       "rgmii_0_txd_1",        Standard
+       "rgmii_0_txd_2",        Standard
+       "rgmii_0_txd_3",        Standard
+       "rgmii_1_rx_ctl",       Standard
+       "rgmii_1_rxc",          Standard
+       "rgmii_1_rxd_0",        Standard
+       "rgmii_1_rxd_1",        Standard
+       "rgmii_1_rxd_2",        Standard
+       "rgmii_1_rxd_3",        Standard
+       "rgmii_1_tx_ctl",       Standard
+       "rgmii_1_txc",          Standard
+       "rgmii_1_txd_0",        Standard
+       "rgmii_1_txd_1",        Standard
+       "rgmii_1_txd_2",        Standard
+       "rgmii_1_txd_3",        Standard
+       "rgmii_gpio_0",         Standard
+       "rgmii_gpio_1",         Standard
+       "rgmii_gpio_2",         Standard
+       "rgmii_gpio_3",         Standard
+       "rtxdata2g_txdata3g1",  Standard
+       "rtxen2g_txdata3g2",    Standard
+       "rxdata3g0",            Standard
+       "rxdata3g1",            Standard
+       "rxdata3g2",            Standard
+       "sdio1_clk",            Standard
+       "sdio1_cmd",            Standard
+       "sdio1_data_0",         Standard
+       "sdio1_data_1",         Standard
+       "sdio1_data_2",         Standard
+       "sdio1_data_3",         Standard
+       "sdio4_clk",            Standard
+       "sdio4_cmd",            Standard
+       "sdio4_data_0",         Standard
+       "sdio4_data_1",         Standard
+       "sdio4_data_2",         Standard
+       "sdio4_data_3",         Standard
+       "sim_clk",              Standard
+       "sim_data",             Standard
+       "sim_det",              Standard
+       "sim_resetn",           Standard
+       "sim2_clk",             Standard
+       "sim2_data",            Standard
+       "sim2_det",             Standard
+       "sim2_resetn",          Standard
+       "sri_c",                Standard
+       "sri_d",                Standard
+       "sri_e",                Standard
+       "ssp_extclk",           Standard
+       "ssp0_clk",             Standard
+       "ssp0_fs",              Standard
+       "ssp0_rxd",             Standard
+       "ssp0_txd",             Standard
+       "ssp2_clk",             Standard
+       "ssp2_fs_0",            Standard
+       "ssp2_fs_1",            Standard
+       "ssp2_fs_2",            Standard
+       "ssp2_fs_3",            Standard
+       "ssp2_rxd_0",           Standard
+       "ssp2_rxd_1",           Standard
+       "ssp2_txd_0",           Standard
+       "ssp2_txd_1",           Standard
+       "ssp3_clk",             Standard
+       "ssp3_fs",              Standard
+       "ssp3_rxd",             Standard
+       "ssp3_txd",             Standard
+       "ssp4_clk",             Standard
+       "ssp4_fs",              Standard
+       "ssp4_rxd",             Standard
+       "ssp4_txd",             Standard
+       "ssp5_clk",             Standard
+       "ssp5_fs",              Standard
+       "ssp5_rxd",             Standard
+       "ssp5_txd",             Standard
+       "ssp6_clk",             Standard
+       "ssp6_fs",              Standard
+       "ssp6_rxd",             Standard
+       "ssp6_txd",             Standard
+       "stat_1",               Standard
+       "stat_2",               Standard
+       "sysclken",             Standard
+       "traceclk",             Standard
+       "tracedt00",            Standard
+       "tracedt01",            Standard
+       "tracedt02",            Standard
+       "tracedt03",            Standard
+       "tracedt04",            Standard
+       "tracedt05",            Standard
+       "tracedt06",            Standard
+       "tracedt07",            Standard
+       "tracedt08",            Standard
+       "tracedt09",            Standard
+       "tracedt10",            Standard
+       "tracedt11",            Standard
+       "tracedt12",            Standard
+       "tracedt13",            Standard
+       "tracedt14",            Standard
+       "tracedt15",            Standard
+       "txdata3g0",            Standard
+       "txpwrind",             Standard
+       "uartb1_ucts",          Standard
+       "uartb1_urts",          Standard
+       "uartb1_urxd",          Standard
+       "uartb1_utxd",          Standard
+       "uartb2_urxd",          Standard
+       "uartb2_utxd",          Standard
+       "uartb3_ucts",          Standard
+       "uartb3_urts",          Standard
+       "uartb3_urxd",          Standard
+       "uartb3_utxd",          Standard
+       "uartb4_ucts",          Standard
+       "uartb4_urts",          Standard
+       "uartb4_urxd",          Standard
+       "uartb4_utxd",          Standard
+       "vc_cam1_scl",          I2C
+       "vc_cam1_sda",          I2C
+       "vc_cam2_scl",          I2C
+       "vc_cam2_sda",          I2C
+       "vc_cam3_scl",          I2C
+       "vc_cam3_sda",          I2C
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,capri-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,capri-pinctrl.txt
deleted file mode 100644 (file)
index 9e9e9ef..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-Broadcom Capri Pin Controller
-
-This is a pin controller for the Broadcom BCM281xx SoC family, which includes
-BCM11130, BCM11140, BCM11351, BCM28145, and BCM28155 SoCs.
-
-=== Pin Controller Node ===
-
-Required Properties:
-
-- compatible:  Must be "brcm,capri-pinctrl".
-- reg:         Base address of the PAD Controller register block and the size
-               of the block.
-
-For example, the following is the bare minimum node:
-
-       pinctrl@35004800 {
-               compatible = "brcm,capri-pinctrl";
-               reg = <0x35004800 0x430>;
-       };
-
-As a pin controller device, in addition to the required properties, this node
-should also contain the pin configuration nodes that client devices reference,
-if any.
-
-=== Pin Configuration Node ===
-
-Each pin configuration node is a sub-node of the pin controller node and is a
-container of an arbitrary number of subnodes, called pin group nodes in this
-document.
-
-Please refer to the pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the definition of a
-"pin configuration node".
-
-=== Pin Group Node ===
-
-A pin group node specifies the desired pin mux and/or pin configuration for an
-arbitrary number of pins.  The name of the pin group node is optional and not
-used.
-
-A pin group node only affects the properties specified in the node, and has no
-effect on any properties that are omitted.
-
-The pin group node accepts a subset of the generic pin config properties. For
-details generic pin config properties, please refer to pinctrl-bindings.txt
-and <include/linux/pinctrl/pinconfig-generic.h>.
-
-Each pin controlled by this pin controller belong to one of three types:
-Standard, I2C, and HDMI.  Each type accepts a different set of pin config
-properties.  A list of pins and their types is provided below.
-
-Required Properties (applicable to all pins):
-
-- pins:                Multiple strings.  Specifies the name(s) of one or more pins to
-               be configured by this node.
-
-Optional Properties (for standard pins):
-
-- function:                    String. Specifies the pin mux selection. Values
-                               must be one of: "alt1", "alt2", "alt3", "alt4"
-- input-schmitt-enable:                No arguments. Enable schmitt-trigger mode.
-- input-schmitt-disable:       No arguments. Disable schmitt-trigger mode.
-- bias-pull-up:                        No arguments. Pull up on pin.
-- bias-pull-down:              No arguments. Pull down on pin.
-- bias-disable:                        No arguments. Disable pin bias.
-- slew-rate:                   Integer. Meaning depends on configured pin mux:
-                               *_SCL or *_SDA:
-                                       0: Standard(100kbps)& Fast(400kbps) mode
-                                       1: Highspeed (3.4Mbps) mode
-                               IC_DM or IC_DP:
-                                       0: normal slew rate
-                                       1: fast slew rate
-                               Otherwise:
-                                       0: fast slew rate
-                                       1: normal slew rate
-- input-enable:                        No arguements. Enable input (does not affect
-                               output.)
-- input-disable:               No arguements. Disable input (does not affect
-                               output.)
-- drive-strength:              Integer. Drive strength in mA.  Valid values are
-                               2, 4, 6, 8, 10, 12, 14, 16 mA.
-
-Optional Properties (for I2C pins):
-
-- function:                    String. Specifies the pin mux selection. Values
-                               must be one of: "alt1", "alt2", "alt3", "alt4"
-- bias-pull-up:                        Integer. Pull up strength in Ohm. There are 3
-                               pull-up resisitors (1.2k, 1.8k, 2.7k) available
-                               in parallel for I2C pins, so the valid values
-                               are: 568, 720, 831, 1080, 1200, 1800, 2700 Ohm.
-- bias-disable:                        No arguments. Disable pin bias.
-- slew-rate:                   Integer. Meaning depends on configured pin mux:
-                               *_SCL or *_SDA:
-                                       0: Standard(100kbps)& Fast(400kbps) mode
-                                       1: Highspeed (3.4Mbps) mode
-                               IC_DM or IC_DP:
-                                       0: normal slew rate
-                                       1: fast slew rate
-                               Otherwise:
-                                       0: fast slew rate
-                                       1: normal slew rate
-- input-enable:                        No arguements. Enable input (does not affect
-                               output.)
-- input-disable:               No arguements. Disable input (does not affect
-                               output.)
-
-Optional Properties (for HDMI pins):
-
-- function:                    String. Specifies the pin mux selection. Values
-                               must be one of: "alt1", "alt2", "alt3", "alt4"
-- slew-rate:                   Integer. Controls slew rate.
-                                       0: Standard(100kbps)& Fast(400kbps) mode
-                                       1: Highspeed (3.4Mbps) mode
-- input-enable:                        No arguements. Enable input (does not affect
-                               output.)
-- input-disable:               No arguements. Disable input (does not affect
-                               output.)
-
-Example:
-// pin controller node
-pinctrl@35004800 {
-       compatible = "brcm,capri-pinctrl";
-       reg = <0x35004800 0x430>;
-
-       // pin configuration node
-       dev_a_default: dev_a_active {
-               //group node defining 1 standard pin
-               grp_1 {
-                       pins            = "std_pin1";
-                       function        = "alt1";
-                       input-schmitt-enable;
-                       bias-disable;
-                       slew-rate       = <1>;
-                       drive-strength  = <4>;
-               };
-
-               // group node defining 2 I2C pins
-               grp_2 {
-                       pins            = "i2c_pin1", "i2c_pin2";
-                       function        = "alt2";
-                       bias-pull-up    = <720>;
-                       input-enable;
-               };
-
-               // group node defining 2 HDMI pins
-               grp_3 {
-                       pins            = "hdmi_pin1", "hdmi_pin2";
-                       function        = "alt3";
-                       slew-rate       = <1>;
-               };
-
-               // other pin group nodes
-               ...
-       };
-
-       // other pin configuration nodes
-       ...
-};
-
-In the example above, "dev_a_active" is a pin configuration node with a number
-of sub-nodes.  In the pin group node "grp_1", one pin, "std_pin1", is defined in
-the "pins" property.  Thus, the remaining properties in the "grp_1" node applies
-only to this pin, including the following settings:
- - setting pinmux to "alt1"
- - enabling schmitt-trigger (hystersis) mode
- - disabling pin bias
- - setting the slew-rate to 1
- - setting the drive strength to 4 mA
-Note that neither "input-enable" nor "input-disable" was specified - the pinctrl
-subsystem will therefore leave this property unchanged from whatever state it
-was in before applying these changes.
-
-The "pins" property in the pin group node "grp_2" specifies two pins -
-"i2c_pin1" and "i2c_pin2"; the remaining properties in this pin group node,
-therefore, applies to both of these pins.  The properties include:
- - setting pinmux to "alt2"
- - setting pull-up resistance to 720 Ohm (ie. enabling 1.2k and 1.8k resistors
-   in parallel)
- - enabling both pins' input
-"slew-rate" is not specified in this pin group node, so the slew-rate for these
-pins are left as-is.
-
-Finally, "grp_3" defines two HDMI pins.  The following properties are applied to
-both pins:
- - setting pinmux to "alt3"
- - setting slew-rate to 1; for HDMI pins, this corresponds to the 3.4 Mbps
-   Highspeed mode
-The input is neither enabled or disabled, and is left untouched.
-
-=== Pin Names and Type ===
-
-The following are valid pin names and their pin types:
-
-       "adcsync",              Standard
-       "bat_rm",               Standard
-       "bsc1_scl",             I2C
-       "bsc1_sda",             I2C
-       "bsc2_scl",             I2C
-       "bsc2_sda",             I2C
-       "classgpwr",            Standard
-       "clk_cx8",              Standard
-       "clkout_0",             Standard
-       "clkout_1",             Standard
-       "clkout_2",             Standard
-       "clkout_3",             Standard
-       "clkreq_in_0",          Standard
-       "clkreq_in_1",          Standard
-       "cws_sys_req1",         Standard
-       "cws_sys_req2",         Standard
-       "cws_sys_req3",         Standard
-       "digmic1_clk",          Standard
-       "digmic1_dq",           Standard
-       "digmic2_clk",          Standard
-       "digmic2_dq",           Standard
-       "gpen13",               Standard
-       "gpen14",               Standard
-       "gpen15",               Standard
-       "gpio00",               Standard
-       "gpio01",               Standard
-       "gpio02",               Standard
-       "gpio03",               Standard
-       "gpio04",               Standard
-       "gpio05",               Standard
-       "gpio06",               Standard
-       "gpio07",               Standard
-       "gpio08",               Standard
-       "gpio09",               Standard
-       "gpio10",               Standard
-       "gpio11",               Standard
-       "gpio12",               Standard
-       "gpio13",               Standard
-       "gpio14",               Standard
-       "gps_pablank",          Standard
-       "gps_tmark",            Standard
-       "hdmi_scl",             HDMI
-       "hdmi_sda",             HDMI
-       "ic_dm",                Standard
-       "ic_dp",                Standard
-       "kp_col_ip_0",          Standard
-       "kp_col_ip_1",          Standard
-       "kp_col_ip_2",          Standard
-       "kp_col_ip_3",          Standard
-       "kp_row_op_0",          Standard
-       "kp_row_op_1",          Standard
-       "kp_row_op_2",          Standard
-       "kp_row_op_3",          Standard
-       "lcd_b_0",              Standard
-       "lcd_b_1",              Standard
-       "lcd_b_2",              Standard
-       "lcd_b_3",              Standard
-       "lcd_b_4",              Standard
-       "lcd_b_5",              Standard
-       "lcd_b_6",              Standard
-       "lcd_b_7",              Standard
-       "lcd_g_0",              Standard
-       "lcd_g_1",              Standard
-       "lcd_g_2",              Standard
-       "lcd_g_3",              Standard
-       "lcd_g_4",              Standard
-       "lcd_g_5",              Standard
-       "lcd_g_6",              Standard
-       "lcd_g_7",              Standard
-       "lcd_hsync",            Standard
-       "lcd_oe",               Standard
-       "lcd_pclk",             Standard
-       "lcd_r_0",              Standard
-       "lcd_r_1",              Standard
-       "lcd_r_2",              Standard
-       "lcd_r_3",              Standard
-       "lcd_r_4",              Standard
-       "lcd_r_5",              Standard
-       "lcd_r_6",              Standard
-       "lcd_r_7",              Standard
-       "lcd_vsync",            Standard
-       "mdmgpio0",             Standard
-       "mdmgpio1",             Standard
-       "mdmgpio2",             Standard
-       "mdmgpio3",             Standard
-       "mdmgpio4",             Standard
-       "mdmgpio5",             Standard
-       "mdmgpio6",             Standard
-       "mdmgpio7",             Standard
-       "mdmgpio8",             Standard
-       "mphi_data_0",          Standard
-       "mphi_data_1",          Standard
-       "mphi_data_2",          Standard
-       "mphi_data_3",          Standard
-       "mphi_data_4",          Standard
-       "mphi_data_5",          Standard
-       "mphi_data_6",          Standard
-       "mphi_data_7",          Standard
-       "mphi_data_8",          Standard
-       "mphi_data_9",          Standard
-       "mphi_data_10",         Standard
-       "mphi_data_11",         Standard
-       "mphi_data_12",         Standard
-       "mphi_data_13",         Standard
-       "mphi_data_14",         Standard
-       "mphi_data_15",         Standard
-       "mphi_ha0",             Standard
-       "mphi_hat0",            Standard
-       "mphi_hat1",            Standard
-       "mphi_hce0_n",          Standard
-       "mphi_hce1_n",          Standard
-       "mphi_hrd_n",           Standard
-       "mphi_hwr_n",           Standard
-       "mphi_run0",            Standard
-       "mphi_run1",            Standard
-       "mtx_scan_clk",         Standard
-       "mtx_scan_data",        Standard
-       "nand_ad_0",            Standard
-       "nand_ad_1",            Standard
-       "nand_ad_2",            Standard
-       "nand_ad_3",            Standard
-       "nand_ad_4",            Standard
-       "nand_ad_5",            Standard
-       "nand_ad_6",            Standard
-       "nand_ad_7",            Standard
-       "nand_ale",             Standard
-       "nand_cen_0",           Standard
-       "nand_cen_1",           Standard
-       "nand_cle",             Standard
-       "nand_oen",             Standard
-       "nand_rdy_0",           Standard
-       "nand_rdy_1",           Standard
-       "nand_wen",             Standard
-       "nand_wp",              Standard
-       "pc1",                  Standard
-       "pc2",                  Standard
-       "pmu_int",              Standard
-       "pmu_scl",              I2C
-       "pmu_sda",              I2C
-       "rfst2g_mtsloten3g",    Standard
-       "rgmii_0_rx_ctl",       Standard
-       "rgmii_0_rxc",          Standard
-       "rgmii_0_rxd_0",        Standard
-       "rgmii_0_rxd_1",        Standard
-       "rgmii_0_rxd_2",        Standard
-       "rgmii_0_rxd_3",        Standard
-       "rgmii_0_tx_ctl",       Standard
-       "rgmii_0_txc",          Standard
-       "rgmii_0_txd_0",        Standard
-       "rgmii_0_txd_1",        Standard
-       "rgmii_0_txd_2",        Standard
-       "rgmii_0_txd_3",        Standard
-       "rgmii_1_rx_ctl",       Standard
-       "rgmii_1_rxc",          Standard
-       "rgmii_1_rxd_0",        Standard
-       "rgmii_1_rxd_1",        Standard
-       "rgmii_1_rxd_2",        Standard
-       "rgmii_1_rxd_3",        Standard
-       "rgmii_1_tx_ctl",       Standard
-       "rgmii_1_txc",          Standard
-       "rgmii_1_txd_0",        Standard
-       "rgmii_1_txd_1",        Standard
-       "rgmii_1_txd_2",        Standard
-       "rgmii_1_txd_3",        Standard
-       "rgmii_gpio_0",         Standard
-       "rgmii_gpio_1",         Standard
-       "rgmii_gpio_2",         Standard
-       "rgmii_gpio_3",         Standard
-       "rtxdata2g_txdata3g1",  Standard
-       "rtxen2g_txdata3g2",    Standard
-       "rxdata3g0",            Standard
-       "rxdata3g1",            Standard
-       "rxdata3g2",            Standard
-       "sdio1_clk",            Standard
-       "sdio1_cmd",            Standard
-       "sdio1_data_0",         Standard
-       "sdio1_data_1",         Standard
-       "sdio1_data_2",         Standard
-       "sdio1_data_3",         Standard
-       "sdio4_clk",            Standard
-       "sdio4_cmd",            Standard
-       "sdio4_data_0",         Standard
-       "sdio4_data_1",         Standard
-       "sdio4_data_2",         Standard
-       "sdio4_data_3",         Standard
-       "sim_clk",              Standard
-       "sim_data",             Standard
-       "sim_det",              Standard
-       "sim_resetn",           Standard
-       "sim2_clk",             Standard
-       "sim2_data",            Standard
-       "sim2_det",             Standard
-       "sim2_resetn",          Standard
-       "sri_c",                Standard
-       "sri_d",                Standard
-       "sri_e",                Standard
-       "ssp_extclk",           Standard
-       "ssp0_clk",             Standard
-       "ssp0_fs",              Standard
-       "ssp0_rxd",             Standard
-       "ssp0_txd",             Standard
-       "ssp2_clk",             Standard
-       "ssp2_fs_0",            Standard
-       "ssp2_fs_1",            Standard
-       "ssp2_fs_2",            Standard
-       "ssp2_fs_3",            Standard
-       "ssp2_rxd_0",           Standard
-       "ssp2_rxd_1",           Standard
-       "ssp2_txd_0",           Standard
-       "ssp2_txd_1",           Standard
-       "ssp3_clk",             Standard
-       "ssp3_fs",              Standard
-       "ssp3_rxd",             Standard
-       "ssp3_txd",             Standard
-       "ssp4_clk",             Standard
-       "ssp4_fs",              Standard
-       "ssp4_rxd",             Standard
-       "ssp4_txd",             Standard
-       "ssp5_clk",             Standard
-       "ssp5_fs",              Standard
-       "ssp5_rxd",             Standard
-       "ssp5_txd",             Standard
-       "ssp6_clk",             Standard
-       "ssp6_fs",              Standard
-       "ssp6_rxd",             Standard
-       "ssp6_txd",             Standard
-       "stat_1",               Standard
-       "stat_2",               Standard
-       "sysclken",             Standard
-       "traceclk",             Standard
-       "tracedt00",            Standard
-       "tracedt01",            Standard
-       "tracedt02",            Standard
-       "tracedt03",            Standard
-       "tracedt04",            Standard
-       "tracedt05",            Standard
-       "tracedt06",            Standard
-       "tracedt07",            Standard
-       "tracedt08",            Standard
-       "tracedt09",            Standard
-       "tracedt10",            Standard
-       "tracedt11",            Standard
-       "tracedt12",            Standard
-       "tracedt13",            Standard
-       "tracedt14",            Standard
-       "tracedt15",            Standard
-       "txdata3g0",            Standard
-       "txpwrind",             Standard
-       "uartb1_ucts",          Standard
-       "uartb1_urts",          Standard
-       "uartb1_urxd",          Standard
-       "uartb1_utxd",          Standard
-       "uartb2_urxd",          Standard
-       "uartb2_utxd",          Standard
-       "uartb3_ucts",          Standard
-       "uartb3_urts",          Standard
-       "uartb3_urxd",          Standard
-       "uartb3_utxd",          Standard
-       "uartb4_ucts",          Standard
-       "uartb4_urts",          Standard
-       "uartb4_urxd",          Standard
-       "uartb4_utxd",          Standard
-       "vc_cam1_scl",          I2C
-       "vc_cam1_sda",          I2C
-       "vc_cam2_scl",          I2C
-       "vc_cam2_sda",          I2C
-       "vc_cam3_scl",          I2C
-       "vc_cam3_sda",          I2C
diff --git a/Documentation/devicetree/bindings/power/bq2415x.txt b/Documentation/devicetree/bindings/power/bq2415x.txt
new file mode 100644 (file)
index 0000000..d0327f0
--- /dev/null
@@ -0,0 +1,47 @@
+Binding for TI bq2415x Li-Ion Charger
+
+Required properties:
+- compatible: Should contain one of the following:
+ * "ti,bq24150"
+ * "ti,bq24150"
+ * "ti,bq24150a"
+ * "ti,bq24151"
+ * "ti,bq24151a"
+ * "ti,bq24152"
+ * "ti,bq24153"
+ * "ti,bq24153a"
+ * "ti,bq24155"
+ * "ti,bq24156"
+ * "ti,bq24156a"
+ * "ti,bq24158"
+- reg:                    integer, i2c address of the device.
+- ti,current-limit:       integer, initial maximum current charger can pull
+                          from power supply in mA.
+- ti,weak-battery-voltage: integer, weak battery voltage threshold in mV.
+                          The chip will use slow precharge if battery voltage
+                          is below this value.
+- ti,battery-regulation-voltage: integer, maximum charging voltage in mV.
+- ti,charge-current:      integer, maximum charging current in mA.
+- ti,termination-current:  integer, charge will be terminated when current in
+                          constant-voltage phase drops below this value (in mA).
+- ti,resistor-sense:      integer, value of sensing resistor in milliohm.
+
+Optional properties:
+- ti,usb-charger-detection: phandle to usb charger detection device.
+                           (required for auto mode)
+
+Example from Nokia N900:
+
+bq24150a {
+       compatible = "ti,bq24150a";
+       reg = <0x6b>;
+
+       ti,current-limit = <100>;
+       ti,weak-battery-voltage = <3400>;
+       ti,battery-regulation-voltage = <4200>;
+       ti,charge-current = <650>;
+       ti,termination-current = <100>;
+       ti,resistor-sense = <68>;
+
+       ti,usb-charger-detection = <&isp1704>;
+};
index 07e04cdc0c9e0c3619347791f40d1177e6707fe2..4f8184d069cb5a472058a59578101d7b70896367 100644 (file)
@@ -5,6 +5,9 @@ Required properties:
 - reg: Address and length of the register set for the device
 - interrupts: Should contain spi interrupt
 - cs-gpios: chipselects
+- clock-names: tuple listing input clock names.
+       Required elements: "spi_clk"
+- clocks: phandles to input clocks.
 
 Example:
 
@@ -14,6 +17,8 @@ spi1: spi@fffcc000 {
        interrupts = <13 4 5>;
        #address-cells = <1>;
        #size-cells = <0>;
+       clocks = <&spi1_clk>;
+       clock-names = "spi_clk";
        cs-gpios = <&pioB 3 0>;
        status = "okay";
 
index 3f900cd51bf00eb546a765145f671dde71fc3d00..40ce2df0e0e95add31ca573c65fc48227e2c1739 100644 (file)
@@ -8,6 +8,7 @@ ad      Avionic Design GmbH
 adi    Analog Devices, Inc.
 aeroflexgaisler        Aeroflex Gaisler AB
 ak     Asahi Kasei Corp.
+allwinner      Allwinner Technology Co., Ltd.
 altr   Altera Corp.
 amcc   Applied Micro Circuits Corporation (APM, formally AMCC)
 amstaos        AMS-Taos Inc.
@@ -40,6 +41,7 @@ gmt   Global Mixed-mode Technology, Inc.
 gumstix        Gumstix, Inc.
 haoyu  Haoyu Microelectronic Co. Ltd.
 hisilicon      Hisilicon Limited.
+honeywell      Honeywell
 hp     Hewlett Packard
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
@@ -55,6 +57,7 @@ maxim Maxim Integrated Products
 microchip      Microchip Technology Inc.
 mosaixtech     Mosaix Technologies, Inc.
 national       National Semiconductor
+neonode                Neonode Inc.
 nintendo       Nintendo
 nvidia NVIDIA
 nxp    NXP Semiconductors
@@ -64,7 +67,7 @@ phytec        PHYTEC Messtechnik GmbH
 picochip       Picochip Ltd
 powervr        PowerVR (deprecated, use img)
 qca    Qualcomm Atheros, Inc.
-qcom   Qualcomm, Inc.
+qcom   Qualcomm Technologies, Inc
 ralink Mediatek/Ralink Technology Corp.
 ramtron        Ramtron International
 realtek Realtek Semiconductor Corp.
@@ -78,6 +81,7 @@ silabs        Silicon Laboratories
 simtek
 sirf   SiRF Technology, Inc.
 snps   Synopsys, Inc.
+spansion       Spansion Inc.
 st     STMicroelectronics
 ste    ST-Ericsson
 stericsson     ST-Ericsson
index 47c30098dab65ed1574805fffc7c17fd6f1429af..731a009723c7cd88a2b4102cce597628758d8bbe 100644 (file)
@@ -78,7 +78,7 @@ Peter Beutner <p.beutner@gmx.net>
 Wilson Michaels <wilsonmichaels@earthlink.net>
   for the lgdt330x frontend driver, and various bugfixes
 
-Michael Krufky <mkrufky@m1k.net>
+Michael Krufky <mkrufky@linuxtv.org>
   for maintaining v4l/dvb inter-tree dependencies
 
 Taylor Jacob <rtjacob@earthlink.net>
index 30a70542e8235d5939056e311dd933597ef49e2a..fe85e7c5907a540305b3de5d6c227db5ad0dbdcf 100644 (file)
@@ -5,6 +5,8 @@ please mail me.
 
 00-INDEX
        - this file.
+api.txt
+       - The frame buffer API between applications and buffer devices.
 arkfb.txt
        - info on the fbdev driver for ARK Logic chips.
 aty128fb.txt
@@ -51,12 +53,16 @@ sh7760fb.txt
        - info on the SH7760/SH7763 integrated LCDC Framebuffer driver.
 sisfb.txt
        - info on the framebuffer device driver for various SiS chips.
+sm501.txt
+       - info on the framebuffer device driver for sm501 videoframebuffer.
 sstfb.txt
        - info on the frame buffer driver for 3dfx' Voodoo Graphics boards.
 tgafb.txt
        - info on the TGA (DECChip 21030) frame buffer driver.
 tridentfb.txt
        info on the framebuffer driver for some Trident chip based cards.
+udlfb.txt
+       - Driver for DisplayLink USB 2.0 chips.
 uvesafb.txt
        - info on the userspace VESA (VBE2+ compliant) frame buffer device.
 vesafb.txt
index 632211cbdd569292b4f8c2e47676a0d0b66049a9..ac28149aede4c15704aaee0b1941aebe30f25eb7 100644 (file)
@@ -2,6 +2,8 @@
        - this file (info on some of the filesystems supported by linux).
 Locking
        - info on locking rules as they pertain to Linux VFS.
+Makefile
+       - Makefile for building the filsystems-part of DocBook.
 9p.txt
        - 9p (v9fs) is an implementation of the Plan 9 remote fs protocol.
 adfs.txt
index 66eb6c8c5334518ddbc10115c7b34b4dfb1b3c0e..53f3b596ac0dd93d1d623e35577f1dfb30205394 100644 (file)
@@ -12,6 +12,8 @@ nfs41-server.txt
        - info on the Linux server implementation of NFSv4 minor version 1.
 nfs-rdma.txt
        - how to install and setup the Linux NFS/RDMA client and server software
+nfsd-admin-interfaces.txt
+       - Administrative interfaces for nfsd.
 nfsroot.txt
        - short guide on setting up a diskless box with NFS root filesystem.
 pnfs.txt
@@ -20,5 +22,5 @@ rpc-cache.txt
        - introduction to the caching mechanisms in the sunrpc layer.
 idmapper.txt
        - information for configuring request-keys to be used by idmapper
-knfsd-rpcgss.txt
+rpc-server-gss.txt
        - Information on GSS authentication support in the NFS Server
index c70e7a7638d1e6e66cbddd3cf7800325560cad28..0d85ac1935b73a98251a434054105c6d28eb7334 100644 (file)
@@ -8,8 +8,8 @@ reason, the kernel code must instantiate I2C devices explicitly. There are
 several ways to achieve this, depending on the context and requirements.
 
 
-Method 1: Declare the I2C devices by bus number
------------------------------------------------
+Method 1a: Declare the I2C devices by bus number
+------------------------------------------------
 
 This method is appropriate when the I2C bus is a system bus as is the case
 for many embedded systems. On such systems, each I2C bus has a number
@@ -51,6 +51,43 @@ The devices will be automatically unbound and destroyed when the I2C bus
 they sit on goes away (if ever.)
 
 
+Method 1b: Declare the I2C devices via devicetree
+-------------------------------------------------
+
+This method has the same implications as method 1a. The declaration of I2C
+devices is here done via devicetree as subnodes of the master controller.
+
+Example:
+
+       i2c1: i2c@400a0000 {
+               /* ... master properties skipped ... */
+               clock-frequency = <100000>;
+
+               flash@50 {
+                       compatible = "atmel,24c256";
+                       reg = <0x50>;
+               };
+
+               pca9532: gpio@60 {
+                       compatible = "nxp,pca9532";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       reg = <0x60>;
+               };
+       };
+
+Here, two devices are attached to the bus using a speed of 100kHz. For
+additional properties which might be needed to set up the device, please refer
+to its devicetree documentation in Documentation/devicetree/bindings/.
+
+
+Method 1c: Declare the I2C devices via ACPI
+-------------------------------------------
+
+ACPI can also describe I2C devices. There is special documentation for this
+which is currently located at Documentation/acpi/enumeration.txt.
+
+
 Method 2: Instantiate the devices explicitly
 --------------------------------------------
 
index d6b778842b754c31dbf14460bf6b8ed09ad34c53..22f98ca79539d57ce309d6d33400dffc19b2b9cf 100644 (file)
@@ -10,3 +10,5 @@ ide-tape.txt
        - info on the IDE ATAPI streaming tape driver
 ide.txt
        - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS).
+warm-plug-howto.txt
+       - using sysfs to remove and add IDE devices.
\ No newline at end of file
index 8f441dab03963624c0f32eb8f030c2b3c9a38f9d..67755ea834a7857afb424bd2353131f23aa85c9a 100644 (file)
@@ -1011,6 +1011,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        parameter will force ia64_sal_cache_flush to call
                        ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
 
+       forcepae [X86-32]
+                       Forcefully enable Physical Address Extension (PAE).
+                       Many Pentium M systems disable PAE but may have a
+                       functionally usable PAE implementation.
+                       Warning: use of this parameter will taint the kernel
+                       and may cause unknown problems.
+
        ftrace=[tracer]
                        [FTRACE] will set and start the specified tracer
                        as early as possible in order to facilitate early
@@ -1726,16 +1733,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        option description.
 
        memmap=nn[KMG]@ss[KMG]
-                       [KNL] Force usage of a specific region of memory
-                       Region of memory to be used, from ss to ss+nn.
+                       [KNL] Force usage of a specific region of memory.
+                       Region of memory to be used is from ss to ss+nn.
 
        memmap=nn[KMG]#ss[KMG]
                        [KNL,ACPI] Mark specific memory as ACPI data.
-                       Region of memory to be used, from ss to ss+nn.
+                       Region of memory to be marked is from ss to ss+nn.
 
        memmap=nn[KMG]$ss[KMG]
                        [KNL,ACPI] Mark specific memory as reserved.
-                       Region of memory to be used, from ss to ss+nn.
+                       Region of memory to be reserved is from ss to ss+nn.
                        Example: Exclude memory from 0x18690000-0x1869ffff
                                 memmap=64K$0x18690000
                                 or
@@ -2053,8 +2060,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        IOAPICs that may be present in the system.
 
        nokaslr         [X86]
-                       Disable kernel base offset ASLR (Address Space
-                       Layout Randomization) if built into the kernel.
+                       Disable kernel and module base offset ASLR (Address
+                       Space Layout Randomization) if built into the kernel.
 
        noautogroup     Disable scheduler automatic task group creation.
 
index 827104fb9364cf60df2359e45c3336f61d4568c5..f3cd299fcc41203f9fe73ad16cd70aa77a421ef3 100644 (file)
@@ -162,7 +162,18 @@ Purpose: Execute workqueue requests
 To reduce its OS jitter, do any of the following:
 1.     Run your workload at a real-time priority, which will allow
        preempting the kworker daemons.
-2.     Do any of the following needed to avoid jitter that your
+2.     A given workqueue can be made visible in the sysfs filesystem
+       by passing the WQ_SYSFS to that workqueue's alloc_workqueue().
+       Such a workqueue can be confined to a given subset of the
+       CPUs using the /sys/devices/virtual/workqueue/*/cpumask sysfs
+       files.  The set of WQ_SYSFS workqueues can be displayed using
+       "ls sys/devices/virtual/workqueue".  That said, the workqueues
+       maintainer would like to caution people against indiscriminately
+       sprinkling WQ_SYSFS across all the workqueues.  The reason for
+       caution is that it is easy to add WQ_SYSFS, but because sysfs is
+       part of the formal user/kernel API, it can be nearly impossible
+       to remove it, even if its addition was a mistake.
+3.     Do any of the following needed to avoid jitter that your
        application cannot tolerate:
        a.      Build your kernel with CONFIG_SLUB=y rather than
                CONFIG_SLAB=y, thus avoiding the slab allocator's periodic
index fa688538e757e9e1f17f8a3f0374764821e94653..d13b9a9a9e002920ff6835cb56191ac61ccb3a32 100644 (file)
@@ -1,13 +1,15 @@
 00-INDEX
        - This file
-acer-wmi.txt
-       - information on the Acer Laptop WMI Extras driver.
+Makefile
+       - Makefile for building dslm example program.
 asus-laptop.txt
        - information on the Asus Laptop Extras driver.
 disk-shock-protection.txt
        - information on hard disk shock protection.
 dslm.c
        - Simple Disk Sleep Monitor program
+hpfall.c
+       - (HP) laptop accelerometer program for disk protection.
 laptop-mode.txt
        - how to conserve battery power using laptop-mode.
 sony-laptop.txt
index 1ecd1596633e58c1d89398c681b18ec645dc2c97..b4ef1f34e25faafe544971f619019d748538e4de 100644 (file)
@@ -1,3 +1,7 @@
+00-INDEX
+       - This file
+leds-blinkm.txt
+       - Driver for BlinkM LED-devices.
 leds-class.txt
        - documents LED handling under Linux.
 leds-lp3944.txt
@@ -12,3 +16,7 @@ leds-lp55xx.txt
        - description about lp55xx common driver.
 leds-lm3556.txt
        - notes on how to use the leds-lm3556 driver.
+ledtrig-oneshot.txt
+       - One-shot LED trigger for both sporadic and dense events.
+ledtrig-transient.txt
+       - LED Transient Trigger, one shot timer activation.
index a014e9f0076511da0a86ae3f7140a8c420327553..2be8c6b00e74642203a8f4bb085f19adbde5f3b0 100644 (file)
@@ -1,5 +1,7 @@
 00-INDEX
        - this file
+README.buddha
+       - Amiga Buddha and Catweasel IDE Driver
 kernel-options.txt
        - command line options for Linux/m68k
 
index 102dc19c411980d0aa17beeb12f0bcdd38447e29..11c1d2049662cc7cff72193e87707a46ad77eca0 100644 (file)
@@ -608,26 +608,30 @@ as follows:
        b = p;  /* BUG: Compiler can reorder!!! */
        do_something();
 
-The solution is again ACCESS_ONCE(), which preserves the ordering between
-the load from variable 'a' and the store to variable 'b':
+The solution is again ACCESS_ONCE() and barrier(), which preserves the
+ordering between the load from variable 'a' and the store to variable 'b':
 
        q = ACCESS_ONCE(a);
        if (q) {
+               barrier();
                ACCESS_ONCE(b) = p;
                do_something();
        } else {
+               barrier();
                ACCESS_ONCE(b) = p;
                do_something_else();
        }
 
-You could also use barrier() to prevent the compiler from moving
-the stores to variable 'b', but barrier() would not prevent the
-compiler from proving to itself that a==1 always, so ACCESS_ONCE()
-is also needed.
+The initial ACCESS_ONCE() is required to prevent the compiler from
+proving the value of 'a', and the pair of barrier() invocations are
+required to prevent the compiler from pulling the two identical stores
+to 'b' out from the legs of the "if" statement.
 
 It is important to note that control dependencies absolutely require a
 a conditional.  For example, the following "optimized" version of
-the above example breaks ordering:
+the above example breaks ordering, which is why the barrier() invocations
+are absolutely required if you have identical stores in both legs of
+the "if" statement:
 
        q = ACCESS_ONCE(a);
        ACCESS_ONCE(b) = p;  /* BUG: No ordering vs. load from a!!! */
@@ -643,9 +647,11 @@ It is of course legal for the prior load to be part of the conditional,
 for example, as follows:
 
        if (ACCESS_ONCE(a) > 0) {
+               barrier();
                ACCESS_ONCE(b) = q / 2;
                do_something();
        } else {
+               barrier();
                ACCESS_ONCE(b) = q / 3;
                do_something_else();
        }
@@ -659,9 +665,11 @@ the needed conditional.  For example:
 
        q = ACCESS_ONCE(a);
        if (q % MAX) {
+               barrier();
                ACCESS_ONCE(b) = p;
                do_something();
        } else {
+               barrier();
                ACCESS_ONCE(b) = p;
                do_something_else();
        }
@@ -723,8 +731,13 @@ In summary:
       use smb_rmb(), smp_wmb(), or, in the case of prior stores and
       later loads, smp_mb().
 
+  (*) If both legs of the "if" statement begin with identical stores
+      to the same variable, a barrier() statement is required at the
+      beginning of each leg of the "if" statement.
+
   (*) Control dependencies require at least one run-time conditional
-      between the prior load and the subsequent store.  If the compiler
+      between the prior load and the subsequent store, and this
+      conditional must involve the prior load.  If the compiler
       is able to optimize the conditional away, it will have also
       optimized away the ordering.  Careful use of ACCESS_ONCE() can
       help to preserve the needed conditional.
@@ -1249,6 +1262,23 @@ The ACCESS_ONCE() function can prevent any number of optimizations that,
 while perfectly safe in single-threaded code, can be fatal in concurrent
 code.  Here are some examples of these sorts of optimizations:
 
+ (*) The compiler is within its rights to reorder loads and stores
+     to the same variable, and in some cases, the CPU is within its
+     rights to reorder loads to the same variable.  This means that
+     the following code:
+
+       a[0] = x;
+       a[1] = x;
+
+     Might result in an older value of x stored in a[1] than in a[0].
+     Prevent both the compiler and the CPU from doing this as follows:
+
+       a[0] = ACCESS_ONCE(x);
+       a[1] = ACCESS_ONCE(x);
+
+     In short, ACCESS_ONCE() provides cache coherence for accesses from
+     multiple CPUs to a single variable.
+
  (*) The compiler is within its rights to merge successive loads from
      the same variable.  Such merging can cause the compiler to "optimize"
      the following code:
@@ -1644,12 +1674,12 @@ for each construct.  These operations all imply certain barriers:
      Memory operations issued after the ACQUIRE will be completed after the
      ACQUIRE operation has completed.
 
-     Memory operations issued before the ACQUIRE may be completed after the
-     ACQUIRE operation has completed.  An smp_mb__before_spinlock(), combined
-     with a following ACQUIRE, orders prior loads against subsequent stores and
-     stores and prior stores against subsequent stores.  Note that this is
-     weaker than smp_mb()!  The smp_mb__before_spinlock() primitive is free on
-     many architectures.
+     Memory operations issued before the ACQUIRE may be completed after
+     the ACQUIRE operation has completed.  An smp_mb__before_spinlock(),
+     combined with a following ACQUIRE, orders prior loads against
+     subsequent loads and stores and also orders prior stores against
+     subsequent stores.  Note that this is weaker than smp_mb()!  The
+     smp_mb__before_spinlock() primitive is free on many architectures.
 
  (2) RELEASE operation implication:
 
@@ -1694,24 +1724,21 @@ may occur as:
 
        ACQUIRE M, STORE *B, STORE *A, RELEASE M
 
-This same reordering can of course occur if the lock's ACQUIRE and RELEASE are
-to the same lock variable, but only from the perspective of another CPU not
-holding that lock.
-
-In short, a RELEASE followed by an ACQUIRE may -not- be assumed to be a full
-memory barrier because it is possible for a preceding RELEASE to pass a
-later ACQUIRE from the viewpoint of the CPU, but not from the viewpoint
-of the compiler.  Note that deadlocks cannot be introduced by this
-interchange because if such a deadlock threatened, the RELEASE would
-simply complete.
-
-If it is necessary for a RELEASE-ACQUIRE pair to produce a full barrier, the
-ACQUIRE can be followed by an smp_mb__after_unlock_lock() invocation.  This
-will produce a full barrier if either (a) the RELEASE and the ACQUIRE are
-executed by the same CPU or task, or (b) the RELEASE and ACQUIRE act on the
-same variable.  The smp_mb__after_unlock_lock() primitive is free on many
-architectures.  Without smp_mb__after_unlock_lock(), the critical sections
-corresponding to the RELEASE and the ACQUIRE can cross:
+When the ACQUIRE and RELEASE are a lock acquisition and release,
+respectively, this same reordering can occur if the lock's ACQUIRE and
+RELEASE are to the same lock variable, but only from the perspective of
+another CPU not holding that lock.  In short, a ACQUIRE followed by an
+RELEASE may -not- be assumed to be a full memory barrier.
+
+Similarly, the reverse case of a RELEASE followed by an ACQUIRE does not
+imply a full memory barrier.  If it is necessary for a RELEASE-ACQUIRE
+pair to produce a full barrier, the ACQUIRE can be followed by an
+smp_mb__after_unlock_lock() invocation.  This will produce a full barrier
+if either (a) the RELEASE and the ACQUIRE are executed by the same
+CPU or task, or (b) the RELEASE and ACQUIRE act on the same variable.
+The smp_mb__after_unlock_lock() primitive is free on many architectures.
+Without smp_mb__after_unlock_lock(), the CPU's execution of the critical
+sections corresponding to the RELEASE and the ACQUIRE can cross, so that:
 
        *A = a;
        RELEASE M
@@ -1722,7 +1749,36 @@ could occur as:
 
        ACQUIRE N, STORE *B, STORE *A, RELEASE M
 
-With smp_mb__after_unlock_lock(), they cannot, so that:
+It might appear that this reordering could introduce a deadlock.
+However, this cannot happen because if such a deadlock threatened,
+the RELEASE would simply complete, thereby avoiding the deadlock.
+
+       Why does this work?
+
+       One key point is that we are only talking about the CPU doing
+       the reordering, not the compiler.  If the compiler (or, for
+       that matter, the developer) switched the operations, deadlock
+       -could- occur.
+
+       But suppose the CPU reordered the operations.  In this case,
+       the unlock precedes the lock in the assembly code.  The CPU
+       simply elected to try executing the later lock operation first.
+       If there is a deadlock, this lock operation will simply spin (or
+       try to sleep, but more on that later).  The CPU will eventually
+       execute the unlock operation (which preceded the lock operation
+       in the assembly code), which will unravel the potential deadlock,
+       allowing the lock operation to succeed.
+
+       But what if the lock is a sleeplock?  In that case, the code will
+       try to enter the scheduler, where it will eventually encounter
+       a memory barrier, which will force the earlier unlock operation
+       to complete, again unraveling the deadlock.  There might be
+       a sleep-unlock race, but the locking primitive needs to resolve
+       such races properly in any case.
+
+With smp_mb__after_unlock_lock(), the two critical sections cannot overlap.
+For example, with the following code, the store to *A will always be
+seen by other CPUs before the store to *B:
 
        *A = a;
        RELEASE M
@@ -1730,13 +1786,18 @@ With smp_mb__after_unlock_lock(), they cannot, so that:
        smp_mb__after_unlock_lock();
        *B = b;
 
-will always occur as either of the following:
+The operations will always occur in one of the following orders:
 
-       STORE *A, RELEASE, ACQUIRE, STORE *B
-       STORE *A, ACQUIRE, RELEASE, STORE *B
+       STORE *A, RELEASE, ACQUIRE, smp_mb__after_unlock_lock(), STORE *B
+       STORE *A, ACQUIRE, RELEASE, smp_mb__after_unlock_lock(), STORE *B
+       ACQUIRE, STORE *A, RELEASE, smp_mb__after_unlock_lock(), STORE *B
 
 If the RELEASE and ACQUIRE were instead both operating on the same lock
-variable, only the first of these two alternatives can occur.
+variable, only the first of these alternatives can occur.  In addition,
+the more strongly ordered systems may rule out some of the above orders.
+But in any case, as noted earlier, the smp_mb__after_unlock_lock()
+ensures that the store to *A will always be seen as happening before
+the store to *B.
 
 Locks and semaphores may not provide any guarantee of ordering on UP compiled
 systems, and so cannot be counted on in such a situation to actually achieve
@@ -2757,7 +2818,7 @@ in that order, but, without intervention, the sequence may have almost any
 combination of elements combined or discarded, provided the program's view of
 the world remains consistent.  Note that ACCESS_ONCE() is -not- optional
 in the above example, as there are architectures where a given CPU might
-interchange successive loads to the same location.  On such architectures,
+reorder successive loads to the same location.  On such architectures,
 ACCESS_ONCE() does whatever is necessary to prevent this, for example, on
 Itanium the volatile casts used by ACCESS_ONCE() cause GCC to emit the
 special ld.acq and st.rel instructions that prevent such reordering.
index f11580f8719a0cf6d939cbd0fd067c54bc9636db..557b6ef70c265da48afbb3df27b03ca4fef6ea3d 100644 (file)
@@ -6,8 +6,14 @@
        - information on the 3Com Etherlink III Series Ethernet cards.
 6pack.txt
        - info on the 6pack protocol, an alternative to KISS for AX.25
-DLINK.txt
-       - info on the D-Link DE-600/DE-620 parallel port pocket adapters
+LICENSE.qla3xxx
+       - GPLv2 for QLogic Linux Networking HBA Driver
+LICENSE.qlge
+       - GPLv2 for QLogic Linux qlge NIC Driver
+LICENSE.qlcnic
+       - GPLv2 for QLogic Linux qlcnic NIC Driver
+Makefile
+       - Makefile for docsrc.
 PLIP.txt
        - PLIP: The Parallel Line Internet Protocol device driver
 README.ipw2100
@@ -17,7 +23,7 @@ README.ipw2200
 README.sb1000
        - info on General Instrument/NextLevel SURFboard1000 cable modem.
 alias.txt
-       - info on using alias network devices 
+       - info on using alias network devices.
 arcnet-hardware.txt
        - tons of info on ARCnet, hubs, jumper settings for ARCnet cards, etc.
 arcnet.txt
@@ -80,7 +86,7 @@ framerelay.txt
        - info on using Frame Relay/Data Link Connection Identifier (DLCI).
 gen_stats.txt
        - Generic networking statistics for netlink users.
-generic_hdlc.txt
+generic-hdlc.txt
        - The generic High Level Data Link Control (HDLC) layer.
 generic_netlink.txt
        - info on Generic Netlink
@@ -88,6 +94,8 @@ gianfar.txt
        - Gianfar Ethernet Driver.
 i40e.txt
        - README for the Intel Ethernet Controller XL710 Driver (i40e).
+i40evf.txt
+       - Short note on the Driver for the Intel(R) XL710 X710 Virtual Function
 ieee802154.txt
        - Linux IEEE 802.15.4 implementation, API and drivers
 igb.txt
@@ -102,6 +110,8 @@ ipddp.txt
        - AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
 iphase.txt
        - Interphase PCI ATM (i)Chip IA Linux driver info.
+ipsec.txt
+       - Note on not compressing IPSec payload and resulting failed policy check.
 ipv6.txt
        - Options to the ipv6 kernel module.
 ipvs-sysctl.txt
@@ -120,6 +130,8 @@ lapb-module.txt
        - programming information of the LAPB module.
 ltpc.txt
        - the Apple or Farallon LocalTalk PC card driver
+mac80211-auth-assoc-deauth.txt
+       - authentication and association / deauth-disassoc with max80211
 mac80211-injection.txt
        - HOWTO use packet injection with mac80211
 multiqueue.txt
@@ -134,6 +146,10 @@ netdevices.txt
        - info on network device driver functions exported to the kernel.
 netif-msg.txt
        - Design of the network interface message level setting (NETIF_MSG_*).
+netlink_mmap.txt
+       - memory mapped I/O with netlink
+nf_conntrack-sysctl.txt
+       - list of netfilter-sysctl knobs.
 nfc.txt
        - The Linux Near Field Communication (NFS) subsystem.
 openvswitch.txt
@@ -176,7 +192,7 @@ skfp.txt
        - SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
 smc9.txt
        - the driver for SMC's 9000 series of Ethernet cards
-spider-net.txt
+spider_net.txt
        - README for the Spidernet Driver (as found in PS3 / Cell BE).
 stmmac.txt
        - README for the STMicro Synopsys Ethernet driver.
@@ -188,6 +204,8 @@ tcp.txt
        - short blurb on how TCP output takes place.
 tcp-thin.txt
        - kernel tuning options for low rate 'thin' TCP streams.
+team.txt
+       - pointer to information for ethernet teaming devices.
 tlan.txt
        - ThunderLAN (Compaq Netelligent 10/100, Olicom OC-2xxx) driver info.
 tproxy.txt
@@ -200,6 +218,8 @@ vortex.txt
        - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
 vxge.txt
        - README for the Neterion X3100 PCIe Server Adapter.
+vxlan.txt
+       - Virtual extensible LAN overview
 x25.txt
        - general info on X.25 development.
 x25-iface.txt
diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt
deleted file mode 100644 (file)
index 72f38b1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-The 3Com Etherlink Plus (3c505) driver.
-
-This driver now uses DMA.  There is currently no support for PIO operation.
-The default DMA channel is 6; this is _not_ autoprobed, so you must
-make sure you configure it correctly.  If loading the driver as a
-module, you can do this with "modprobe 3c505 dma=n".  If the driver is
-linked statically into the kernel, you must either use an "ether="
-statement on the command line, or change the definition of ELP_DMA in 3c505.h.
-
-The driver will warn you if it has to fall back on the compiled in
-default DMA channel. 
-
-If no base address is given at boot time, the driver will autoprobe
-ports 0x300, 0x280 and 0x310 (in that order).  If no IRQ is given, the driver
-will try to probe for it.
-
-The driver can be used as a loadable module.
-
-Theoretically, one instance of the driver can now run multiple cards,
-in the standard way (when loading a module, say "modprobe 3c505
-io=0x300,0x340 irq=10,11 dma=6,7" or whatever).  I have not tested
-this, though.
-
-The driver may now support revision 2 hardware; the dependency on
-being able to read the host control register has been removed.  This
-is also untested, since I don't have a suitable card.
-
-Known problems:
- I still see "DMA upload timed out" messages from time to time.  These
-seem to be fairly non-fatal though.
- The card is old and slow.
-
-To do:
- Improve probe/setup code
- Test multicast and promiscuous operation
-
-Authors:
- The driver is mainly written by Craig Southeren, email
- <craigs@ineluki.apana.org.au>.
- Parts of the driver (adapting the driver to 1.1.4+ kernels,
- IRQ/address detection, some changes) and this README by
- Juha Laiho <jlaiho@ichaos.nullnet.fi>.
- DMA mode, more fixes, etc, by Philip Blundell <pjb27@cam.ac.uk>
- Multicard support, Software configurable DMA, etc., by
- Christopher Collins <ccollins@pcug.org.au>
index f3089d4235153b6fa03aaf5c8d09c81043bba996..0cbe6ec22d6ff1d6a3c739f05ae61f4dc24781ec 100644 (file)
@@ -554,12 +554,6 @@ solution for a couple of reasons:
   not specified in the struct can_frame and therefore it is only valid in
   CANFD_MTU sized CAN FD frames.
 
-  As long as the payload length is <=8 the received CAN frames from CAN FD
-  capable CAN devices can be received and read by legacy sockets too. When
-  user-generated CAN FD frames have a payload length <=8 these can be send
-  by legacy CAN network interfaces too. Sending CAN FD frames with payload
-  length > 8 to a legacy CAN network interface returns an -EMSGSIZE error.
-
   Implementation hint for new CAN applications:
 
   To build a CAN FD aware application use struct canfd_frame as basic CAN
index b26122973525f81e691f2ef05e7069647d6b7e19..c6af4bac5aa8f914a83305831e10f285c1699fb2 100644 (file)
@@ -226,9 +226,9 @@ Ring setup:
        void *rx_ring, *tx_ring;
 
        /* Configure ring parameters */
-       if (setsockopt(fd, NETLINK_RX_RING, &req, sizeof(req)) < 0)
+       if (setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req)) < 0)
                exit(1);
-       if (setsockopt(fd, NETLINK_TX_RING, &req, sizeof(req)) < 0)
+       if (setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req)) < 0)
                exit(1)
 
        /* Calculate size of each individual ring */
index 1404674c0a0282af7d077cf55a5da076875bd2ed..6fea79efb4cbfd31cc1d0155aef320b94b89da9e 100644 (file)
@@ -453,7 +453,7 @@ TP_STATUS_COPY        : This flag indicates that the frame (and associated
                         enabled previously with setsockopt() and 
                         the PACKET_COPY_THRESH option. 
 
-                        The number of frames than can be buffered to 
+                        The number of frames that can be buffered to
                         be read with recvfrom is limited like a normal socket.
                         See the SO_RCVBUF option in the socket (7) man page.
 
index 661d3c316a17721d787a8a601f3e9c8356e957be..048c92b487f6a50b552cf12d47abe4212ba66f36 100644 (file)
@@ -21,26 +21,38 @@ has such a feature).
 
 SO_TIMESTAMPING:
 
-Instructs the socket layer which kind of information is wanted. The
-parameter is an integer with some of the following bits set. Setting
-other bits is an error and doesn't change the current state.
-
-SOF_TIMESTAMPING_TX_HARDWARE:  try to obtain send time stamp in hardware
-SOF_TIMESTAMPING_TX_SOFTWARE:  if SOF_TIMESTAMPING_TX_HARDWARE is off or
-                               fails, then do it in software
-SOF_TIMESTAMPING_RX_HARDWARE:  return the original, unmodified time stamp
-                               as generated by the hardware
-SOF_TIMESTAMPING_RX_SOFTWARE:  if SOF_TIMESTAMPING_RX_HARDWARE is off or
-                               fails, then do it in software
-SOF_TIMESTAMPING_RAW_HARDWARE: return original raw hardware time stamp
-SOF_TIMESTAMPING_SYS_HARDWARE: return hardware time stamp transformed to
-                               the system time base
-SOF_TIMESTAMPING_SOFTWARE:     return system time stamp generated in
-                               software
-
-SOF_TIMESTAMPING_TX/RX determine how time stamps are generated.
-SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the
-following control message:
+Instructs the socket layer which kind of information should be collected
+and/or reported.  The parameter is an integer with some of the following
+bits set. Setting other bits is an error and doesn't change the current
+state.
+
+Four of the bits are requests to the stack to try to generate
+timestamps.  Any combination of them is valid.
+
+SOF_TIMESTAMPING_TX_HARDWARE:  try to obtain send time stamps in hardware
+SOF_TIMESTAMPING_TX_SOFTWARE:  try to obtain send time stamps in software
+SOF_TIMESTAMPING_RX_HARDWARE:  try to obtain receive time stamps in hardware
+SOF_TIMESTAMPING_RX_SOFTWARE:  try to obtain receive time stamps in software
+
+The other three bits control which timestamps will be reported in a
+generated control message.  If none of these bits are set or if none of
+the set bits correspond to data that is available, then the control
+message will not be generated:
+
+SOF_TIMESTAMPING_SOFTWARE:     report systime if available
+SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available
+SOF_TIMESTAMPING_RAW_HARDWARE: report hwtimeraw if available
+
+It is worth noting that timestamps may be collected for reasons other
+than being requested by a particular socket with
+SOF_TIMESTAMPING_[TR]X_(HARD|SOFT)WARE.  For example, most drivers that
+can generate hardware receive timestamps ignore
+SOF_TIMESTAMPING_RX_HARDWARE.  It is still a good idea to set that flag
+in case future drivers pay attention.
+
+If timestamps are reported, they will appear in a control message with
+cmsg_level==SOL_SOCKET, cmsg_type==SO_TIMESTAMPING, and a payload like
+this:
 
 struct scm_timestamping {
        struct timespec systime;
index 0103e4b15b0eadb099b091618d19b5d247dcc906..ebff6ee52441edbca95a0ebc8b20cd49ac218d3d 100644 (file)
@@ -75,14 +75,26 @@ Before the controller can make use of the PHY, it has to get a reference to
 it. This framework provides the following APIs to get a reference to the PHY.
 
 struct phy *phy_get(struct device *dev, const char *string);
+struct phy *phy_optional_get(struct device *dev, const char *string);
 struct phy *devm_phy_get(struct device *dev, const char *string);
-
-phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot,
-the string arguments should contain the phy name as given in the dt data and
-in the case of non-dt boot, it should contain the label of the PHY.
-The only difference between the two APIs is that devm_phy_get associates the
-device with the PHY using devres on successful PHY get. On driver detach,
-release function is invoked on the the devres data and devres data is freed.
+struct phy *devm_phy_optional_get(struct device *dev, const char *string);
+
+phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can
+be used to get the PHY. In the case of dt boot, the string arguments
+should contain the phy name as given in the dt data and in the case of
+non-dt boot, it should contain the label of the PHY.  The two
+devm_phy_get associates the device with the PHY using devres on
+successful PHY get. On driver detach, release function is invoked on
+the the devres data and devres data is freed. phy_optional_get and
+devm_phy_optional_get should be used when the phy is optional. These
+two functions will never return -ENODEV, but instead returns NULL when
+the phy cannot be found.
+
+It should be noted that NULL is a valid phy reference. All phy
+consumer calls on the NULL phy become NOPs. That is the release calls,
+the phy_init() and phy_exit() calls, and phy_power_on() and
+phy_power_off() calls are all NOP when applied to a NULL phy. The NULL
+phy is useful in devices for handling optional phy devices.
 
 5. Releasing a reference to the PHY
 
index a4d682f54231d01eafdbb23ebab39d571a409c52..ad04cc8097ed97ffbf1ae6189e92a20ef7ca9de9 100644 (file)
@@ -4,6 +4,8 @@ apm-acpi.txt
        - basic info about the APM and ACPI support.
 basic-pm-debugging.txt
        - Debugging suspend and resume
+charger-manager.txt
+       - Battery charger management.
 devices.txt
        - How drivers interact with system-wide power management
 drivers-testing.txt
@@ -22,6 +24,8 @@ pm_qos_interface.txt
        - info on Linux PM Quality of Service interface
 power_supply_class.txt
        - Tells userspace about battery, UPS, AC or DC power supply properties
+runtime_pm.txt
+       - Power management framework for I/O devices.
 s2ram.txt
        - How to get suspend to ram working (and debug it when it isn't)
 states.txt
@@ -38,7 +42,5 @@ tricks.txt
        - How to trick software suspend (to disk) into working when it isn't
 userland-swsusp.txt
        - Experimental implementation of software suspend in userspace
-video_extension.txt
-       - ACPI video extensions
 video.txt
        - Video issues during resume from suspend
index a74d0a84d329a2909186256d9ad5fdb5f5327a2e..4aba0436da65c309c167028cfa70d7058cbf7fd0 100644 (file)
@@ -117,6 +117,7 @@ static void usage(char *progname)
                " -f val     adjust the ptp clock frequency by 'val' ppb\n"
                " -g         get the ptp clock time\n"
                " -h         prints this message\n"
+               " -i val     index for event/trigger\n"
                " -k val     measure the time offset between system and phc clock\n"
                "            for 'val' times (Maximum 25)\n"
                " -p val     enable output with a period of 'val' nanoseconds\n"
@@ -154,6 +155,7 @@ int main(int argc, char *argv[])
        int capabilities = 0;
        int extts = 0;
        int gettime = 0;
+       int index = 0;
        int oneshot = 0;
        int pct_offset = 0;
        int n_samples = 0;
@@ -167,7 +169,7 @@ int main(int argc, char *argv[])
 
        progname = strrchr(argv[0], '/');
        progname = progname ? 1+progname : argv[0];
-       while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghk:p:P:sSt:v"))) {
+       while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:p:P:sSt:v"))) {
                switch (c) {
                case 'a':
                        oneshot = atoi(optarg);
@@ -190,6 +192,9 @@ int main(int argc, char *argv[])
                case 'g':
                        gettime = 1;
                        break;
+               case 'i':
+                       index = atoi(optarg);
+                       break;
                case 'k':
                        pct_offset = 1;
                        n_samples = atoi(optarg);
@@ -301,7 +306,7 @@ int main(int argc, char *argv[])
 
        if (extts) {
                memset(&extts_request, 0, sizeof(extts_request));
-               extts_request.index = 0;
+               extts_request.index = index;
                extts_request.flags = PTP_ENABLE_FEATURE;
                if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
                        perror("PTP_EXTTS_REQUEST");
@@ -375,7 +380,7 @@ int main(int argc, char *argv[])
                        return -1;
                }
                memset(&perout_request, 0, sizeof(perout_request));
-               perout_request.index = 0;
+               perout_request.index = index;
                perout_request.start.sec = ts.tv_sec + 2;
                perout_request.start.nsec = 0;
                perout_request.period.sec = 0;
index 3a2b96302eccc5dfb07ab4d755ba3d209efe0bc2..10c874ebdfe5293a0da287ac2037a46904f23bc4 100644 (file)
@@ -16,11 +16,13 @@ Debugging390.txt
        - hints for debugging on s390 systems.
 driver-model.txt
        - information on s390 devices and the driver model.
+kvm.txt
+       - ioctl calls to /dev/kvm on s390.
 monreader.txt
        - information on accessing the z/VM monitor stream from Linux.
+qeth.txt
+       - HiperSockets Bridge Port Support.
 s390dbf.txt
        - information on using the s390 debug feature.
-TAPE
-       - information on the driver for channel-attached tapes.
-zfcpdump
+zfcpdump.txt
        - information on the s390 SCSI dump tool.
index 46702e4f89c937d3d5a900b2da0f8af57163bc7f..eccf7ad2e7f96b8976dd9e7a06e726f5c5d4b4a1 100644 (file)
@@ -2,6 +2,8 @@
        - this file.
 sched-arch.txt
        - CPU Scheduler implementation hints for architecture specific code.
+sched-bwc.txt
+       - CFS bandwidth control overview.
 sched-design-CFS.txt
        - goals, design and implementation of the Completely Fair Scheduler.
 sched-domains.txt
index 2044be565d93b934a232d133d5e63cc4c430270a..c4b978a72f78d4e8adda44ba88e3fad0455884f5 100644 (file)
@@ -36,6 +36,8 @@ NinjaSCSI.txt
        - info on WorkBiT NinjaSCSI-32/32Bi driver
 aacraid.txt
        - Driver supporting Adaptec RAID controllers
+advansys.txt
+       - List of Advansys Host Adapters
 aha152x.txt
        - info on driver for Adaptec AHA152x based adapters
 aic79xx.txt
@@ -44,6 +46,12 @@ aic7xxx.txt
        - info on driver for Adaptec controllers
 arcmsr_spec.txt
        - ARECA FIRMWARE SPEC (for IOP331 adapter)
+bfa.txt
+       - Brocade FC/FCOE adapter driver.
+bnx2fc.txt
+       - FCoE hardware offload for Broadcom network interfaces.
+cxgb3i.txt
+       - Chelsio iSCSI Linux Driver
 dc395x.txt
        - README file for the dc395x SCSI driver
 dpti.txt
@@ -52,18 +60,24 @@ dtc3x80.txt
        - info on driver for DTC 2x80 based adapters
 g_NCR5380.txt
        - info on driver for NCR5380 and NCR53c400 based adapters
+hpsa.txt
+       - HP Smart Array Controller SCSI driver.
 hptiop.txt
        - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
 in2000.txt
        - info on in2000 driver
 libsas.txt
        - Serial Attached SCSI management layer.
+link_power_management_policy.txt
+       - Link power management options.
 lpfc.txt
        - LPFC driver release notes
 megaraid.txt
        - Common Management Module, shared code handling ioctls for LSI drivers
 ncr53c8xx.txt
        - info on driver for NCR53c8xx based adapters
+osd.txt
+       Object-Based Storage Device, command set introduction.
 osst.txt
        - info on driver for OnStream SC-x0 SCSI tape
 ppa.txt
@@ -74,6 +88,8 @@ scsi-changer.txt
        - README for the SCSI media changer driver
 scsi-generic.txt
        - info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
+scsi-parameters.txt
+       - List of SCSI-parameters to pass to the kernel at module load-time.
 scsi.txt
        - short blurb on using SCSI support as a module.
 scsi_mid_low_api.txt
index 1f1b22fbd73935d8677fa959ecb8e8d1b7b2dd3c..f9c6b5ed03e7f0809b7ebe2558474ce394c523e5 100644 (file)
@@ -4,10 +4,12 @@ README.cycladesZ
        - info on Cyclades-Z firmware loading.
 digiepca.txt
        - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
-hayes-esp.txt
-       - info on using the Hayes ESP serial driver.
+driver
+       - intro to the low level serial driver.
 moxa-smartio
        - file with info on installing/using Moxa multiport serial driver.
+n_gsm.txt
+       - GSM 0710 tty multiplexer howto.
 riscom8.txt
        - notes on using the RISCom/8 multi-port serial driver.
 rocket.txt
diff --git a/Documentation/spi/00-INDEX b/Documentation/spi/00-INDEX
new file mode 100644 (file)
index 0000000..a128fa8
--- /dev/null
@@ -0,0 +1,22 @@
+00-INDEX
+       - this file.
+Makefile
+       - Makefile for the example sourcefiles.
+butterfly
+       - AVR Butterfly SPI driver overview and pin configuration.
+ep93xx_spi
+       - Basic EP93xx SPI driver configuration.
+pxa2xx
+       - PXA2xx SPI master controller build by spi_message fifo wq
+spidev
+       - Intro to the userspace API for spi devices
+spidev_fdx.c
+       - spidev example file
+spi-lm70llp
+       - Connecting an LM70-LLP sensor to the kernel via the SPI subsys.
+spi-sc18is602
+       - NXP SC18IS602/603 I2C-bus to SPI bridge
+spi-summary
+       - (Linux) SPI overview. If unsure about SPI or SPI in Linux, start here.
+spidev_test.c
+       - SPI testing utility.
index f72e0d1e0da852ac3e89e97f8bd0c22055d66608..7982bcc4d151adfa6f0782182a84a482b8d976a0 100644 (file)
@@ -543,7 +543,22 @@ SPI MASTER METHODS
        queuing transfers that arrive in the meantime. When the driver is
        finished with this message, it must call
        spi_finalize_current_message() so the subsystem can issue the next
-       transfer. This may sleep.
+       message. This may sleep.
+
+    master->transfer_one(struct spi_master *master, struct spi_device *spi,
+                        struct spi_transfer *transfer)
+       The subsystem calls the driver to transfer a single transfer while
+       queuing transfers that arrive in the meantime. When the driver is
+       finished with this transfer, it must call
+       spi_finalize_current_transfer() so the subsystem can issue the next
+       transfer. This may sleep. Note: transfer_one and transfer_one_message
+       are mutually exclusive; when both are set, the generic subsystem does
+       not call your transfer_one callback.
+
+       Return values:
+       negative errno: error
+       0: transfer is finished
+       1: transfer is still in progress
 
     DEPRECATED METHODS
 
index e55124e7c40cd0eef8afb92c34913cd68c42faac..ec8be46bf48da2146cbf2689a6aa51a315e1f2f4 100644 (file)
@@ -320,10 +320,11 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 ==============================================================
 
-hung_task_warning:
+hung_task_warnings:
 
 The maximum number of warnings to report. During a check interval
-When this value is reached, no more the warnings will be reported.
+if a hung task is detected, this value is decreased by 1.
+When this value reaches 0, no more warnings will be reported.
 This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 -1: report an infinite number of warnings.
@@ -441,8 +442,7 @@ feature should be disabled. Otherwise, if the system overhead from the
 feature is too high then the rate the kernel samples for NUMA hinting
 faults may be controlled by the numa_balancing_scan_period_min_ms,
 numa_balancing_scan_delay_ms, numa_balancing_scan_period_max_ms,
-numa_balancing_scan_size_mb, numa_balancing_settle_count sysctls and
-numa_balancing_migrate_deferred.
+numa_balancing_scan_size_mb, and numa_balancing_settle_count sysctls.
 
 ==============================================================
 
@@ -483,13 +483,6 @@ rate for each task.
 numa_balancing_scan_size_mb is how many megabytes worth of pages are
 scanned for a given scan.
 
-numa_balancing_migrate_deferred is how many page migrations get skipped
-unconditionally, after a page migration is skipped because a page is shared
-with other tasks. This reduces page migration overhead, and determines
-how much stronger the "move task near its memory" policy scheduler becomes,
-versus the "move memory near its task" memory management policy, for workloads
-with shared memory.
-
 ==============================================================
 
 osrelease, ostype & version:
index ef2ccbf77fa2d4e8b8152d844d3a24de8fb54045..6d042dc1cce0db6d2862200e456f6d7b3324af4e 100644 (file)
@@ -8,6 +8,8 @@ hpet_example.c
        - sample hpet timer test program
 hrtimers.txt
        - subsystem for high-resolution kernel timers
+Makefile
+       - Build and link hpet_example
 NO_HZ.txt
        - Summary of the different methods for the scheduler clock-interrupts management.
 timers-howto.txt
index 641ec922017993ec1aaa75f19b08dcb76c2f49cf..fee9f2bf9c64a825c068046c5b7100d62c5757e9 100644 (file)
@@ -20,5 +20,7 @@ ppc-pv.txt
        - the paravirtualization interface on PowerPC.
 review-checklist.txt
        - review checklist for KVM patches.
+s390-diag.txt
+       - Diagnose hypercall description (for IBM S/390)
 timekeeping.txt
        - timekeeping virtualization for x86-based architectures.
index a39d06680e1c1a738437dfafdb36f1fda29b2f66..081c49777abb81e54bc6bfee8b2ae553b3954b3e 100644 (file)
@@ -16,8 +16,6 @@ hwpoison.txt
        - explains what hwpoison is
 ksm.txt
        - how to use the Kernel Samepage Merging feature.
-locking
-       - info on how locking and synchronization is done in the Linux vm code.
 numa
        - information about NUMA specific code in the Linux vm.
 numa_memory_policy.txt
@@ -32,6 +30,8 @@ slub.txt
        - a short users guide for SLUB.
 soft-dirty.txt
        - short explanation for soft-dirty PTEs
+split_page_table_lock
+       - Separate per-table lock to improve scalability of the old page_table_lock.
 transhuge.txt
        - Transparent Hugepage Support, alternative way of using hugepages.
 unevictable-lru.txt
index d63fa024ac05901252a3ea9af825c85b866845e3..8330cf9325f0ad6da97b4bdc1c8e02414bfa9cbc 100644 (file)
@@ -4,7 +4,9 @@ ds2482
        - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses.
 ds2490
        - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges.
-mxc_w1
+mxc-w1
        - W1 master controller driver found on Freescale MX2/MX3 SoCs
+omap-hdq
+       - HDQ/1-wire module of TI OMAP 2430/3430.
 w1-gpio
        - GPIO 1-wire bus master driver.
index 75613c9ac4dbe2eae00d12d15b043bfc47720a6c..6e18c70c347488756987040d73e6f1e790c11ed6 100644 (file)
@@ -4,3 +4,5 @@ w1_therm
        - The Maxim/Dallas Semiconductor ds18*20 temperature sensor.
 w1_ds2423
        - The Maxim/Dallas Semiconductor ds2423 counter device.
+w1_ds28e04
+       - The Maxim/Dallas Semiconductor ds28e04 eeprom.
index f37b46d348614be9fc5a0b54a8c303617e979d56..692264456f0f6cd2bce609207251472c3fcc9005 100644 (file)
@@ -1,6 +1,20 @@
 00-INDEX
        - this file
-mtrr.txt
-       - how to use x86 Memory Type Range Registers to increase performance
+boot.txt
+       - List of boot protocol versions
+early-microcode.txt
+       - How to load microcode from an initrd-CPIO archive early to fix CPU issues.
+earlyprintk.txt
+       - Using earlyprintk with a USB2 debug port key.
+entry_64.txt
+       - Describe (some of the) kernel entry points for x86.
 exception-tables.txt
        - why and how Linux kernel uses exception tables on x86
+mtrr.txt
+       - how to use x86 Memory Type Range Registers to increase performance
+pat.txt
+       - Page Attribute Table intro and API
+usb-legacy-support.txt
+       - how to fix/avoid quirks when using emulated PS/2 mouse/keyboard.
+zero-page.txt
+       - layout of the first page of memory.
index cb81741d3b0bd92b70aa87918e632edd0bfef3f1..a75e3adaa39da277fb89150fb1d31daf8d1296ef 100644 (file)
@@ -182,7 +182,7 @@ Offset      Proto   Name            Meaning
 0226/1 2.02+(3 ext_loader_ver  Extended boot loader version
 0227/1 2.02+(3 ext_loader_type Extended boot loader ID
 0228/4 2.02+   cmd_line_ptr    32-bit pointer to the kernel command line
-022C/4 2.03+   ramdisk_max     Highest legal initrd address
+022C/4 2.03+   initrd_addr_max Highest legal initrd address
 0230/4 2.05+   kernel_alignment Physical addr alignment required for kernel
 0234/1 2.05+   relocatable_kernel Whether kernel is relocatable or not
 0235/1 2.10+   min_alignment   Minimum alignment, as a power of two
@@ -534,7 +534,7 @@ Protocol:   2.02+
   zero, the kernel will assume that your boot loader does not support
   the 2.02+ protocol.
 
-Field name:    ramdisk_max
+Field name:    initrd_addr_max
 Type:          read
 Offset/size:   0x22c/4
 Protocol:      2.03+
index 28fa325b74617f513e3b2cd478f1b03d5a6edd62..6f6d956ac1c9724bd47fd6a5a77d22f09fe1cd9b 100644 (file)
@@ -7,7 +7,7 @@ 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>
+Chinese maintainer: Fu Wei <wefu@redhat.com>
 ---------------------------------------------------------------------
 Documentation/arm64/booting.txt 的中文翻译
 
@@ -16,9 +16,9 @@ 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>
+中文版维护者: 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者: 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者: 傅炜  Fu Wei <wefu@redhat.com>
 
 以下为正文
 ---------------------------------------------------------------------
@@ -64,8 +64,8 @@ RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何
 
 必要性: 强制
 
-设å¤\87æ \91æ\95°æ\8d®å\9d\97ï¼\88dtbï¼\89大å°\8få¿\85é¡»ä¸\8d大äº\8e 2 MBï¼\8cä¸\94ä½\8däº\8eä»\8eå\86\85æ ¸æ\98 å\83\8fèµ·å§\8bç®\97起第ä¸\80个
-512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来
+设å¤\87æ \91æ\95°æ\8d®å\9d\97ï¼\88dtbï¼\89å¿\85é¡» 8 å­\97è\8a\82对é½\90ï¼\8c并ä½\8däº\8eä»\8eå\86\85æ ¸æ\98 å\83\8fèµ·å§\8bç®\97起第ä¸\80个 512MB
+内,且不得跨越 2MB 对齐边界。这使得内核可以通过初始页表中的单个节描述符来
 映射此数据块。
 
 
@@ -84,13 +84,23 @@ AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内
 
 必要性: 强制
 
-已解压的内核映像包含一个 32 字节的头,内容如下:
+已解压的内核映像包含一个 64 字节的头,内容如下:
 
-  u32 magic    = 0x14000008;   /* 跳转到 stext, 小端 */
-  u32 res0     = 0;            /* 保留 */
+  u32 code0;                   /* 可执行代码 */
+  u32 code1;                   /* 可执行代码 */
   u64 text_offset;             /* 映像装载偏移 */
+  u64 res0     = 0;            /* 保留 */
   u64 res1     = 0;            /* 保留 */
   u64 res2     = 0;            /* 保留 */
+  u64 res3     = 0;            /* 保留 */
+  u64 res4     = 0;            /* 保留 */
+  u32 magic    = 0x644d5241;   /* 魔数, 小端, "ARM\x64" */
+  u32 res5 = 0;                /* 保留 */
+
+
+映像头注释:
+
+- code0/code1 负责跳转到 stext.
 
 映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM
 的起始地址必须是以 2MB 对齐的。
@@ -118,9 +128,9 @@ AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内
   外部高速缓存(如果存在)必须配置并禁用。
 
 - 架构计时器
-  CNTFRQ 必须设定为计时器的频率
-  如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0)
-  必须置位。
+  CNTFRQ 必须设定为计时器的频率,且 CNTVOFF 必须设定为对所有 CPU
+  都一致的值。如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的
+  EL1PCTEN (bit 0) 必须置位。
 
 - 一致性
   通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
@@ -131,23 +141,40 @@ AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内
   在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件
   在一个更高的异常级别下初始化,以防止在 未知 状态下运行。
 
+以上对于 CPU 模式、高速缓存、MMU、架构计时器、一致性、系统寄存器的
+必要条件描述适用于所有 CPU。所有 CPU 必须在同一异常级别跳入内核。
+
 引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口:
 
 - 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
-  数据块必须在每个 CPU 节点中包含以下内容:
-
-    1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。
-
-    2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。
+  数据块必须在每个 CPU 节点中包含一个 ‘enable-method’ 属性,所
+  支持的 enable-method 请见下文。
 
   引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入
   数据块。
 
-- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递
+- enable-method 为 “spin-table” 的 CPU 必须在它们的 CPU
+  节点中包含一个 ‘cpu-release-addr’ 属性。这个属性标识了一个
+  64 位自然对齐且初始化为零的内存位置。
+
+  这些 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递
   给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须
   包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将
   发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
-  时,CPU 必须直接跳入此值所指向的地址。
+  时,CPU 必须跳入此值所指向的地址。此值为一个单独的 64 位小端值,
+  因此 CPU 须在跳转前将所读取的值转换为其本身的端模式。
+
+- enable-method 为 “psci” 的 CPU 保持在内核外(比如,在
+  memory 节点中描述为内核空间的内存区外,或在通过设备树 /memreserve/
+  域中描述为内核保留区的空间中)。内核将会发起在 ARM 文档(编号
+  ARM DEN 0022A:用于 ARM 上的电源状态协调接口系统软件)中描述的
+  CPU_ON 调用来将 CPU 带入内核。
+
+  *译者注:到文档翻译时,此文档已更新为 ARM DEN 0022B。
+
+  设备树必须包含一个 ‘psci’ 节点,请参考以下文档:
+  Documentation/devicetree/bindings/arm/psci.txt
+
 
 - 辅助 CPU 通用寄存器设置
   x0 = 0 (保留,将来可能使用)
index a5f6283829f9c90bb9d3de64d414589192d01788..a782704c1cb59ab868de82d573291ac8780f6297 100644 (file)
@@ -7,7 +7,7 @@ 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>
+Chinese maintainer: Fu Wei <wefu@redhat.com>
 ---------------------------------------------------------------------
 Documentation/arm64/memory.txt 的中文翻译
 
@@ -16,9 +16,9 @@ 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>
+中文版维护者: 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者: 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者: 傅炜  Fu Wei <wefu@redhat.com>
 
 以下为正文
 ---------------------------------------------------------------------
@@ -41,7 +41,7 @@ AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和
 TTBR1 中,且从不写入 TTBR0。
 
 
-AArch64 Linux 内存布局:
+AArch64 Linux å\9c¨é¡µå¤§å°\8f为 4KB æ\97¶ç\9a\84å\86\85å­\98å¸\83å±\80ï¼\9a
 
 起始地址                   结束地址                    大小          用途
 -----------------------------------------------------------------------
@@ -55,15 +55,42 @@ ffffffbc00000000    ffffffbdffffffff           8GB          vmemmap
 
 ffffffbe00000000       ffffffbffbbfffff          ~8GB          [防护页,未来用于 vmmemap]
 
+ffffffbffbc00000       ffffffbffbdfffff           2MB          earlyprintk 设备
+
 ffffffbffbe00000       ffffffbffbe0ffff          64KB          PCI I/O 空间
 
-ffffffbbffff0000       ffffffbcffffffff          ~2MB          [防护页]
+ffffffbffbe10000       ffffffbcffffffff          ~2MB          [防护页]
 
 ffffffbffc000000       ffffffbfffffffff          64MB          模块
 
 ffffffc000000000       ffffffffffffffff         256GB          内核逻辑内存映射
 
 
+AArch64 Linux 在页大小为 64KB 时的内存布局:
+
+起始地址                   结束地址                    大小          用途
+-----------------------------------------------------------------------
+0000000000000000       000003ffffffffff           4TB          用户空间
+
+fffffc0000000000       fffffdfbfffeffff          ~2TB          vmalloc
+
+fffffdfbffff0000       fffffdfbffffffff          64KB          [防护页]
+
+fffffdfc00000000       fffffdfdffffffff           8GB          vmemmap
+
+fffffdfe00000000       fffffdfffbbfffff          ~8GB          [防护页,未来用于 vmmemap]
+
+fffffdfffbc00000       fffffdfffbdfffff           2MB          earlyprintk 设备
+
+fffffdfffbe00000       fffffdfffbe0ffff          64KB          PCI I/O 空间
+
+fffffdfffbe10000       fffffdfffbffffff          ~2MB          [防护页]
+
+fffffdfffc000000       fffffdffffffffff          64MB          模块
+
+fffffe0000000000       ffffffffffffffff           2TB          内核逻辑内存映射
+
+
 4KB 页大小的转换表查找:
 
 +--------+--------+--------+--------+--------+--------+--------+--------+
@@ -91,3 +118,10 @@ ffffffc000000000    ffffffffffffffff         256GB          内核逻辑内存映射
  |                 |    +--------------------------> [41:29] L2 索引 (仅使用 38:29 )
  |                 +-------------------------------> [47:42] L1 索引 (未使用)
  +-------------------------------------------------> [63] TTBR0/1
+
+当使用 KVM 时, 管理程序(hypervisor)在 EL2 中通过相对内核虚拟地址的
+一个固定偏移来映射内核页(内核虚拟地址的高 24 位设为零):
+
+起始地址                   结束地址                    大小          用途
+-----------------------------------------------------------------------
+0000004000000000       0000007fffffffff         256GB          在 HYP 中映射的内核对象
diff --git a/Documentation/zh_CN/arm64/tagged-pointers.txt b/Documentation/zh_CN/arm64/tagged-pointers.txt
new file mode 100644 (file)
index 0000000..2664d1b
--- /dev/null
@@ -0,0 +1,52 @@
+Chinese translated version of Documentation/arm64/tagged-pointers.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 <wefu@redhat.com>
+---------------------------------------------------------------------
+Documentation/arm64/tagged-pointers.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Will Deacon <will.deacon@arm.com>
+中文版维护者: 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者: 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者: 傅炜  Fu Wei <wefu@redhat.com>
+
+以下为正文
+---------------------------------------------------------------------
+               Linux 在 AArch64 中带标记的虚拟地址
+               =================================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2013 年 06 月 12 日
+
+本文档简述了在 AArch64 地址转换系统中提供的带标记的虚拟地址及其在
+AArch64 Linux 中的潜在用途。
+
+内核提供的地址转换表配置使通过 TTBR0 完成的虚拟地址转换(即用户空间
+映射),其虚拟地址的最高 8 位(63:56)会被转换硬件所忽略。这种机制
+让这些位可供应用程序自由使用,其注意事项如下:
+
+       (1) 内核要求所有传递到 EL1 的用户空间地址带有 0x00 标记。
+           这意味着任何携带用户空间虚拟地址的系统调用(syscall)
+           参数 *必须* 在陷入内核前使它们的最高字节被清零。
+
+       (2) 非零标记在传递信号时不被保存。这意味着在应用程序中利用了
+           标记的信号处理函数无法依赖 siginfo_t 的用户空间虚拟
+           地址所携带的包含其内部域信息的标记。此规则的一个例外是
+           当信号是在调试观察点的异常处理程序中产生的,此时标记的
+           信息将被保存。
+
+       (3) 当使用带标记的指针时需特别留心,因为仅对两个虚拟地址
+           的高字节,C 编译器很可能无法判断它们是不同的。
+
+此构架会阻止对带标记的 PC 指针的利用,因此在异常返回时,其高字节
+将被设置成一个为 “55” 的扩展符。
index edd6139c7c7c4596ac3620c5ca81102571c34c4d..d1f3cb340e0141fd40db1db68f42543077bcc653 100644 (file)
@@ -73,7 +73,8 @@ Descriptions of section entries:
        L: Mailing list that is relevant to this area
        W: Web-page with status/info
        Q: Patchwork web based patch tracking system site
-       T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit, topgit.
+       T: SCM tree type and location.
+          Type is one of: git, hg, quilt, stgit, topgit
        S: Status, one of the following:
           Supported:   Someone is actually paid to look after this.
           Maintained:  Someone actually looks after it.
@@ -473,7 +474,7 @@ F:  net/rxrpc/af_rxrpc.c
 
 AGPGART DRIVER
 M:     David Airlie <airlied@linux.ie>
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+T:     git git://people.freedesktop.org/~airlied/linux (part of drm maint)
 S:     Maintained
 F:     drivers/char/agp/
 F:     include/linux/agp*
@@ -538,7 +539,7 @@ F:  arch/alpha/
 ALTERA UART/JTAG UART SERIAL DRIVERS
 M:     Tobias Klauser <tklauser@distanz.ch>
 L:     linux-serial@vger.kernel.org
-L:     nios2-dev@sopc.et.ntust.edu.tw (moderated for non-subscribers)
+L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/tty/serial/altera_uart.c
 F:     drivers/tty/serial/altera_jtaguart.c
@@ -910,11 +911,11 @@ F:        arch/arm/include/asm/hardware/dec21285.h
 F:     arch/arm/mach-footbridge/
 
 ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
-M:     Shawn Guo <shawn.guo@linaro.org>
+M:     Shawn Guo <shawn.guo@freescale.com>
 M:     Sascha Hauer <kernel@pengutronix.de>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
 F:     arch/arm/mach-imx/
 F:     arch/arm/boot/dts/imx*
 F:     arch/arm/configs/imx*_defconfig
@@ -1613,11 +1614,11 @@ S:      Maintained
 F:     drivers/net/wireless/atmel*
 
 ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
-M:      Bradley Grove <linuxdrivers@attotech.com>
-L:      linux-scsi@vger.kernel.org
-W:      http://www.attotech.com
-S:      Supported
-F:      drivers/scsi/esas2r
+M:     Bradley Grove <linuxdrivers@attotech.com>
+L:     linux-scsi@vger.kernel.org
+W:     http://www.attotech.com
+S:     Supported
+F:     drivers/scsi/esas2r
 
 AUDIT SUBSYSTEM
 M:     Eric Paris <eparis@redhat.com>
@@ -1738,6 +1739,7 @@ F:        include/uapi/linux/bfs_fs.h
 BLACKFIN ARCHITECTURE
 M:     Steven Miao <realmz6@gmail.com>
 L:     adi-buildroot-devel@lists.sourceforge.net
+T:     git git://git.code.sf.net/p/adi-linux/code
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     arch/blackfin/
@@ -1831,8 +1833,8 @@ F:        net/bluetooth/
 F:     include/net/bluetooth/
 
 BONDING DRIVER
-M:     Jay Vosburgh <fubar@us.ibm.com>
-M:     Veaceslav Falico <vfalico@redhat.com>
+M:     Jay Vosburgh <j.vosburgh@gmail.com>
+M:     Veaceslav Falico <vfalico@gmail.com>
 M:     Andy Gospodarek <andy@greyhouse.net>
 L:     netdev@vger.kernel.org
 W:     http://sourceforge.net/projects/bonding/
@@ -1861,6 +1863,7 @@ F:        drivers/net/ethernet/broadcom/bnx2x/
 
 BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
 M:     Christian Daudt <bcm@fixthebug.org>
+M:     Matt Porter <mporter@linaro.org>
 L:     bcm-kernel-feedback-list@broadcom.com
 T:     git git://git.github.com/broadcom/bcm11351
 S:     Maintained
@@ -2159,7 +2162,7 @@ F:        Documentation/zh_CN/
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
 M:     Peter Chen <Peter.Chen@freescale.com>
-T:     git://github.com/hzpeterchen/linux-usb.git
+T:     git git://github.com/hzpeterchen/linux-usb.git
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/chipidea/
@@ -2179,9 +2182,9 @@ S:        Supported
 F:     drivers/net/ethernet/cisco/enic/
 
 CISCO VIC LOW LATENCY NIC DRIVER
-M:      Upinder Malhi <umalhi@cisco.com>
-S:      Supported
-F:      drivers/infiniband/hw/usnic
+M:     Upinder Malhi <umalhi@cisco.com>
+S:     Supported
+F:     drivers/infiniband/hw/usnic
 
 CIRRUS LOGIC EP93XX ETHERNET DRIVER
 M:     Hartley Sweeten <hsweeten@visionengravers.com>
@@ -2368,7 +2371,7 @@ F:        include/linux/cpufreq.h
 
 CPU FREQUENCY DRIVERS - ARM BIG LITTLE
 M:     Viresh Kumar <viresh.kumar@linaro.org>
-M:     Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
+M:     Sudeep Holla <sudeep.holla@arm.com>
 L:     cpufreq@vger.kernel.org
 L:     linux-pm@vger.kernel.org
 W:     http://www.arm.com/products/processors/technologies/biglittleprocessing.php
@@ -2378,20 +2381,20 @@ F:      drivers/cpufreq/arm_big_little.c
 F:     drivers/cpufreq/arm_big_little_dt.c
 
 CPUIDLE DRIVER - ARM BIG LITTLE
-M:      Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-M:      Daniel Lezcano <daniel.lezcano@linaro.org>
-L:      linux-pm@vger.kernel.org
-L:      linux-arm-kernel@lists.infradead.org
-T:      git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
-S:      Maintained
-F:      drivers/cpuidle/cpuidle-big_little.c
+M:     Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+M:     Daniel Lezcano <daniel.lezcano@linaro.org>
+L:     linux-pm@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
+S:     Maintained
+F:     drivers/cpuidle/cpuidle-big_little.c
 
 CPUIDLE DRIVERS
 M:     Rafael J. Wysocki <rjw@rjwysocki.net>
 M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
-T:     git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
 F:     drivers/cpuidle/*
 F:     include/linux/cpuidle.h
 
@@ -2409,8 +2412,10 @@ F:       tools/power/cpupower/
 
 CPUSETS
 M:     Li Zefan <lizefan@huawei.com>
+L:     cgroups@vger.kernel.org
 W:     http://www.bullopensource.org/cpuset/
 W:     http://oss.sgi.com/projects/cpusets/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
 S:     Maintained
 F:     Documentation/cgroups/cpusets.txt
 F:     include/linux/cpuset.h
@@ -2456,9 +2461,9 @@ S:        Maintained
 F:     sound/pci/cs5535audio/
 
 CW1200 WLAN driver
-M:     Solomon Peachy <pizza@shaftnet.org>
-S:     Maintained
-F:     drivers/net/wireless/cw1200/
+M:     Solomon Peachy <pizza@shaftnet.org>
+S:     Maintained
+F:     drivers/net/wireless/cw1200/
 
 CX18 VIDEO4LINUX DRIVER
 M:     Andy Walls <awalls@md.metrocast.net>
@@ -2609,9 +2614,9 @@ DC395x SCSI driver
 M:     Oliver Neukum <oliver@neukum.org>
 M:     Ali Akcaagac <aliakc@web.de>
 M:     Jamie Lenehan <lenehan@twibble.org>
-W:     http://twibble.org/dist/dc395x/
 L:     dc395x@twibble.org
-L:     http://lists.twibble.org/mailman/listinfo/dc395x/
+W:     http://twibble.org/dist/dc395x/
+W:     http://lists.twibble.org/mailman/listinfo/dc395x/
 S:     Maintained
 F:     Documentation/scsi/dc395x.txt
 F:     drivers/scsi/dc395x.*
@@ -2797,9 +2802,9 @@ S:        Supported
 F:     drivers/acpi/dock.c
 
 DOCUMENTATION
-M:     Rob Landley <rob@landley.net>
+M:     Randy Dunlap <rdunlap@infradead.org>
 L:     linux-doc@vger.kernel.org
-T:     TBD
+T:     quilt http://www.infradead.org/~rdunlap/Doc/patches/
 S:     Maintained
 F:     Documentation/
 
@@ -2846,19 +2851,29 @@ F:      lib/kobj*
 DRM DRIVERS
 M:     David Airlie <airlied@linux.ie>
 L:     dri-devel@lists.freedesktop.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+T:     git git://people.freedesktop.org/~airlied/linux
 S:     Maintained
 F:     drivers/gpu/drm/
 F:     include/drm/
 F:     include/uapi/drm/
 
+RADEON DRM DRIVERS
+M:     Alex Deucher <alexander.deucher@amd.com>
+M:     Christian König <christian.koenig@amd.com>
+L:     dri-devel@lists.freedesktop.org
+T:     git git://people.freedesktop.org/~agd5f/linux
+S:     Supported
+F:     drivers/gpu/drm/radeon/
+F:     include/drm/radeon*
+F:     include/uapi/drm/radeon*
+
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
 M:     Jani Nikula <jani.nikula@linux.intel.com>
 L:     intel-gfx@lists.freedesktop.org
 L:     dri-devel@lists.freedesktop.org
 Q:     http://patchwork.freedesktop.org/project/intel-gfx/
-T:     git git://people.freedesktop.org/~danvet/drm-intel
+T:     git git://anongit.freedesktop.org/drm-intel
 S:     Supported
 F:     drivers/gpu/drm/i915/
 F:     include/drm/i915*
@@ -3083,6 +3098,8 @@ F:        fs/ecryptfs/
 
 EDAC-CORE
 M:     Doug Thompson <dougthompson@xmission.com>
+M:     Borislav Petkov <bp@alien8.de>
+M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Supported
@@ -3325,6 +3342,17 @@ S:       Maintained
 F:     include/linux/netfilter_bridge/
 F:     net/bridge/
 
+ETHERNET PHY LIBRARY
+M:     Florian Fainelli <f.fainelli@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     include/linux/phy.h
+F:     include/linux/phy_fixed.h
+F:     drivers/net/phy/
+F:     Documentation/networking/phy.txt
+F:     drivers/of/of_mdio.c
+F:     drivers/of/of_net.c
+
 EXT2 FILE SYSTEM
 M:     Jan Kara <jack@suse.cz>
 L:     linux-ext4@vger.kernel.org
@@ -4518,6 +4546,7 @@ M:        Greg Rose <gregory.v.rose@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
 M:     Mitch Williams <mitch.a.williams@intel.com>
+M:     Linux NICS <linux.nics@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
@@ -4535,6 +4564,7 @@ F:        Documentation/networking/ixgbevf.txt
 F:     Documentation/networking/i40e.txt
 F:     Documentation/networking/i40evf.txt
 F:     drivers/net/ethernet/intel/
+F:     drivers/net/ethernet/intel/*/
 
 INTEL-MID GPIO DRIVER
 M:     David Cohen <david.a.cohen@linux.intel.com>
@@ -4891,7 +4921,7 @@ F:        drivers/staging/ktap/
 KCONFIG
 M:     "Yann E. MORIN" <yann.morin.1998@free.fr>
 L:     linux-kbuild@vger.kernel.org
-T:     git://gitorious.org/linux-kconfig/linux-kconfig
+T:     git git://gitorious.org/linux-kconfig/linux-kconfig
 S:     Maintained
 F:     Documentation/kbuild/kconfig-language.txt
 F:     scripts/kconfig/
@@ -5448,11 +5478,11 @@ S:      Maintained
 F:     drivers/media/tuners/m88ts2022*
 
 MA901 MASTERKIT USB FM RADIO DRIVER
-M:      Alexey Klimov <klimov.linux@gmail.com>
-L:      linux-media@vger.kernel.org
-T:      git git://linuxtv.org/media_tree.git
-S:      Maintained
-F:      drivers/media/radio/radio-ma901.c
+M:     Alexey Klimov <klimov.linux@gmail.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/radio/radio-ma901.c
 
 MAC80211
 M:     Johannes Berg <johannes@sipsolutions.net>
@@ -5488,6 +5518,11 @@ W:       http://www.kernel.org/doc/man-pages
 L:     linux-man@vger.kernel.org
 S:     Maintained
 
+MARVELL ARMADA DRM SUPPORT
+M:     Russell King <rmk+kernel@arm.linux.org.uk>
+S:     Maintained
+F:     drivers/gpu/drm/armada/
+
 MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
 M:     Mirko Lindner <mlindner@marvell.com>
 M:     Stephen Hemminger <stephen@networkplumber.org>
@@ -5608,7 +5643,7 @@ F:        drivers/scsi/megaraid/
 
 MELLANOX ETHERNET DRIVER (mlx4_en)
 M:     Amir Vadai <amirv@mellanox.com>
-L:     netdev@vger.kernel.org
+L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
@@ -5649,7 +5684,7 @@ F:        include/linux/mtd/
 F:     include/uapi/mtd/
 
 MEN A21 WATCHDOG DRIVER
-M:     Johannes Thumshirn <johannes.thumshirn@men.de>
+M:     Johannes Thumshirn <johannes.thumshirn@men.de>
 L:     linux-watchdog@vger.kernel.org
 S:     Supported
 F:     drivers/watchdog/mena21_wdt.c
@@ -5705,20 +5740,20 @@ L:      linux-rdma@vger.kernel.org
 W:     http://www.mellanox.com
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
 Q:     http://patchwork.kernel.org/project/linux-rdma/list/
-T:     git://openfabrics.org/~eli/connect-ib.git
+T:     git git://openfabrics.org/~eli/connect-ib.git
 S:     Supported
 F:     drivers/net/ethernet/mellanox/mlx5/core/
 F:     include/linux/mlx5/
 
 Mellanox MLX5 IB driver
-M:      Eli Cohen <eli@mellanox.com>
-L:      linux-rdma@vger.kernel.org
-W:      http://www.mellanox.com
-Q:      http://patchwork.kernel.org/project/linux-rdma/list/
-T:      git://openfabrics.org/~eli/connect-ib.git
-S:      Supported
-F:      include/linux/mlx5/
-F:      drivers/infiniband/hw/mlx5/
+M:     Eli Cohen <eli@mellanox.com>
+L:     linux-rdma@vger.kernel.org
+W:     http://www.mellanox.com
+Q:     http://patchwork.kernel.org/project/linux-rdma/list/
+T:     git git://openfabrics.org/~eli/connect-ib.git
+S:     Supported
+F:     include/linux/mlx5/
+F:     drivers/infiniband/hw/mlx5/
 
 MODULE SUPPORT
 M:     Rusty Russell <rusty@rustcorp.com.au>
@@ -5970,6 +6005,9 @@ F:        include/linux/netdevice.h
 F:     include/uapi/linux/in.h
 F:     include/uapi/linux/net.h
 F:     include/uapi/linux/netdevice.h
+F:     tools/net/
+F:     tools/testing/selftests/net/
+F:     lib/random32.c
 
 NETWORKING [IPv4/IPv6]
 M:     "David S. Miller" <davem@davemloft.net>
@@ -6143,6 +6181,12 @@ S:       Supported
 F:     drivers/block/nvme*
 F:     include/linux/nvme.h
 
+NXP TDA998X DRM DRIVER
+M:     Russell King <rmk+kernel@arm.linux.org.uk>
+S:     Supported
+F:     drivers/gpu/drm/i2c/tda998x_drv.c
+F:     include/drm/i2c/tda998x.h
+
 OMAP SUPPORT
 M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
@@ -7197,7 +7241,7 @@ S:        Maintained
 F:     drivers/net/ethernet/rdc/r6040.c
 
 RDS - RELIABLE DATAGRAM SOCKETS
-M:     Venkat Venkatsubra <venkat.x.venkatsubra@oracle.com>
+M:     Chien Yen <chien.yen@oracle.com>
 L:     rds-devel@oss.oracle.com (moderated for non-subscribers)
 S:     Supported
 F:     net/rds/
@@ -7362,10 +7406,26 @@ W:      http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 F:     arch/s390/
 F:     drivers/s390/
-F:     block/partitions/ibm.c
 F:     Documentation/s390/
 F:     Documentation/DocBook/s390*
 
+S390 COMMON I/O LAYER
+M:     Sebastian Ott <sebott@linux.vnet.ibm.com>
+M:     Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+L:     linux-s390@vger.kernel.org
+W:     http://www.ibm.com/developerworks/linux/linux390/
+S:     Supported
+F:     drivers/s390/cio/
+
+S390 DASD DRIVER
+M:     Stefan Weinhuber <wein@de.ibm.com>
+M:     Stefan Haberland <stefan.haberland@de.ibm.com>
+L:     linux-s390@vger.kernel.org
+W:     http://www.ibm.com/developerworks/linux/linux390/
+S:     Supported
+F:     drivers/s390/block/dasd*
+F:     block/partitions/ibm.c
+
 S390 NETWORK DRIVERS
 M:     Ursula Braun <ursula.braun@de.ibm.com>
 M:     Frank Blaschka <blaschka@linux.vnet.ibm.com>
@@ -7375,6 +7435,15 @@ W:       http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 F:     drivers/s390/net/
 
+S390 PCI SUBSYSTEM
+M:     Sebastian Ott <sebott@linux.vnet.ibm.com>
+M:     Gerald Schaefer <gerald.schaefer@de.ibm.com>
+L:     linux-s390@vger.kernel.org
+W:     http://www.ibm.com/developerworks/linux/linux390/
+S:     Supported
+F:     arch/s390/pci/
+F:     drivers/pci/hotplug/s390_pci_hpc.c
+
 S390 ZCRYPT DRIVER
 M:     Ingo Tuchscherer <ingo.tuchscherer@de.ibm.com>
 M:     linux390@de.ibm.com
@@ -8430,8 +8499,8 @@ TARGET SUBSYSTEM
 M:     Nicholas A. Bellinger <nab@linux-iscsi.org>
 L:     linux-scsi@vger.kernel.org
 L:     target-devel@vger.kernel.org
-L:     http://groups.google.com/group/linux-iscsi-target-dev
 W:     http://www.linux-iscsi.org
+W:     http://groups.google.com/group/linux-iscsi-target-dev
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master
 S:     Supported
 F:     drivers/target/
@@ -8672,17 +8741,17 @@ S:      Maintained
 F:     drivers/media/radio/radio-raremono.c
 
 THERMAL
-M:      Zhang Rui <rui.zhang@intel.com>
-M:      Eduardo Valentin <eduardo.valentin@ti.com>
-L:      linux-pm@vger.kernel.org
-T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
-T:      git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
-Q:      https://patchwork.kernel.org/project/linux-pm/list/
-S:      Supported
-F:      drivers/thermal/
-F:      include/linux/thermal.h
-F:      include/linux/cpu_cooling.h
-F:      Documentation/devicetree/bindings/thermal/
+M:     Zhang Rui <rui.zhang@intel.com>
+M:     Eduardo Valentin <eduardo.valentin@ti.com>
+L:     linux-pm@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
+Q:     https://patchwork.kernel.org/project/linux-pm/list/
+S:     Supported
+F:     drivers/thermal/
+F:     include/linux/thermal.h
+F:     include/linux/cpu_cooling.h
+F:     Documentation/devicetree/bindings/thermal/
 
 THINGM BLINK(1) USB RGB LED DRIVER
 M:     Vivien Didelot <vivien.didelot@savoirfairelinux.com>
@@ -9716,7 +9785,6 @@ F:        drivers/xen/*swiotlb*
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
 M:     Dave Chinner <david@fromorbit.com>
-M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
 W:     http://oss.sgi.com/projects/xfs
@@ -9785,7 +9853,7 @@ ZR36067 VIDEO FOR LINUX DRIVER
 L:     mjpeg-users@lists.sourceforge.net
 L:     linux-media@vger.kernel.org
 W:     http://mjpeg.sourceforge.net/driver-zoran/
-T:     Mercurial http://linuxtv.org/hg/v4l-dvb
+T:     hg http://linuxtv.org/hg/v4l-dvb
 S:     Odd Fixes
 F:     drivers/media/pci/zoran/
 
index 606ef7c4a544913bf0fdcd6c4b62a359d5ad8e53..e5ac8a62e6e57c855c4da06e3d80c2438fccee48 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION =
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
@@ -605,10 +605,11 @@ endif
 ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
   stackp-flag := -fstack-protector
   ifeq ($(call cc-option, $(stackp-flag)),)
-    $(warning Cannot use CONFIG_CC_STACKPROTECTOR: \
-             -fstack-protector not supported by compiler))
+    $(warning Cannot use CONFIG_CC_STACKPROTECTOR_REGULAR: \
+             -fstack-protector not supported by compiler)
   endif
-else ifdef CONFIG_CC_STACKPROTECTOR_STRONG
+else
+ifdef CONFIG_CC_STACKPROTECTOR_STRONG
   stackp-flag := -fstack-protector-strong
   ifeq ($(call cc-option, $(stackp-flag)),)
     $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
@@ -618,6 +619,7 @@ else
   # Force off for distro compilers that enable stack protector by default.
   stackp-flag := $(call cc-option, -fno-stack-protector)
 endif
+endif
 KBUILD_CFLAGS += $(stackp-flag)
 
 # This warning generated too much noise in a regular build.
index a73a8e208a4ae00154c0e1adb6ef4a3f311ebcb6..96e54bed50889e4fe62c71ac6125ac6fe0dad5f2 100644 (file)
@@ -1,7 +1,9 @@
 
-generic-y += clkdev.h
 
+generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += exec.h
-generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/alpha/include/asm/cputime.h b/arch/alpha/include/asm/cputime.h
deleted file mode 100644 (file)
index 19577fd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ALPHA_CPUTIME_H
-#define __ALPHA_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __ALPHA_CPUTIME_H */
index 0d3362991c316efd8236933c178523565c3f29ad..e76fd79f32b0126ee2e83dfaa5ba05d3d4c98452 100644 (file)
@@ -1,15 +1,15 @@
 generic-y += auxvec.h
 generic-y += barrier.h
-generic-y += bugs.h
 generic-y += bitsperlong.h
+generic-y += bugs.h
 generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += device.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
-generic-y += fcntl.h
 generic-y += fb.h
+generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += hardirq.h
 generic-y += hash.h
@@ -22,6 +22,7 @@ generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += param.h
@@ -30,6 +31,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -48,4 +50,3 @@ generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
index 6b58c1de757744feac1d0ae54ec1fdd0693fc500..400c663b21c2bf075e977a8ccf3016fb7e03b5a6 100644 (file)
@@ -282,7 +282,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr,
 #else
        /* if V-P const for loop, PTAG can be written once outside loop */
        if (full_page_op)
-               write_aux_reg(ARC_REG_DC_PTAG, paddr);
+               write_aux_reg(aux_tag, paddr);
 #endif
 
        while (num_lines-- > 0) {
@@ -296,7 +296,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr,
                write_aux_reg(aux_cmd, vaddr);
                vaddr += L1_CACHE_BYTES;
 #else
-               write_aux_reg(aux, paddr);
+               write_aux_reg(aux_cmd, paddr);
                paddr += L1_CACHE_BYTES;
 #endif
        }
index e254198177914ca13050f37519a6ca43e0da596d..15949459611f194376dafcdebaf569f8ef141dc5 100644 (file)
@@ -1578,6 +1578,7 @@ config BL_SWITCHER_DUMMY_IF
 
 choice
        prompt "Memory split"
+       depends on MMU
        default VMSPLIT_3G
        help
          Select the desired split between kernel and user memory.
@@ -1595,6 +1596,7 @@ endchoice
 
 config PAGE_OFFSET
        hex
+       default PHYS_OFFSET if !MMU
        default 0x40000000 if VMSPLIT_1G
        default 0x80000000 if VMSPLIT_2G
        default 0xC0000000
@@ -1903,6 +1905,7 @@ config XEN
        depends on ARM && AEABI && OF
        depends on CPU_V7 && !CPU_V6
        depends on !GENERIC_ATOMIC64
+       depends on MMU
        select ARM_PSCI
        select SWIOTLB_XEN
        select ARCH_DMA_ADDR_T_64BIT
index 47279aa96a6a48fd1945ae9faa7584d49f24a355..0714e0334e33c9790b221d03859574b2f4e774ad 100644 (file)
@@ -1,4 +1,5 @@
 ashldi3.S
+bswapsdi2.S
 font.c
 lib1funcs.S
 hyp-stub.S
index b9d6a8b485e0bdeba13c1848391fca3ca263341b..032030361bef2448ce84075212615d58c469cb8b 100644 (file)
@@ -38,6 +38,7 @@ dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb
 # sama5d3
+dtb-$(CONFIG_ARCH_AT91)        += at91-sama5d3_xplained.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d31ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d33ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d34ek.dtb
@@ -208,7 +209,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
        omap3-n900.dtb \
        omap3-n9.dtb \
        omap3-n950.dtb \
-       omap3-tobi.dtb \
+       omap3-overo-tobi.dtb \
+       omap3-overo-storm-tobi.dtb \
        omap3-gta04.dtb \
        omap3-igep0020.dtb \
        omap3-igep0030.dtb \
index 4718ec4a4dbfef5e2a7273726cb6a8f0750623e3..486880b7483134c88f8638a6e7fb4cc98518e7e3 100644 (file)
                ti,model = "AM335x-EVMSK";
                ti,audio-codec = <&tlv320aic3106>;
                ti,mcasp-controller = <&mcasp1>;
-               ti,codec-clock-rate = <24576000>;
+               ti,codec-clock-rate = <24000000>;
                ti,audio-routing =
                        "Headphone Jack",       "HPLOUT",
                        "Headphone Jack",       "HPROUT";
                >;
        };
 
+       mmc1_pins: pinmux_mmc1_pins {
+               pinctrl-single,pins = <
+                       0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+               >;
+       };
+
        mcasp1_pins: mcasp1_pins {
                pinctrl-single,pins = <
                        0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
        status = "okay";
        vmmc-supply = <&vmmc_reg>;
        bus-width = <4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
 };
 
 &sham {
index 66609684d41b59ef701530fd2076553ffc4e9b6b..9480cf891f8cd0ce475d87cf2eed904a6a740eb7 100644 (file)
@@ -23,6 +23,7 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
+               eth3 = &eth3;
        };
 
        cpus {
                                interrupts = <91>;
                        };
 
-                       ethernet@34000 {
+                       eth3: ethernet@34000 {
                                compatible = "marvell,armada-370-neta";
                                reg = <0x34000 0x4000>;
                                interrupts = <14>;
diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts
new file mode 100644 (file)
index 0000000..ce13755
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * at91-sama5d3_xplained.dts - Device Tree file for the SAMA5D3 Xplained board
+ *
+ *  Copyright (C) 2014 Atmel,
+ *               2014 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+#include "sama5d36.dtsi"
+
+/ {
+       model = "SAMA5D3 Xplained";
+       compatible = "atmel,sama5d3-xplained", "atmel,sama5d3", "atmel,sama5";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x20000000 0x10000000>;
+       };
+
+       ahb {
+               apb {
+                       mmc0: mmc@f0000000 {
+                               pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_dat4_7 &pinctrl_mmc0_cd>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <8>;
+                                       cd-gpios = <&pioE 0 GPIO_ACTIVE_LOW>;
+                               };
+                       };
+
+                       spi0: spi@f0004000 {
+                               cs-gpios = <&pioD 13 0>;
+                               status = "okay";
+                       };
+
+                       can0: can@f000c000 {
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@f0014000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@f0018000 {
+                               status = "okay";
+                       };
+
+                       macb0: ethernet@f0028000 {
+                               phy-mode = "rgmii";
+                               status = "okay";
+                       };
+
+                       usart0: serial@f001c000 {
+                               status = "okay";
+                       };
+
+                       usart1: serial@f0020000 {
+                               pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>;
+                               status = "okay";
+                       };
+
+                       uart0: serial@f0024000 {
+                               status = "okay";
+                       };
+
+                       mmc1: mmc@f8000000 {
+                               pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_mmc1_cd>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioE 1 GPIO_ACTIVE_HIGH>;
+                               };
+                       };
+
+                       spi1: spi@f8008000 {
+                               cs-gpios = <&pioC 25 0>, <0>, <0>, <&pioD 16 0>;
+                               status = "okay";
+                       };
+
+                       adc0: adc@f8018000 {
+                               pinctrl-0 = <
+                                       &pinctrl_adc0_adtrg
+                                       &pinctrl_adc0_ad0
+                                       &pinctrl_adc0_ad1
+                                       &pinctrl_adc0_ad2
+                                       &pinctrl_adc0_ad3
+                                       &pinctrl_adc0_ad4
+                                       &pinctrl_adc0_ad5
+                                       &pinctrl_adc0_ad6
+                                       &pinctrl_adc0_ad7
+                                       &pinctrl_adc0_ad8
+                                       &pinctrl_adc0_ad9
+                                       >;
+                               status = "okay";
+                       };
+
+                       i2c2: i2c@f801c000 {
+                               dmas = <0>, <0>;        /* Do not use DMA for i2c2 */
+                               status = "okay";
+                       };
+
+                       macb1: ethernet@f802c000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       dbgu: serial@ffffee00 {
+                               status = "okay";
+                       };
+
+                       pinctrl@fffff200 {
+                               board {
+                                       pinctrl_mmc0_cd: mmc0_cd {
+                                               atmel,pins =
+                                                       <AT91_PIOE 0 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+                                       };
+
+                                       pinctrl_mmc1_cd: mmc1_cd {
+                                               atmel,pins =
+                                                       <AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+                                       };
+
+                                       pinctrl_usba_vbus: usba_vbus {
+                                               atmel,pins =
+                                                       <AT91_PIOE 9 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;   /* PE9, conflicts with A9 */
+                                       };
+                               };
+                       };
+
+                       pmc: pmc@fffffc00 {
+                               main: mainck {
+                                       clock-frequency = <12000000>;
+                               };
+                       };
+               };
+
+               nand0: nand@60000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "hw";
+                       atmel,has-pmecc;
+                       atmel,pmecc-cap = <4>;
+                       atmel,pmecc-sector-size = <512>;
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x40000>;
+                       };
+
+                       bootloader@40000 {
+                               label = "bootloader";
+                               reg = <0x40000 0x80000>;
+                       };
+
+                       bootloaderenv@c0000 {
+                               label = "bootloader env";
+                               reg = <0xc0000 0xc0000>;
+                       };
+
+                       dtb@180000 {
+                               label = "device tree";
+                               reg = <0x180000 0x80000>;
+                       };
+
+                       kernel@200000 {
+                               label = "kernel";
+                               reg = <0x200000 0x600000>;
+                       };
+
+                       rootfs@800000 {
+                               label = "rootfs";
+                               reg = <0x800000 0x0f800000>;
+                       };
+               };
+
+               usb0: gadget@00500000 {
+                       atmel,vbus-gpio = <&pioE 9 GPIO_ACTIVE_HIGH>;   /* PE9, conflicts with A9 */
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usba_vbus>;
+                       status = "okay";
+               };
+
+               usb1: ohci@00600000 {
+                       num-ports = <3>;
+                       atmel,vbus-gpio = <0
+                                          &pioE 3 GPIO_ACTIVE_LOW
+                                          &pioE 4 GPIO_ACTIVE_LOW
+                                         >;
+                       status = "okay";
+               };
+
+               usb2: ehci@00700000 {
+                       status = "okay";
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               bp3 {
+                       label = "PB_USER";
+                       gpios = <&pioE 29 GPIO_ACTIVE_LOW>;
+                       linux,code = <0x104>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               d2 {
+                       label = "d2";
+                       gpios = <&pioE 23 GPIO_ACTIVE_LOW>;     /* PE23, conflicts with A23, CTS2 */
+                       linux,default-trigger = "heartbeat";
+               };
+
+               d3 {
+                       label = "d3";
+                       gpios = <&pioE 24 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
index 0042f73068b0c913f729cb6e0fd5b3b5b01609d5..fece8665fb63ad89232a821c4da307475bbc4f88 100644 (file)
                        };
 
                        i2c0: i2c@fff88000 {
-                               compatible = "atmel,at91sam9263-i2c";
+                               compatible = "atmel,at91sam9260-i2c";
                                reg = <0xfff88000 0x100>;
                                interrupts = <13 IRQ_TYPE_LEVEL_HIGH 6>;
                                #address-cells = <1>;
index e9487f6f01660409ee193649d3c1d56c98376cb5..924a6a6ffd0f0a03d6fcde286fff1383e696eb70 100644 (file)
                        nand-on-flash-bbt;
                        status = "okay";
                };
+
+               usb0: ohci@00500000 {
+                       status = "okay";
+               };
        };
 
        leds {
index e491b82f8d67099ce25b4d1f08cdc6777bf55d7f..792fde1b7f752a93ffa42f2e5f8c7083dc1bb55c 100644 (file)
        };
 
        pinctrl@35004800 {
-               compatible = "brcm,capri-pinctrl";
+               compatible = "brcm,bcm11351-pinctrl";
                reg = <0x35004800 0x430>;
        };
 
index 2b76524f4aa74ee475d7e027f24683097ef4770f..187fd46b7b5ef018c2985e7db5298784338f0507 100644 (file)
                                #clock-cells = <1>;
                        };
 
-                       pmu_intc: pmu-interrupt-ctrl@d0050 {
-                               compatible = "marvell,dove-pmu-intc";
-                               interrupt-controller;
-                               #interrupt-cells = <1>;
-                               reg = <0xd0050 0x8>;
-                               interrupts = <33>;
-                               marvell,#interrupts = <7>;
-                       };
-
                        pinctrl: pin-ctrl@d0200 {
                                compatible = "marvell,dove-pinctrl";
                                reg = <0xd0200 0x10>;
                        rtc: real-time-clock@d8500 {
                                compatible = "marvell,orion-rtc";
                                reg = <0xd8500 0x20>;
-                               interrupt-parent = <&pmu_intc>;
-                               interrupts = <5>;
                        };
 
                        gpio2: gpio-ctrl@e8400 {
index fd8fc7cd53f3158bf7e030659a09a0c3ae476edc..5bfae54fb7806f4391a93ab89bdb1dd621358c03 100644 (file)
                };
        };
 
-       codec: spdif-transmitter {
-               compatible = "linux,spdif-dit";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_hummingboard_spdif>;
-       };
-
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
                model = "imx-spdif";
                };
 
                pinctrl_hummingboard_spdif: hummingboard-spdif {
-                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>;
+                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
                };
 
                pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus {
 };
 
 &spdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hummingboard_spdif>;
        status = "okay";
 };
 
index 64daa3b311f6f057e8ecf05ec6f7ea84b9c36ed8..c2a24888a2768969263e1b8536e98ec869b4ff4f 100644 (file)
                };
        };
 
-       codec: spdif-transmitter {
-               compatible = "linux,spdif-dit";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_cubox_i_spdif>;
-       };
-
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
                model = "imx-spdif";
@@ -89,7 +83,7 @@
                };
 
                pinctrl_cubox_i_spdif: cubox-i-spdif {
-                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0>;
+                       fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
                };
 
                pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
 };
 
 &spdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cubox_i_spdif>;
        status = "okay";
 };
 
index 2363593e1050b7b84b4705878fc10cb653b33cca..ef58d1c24313541a068436c5e590378120c6bb3b 100644 (file)
@@ -612,7 +612,7 @@ clocks {
                compatible = "ti,keystone,psc-clock";
                clocks = <&chipclk13>;
                clock-output-names = "vcp-3";
-               reg = <0x0235000a8 0xb00>, <0x02350060 0x400>;
+               reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
                reg-names = "control", "domain";
                domain-id = <24>;
        };
index b9b55c95a566c3ea6f6f21e55b787b9c31c2194f..d3b253bbc8856a9ba0a2f1810c1860f875931462 100644 (file)
@@ -13,7 +13,7 @@
 
 / {
        model = "OMAP3 GTA04";
-       compatible = "ti,omap3-gta04", "ti,omap3";
+       compatible = "ti,omap3-gta04", "ti,omap36xx", "ti,omap3";
 
        cpus {
                cpu@0 {
@@ -32,7 +32,7 @@
                aux-button {
                        label = "aux";
                        linux,code = <169>;
-                       gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+                       gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
                        gpio-key,wakeup;
                };
        };
@@ -92,6 +92,8 @@
        bmp085@77 {
                compatible = "bosch,bmp085";
                reg = <0x77>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <17 IRQ_TYPE_EDGE_RISING>;
        };
 
        /* leds */
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        vmmc-supply = <&vmmc1>;
-       vmmc_aux-supply = <&vsim>;
        bus-width = <4>;
+       ti,non-removable;
 };
 
 &mmc2 {
index 25a2b5f652fd1949ceac364ec8a154436aba05e4..f2779ac75872a4a44e2d03402fab7b6fe1a4b66b 100644 (file)
@@ -14,7 +14,7 @@
 
 / {
        model = "IGEPv2 (TI OMAP AM/DM37x)";
-       compatible = "isee,omap3-igep0020", "ti,omap3";
+       compatible = "isee,omap3-igep0020", "ti,omap36xx", "ti,omap3";
 
        leds {
                pinctrl-names = "default";
index 145c58cfc8ac1d3c322f2a2ad44abac2734bbb30..2793749eb1ba460dcf8736fc964aef7b87b05d1a 100644 (file)
@@ -13,7 +13,7 @@
 
 / {
        model = "IGEP COM MODULE (TI OMAP AM/DM37x)";
-       compatible = "isee,omap3-igep0030", "ti,omap3";
+       compatible = "isee,omap3-igep0030", "ti,omap36xx", "ti,omap3";
 
        leds {
                pinctrl-names = "default";
index 39828ce464ee527b900ff6a2013660fe1c231822..9938b5dc1909c00f01e587f15a4a1c1d2a6bc665 100644 (file)
@@ -14,5 +14,5 @@
 
 / {
        model = "Nokia N9";
-       compatible = "nokia,omap3-n9", "ti,omap3";
+       compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3";
 };
index 6fc85f96353024ad61d04d74d7ca51f8afb1c7ce..0bf40c90faba626c88b539965a1f928aa09bf313 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Pavel Machek <pavel@ucw.cz>
- * Copyright 2013 Aaro Koskinen <aaro.koskinen@iki.fi>
+ * Copyright (C) 2013-2014 Aaro Koskinen <aaro.koskinen@iki.fi>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 (or later) as
@@ -13,7 +13,7 @@
 
 / {
        model = "Nokia N900";
-       compatible = "nokia,omap3-n900", "ti,omap3";
+       compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3";
 
        cpus {
                cpu@0 {
index b076a526b99973a3489bf831e0cec5c1dcff93bb..261c5589bfa3170e76cc8f469ac1d6ca07a02765 100644 (file)
@@ -14,5 +14,5 @@
 
 / {
        model = "Nokia N950";
-       compatible = "nokia,omap3-n950", "ti,omap3";
+       compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3";
 };
diff --git a/arch/arm/boot/dts/omap3-overo-storm-tobi.dts b/arch/arm/boot/dts/omap3-overo-storm-tobi.dts
new file mode 100644 (file)
index 0000000..966b5c9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * 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.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+       model = "OMAP36xx/AM37xx/DM37xx Gumstix Overo on Tobi";
+       compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap36xx", "ti,omap3";
+};
+
diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
new file mode 100644 (file)
index 0000000..4edc013
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * 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.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+#include "omap3-overo.dtsi"
+
+/ {
+       leds {
+               compatible = "gpio-leds";
+               heartbeat {
+                       label = "overo:red:gpio21";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       vddvario: regulator-vddvario {
+                 compatible = "regulator-fixed";
+                 regulator-name = "vddvario";
+                 regulator-always-on;
+       };
+
+       vdd33a: regulator-vdd33a {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd33a";
+               regulator-always-on;
+       };
+};
+
+&gpmc {
+       ranges = <5 0 0x2c000000 0x1000000>;    /* CS5 */
+
+       ethernet@5,0 {
+               compatible = "smsc,lan9221", "smsc,lan9115";
+               reg = <5 0 0xff>;
+               bank-width = <2>;
+
+               gpmc,mux-add-data;
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <42>;
+               gpmc,cs-wr-off-ns = <36>;
+               gpmc,adv-on-ns = <6>;
+               gpmc,adv-rd-off-ns = <12>;
+               gpmc,adv-wr-off-ns = <12>;
+               gpmc,oe-on-ns = <0>;
+               gpmc,oe-off-ns = <42>;
+               gpmc,we-on-ns = <0>;
+               gpmc,we-off-ns = <36>;
+               gpmc,rd-cycle-ns = <60>;
+               gpmc,wr-cycle-ns = <54>;
+               gpmc,access-ns = <36>;
+               gpmc,page-burst-access-ns = <0>;
+               gpmc,bus-turnaround-ns = <0>;
+               gpmc,cycle2cycle-delay-ns = <0>;
+               gpmc,wr-data-mux-bus-ns = <18>;
+               gpmc,wr-access-ns = <42>;
+               gpmc,cycle2cycle-samecsen;
+               gpmc,cycle2cycle-diffcsen;
+
+               interrupt-parent = <&gpio6>;
+               interrupts = <16 IRQ_TYPE_LEVEL_LOW>;   /* GPIO 176 */
+               reg-io-width = <4>;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+};
+
+&mmc3 {
+       status = "disabled";
+};
diff --git a/arch/arm/boot/dts/omap3-overo-tobi.dts b/arch/arm/boot/dts/omap3-overo-tobi.dts
new file mode 100644 (file)
index 0000000..de5653e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
+ *
+ * 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.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+#include "omap3-overo-tobi-common.dtsi"
+
+/ {
+       model = "OMAP35xx Gumstix Overo on Tobi";
+       compatible = "gumstix,omap3-overo-tobi", "gumstix,omap3-overo", "ti,omap3430", "ti,omap3";
+};
+
index a461d2fd1fb0e81862805ccec939e1c1b3a41244..597099907f8ef77423210bcf6cb2be26f8799eb5 100644 (file)
@@ -9,9 +9,6 @@
 /*
  * The Gumstix Overo must be combined with an expansion board.
  */
-/dts-v1/;
-
-#include "omap34xx.dtsi"
 
 / {
        pwmleds {
diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts
deleted file mode 100644 (file)
index 7e4ad2a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2012 Florian Vaussard, EPFL Mobots group
- *
- * 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.
- */
-
-/*
- * Tobi expansion board is manufactured by Gumstix Inc.
- */
-
-#include "omap3-overo.dtsi"
-
-/ {
-       model = "TI OMAP3 Gumstix Overo on Tobi";
-       compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3";
-
-       leds {
-               compatible = "gpio-leds";
-               heartbeat {
-                       label = "overo:red:gpio21";
-                       gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "heartbeat";
-               };
-       };
-
-       vddvario: regulator-vddvario {
-                 compatible = "regulator-fixed";
-                 regulator-name = "vddvario";
-                 regulator-always-on;
-       };
-
-       vdd33a: regulator-vdd33a {
-               compatible = "regulator-fixed";
-               regulator-name = "vdd33a";
-               regulator-always-on;
-       };
-};
-
-&gpmc {
-       ranges = <5 0 0x2c000000 0x1000000>;    /* CS5 */
-
-       ethernet@5,0 {
-               compatible = "smsc,lan9221", "smsc,lan9115";
-               reg = <5 0 0xff>;
-               bank-width = <2>;
-
-               gpmc,mux-add-data;
-               gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <42>;
-               gpmc,cs-wr-off-ns = <36>;
-               gpmc,adv-on-ns = <6>;
-               gpmc,adv-rd-off-ns = <12>;
-               gpmc,adv-wr-off-ns = <12>;
-               gpmc,oe-on-ns = <0>;
-               gpmc,oe-off-ns = <42>;
-               gpmc,we-on-ns = <0>;
-               gpmc,we-off-ns = <36>;
-               gpmc,rd-cycle-ns = <60>;
-               gpmc,wr-cycle-ns = <54>;
-               gpmc,access-ns = <36>;
-               gpmc,page-burst-access-ns = <0>;
-               gpmc,bus-turnaround-ns = <0>;
-               gpmc,cycle2cycle-delay-ns = <0>;
-               gpmc,wr-data-mux-bus-ns = <18>;
-               gpmc,wr-access-ns = <42>;
-               gpmc,cycle2cycle-samecsen;
-               gpmc,cycle2cycle-diffcsen;
-
-               interrupt-parent = <&gpio6>;
-               interrupts = <16 IRQ_TYPE_LEVEL_LOW>;   /* GPIO 176 */
-               reg-io-width = <4>;
-       };
-};
-
-&i2c3 {
-       clock-frequency = <100000>;
-};
-
-&mmc3 {
-       status = "disabled";
-};
index 52447c17537a17c6035bf33694909e7252b78733..3d5faf85f51be4c283451b263e22450650019d7c 100644 (file)
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00600000 0x100000>;
                        interrupts = <32 IRQ_TYPE_LEVEL_HIGH 2>;
-                       clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>,
+                       clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>,
                                 <&uhpck>;
                        clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
                        status = "disabled";
index 6c31c26e6cc09511b9e4cd11b12dc946ecea8aeb..db58cad6acd32633b88bf88a0589885bfa58ed9b 100644 (file)
@@ -8,8 +8,8 @@
  */
 #include "sama5d3.dtsi"
 #include "sama5d3_can.dtsi"
-#include "sama5d3_emac.dtsi"
 #include "sama5d3_gmac.dtsi"
+#include "sama5d3_emac.dtsi"
 #include "sama5d3_lcd.dtsi"
 #include "sama5d3_mci2.dtsi"
 #include "sama5d3_tcb1.dtsi"
index 0c1e8d871ed1a45662198501fb133aa29bf46af0..6cb9b68e2188a59fecb89e750023551a17c0334f 100644 (file)
                msp2: msp@80117000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&msp2_default_mode>;
-                       status = "okay";
                };
 
                msp3: msp@80125000 {
index dd64cc0dbef38f6707d59b7230fcf69ffed6a6eb..2ce61228d5f9def1ca42f4d427f3b148786e038b 100644 (file)
                ranges;
 
                emac: ethernet@01c0b000 {
-                       compatible = "allwinner,sun4i-emac";
+                       compatible = "allwinner,sun4i-a10-emac";
                        reg = <0x01c0b000 0x1000>;
                        interrupts = <55>;
                        clocks = <&ahb_gates 17>;
                };
 
                mdio@01c0b080 {
-                       compatible = "allwinner,sun4i-mdio";
+                       compatible = "allwinner,sun4i-a10-mdio";
                        reg = <0x01c0b080 0x14>;
                        status = "disabled";
                        #address-cells = <1>;
                };
 
                rtp: rtp@01c25000 {
-                       compatible = "allwinner,sun4i-ts";
+                       compatible = "allwinner,sun4i-a10-ts";
                        reg = <0x01c25000 0x100>;
                        interrupts = <29>;
                };
index 9cee110bd8941555e24fd837772333d1cc825835..29dd32d8e77e399789d62952501aaae19a216c6a 100644 (file)
                ranges;
 
                emac: ethernet@01c0b000 {
-                       compatible = "allwinner,sun4i-emac";
+                       compatible = "allwinner,sun4i-a10-emac";
                        reg = <0x01c0b000 0x1000>;
                        interrupts = <55>;
                        clocks = <&ahb_gates 17>;
                };
 
                mdio@01c0b080 {
-                       compatible = "allwinner,sun4i-mdio";
+                       compatible = "allwinner,sun4i-a10-mdio";
                        reg = <0x01c0b080 0x14>;
                        status = "disabled";
                        #address-cells = <1>;
                };
 
                rtp: rtp@01c25000 {
-                       compatible = "allwinner,sun4i-ts";
+                       compatible = "allwinner,sun4i-a10-ts";
                        reg = <0x01c25000 0x100>;
                        interrupts = <29>;
                };
index f5cba632fd95b59ac2da4be81aacf60875420a6f..e63bb383b43df6cf31251627cd0059a8ea2d233f 100644 (file)
                };
 
                rtp: rtp@01c25000 {
-                       compatible = "allwinner,sun4i-ts";
+                       compatible = "allwinner,sun4i-a10-ts";
                        reg = <0x01c25000 0x100>;
                        interrupts = <29>;
                };
index 4bc5c6f4cadaafa887d070e875a9d2da1037e67c..dddc8ac2d52290086437ac12aea2441a7fc4921a 100644 (file)
                ranges;
 
                emac: ethernet@01c0b000 {
-                       compatible = "allwinner,sun4i-emac";
+                       compatible = "allwinner,sun4i-a10-emac";
                        reg = <0x01c0b000 0x1000>;
                        interrupts = <0 55 4>;
                        clocks = <&ahb_gates 17>;
                };
 
                mdio@01c0b080 {
-                       compatible = "allwinner,sun4i-mdio";
+                       compatible = "allwinner,sun4i-a10-mdio";
                        reg = <0x01c0b080 0x14>;
                        status = "disabled";
                        #address-cells = <1>;
                rtc: rtc@01c20d00 {
                        compatible = "allwinner,sun7i-a20-rtc";
                        reg = <0x01c20d00 0x20>;
-                       interrupts = <0 24 1>;
+                       interrupts = <0 24 4>;
                };
 
                sid: eeprom@01c23800 {
                };
 
                rtp: rtp@01c25000 {
-                       compatible = "allwinner,sun4i-ts";
+                       compatible = "allwinner,sun4i-a10-ts";
                        reg = <0x01c25000 0x100>;
                        interrupts = <0 29 4>;
                };
                hstimer@01c60000 {
                        compatible = "allwinner,sun7i-a20-hstimer";
                        reg = <0x01c60000 0x1000>;
-                       interrupts = <0 81 1>,
-                                    <0 82 1>,
-                                    <0 83 1>,
-                                    <0 84 1>;
+                       interrupts = <0 81 4>,
+                                    <0 82 4>,
+                                    <0 83 4>,
+                                    <0 84 4>;
                        clocks = <&ahb_gates 28>;
                };
 
index 389e987ec2819e31725329102f84d6f3cecbb5cd..44ec401ec36682289d8e4afa3b9b87791cd82c73 100644 (file)
@@ -57,6 +57,8 @@
                        resets = <&tegra_car 27>;
                        reset-names = "dc";
 
+                       nvidia,head = <0>;
+
                        rgb {
                                status = "disabled";
                        };
@@ -72,6 +74,8 @@
                        resets = <&tegra_car 26>;
                        reset-names = "dc";
 
+                       nvidia,head = <1>;
+
                        rgb {
                                status = "disabled";
                        };
index 480ecda3416b841b8941105d24646f1240f5ab37..48d2a7f4d0c05e2808a5cb2150298c41c1aa3367 100644 (file)
@@ -94,6 +94,8 @@
                        resets = <&tegra_car 27>;
                        reset-names = "dc";
 
+                       nvidia,head = <0>;
+
                        rgb {
                                status = "disabled";
                        };
                        resets = <&tegra_car 26>;
                        reset-names = "dc";
 
+                       nvidia,head = <1>;
+
                        rgb {
                                status = "disabled";
                        };
index 9104224124eeaac83bcedbd0e2fb7bcb3887d631..1e156d9d0506085c4ea615ac8c7e06193573edcb 100644 (file)
@@ -28,7 +28,7 @@
        compatible = "nvidia,cardhu", "nvidia,tegra30";
 
        aliases {
-               rtc0 = "/i2c@7000d000/tps6586x@34";
+               rtc0 = "/i2c@7000d000/tps65911@2d";
                rtc1 = "/rtc@7000e000";
        };
 
index ed8e7700b46dac0ba9d5ba34754fb5f8ae3dd976..19a84e933f4eae0799fc194b386bfdc51b85b880 100644 (file)
                        resets = <&tegra_car 27>;
                        reset-names = "dc";
 
+                       nvidia,head = <0>;
+
                        rgb {
                                status = "disabled";
                        };
                        resets = <&tegra_car 26>;
                        reset-names = "dc";
 
+                       nvidia,head = <1>;
+
                        rgb {
                                status = "disabled";
                        };
diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
deleted file mode 100644 (file)
index c843720..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-
-/ {
-       testcase-data {
-               interrupts {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       test_intc0: intc0 {
-                               interrupt-controller;
-                               #interrupt-cells = <1>;
-                       };
-
-                       test_intc1: intc1 {
-                               interrupt-controller;
-                               #interrupt-cells = <3>;
-                       };
-
-                       test_intc2: intc2 {
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
-
-                       test_intmap0: intmap0 {
-                               #interrupt-cells = <1>;
-                               #address-cells = <0>;
-                               interrupt-map = <1 &test_intc0 9>,
-                                               <2 &test_intc1 10 11 12>,
-                                               <3 &test_intc2 13 14>,
-                                               <4 &test_intc2 15 16>;
-                       };
-
-                       test_intmap1: intmap1 {
-                               #interrupt-cells = <2>;
-                               interrupt-map = <0x5000 1 2 &test_intc0 15>;
-                       };
-
-                       interrupts0 {
-                               interrupt-parent = <&test_intc0>;
-                               interrupts = <1>, <2>, <3>, <4>;
-                       };
-
-                       interrupts1 {
-                               interrupt-parent = <&test_intmap0>;
-                               interrupts = <1>, <2>, <3>, <4>;
-                       };
-
-                       interrupts-extended0 {
-                               reg = <0x5000 0x100>;
-                               interrupts-extended = <&test_intc0 1>,
-                                                     <&test_intc1 2 3 4>,
-                                                     <&test_intc2 5 6>,
-                                                     <&test_intmap0 1>,
-                                                     <&test_intmap0 2>,
-                                                     <&test_intmap0 3>,
-                                                     <&test_intmap1 1 2>;
-                       };
-               };
-       };
-};
diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi
deleted file mode 100644 (file)
index 0007d3c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-
-/ {
-       testcase-data {
-               phandle-tests {
-                       provider0: provider0 {
-                               #phandle-cells = <0>;
-                       };
-
-                       provider1: provider1 {
-                               #phandle-cells = <1>;
-                       };
-
-                       provider2: provider2 {
-                               #phandle-cells = <2>;
-                       };
-
-                       provider3: provider3 {
-                               #phandle-cells = <3>;
-                       };
-
-                       consumer-a {
-                               phandle-list =  <&provider1 1>,
-                                               <&provider2 2 0>,
-                                               <0>,
-                                               <&provider3 4 4 3>,
-                                               <&provider2 5 100>,
-                                               <&provider0>,
-                                               <&provider1 7>;
-                               phandle-list-names = "first", "second", "third";
-
-                               phandle-list-bad-phandle = <12345678 0 0>;
-                               phandle-list-bad-args = <&provider2 1 0>,
-                                                       <&provider3 0>;
-                               empty-property;
-                               unterminated-string = [40 41 42 43];
-                       };
-               };
-       };
-};
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
deleted file mode 100644 (file)
index 3f123ec..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/include/ "tests-phandle.dtsi"
-/include/ "tests-interrupts.dtsi"
index f43907c40c93a8cb9b101d72043fc48621e0f795..65f6577113235749c3635dc30d321fa3c775b1c0 100644 (file)
@@ -1,4 +1,4 @@
-/include/ "versatile-ab.dts"
+#include <versatile-ab.dts>
 
 / {
        model = "ARM Versatile PB";
@@ -47,4 +47,4 @@
        };
 };
 
-/include/ "testcases/tests.dtsi"
+#include <testcases.dtsi>
index 845bc745706b53ff616dacf908679c9435113e8d..ee6982976d661d0086ff9886851ec9948e4ee909 100644 (file)
@@ -29,6 +29,7 @@ CONFIG_ARCH_OMAP3=y
 CONFIG_ARCH_OMAP4=y
 CONFIG_SOC_OMAP5=y
 CONFIG_SOC_AM33XX=y
+CONFIG_SOC_DRA7XX=y
 CONFIG_SOC_AM43XX=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SOCFPGA=y
index 00fe9e9710fd77e4a11c4c9c8c6c03534d5e6690..27d69b558c5de2caf1be2b9ac79388ae997f562a 100644 (file)
@@ -204,7 +204,10 @@ CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_ONESHOT=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
index 3278afe2c3ab9014e2ed80904e5e6e98508e14f7..23e728ecf8ab3707403c811b6b43baead7198380 100644 (file)
@@ -7,16 +7,19 @@ generic-y += current.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += msgbuf.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += poll.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += sections.h
 generic-y += segment.h
@@ -33,5 +36,3 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
-generic-y += preempt.h
-generic-y += hash.h
index e9a49fe0284e41c2f6d6d9448fb73e9a2ad99ead..8b8b61685a3436158923b30cc80106364e02d509 100644 (file)
@@ -212,6 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 static inline void __flush_icache_all(void)
 {
        __flush_icache_preferred();
+       dsb();
 }
 
 /*
index 8756e4bcdba0609ff789a4f1efaa551faa39ed98..4afb376d9c7c13d07ea81502e17ba53f0554c122 100644 (file)
  */
 #define UL(x) _AC(x, UL)
 
+/* PAGE_OFFSET - the virtual address of the start of the kernel image */
+#define PAGE_OFFSET            UL(CONFIG_PAGE_OFFSET)
+
 #ifdef CONFIG_MMU
 
 /*
- * PAGE_OFFSET - the virtual address of the start of the kernel image
  * TASK_SIZE - the maximum size of a user space task.
  * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
  */
-#define PAGE_OFFSET            UL(CONFIG_PAGE_OFFSET)
 #define TASK_SIZE              (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M))
 #define TASK_UNMAPPED_BASE     ALIGN(TASK_SIZE / 3, SZ_16M)
 
 #define END_MEM                (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
 #endif
 
-#ifndef PAGE_OFFSET
-#define PAGE_OFFSET            PLAT_PHYS_OFFSET
-#endif
-
 /*
  * The module can be at any place in ram in nommu mode.
  */
index 03243f7eeddfc57beebb8100132dae059f96af77..85c60adc8b60bd04a68c3012b0c22ec7c1bf9bba 100644 (file)
 /*
  * 2nd stage PTE definitions for LPAE.
  */
-#define L_PTE_S2_MT_UNCACHED    (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITEBACK   (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_RDONLY                 (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
-#define L_PTE_S2_RDWR           (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_MT_UNCACHED           (_AT(pteval_t, 0x0) << 2) /* strongly ordered */
+#define L_PTE_S2_MT_WRITETHROUGH       (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */
+#define L_PTE_S2_MT_WRITEBACK          (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */
+#define L_PTE_S2_MT_DEV_SHARED         (_AT(pteval_t, 0x1) << 2) /* device */
+#define L_PTE_S2_MT_MASK               (_AT(pteval_t, 0xf) << 2)
 
-#define L_PMD_S2_RDWR           (_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
+#define L_PTE_S2_RDONLY                        (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
+#define L_PTE_S2_RDWR                  (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
+
+#define L_PMD_S2_RDWR                  (_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
 
 /*
  * Hyp-mode PL2 PTE definitions for LPAE.
index ef3c6072aa45345ae4594f22aebbe9a9ebc538f1..ac4bfae26702b0be3333c1184f1ac552f6c0eddd 100644 (file)
 
 static inline void dsb_sev(void)
 {
-#if __LINUX_ARM_ARCH__ >= 7
-       __asm__ __volatile__ (
-               "dsb ishst\n"
-               SEV
-       );
-#else
-       __asm__ __volatile__ (
-               "mcr p15, 0, %0, c7, c10, 4\n"
-               SEV
-               : : "r" (0)
-       );
-#endif
+
+       dsb(ishst);
+       __asm__(SEV);
 }
 
 /*
index 58b8b84adcd2cf5f295e6869b68350f9dcadc798..2fe85fff5ccacd3dfe67d72c4b6fd5d65342e5e9 100644 (file)
@@ -20,9 +20,6 @@ extern struct cputopo_arm cpu_topology[NR_CPUS];
 #define topology_core_cpumask(cpu)     (&cpu_topology[cpu].core_sibling)
 #define topology_thread_cpumask(cpu)   (&cpu_topology[cpu].thread_sibling)
 
-#define mc_capable()   (cpu_topology[0].socket_id != -1)
-#define smt_capable()  (cpu_topology[0].thread_id != -1)
-
 void init_cpu_topology(void);
 void store_cpu_topology(unsigned int cpuid);
 const struct cpumask *cpu_coregroup_mask(int cpu);
index 47cd974e57ea3ca0de7e9feccd9e527c2ba39f1f..c96ecacb2021222936844a4807f39ef474965879 100644 (file)
@@ -177,6 +177,18 @@ __lookup_processor_type_data:
        .long   __proc_info_end
        .size   __lookup_processor_type_data, . - __lookup_processor_type_data
 
+__error_lpae:
+#ifdef CONFIG_DEBUG_LL
+       adr     r0, str_lpae
+       bl      printascii
+       b       __error
+str_lpae: .asciz "\nError: Kernel with LPAE support, but CPU does not support LPAE.\n"
+#else
+       b       __error
+#endif
+       .align
+ENDPROC(__error_lpae)
+
 __error_p:
 #ifdef CONFIG_DEBUG_LL
        adr     r0, str_p1
index 914616e0bdcd0c0108376a9e5834e9cb73219b51..f5f381d915560818dcf0d2200731a90b0c7ae404 100644 (file)
@@ -102,7 +102,7 @@ ENTRY(stext)
        and     r3, r3, #0xf                    @ extract VMSA support
        cmp     r3, #5                          @ long-descriptor translation table format?
  THUMB( it     lo )                            @ force fixup-able long branch encoding
-       blo     __error_p                       @ only classic page table format
+       blo     __error_lpae                    @ only classic page table format
 #endif
 
 #ifndef CONFIG_XIP_KERNEL
index 92f7b15dd22121d4aa674fd78cd95cac8924c07f..adabeababeb03d5fc34efe76fa5c12d4eab90a5d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/uaccess.h>
 #include <linux/random.h>
 #include <linux/hw_breakpoint.h>
-#include <linux/cpuidle.h>
 #include <linux/leds.h>
 #include <linux/reboot.h>
 
@@ -133,7 +132,11 @@ EXPORT_SYMBOL_GPL(arm_pm_restart);
 
 void (*arm_pm_idle)(void);
 
-static void default_idle(void)
+/*
+ * Called from the core idle loop.
+ */
+
+void arch_cpu_idle(void)
 {
        if (arm_pm_idle)
                arm_pm_idle();
@@ -167,15 +170,6 @@ void arch_cpu_idle_dead(void)
 }
 #endif
 
-/*
- * Called from the core idle loop.
- */
-void arch_cpu_idle(void)
-{
-       if (cpuidle_idle_call())
-               default_idle();
-}
-
 /*
  * Called by kexec, immediately prior to machine_kexec().
  *
index b0df9761de6dc1109f727e0300ff91448f8fd55b..1e8b030dbefd8b2b19da27d9ca8ecabfaf610bba 100644 (file)
@@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
        kernel_data.end     = virt_to_phys(_end - 1);
 
        for_each_memblock(memory, region) {
-               res = memblock_virt_alloc_low(sizeof(*res), 0);
+               res = memblock_virt_alloc(sizeof(*res), 0);
                res->name  = "System RAM";
                res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
                res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
index 1d8248ea5669fa81209b2a7a8a055b7855a8c1f3..bd18bb8b2770ced6a65e5b3ad50dd79963d49c3b 100644 (file)
@@ -878,7 +878,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
                                    unsigned long cmd,
                                    void *v)
 {
-       if (cmd == CPU_PM_EXIT) {
+       if (cmd == CPU_PM_EXIT &&
+           __hyp_get_vectors() == hyp_default_vectors) {
                cpu_init_hyp_mode(NULL);
                return NOTIFY_OK;
        }
index ddc15539bad2c5996dcd5167e694b16dbdd9488b..0d68d4073068e8ad665840b8f51319e9b2bdbd89 100644 (file)
@@ -220,6 +220,10 @@ after_vfp_restore:
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
  * passed in r0 and r1.
  *
+ * A function pointer with a value of 0xffffffff has a special meaning,
+ * and is used to implement __hyp_get_vectors in the same way as in
+ * arch/arm/kernel/hyp_stub.S.
+ *
  * The calling convention follows the standard AAPCS:
  *   r0 - r3: caller save
  *   r12:     caller save
@@ -363,6 +367,11 @@ hyp_hvc:
 host_switch_to_hyp:
        pop     {r0, r1, r2}
 
+       /* Check for __hyp_get_vectors */
+       cmp     r0, #-1
+       mrceq   p15, 4, r0, c12, c0, 0  @ get HVBAR
+       beq     1f
+
        push    {lr}
        mrs     lr, SPSR
        push    {lr}
@@ -378,7 +387,7 @@ THUMB(      orr     lr, #1)
        pop     {lr}
        msr     SPSR_csxf, lr
        pop     {lr}
-       eret
+1:     eret
 
 guest_trap:
        load_vcpu                       @ Load VCPU pointer to r0
index 2ab00434b2eb64405a2c4b75f315950cbe9663c0..85399c98f84a7f30657ecc57beb267d404593560 100644 (file)
@@ -472,7 +472,7 @@ static struct clk_lookup da850_clks[] = {
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
        CLK("spi_davinci.1",    NULL,           &spi1_clk),
        CLK("vpif",             NULL,           &vpif_clk),
-       CLK("ahci",             NULL,           &sata_clk),
+       CLK("ahci_da850",               NULL,           &sata_clk),
        CLK("davinci-rproc.0",  NULL,           &dsp_clk),
        CLK("ehrpwm",           "fck",          &ehrpwm_clk),
        CLK("ehrpwm",           "tbclk",        &ehrpwm_tbclk),
index 0486cdf28c8d552205ff4285fe7d7476721cc2a6..56ea41d5f8491307ab89b3178365071cec34ee3d 100644 (file)
@@ -1020,111 +1020,29 @@ int __init da8xx_register_spi_bus(int instance, unsigned num_chipselect)
 }
 
 #ifdef CONFIG_ARCH_DAVINCI_DA850
-
 static struct resource da850_sata_resources[] = {
        {
                .start  = DA850_SATA_BASE,
                .end    = DA850_SATA_BASE + 0x1fff,
                .flags  = IORESOURCE_MEM,
        },
+       {
+               .start  = DA8XX_SYSCFG1_BASE + DA8XX_PWRDN_REG,
+               .end    = DA8XX_SYSCFG1_BASE + DA8XX_PWRDN_REG + 0x3,
+               .flags  = IORESOURCE_MEM,
+       },
        {
                .start  = IRQ_DA850_SATAINT,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
-/* SATA PHY Control Register offset from AHCI base */
-#define SATA_P0PHYCR_REG       0x178
-
-#define SATA_PHY_MPY(x)                ((x) << 0)
-#define SATA_PHY_LOS(x)                ((x) << 6)
-#define SATA_PHY_RXCDR(x)      ((x) << 10)
-#define SATA_PHY_RXEQ(x)       ((x) << 13)
-#define SATA_PHY_TXSWING(x)    ((x) << 19)
-#define SATA_PHY_ENPLL(x)      ((x) << 31)
-
-static struct clk *da850_sata_clk;
-static unsigned long da850_sata_refclkpn;
-
-/* Supported DA850 SATA crystal frequencies */
-#define KHZ_TO_HZ(freq) ((freq) * 1000)
-static unsigned long da850_sata_xtal[] = {
-       KHZ_TO_HZ(300000),
-       KHZ_TO_HZ(250000),
-       0,                      /* Reserved */
-       KHZ_TO_HZ(187500),
-       KHZ_TO_HZ(150000),
-       KHZ_TO_HZ(125000),
-       KHZ_TO_HZ(120000),
-       KHZ_TO_HZ(100000),
-       KHZ_TO_HZ(75000),
-       KHZ_TO_HZ(60000),
-};
-
-static int da850_sata_init(struct device *dev, void __iomem *addr)
-{
-       int i, ret;
-       unsigned int val;
-
-       da850_sata_clk = clk_get(dev, NULL);
-       if (IS_ERR(da850_sata_clk))
-               return PTR_ERR(da850_sata_clk);
-
-       ret = clk_prepare_enable(da850_sata_clk);
-       if (ret)
-               goto err0;
-
-       /* Enable SATA clock receiver */
-       val = __raw_readl(DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
-       val &= ~BIT(0);
-       __raw_writel(val, DA8XX_SYSCFG1_VIRT(DA8XX_PWRDN_REG));
-
-       /* Get the multiplier needed for 1.5GHz PLL output */
-       for (i = 0; i < ARRAY_SIZE(da850_sata_xtal); i++)
-               if (da850_sata_xtal[i] == da850_sata_refclkpn)
-                       break;
-
-       if (i == ARRAY_SIZE(da850_sata_xtal)) {
-               ret = -EINVAL;
-               goto err1;
-       }
-
-       val = SATA_PHY_MPY(i + 1) |
-               SATA_PHY_LOS(1) |
-               SATA_PHY_RXCDR(4) |
-               SATA_PHY_RXEQ(1) |
-               SATA_PHY_TXSWING(3) |
-               SATA_PHY_ENPLL(1);
-
-       __raw_writel(val, addr + SATA_P0PHYCR_REG);
-
-       return 0;
-
-err1:
-       clk_disable_unprepare(da850_sata_clk);
-err0:
-       clk_put(da850_sata_clk);
-       return ret;
-}
-
-static void da850_sata_exit(struct device *dev)
-{
-       clk_disable_unprepare(da850_sata_clk);
-       clk_put(da850_sata_clk);
-}
-
-static struct ahci_platform_data da850_sata_pdata = {
-       .init   = da850_sata_init,
-       .exit   = da850_sata_exit,
-};
-
 static u64 da850_sata_dmamask = DMA_BIT_MASK(32);
 
 static struct platform_device da850_sata_device = {
-       .name   = "ahci",
+       .name   = "ahci_da850",
        .id     = -1,
        .dev    = {
-               .platform_data          = &da850_sata_pdata,
                .dma_mask               = &da850_sata_dmamask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
@@ -1134,9 +1052,8 @@ static struct platform_device da850_sata_device = {
 
 int __init da850_register_sata(unsigned long refclkpn)
 {
-       da850_sata_refclkpn = refclkpn;
-       if (!da850_sata_refclkpn)
-               return -EINVAL;
+       /* please see comment in drivers/ata/ahci_da850.c */
+       BUG_ON(refclkpn != 100 * 1000 * 1000);
 
        return platform_device_register(&da850_sata_device);
 }
index 8f4649b301b2b8edba6f03e190719a967b883657..1abae5f6a4181013a83e286d8ec9b1518179ce39 100644 (file)
@@ -8,7 +8,7 @@ config ARCH_HI3xxx
        select CLKSRC_OF
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU
-       select HAVE_ARM_TWD
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select PINCTRL
        select PINCTRL_SINGLE
index befcaf5d05740c4ad1a417d8be62ddae9a38f59a..ec419649320ffe8fd6cae929d4664ae8071c9fff 100644 (file)
@@ -101,11 +101,9 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 
-ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
 # i.MX6SL reuses i.MX6Q code
 obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o
-endif
 
 # i.MX5 based machines
 obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
index af2e582d2b7427e1ffa72b65fb3b90bcdb257c3a..4d677f4425399c03c07827c7fca39719ca00620c 100644 (file)
@@ -482,6 +482,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        if (IS_ENABLED(CONFIG_PCI_IMX6))
                clk_set_parent(clk[lvds1_sel], clk[sata_ref]);
 
+       /* Set initial power mode */
+       imx6q_set_lpm(WAIT_CLOCKED);
+
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
        base = of_iomap(np, 0);
        WARN_ON(!base);
index 3781a1853998c30520961cde9c27dd02e8068267..4c86f303520573d544528c983cade541135e71a2 100644 (file)
@@ -266,6 +266,9 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
        /* Audio-related clocks configuration */
        clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]);
 
+       /* Set initial power mode */
+       imx6q_set_lpm(WAIT_CLOCKED);
+
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt");
        base = of_iomap(np, 0);
        WARN_ON(!base);
index 59c3b9b26bb40bbabe40f471d6a420efee43a1c2..baf439dc22d8268d65bd269f508c968aae822046 100644 (file)
@@ -144,13 +144,11 @@ void imx6q_set_chicken_bit(void);
 void imx_cpu_die(unsigned int cpu);
 int imx_cpu_kill(unsigned int cpu);
 
-#ifdef CONFIG_PM
 void imx6q_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
+#ifdef CONFIG_PM
 void imx5_pm_init(void);
 #else
-static inline void imx6q_pm_init(void) {}
-static inline void imx6q_pm_set_ccm_base(void __iomem *base) {}
 static inline void imx5_pm_init(void) {}
 #endif
 
index 9d47adc078aa76cac2262063dfc94d3d54a6966b..7a9b98589db7260ea0c56deca6872b3667158c2a 100644 (file)
@@ -236,8 +236,6 @@ void __init imx6q_pm_init(void)
                regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
                                   IMX6Q_GPR1_GINT);
 
-       /* Set initial power mode */
-       imx6q_set_lpm(WAIT_CLOCKED);
 
        suspend_set_ops(&imx6q_pm_ops);
 }
index ba470d64493bc18abf610f765259409df92d08bf..3795ae28a6134637cf06226d2b50629ff5ad586c 100644 (file)
@@ -2,7 +2,6 @@ config ARCH_MOXART
        bool "MOXA ART SoC" if ARCH_MULTI_V4T
        select CPU_FA526
        select ARM_DMA_MEM_BUFFERABLE
-       select DMA_OF
        select USE_OF
        select CLKSRC_OF
        select CLKSRC_MMIO
index 91449c5cb70f46affaf85602ec8f98b6f393d10f..85089d821982193b2e2d79f5f5fbf050eefad464 100644 (file)
@@ -156,6 +156,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = {
        .register_dev   = 1,
        .hmc_mode       = 16,
        .pins[0]        = 6,
+       .extcon         = "tahvo-usb",
 };
 
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
index 653b489479e0ee2d4166d6d033d315a1e56430e4..0af7ca02314d99aa72baefb69959ccfba3380758 100644 (file)
@@ -50,11 +50,12 @@ config SOC_OMAP5
        bool "TI OMAP5"
        depends on ARCH_MULTI_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select CPU_V7
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select HAVE_ARM_ARCH_TIMER
        select ARM_ERRATA_798181 if SMP
@@ -63,6 +64,7 @@ config SOC_AM33XX
        bool "TI AM33XX"
        depends on ARCH_MULTI_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select CPU_V7
        select MULTI_IRQ_HANDLER
@@ -72,6 +74,7 @@ config SOC_AM43XX
        depends on ARCH_MULTI_V7
        select CPU_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select MULTI_IRQ_HANDLER
        select ARM_GIC
        select MACH_OMAP_GENERIC
@@ -80,6 +83,7 @@ config SOC_DRA7XX
        bool "TI DRA7XX"
        depends on ARCH_MULTI_V7
        select ARCH_OMAP2PLUS
+       select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select CPU_V7
@@ -268,9 +272,6 @@ config MACH_OMAP_3430SDP
        default y
        select OMAP_PACKAGE_CBB
 
-config MACH_NOKIA_N800
-       bool
-
 config MACH_NOKIA_N810
        bool
 
@@ -281,7 +282,6 @@ config MACH_NOKIA_N8X0
        bool "Nokia N800/N810"
        depends on SOC_OMAP2420
        default y
-       select MACH_NOKIA_N800
        select MACH_NOKIA_N810
        select MACH_NOKIA_N810_WIMAX
        select OMAP_PACKAGE_ZAC
index 3b05aea56d1f5636d5ff2e154513cf22349b3eec..11ed9152e665274793ee83f50881efc2d9fbdded 100644 (file)
@@ -433,7 +433,9 @@ static const struct clk_ops dpll4_m5x2_ck_ops = {
        .enable         = &omap2_dflt_clk_enable,
        .disable        = &omap2_dflt_clk_disable,
        .is_enabled     = &omap2_dflt_clk_is_enabled,
+       .set_rate       = &omap3_clkoutx2_set_rate,
        .recalc_rate    = &omap3_clkoutx2_recalc,
+       .round_rate     = &omap3_clkoutx2_round_rate,
 };
 
 static const struct clk_ops dpll4_m5x2_ck_3630_ops = {
index 4c158c838d4062e1eaee78ff770e4b9dc257146f..01fc710c81818e9d48e2b26ca8742b77b392ff1c 100644 (file)
@@ -23,6 +23,8 @@
 #include "prm.h"
 #include "clockdomain.h"
 
+#define MAX_CPUS       2
+
 /* Machine specific information */
 struct idle_statedata {
        u32 cpu_state;
@@ -48,11 +50,11 @@ static struct idle_statedata omap4_idle_data[] = {
        },
 };
 
-static struct powerdomain *mpu_pd, *cpu_pd[NR_CPUS];
-static struct clockdomain *cpu_clkdm[NR_CPUS];
+static struct powerdomain *mpu_pd, *cpu_pd[MAX_CPUS];
+static struct clockdomain *cpu_clkdm[MAX_CPUS];
 
 static atomic_t abort_barrier;
-static bool cpu_done[NR_CPUS];
+static bool cpu_done[MAX_CPUS];
 static struct idle_statedata *state_ptr = &omap4_idle_data[0];
 
 /* Private functions */
index 3185ced807c952804d50199fd3ff7bc8ea68fb8f..3c418ea54bbe1a483ddc37759f0580ca7c949dd5 100644 (file)
@@ -623,6 +623,32 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 
 /* Clock control for DPLL outputs */
 
+/* Find the parent DPLL for the given clkoutx2 clock */
+static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
+{
+       struct clk_hw_omap *pclk = NULL;
+       struct clk *parent;
+
+       /* Walk up the parents of clk, looking for a DPLL */
+       do {
+               do {
+                       parent = __clk_get_parent(hw->clk);
+                       hw = __clk_get_hw(parent);
+               } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
+               if (!hw)
+                       break;
+               pclk = to_clk_hw_omap(hw);
+       } while (pclk && !pclk->dpll_data);
+
+       /* clk does not have a DPLL as a parent?  error in the clock data */
+       if (!pclk) {
+               WARN_ON(1);
+               return NULL;
+       }
+
+       return pclk;
+}
+
 /**
  * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
  * @clk: DPLL output struct clk
@@ -637,27 +663,14 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
        unsigned long rate;
        u32 v;
        struct clk_hw_omap *pclk = NULL;
-       struct clk *parent;
 
        if (!parent_rate)
                return 0;
 
-       /* Walk up the parents of clk, looking for a DPLL */
-       do {
-               do {
-                       parent = __clk_get_parent(hw->clk);
-                       hw = __clk_get_hw(parent);
-               } while (hw && (__clk_get_flags(hw->clk) & CLK_IS_BASIC));
-               if (!hw)
-                       break;
-               pclk = to_clk_hw_omap(hw);
-       } while (pclk && !pclk->dpll_data);
+       pclk = omap3_find_clkoutx2_dpll(hw);
 
-       /* clk does not have a DPLL as a parent?  error in the clock data */
-       if (!pclk) {
-               WARN_ON(1);
+       if (!pclk)
                return 0;
-       }
 
        dd = pclk->dpll_data;
 
@@ -672,6 +685,55 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
        return rate;
 }
 
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long parent_rate)
+{
+       return 0;
+}
+
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *prate)
+{
+       const struct dpll_data *dd;
+       u32 v;
+       struct clk_hw_omap *pclk = NULL;
+
+       if (!*prate)
+               return 0;
+
+       pclk = omap3_find_clkoutx2_dpll(hw);
+
+       if (!pclk)
+               return 0;
+
+       dd = pclk->dpll_data;
+
+       /* TYPE J does not have a clkoutx2 */
+       if (dd->flags & DPLL_J_TYPE) {
+               *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
+               return *prate;
+       }
+
+       WARN_ON(!dd->enable_mask);
+
+       v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
+       v >>= __ffs(dd->enable_mask);
+
+       /* If in bypass, the rate is fixed to the bypass rate*/
+       if (v != OMAP3XXX_EN_DPLL_LOCKED)
+               return *prate;
+
+       if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+               unsigned long best_parent;
+
+               best_parent = (rate / 2);
+               *prate = __clk_round_rate(__clk_get_parent(hw->clk),
+                               best_parent);
+       }
+
+       return *prate * 2;
+}
+
 /* OMAP3/4 non-CORE DPLL clkops */
 const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
        .allow_idle     = omap3_dpll_allow_idle,
index d24926e6340fa714cf0aeacca14a6578e5b481a4..ab43755364f5a7c06ecfc367c0f055d65876dc54 100644 (file)
@@ -1339,7 +1339,7 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
                of_property_read_bool(np, "gpmc,time-para-granularity");
 }
 
-#ifdef CONFIG_MTD_NAND
+#if IS_ENABLED(CONFIG_MTD_NAND)
 
 static const char * const nand_xfer_types[] = {
        [NAND_OMAP_PREFETCH_POLLED]             = "prefetch-polled",
@@ -1429,7 +1429,7 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
 }
 #endif
 
-#ifdef CONFIG_MTD_ONENAND
+#if IS_ENABLED(CONFIG_MTD_ONENAND)
 static int gpmc_probe_onenand_child(struct platform_device *pdev,
                                 struct device_node *child)
 {
index d408b15b4fbfd97ecd3d82aaa46cc86788e63a8c..af432b191255030a7c8fda2be849be0a75620482 100644 (file)
@@ -179,15 +179,6 @@ static struct map_desc omap34xx_io_desc[] __initdata = {
                .length         = L4_EMU_34XX_SIZE,
                .type           = MT_DEVICE
        },
-#if defined(CONFIG_DEBUG_LL) &&                                                        \
-       (defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3))
-       {
-               .virtual        = ZOOM_UART_VIRT,
-               .pfn            = __phys_to_pfn(ZOOM_UART_BASE),
-               .length         = SZ_1M,
-               .type           = MT_DEVICE
-       },
-#endif
 };
 #endif
 
index 42d81885c700c498babd2dd2e5d322e3af2c3f19..1f33f5db10d5a2dde0d90bd29f1eb6fce9b65995 100644 (file)
@@ -1946,30 +1946,32 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        if (ret)
                goto dis_opt_clks;
 
-       _write_sysconfig(v, oh);
-       ret = _clear_softreset(oh, &v);
-       if (ret)
-               goto dis_opt_clks;
-
        _write_sysconfig(v, oh);
 
        if (oh->class->sysc->srst_udelay)
                udelay(oh->class->sysc->srst_udelay);
 
        c = _wait_softreset_complete(oh);
-       if (c == MAX_MODULE_SOFTRESET_WAIT)
+       if (c == MAX_MODULE_SOFTRESET_WAIT) {
                pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
                           oh->name, MAX_MODULE_SOFTRESET_WAIT);
-       else
+               ret = -ETIMEDOUT;
+               goto dis_opt_clks;
+       } else {
                pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
+       }
+
+       ret = _clear_softreset(oh, &v);
+       if (ret)
+               goto dis_opt_clks;
+
+       _write_sysconfig(v, oh);
 
        /*
         * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
         * _wait_target_ready() or _reset()
         */
 
-       ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
-
 dis_opt_clks:
        if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
                _disable_optional_clocks(oh);
index 18f333c440db3b72ff49577ef71d24b64dbcc916..810c205d668bfa5040ed2ad0458b412eb83b538e 100644 (file)
@@ -1365,11 +1365,10 @@ static struct omap_hwmod_class_sysconfig dra7xx_spinlock_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
-       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
+       .sysc_flags     = (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                          SYSS_HAS_RESET_STATUS),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
index 3d5b24dcd9a41e2b7f4c16052bc2d931de74a0e4..c33e07e2f0d4e3d01b9e58e6347d4ca42ed81a18 100644 (file)
@@ -22,6 +22,8 @@
 #include "common-board-devices.h"
 #include "dss-common.h"
 #include "control.h"
+#include "omap-secure.h"
+#include "soc.h"
 
 struct pdata_init {
        const char *compatible;
@@ -169,6 +171,22 @@ static void __init am3517_evm_legacy_init(void)
        omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET);
        omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */
 }
+
+static void __init nokia_n900_legacy_init(void)
+{
+       hsmmc2_internal_input_clk();
+
+       if (omap_type() == OMAP2_DEVICE_TYPE_SEC) {
+               if (IS_ENABLED(CONFIG_ARM_ERRATA_430973)) {
+                       pr_info("RX-51: Enabling ARM errata 430973 workaround\n");
+                       /* set IBE to 1 */
+                       rx51_secure_update_aux_cr(BIT(6), 0);
+               } else {
+                       pr_warning("RX-51: Not enabling ARM errata 430973 workaround\n");
+                       pr_warning("Thumb binaries may crash randomly without this workaround\n");
+               }
+       }
+}
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #ifdef CONFIG_ARCH_OMAP4
@@ -239,6 +257,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 #endif
 #ifdef CONFIG_ARCH_OMAP3
        OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002030, "48002030.pinmux", &pcs_pdata),
+       OF_DEV_AUXDATA("ti,omap3-padconf", 0x480025a0, "480025a0.pinmux", &pcs_pdata),
        OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata),
        /* Only on am3517 */
        OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
@@ -259,7 +278,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 static struct pdata_init pdata_quirks[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP3
        { "compulab,omap3-sbc-t3730", omap3_sbc_t3730_legacy_init, },
-       { "nokia,omap3-n900", hsmmc2_internal_input_clk, },
+       { "nokia,omap3-n900", nokia_n900_legacy_init, },
        { "nokia,omap3-n9", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n950", hsmmc2_internal_input_clk, },
        { "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
index 6334b96b4097b6977ae29047040bf6990aed06a7..280f3c58abe505c9047e6027071ec8bafd720c57 100644 (file)
@@ -183,11 +183,11 @@ void omap4_prminst_global_warm_sw_reset(void)
                                        OMAP4_PRM_RSTCTRL_OFFSET);
        v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
        omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
-                                OMAP4430_PRM_DEVICE_INST,
+                                dev_inst,
                                 OMAP4_PRM_RSTCTRL_OFFSET);
 
        /* OCP barrier */
        v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-                                   OMAP4430_PRM_DEVICE_INST,
+                                   dev_inst,
                                    OMAP4_PRM_RSTCTRL_OFFSET);
 }
index c9f309ae88c5b57d0ecf60ac8025d704df37bdc2..8b90c4f2d430829e42213cb0b23eebeab23600f6 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <mach/gumstix.h>
 #include <mach/mfp-pxa25x.h>
+#include <mach/irqs.h>
 #include <linux/platform_data/video-pxafb.h>
 
 #include "generic.h"
index 954641e6c8b1cec4f1b0f29ea8fae26f0cbfcdf3..1b0825911e62c168dd8c4cf144e4334f88def99c 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef ASM_ARCH_BALLOON3_H
 #define ASM_ARCH_BALLOON3_H
 
+#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */
+
 enum balloon3_features {
        BALLOON3_FEATURE_OHCI,
        BALLOON3_FEATURE_MMC,
index f3c3493b468dff61399381567e89dbb6d6c5eeda..c030d955bbd7adfddc4f606cf4c69fb25a26030b 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __ASM_ARCH_CORGI_H
 #define __ASM_ARCH_CORGI_H  1
 
+#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */
 
 /*
  * Corgi (Non Standard) GPIO Definitions
index 2628e7b721168c99cb8dc1214934bcdffbfa8e1c..00cfbbbf73f78d5a7dd4f6bb288046b6caad0251 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef CSB726_H
 #define CSB726_H
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 #define CSB726_GPIO_IRQ_LAN    52
 #define CSB726_GPIO_IRQ_SM501  53
 #define CSB726_GPIO_MMC_DETECT 100
index dba14b6503ad17008660d23f81306db42c72119c..f7df27bbb42e0099c8d9567793deb95bcd6ce316 100644 (file)
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
 
 /* BTRESET - Reset line to Bluetooth module, active low signal. */
 #define GPIO_GUMSTIX_BTRESET          7
index 22a96f87232b5d5bdf894b55624900e832d054f4..7e63f4680271f3bb8ab9f9fdc4983e9371618a72 100644 (file)
@@ -23,6 +23,7 @@
  * IDP hardware.
  */
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
 
 #define IDP_FLASH_PHYS         (PXA_CS0_PHYS)
 #define IDP_ALT_FLASH_PHYS     (PXA_CS1_PHYS)
index 2c4471336570f0c38563f8b19d61b2a1b3bd5ed3..b184f296023bbf22e3986b882f293d47426c11ac 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _INCLUDE_PALMLD_H_
 #define _INCLUDE_PALMLD_H_
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /** HERE ARE GPIOs **/
 
 /* GPIOs */
index 0bd4f036c72fbb1deda29f4a2097785a9aee8a5c..e342c59214053c2fcb05ed5ee8adb186c6ffa4a8 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef _INCLUDE_PALMT5_H_
 #define _INCLUDE_PALMT5_H_
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /** HERE ARE GPIOs **/
 
 /* GPIOs */
index c383a21680b6992e711f8397e0dee98498cb0c94..81c727b3cfd23c60bc31e88087e3299eca1e5b3b 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef _INCLUDE_PALMTC_H_
 #define _INCLUDE_PALMTC_H_
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /** HERE ARE GPIOs **/
 
 /* GPIOs */
index f2e5303802537d79bac10b397b7b1d17e23bdf3d..92bc1f05300dde13e9ee79b4f01d967221de7ee4 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef _INCLUDE_PALMTX_H_
 #define _INCLUDE_PALMTX_H_
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /** HERE ARE GPIOs **/
 
 /* GPIOs */
index 6bf28de228bdeb8952f14458a5ebde1a93653530..86ebd7b6c9602859b0713903cca0c70f97595bf4 100644 (file)
@@ -23,6 +23,8 @@
  * Definitions of CPU card resources only
  */
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /* phyCORE-PXA270 (PCM027) Interrupts */
 #define PCM027_IRQ(x)          (IRQ_BOARD_START + (x))
 #define PCM027_BTDET_IRQ       PCM027_IRQ(0)
index 0260aaa2fc178670e597014eff70f358a16c5ad1..7e544c14967ed45177a2cc8a3d393f5bfe5b90b8 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <mach/pcm027.h>
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
 
 /*
  * definitions relevant only when the PCM-990
index f32ff75dcca83abd42fb8dfc30ac7a8ebdbf9e59..b56b19351a0389d2cd8ac7d76f027b2bcf1b39ba 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef __ASM_ARCH_POODLE_H
 #define __ASM_ARCH_POODLE_H  1
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /*
  * GPIOs
  */
index 0bfe6507c95dd2c4e89e8c23384a179ba1b0030d..25c9f62e46aa3fcbaae5210663b64fdaf6c18bb4 100644 (file)
@@ -15,8 +15,8 @@
 #define __ASM_ARCH_SPITZ_H  1
 #endif
 
+#include "irqs.h" /* PXA_NR_BUILTIN_GPIO, PXA_GPIO_TO_IRQ */
 #include <linux/fb.h>
-#include <linux/gpio.h>
 
 /* Spitz/Akita GPIOs */
 
index 2bb0e862598c41eeca0c20b36469b49f7cdc9692..0497d95cef25541c65da7c2e4b572784d191410e 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _ASM_ARCH_TOSA_H_
 #define _ASM_ARCH_TOSA_H_ 1
 
+#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */
+
 /*  TOSA Chip selects  */
 #define TOSA_LCDC_PHYS         PXA_CS4_PHYS
 /* Internel Scoop */
index d2ca01053f697d888bb3d529e5f8a998efcbb27b..ae3ca013afabe82185104aecd3252f31a6a3434b 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef _TRIPEPS4_H_
 #define _TRIPEPS4_H_
 
+#include "irqs.h" /* PXA_GPIO_TO_IRQ */
+
 /* physical memory regions */
 #define TRIZEPS4_FLASH_PHYS    (PXA_CS0_PHYS)  /* Flash region */
 #define TRIZEPS4_DISK_PHYS     (PXA_CS1_PHYS)  /* Disk On Chip region */
index f70583fee59f8b61e59a1022f07b36c26fd3210c..29997bde277d1be730aa85d98a2ae17bc0bc2da5 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/reboot.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/max1586.h>
 #include <linux/slab.h>
 #include <linux/i2c/pxa-i2c.h>
@@ -714,6 +715,10 @@ static struct gpio global_gpios[] = {
        { GPIO56_MT9M111_nOE, GPIOF_OUT_INIT_LOW, "Camera nOE" },
 };
 
+static struct regulator_consumer_supply fixed_5v0_consumers[] = {
+       REGULATOR_SUPPLY("power", "pwm-backlight"),
+};
+
 static void __init mioa701_machine_init(void)
 {
        int rc;
@@ -753,6 +758,10 @@ static void __init mioa701_machine_init(void)
        pxa_set_i2c_info(&i2c_pdata);
        pxa27x_set_i2c_power_info(NULL);
        pxa_set_camera_info(&mioa701_pxacamera_platform_data);
+
+       regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers,
+                                    ARRAY_SIZE(fixed_5v0_consumers),
+                                    5000000);
 }
 
 static void mioa701_machine_exit(void)
index f33679d2d3ee0a218d280972c5f409f0b561d41b..50e1d850ee2e01d6f29ee5004af4339f40c712b0 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_COLLIE_H
 #define __ASM_ARCH_COLLIE_H
 
+#include "hardware.h" /* Gives GPIO_MAX */
+
 extern void locomolcd_power(int on);
 
 #define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1)
index c1a9538fb6bbe0f31e3d799ead237bd465454840..f6db7dcae3f4dd044bc8ffea87cbd7779dd4602b 100644 (file)
@@ -8,7 +8,7 @@ config ARCH_SHMOBILE_MULTI
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select ARM_GIC
        select MIGHT_HAVE_CACHE_L2X0
index 4ae0286b468db6209311d14d13cd9cc673fb200b..f55b05a29b55f3ed655b36b1edf1f93f85d09c9d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/suspend.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <linux/clk/tegra.h>
 
 #include <asm/smp_plat.h>
index 303a285d80fd7b7d7cc4280779c343b4a3123f4a..6191603379e13cad2da1552954c3e2fb903cc241 100644 (file)
@@ -73,10 +73,20 @@ u32 tegra_uart_config[3] = {
 static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
+       static const struct of_device_id pl310_ids[] __initconst = {
+               { .compatible = "arm,pl310-cache",  },
+               {}
+       };
+
+       struct device_node *np;
        int ret;
        void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
        u32 aux_ctrl, cache_type;
 
+       np = of_find_matching_node(NULL, pl310_ids);
+       if (!np)
+               return;
+
        cache_type = readl(p + L2X0_CACHE_TYPE);
        aux_ctrl = (cache_type & 0x700) << (17-8);
        aux_ctrl |= 0x7C400001;
index 644468151c046fda63052ff2ebe2e3783e2e9207..a39be8e8085607c49156af97a4ba46462e0dac26 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of.h>
+#include <linux/memblock.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
 
 
 void __iomem *zynq_scu_base;
 
+/**
+ * zynq_memory_init - Initialize special memory
+ *
+ * We need to stop things allocating the low memory as DMA can't work in
+ * the 1st 512K of memory.
+ */
+static void __init zynq_memory_init(void)
+{
+       if (!__pa(PAGE_OFFSET))
+               memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
+}
+
 static struct platform_device zynq_cpuidle_device = {
        .name = "cpuidle-zynq",
 };
@@ -120,5 +133,6 @@ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
        .init_machine   = zynq_init_machine,
        .init_time      = zynq_timer_init,
        .dt_compat      = zynq_dt_match,
+       .reserve        = zynq_memory_init,
        .restart        = zynq_system_reset,
 MACHINE_END
index 1a77450e728ad17cf6b8fec2beb3111a2a8bfb94..11b3914660d2a9f518f15b09028d3dad78ad07e0 100644 (file)
@@ -1358,7 +1358,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
-       if (gfp & GFP_ATOMIC)
+       if (!(gfp & __GFP_WAIT))
                return __iommu_alloc_atomic(dev, size, handle);
 
        /*
index 2b3a56414271e5e31323566676097b774fca9406..ef69152f9b52e473796829545bf5cf5d1e83926a 100644 (file)
@@ -264,6 +264,9 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
                        note_page(st, addr, 3, pmd_val(*pmd));
                else
                        walk_pte(st, pmd, addr);
+
+               if (SECTION_SIZE < PMD_SIZE && pmd_large(pmd[1]))
+                       note_page(st, addr + SECTION_SIZE, 3, pmd_val(pmd[1]));
        }
 }
 
index d5a982d15a88e2a37a524267f31633f497aa0d4b..7ea641b7aa7d2b6ffd240b9fe0e7f7897a5a2d1a 100644 (file)
@@ -38,6 +38,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt)
 
 struct mem_type {
        pteval_t prot_pte;
+       pteval_t prot_pte_s2;
        pmdval_t prot_l1;
        pmdval_t prot_sect;
        unsigned int domain;
index 4f08c133cc255e2e2c2b93a0f28b79caaf3fc795..a623cb3ad012b196aacd11fc7f122fb84c0e3765 100644 (file)
@@ -232,12 +232,16 @@ __setup("noalign", noalign_setup);
 #endif /* ifdef CONFIG_CPU_CP15 / else */
 
 #define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
+#define PROT_PTE_S2_DEVICE     PROT_PTE_DEVICE
 #define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
 static struct mem_type mem_types[] = {
        [MT_DEVICE] = {           /* Strongly ordered / ARMv6 shared device */
                .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
                                  L_PTE_SHARED,
+               .prot_pte_s2    = s2_policy(PROT_PTE_S2_DEVICE) |
+                                 s2_policy(L_PTE_S2_MT_DEV_SHARED) |
+                                 L_PTE_SHARED,
                .prot_l1        = PMD_TYPE_TABLE,
                .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_S,
                .domain         = DOMAIN_IO,
@@ -508,7 +512,8 @@ static void __init build_mem_type_table(void)
        cp = &cache_policies[cachepolicy];
        vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
        s2_pgprot = cp->pte_s2;
-       hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+       hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+       s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2;
 
        /*
         * ARMv6 and above have extended page tables.
index 45dc29f85d56ca79ae7fa6076f3cee103465e15b..32b3558321c40db0d31e6898ad3ea329e049bca4 100644 (file)
@@ -208,7 +208,6 @@ __v6_setup:
        mcr     p15, 0, r0, c7, c14, 0          @ clean+invalidate D cache
        mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
        mcr     p15, 0, r0, c7, c15, 0          @ clean+invalidate cache
-       mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
 #ifdef CONFIG_MMU
        mcr     p15, 0, r0, c8, c7, 0           @ invalidate I + D TLBs
        mcr     p15, 0, r0, c2, c0, 2           @ TTB control register
@@ -218,6 +217,8 @@ __v6_setup:
        ALT_UP(orr      r8, r8, #TTB_FLAGS_UP)
        mcr     p15, 0, r8, c2, c0, 1           @ load TTB1
 #endif /* CONFIG_MMU */
+       mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer and
+                                               @ complete invalidations
        adr     r5, v6_crval
        ldmia   r5, {r5, r6}
  ARM_BE8(orr   r6, r6, #1 << 25)               @ big-endian page tables
index bd1781979a391825043d078192666e5a846cdae5..74f6033e76dd1702e89631334a813f5ea9ec1046 100644 (file)
@@ -351,7 +351,6 @@ __v7_setup:
 
 4:     mov     r10, #0
        mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
-       dsb
 #ifdef CONFIG_MMU
        mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
        v7_ttb_setup r10, r4, r8, r5            @ TTBCR, TTBRx setup
@@ -360,6 +359,7 @@ __v7_setup:
        mcr     p15, 0, r5, c10, c2, 0          @ write PRRR
        mcr     p15, 0, r6, c10, c2, 1          @ write NMRR
 #endif
+       dsb                                     @ Complete invalidations
 #ifndef CONFIG_ARM_THUMBEE
        mrc     p15, 0, r0, c0, c1, 0           @ read ID_PFR0 for ThumbEE
        and     r0, r0, #(0xf << 12)            @ ThumbEE enabled field
index dd4327f09ba45b9eb42462e073bea74422d7cde7..516d8a7ca697d5fb0ed642316d2187bfa4ad9b22 100644 (file)
@@ -16,6 +16,7 @@ config ARM64
        select DCACHE_WORD_ACCESS
        select GENERIC_CLOCKEVENTS
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+       select GENERIC_CPU_AUTOPROBE
        select GENERIC_IOMAP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
@@ -26,6 +27,7 @@ config ARM64
        select GENERIC_TIME_VSYSCALL
        select HARDIRQS_SW_RESEND
        select HAVE_ARCH_JUMP_LABEL
+       select HAVE_ARCH_KGDB
        select HAVE_ARCH_TRACEHOOK
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_DEBUG_KMEMLEAK
@@ -36,7 +38,10 @@ config ARM64
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_HW_BREAKPOINT if PERF_EVENTS
        select HAVE_MEMBLOCK
+       select HAVE_PATA_PLATFORM
        select HAVE_PERF_EVENTS
+       select HAVE_PERF_REGS
+       select HAVE_PERF_USER_STACK_DUMP
        select IRQ_DOMAIN
        select MODULES_USE_ELF_RELA
        select NO_BOOTMEM
@@ -72,7 +77,7 @@ config LOCKDEP_SUPPORT
 config TRACE_IRQFLAGS_SUPPORT
        def_bool y
 
-config RWSEM_GENERIC_SPINLOCK
+config RWSEM_XCHGADD_ALGORITHM
        def_bool y
 
 config GENERIC_HWEIGHT
@@ -84,7 +89,7 @@ config GENERIC_CSUM
 config GENERIC_CALIBRATE_DELAY
        def_bool y
 
-config ZONE_DMA32
+config ZONE_DMA
        def_bool y
 
 config ARCH_DMA_ADDR_T_64BIT
@@ -163,6 +168,22 @@ config SMP
 
          If you don't know what to do here, say N.
 
+config SCHED_MC
+       bool "Multi-core scheduler support"
+       depends on SMP
+       help
+         Multi-core scheduler support improves the CPU scheduler's decision
+         making when dealing with multi-core CPU chips at a cost of slightly
+         increased overhead in some places. If unsure say N here.
+
+config SCHED_SMT
+       bool "SMT scheduler support"
+       depends on SMP
+       help
+         Improves the CPU scheduler's decision making when dealing with
+         MultiThreading at a cost of slightly increased overhead in some
+         places. If unsure say N here.
+
 config NR_CPUS
        int "Maximum number of CPUs (2-32)"
        range 2 32
@@ -300,6 +321,8 @@ menu "CPU Power Management"
 
 source "drivers/cpuidle/Kconfig"
 
+source "drivers/cpufreq/Kconfig"
+
 endmenu
 
 source "net/Kconfig"
index d37d7369e260f3f7d2564711217f6d6ac19a859a..93f4b2dd92484863e8015da4a622a0c17745de5a 100644 (file)
                                reg-names = "csr-reg";
                                clock-output-names = "eth8clk";
                        };
+
+                       sataphy1clk: sataphy1clk@1f21c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f21c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sataphy1clk";
+                               status = "disabled";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x00>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x06>;
+                       };
+
+                       sataphy2clk: sataphy1clk@1f22c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f22c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sataphy2clk";
+                               status = "ok";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x3a>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x06>;
+                       };
+
+                       sataphy3clk: sataphy1clk@1f23c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f23c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sataphy3clk";
+                               status = "ok";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x3a>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x06>;
+                       };
+
+                       sata01clk: sata01clk@1f21c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f21c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sata01clk";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x05>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x39>;
+                       };
+
+                       sata23clk: sata23clk@1f22c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f22c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sata23clk";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x05>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x39>;
+                       };
+
+                       sata45clk: sata45clk@1f23c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f23c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sata45clk";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x05>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x39>;
+                       };
                };
 
                serial0: serial@1c020000 {
                        interrupt-parent = <&gic>;
                        interrupts = <0x0 0x4c 0x4>;
                };
+
+               phy1: phy@1f21a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f21a000 0x0 0x100>;
+                       #phy-cells = <1>;
+                       clocks = <&sataphy1clk 0>;
+                       status = "disabled";
+                       apm,tx-boost-gain = <30 30 30 30 30 30>;
+                       apm,tx-eye-tuning = <2 10 10 2 10 10>;
+               };
+
+               phy2: phy@1f22a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f22a000 0x0 0x100>;
+                       #phy-cells = <1>;
+                       clocks = <&sataphy2clk 0>;
+                       status = "ok";
+                       apm,tx-boost-gain = <30 30 30 30 30 30>;
+                       apm,tx-eye-tuning = <1 10 10 2 10 10>;
+               };
+
+               phy3: phy@1f23a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f23a000 0x0 0x100>;
+                       #phy-cells = <1>;
+                       clocks = <&sataphy3clk 0>;
+                       status = "ok";
+                       apm,tx-boost-gain = <31 31 31 31 31 31>;
+                       apm,tx-eye-tuning = <2 10 10 2 10 10>;
+               };
+
+               sata1: sata@1a000000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a000000 0x0 0x1000>,
+                             <0x0 0x1f210000 0x0 0x1000>,
+                             <0x0 0x1f21d000 0x0 0x1000>,
+                             <0x0 0x1f21e000 0x0 0x1000>,
+                             <0x0 0x1f217000 0x0 0x1000>;
+                       interrupts = <0x0 0x86 0x4>;
+                       status = "disabled";
+                       clocks = <&sata01clk 0>;
+                       phys = <&phy1 0>;
+                       phy-names = "sata-phy";
+               };
+
+               sata2: sata@1a400000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a400000 0x0 0x1000>,
+                             <0x0 0x1f220000 0x0 0x1000>,
+                             <0x0 0x1f22d000 0x0 0x1000>,
+                             <0x0 0x1f22e000 0x0 0x1000>,
+                             <0x0 0x1f227000 0x0 0x1000>;
+                       interrupts = <0x0 0x87 0x4>;
+                       status = "ok";
+                       clocks = <&sata23clk 0>;
+                       phys = <&phy2 0>;
+                       phy-names = "sata-phy";
+               };
+
+               sata3: sata@1a800000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a800000 0x0 0x1000>,
+                             <0x0 0x1f230000 0x0 0x1000>,
+                             <0x0 0x1f23d000 0x0 0x1000>,
+                             <0x0 0x1f23e000 0x0 0x1000>;
+                       interrupts = <0x0 0x88 0x4>;
+                       status = "ok";
+                       clocks = <&sata45clk 0>;
+                       phys = <&phy3 0>;
+                       phy-names = "sata-phy";
+               };
        };
 };
index 84139be62ae66348e3f9654b4cd14cabac4ba4eb..7959dd0ca5d5edee6678f7780f8e9d49cafb699b 100644 (file)
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
@@ -19,6 +18,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -27,6 +27,7 @@ CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
+CONFIG_CMA=y
 CONFIG_CMDLINE="console=ttyAMA0"
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
@@ -42,14 +43,17 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
-CONFIG_BLK_DEV=y
+CONFIG_DMA_CMA=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_PLATFORM=y
+CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
-CONFIG_MII=y
 CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_I8042 is not set
@@ -62,13 +66,19 @@ CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_FB=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
index 71c53ecfcc3ae356f0c5d0bd4c593e3b7bef8b89..4bca4923fc0b7eef27e37532358fe7eb48aa1224 100644 (file)
@@ -12,6 +12,7 @@ generic-y += dma.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += ftrace.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -22,13 +23,16 @@ generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += pci.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
+generic-y += rwsem.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += segment.h
@@ -38,8 +42,8 @@ generic-y += shmbuf.h
 generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += switch_to.h
 generic-y += swab.h
+generic-y += switch_to.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
@@ -49,5 +53,3 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 01de5aaa3edc112a42548a1b3906e4353bcce949..0237f0867e377a1acc4f3840e1a9307cff6a3fe8 100644 (file)
@@ -54,8 +54,7 @@ static inline void atomic_add(int i, atomic_t *v)
 "      stxr    %w1, %w0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
-       : "Ir" (i)
-       : "cc");
+       : "Ir" (i));
 }
 
 static inline int atomic_add_return(int i, atomic_t *v)
@@ -64,14 +63,15 @@ static inline int atomic_add_return(int i, atomic_t *v)
        int result;
 
        asm volatile("// atomic_add_return\n"
-"1:    ldaxr   %w0, %2\n"
+"1:    ldxr    %w0, %2\n"
 "      add     %w0, %w0, %w3\n"
 "      stlxr   %w1, %w0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
        : "Ir" (i)
-       : "cc", "memory");
+       : "memory");
 
+       smp_mb();
        return result;
 }
 
@@ -86,8 +86,7 @@ static inline void atomic_sub(int i, atomic_t *v)
 "      stxr    %w1, %w0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
-       : "Ir" (i)
-       : "cc");
+       : "Ir" (i));
 }
 
 static inline int atomic_sub_return(int i, atomic_t *v)
@@ -96,14 +95,15 @@ static inline int atomic_sub_return(int i, atomic_t *v)
        int result;
 
        asm volatile("// atomic_sub_return\n"
-"1:    ldaxr   %w0, %2\n"
+"1:    ldxr    %w0, %2\n"
 "      sub     %w0, %w0, %w3\n"
 "      stlxr   %w1, %w0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
        : "Ir" (i)
-       : "cc", "memory");
+       : "memory");
 
+       smp_mb();
        return result;
 }
 
@@ -112,17 +112,20 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
        unsigned long tmp;
        int oldval;
 
+       smp_mb();
+
        asm volatile("// atomic_cmpxchg\n"
-"1:    ldaxr   %w1, %2\n"
+"1:    ldxr    %w1, %2\n"
 "      cmp     %w1, %w3\n"
 "      b.ne    2f\n"
-"      stlxr   %w0, %w4, %2\n"
+"      stxr    %w0, %w4, %2\n"
 "      cbnz    %w0, 1b\n"
 "2:"
        : "=&r" (tmp), "=&r" (oldval), "+Q" (ptr->counter)
        : "Ir" (old), "r" (new)
-       : "cc", "memory");
+       : "cc");
 
+       smp_mb();
        return oldval;
 }
 
@@ -173,8 +176,7 @@ static inline void atomic64_add(u64 i, atomic64_t *v)
 "      stxr    %w1, %0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
-       : "Ir" (i)
-       : "cc");
+       : "Ir" (i));
 }
 
 static inline long atomic64_add_return(long i, atomic64_t *v)
@@ -183,14 +185,15 @@ static inline long atomic64_add_return(long i, atomic64_t *v)
        unsigned long tmp;
 
        asm volatile("// atomic64_add_return\n"
-"1:    ldaxr   %0, %2\n"
+"1:    ldxr    %0, %2\n"
 "      add     %0, %0, %3\n"
 "      stlxr   %w1, %0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
        : "Ir" (i)
-       : "cc", "memory");
+       : "memory");
 
+       smp_mb();
        return result;
 }
 
@@ -205,8 +208,7 @@ static inline void atomic64_sub(u64 i, atomic64_t *v)
 "      stxr    %w1, %0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
-       : "Ir" (i)
-       : "cc");
+       : "Ir" (i));
 }
 
 static inline long atomic64_sub_return(long i, atomic64_t *v)
@@ -215,14 +217,15 @@ static inline long atomic64_sub_return(long i, atomic64_t *v)
        unsigned long tmp;
 
        asm volatile("// atomic64_sub_return\n"
-"1:    ldaxr   %0, %2\n"
+"1:    ldxr    %0, %2\n"
 "      sub     %0, %0, %3\n"
 "      stlxr   %w1, %0, %2\n"
 "      cbnz    %w1, 1b"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
        : "Ir" (i)
-       : "cc", "memory");
+       : "memory");
 
+       smp_mb();
        return result;
 }
 
@@ -231,17 +234,20 @@ static inline long atomic64_cmpxchg(atomic64_t *ptr, long old, long new)
        long oldval;
        unsigned long res;
 
+       smp_mb();
+
        asm volatile("// atomic64_cmpxchg\n"
-"1:    ldaxr   %1, %2\n"
+"1:    ldxr    %1, %2\n"
 "      cmp     %1, %3\n"
 "      b.ne    2f\n"
-"      stlxr   %w0, %4, %2\n"
+"      stxr    %w0, %4, %2\n"
 "      cbnz    %w0, 1b\n"
 "2:"
        : "=&r" (res), "=&r" (oldval), "+Q" (ptr->counter)
        : "Ir" (old), "r" (new)
-       : "cc", "memory");
+       : "cc");
 
+       smp_mb();
        return oldval;
 }
 
@@ -253,11 +259,12 @@ static inline long atomic64_dec_if_positive(atomic64_t *v)
        unsigned long tmp;
 
        asm volatile("// atomic64_dec_if_positive\n"
-"1:    ldaxr   %0, %2\n"
+"1:    ldxr    %0, %2\n"
 "      subs    %0, %0, #1\n"
 "      b.mi    2f\n"
 "      stlxr   %w1, %0, %2\n"
 "      cbnz    %w1, 1b\n"
+"      dmb     ish\n"
 "2:"
        : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
        :
index 78e20ba8806b8b86338ee1ccafc1c3aa97b5a034..66eb7648043bc9c1ba6383b0e2187a74c8dc8d5c 100644 (file)
@@ -25,7 +25,8 @@
 #define wfi()          asm volatile("wfi" : : : "memory")
 
 #define isb()          asm volatile("isb" : : : "memory")
-#define dsb()          asm volatile("dsb sy" : : : "memory")
+#define dmb(opt)       asm volatile("dmb sy" : : : "memory")
+#define dsb(opt)       asm volatile("dsb sy" : : : "memory")
 
 #define mb()           dsb()
 #define rmb()          asm volatile("dsb ld" : : : "memory")
index fea9ee32720678b348685ef4803bb2c622c3eb8e..4c60e64a801c5cf3a3c5e379a3270ea3ff31eea5 100644 (file)
@@ -84,6 +84,13 @@ static inline void flush_cache_page(struct vm_area_struct *vma,
 {
 }
 
+/*
+ * Cache maintenance functions used by the DMA API. No to be used directly.
+ */
+extern void __dma_map_area(const void *, size_t, int);
+extern void __dma_unmap_area(const void *, size_t, int);
+extern void __dma_flush_range(const void *, const void *);
+
 /*
  * Copy user data from/to a page which is mapped into a different
  * processes address space.  Really, we want to allow our "user
@@ -116,6 +123,7 @@ extern void flush_dcache_page(struct page *);
 static inline void __flush_icache_all(void)
 {
        asm("ic ialluis");
+       dsb();
 }
 
 #define flush_dcache_mmap_lock(mapping) \
index 56166d7f4a258867d817804c4c17145952895a20..57c0fa7bf71141c62f954f730d50fddb8669cfa7 100644 (file)
@@ -29,44 +29,45 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
        switch (size) {
        case 1:
                asm volatile("//        __xchg1\n"
-               "1:     ldaxrb  %w0, %2\n"
+               "1:     ldxrb   %w0, %2\n"
                "       stlxrb  %w1, %w3, %2\n"
                "       cbnz    %w1, 1b\n"
                        : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)
                        : "r" (x)
-                       : "cc", "memory");
+                       : "memory");
                break;
        case 2:
                asm volatile("//        __xchg2\n"
-               "1:     ldaxrh  %w0, %2\n"
+               "1:     ldxrh   %w0, %2\n"
                "       stlxrh  %w1, %w3, %2\n"
                "       cbnz    %w1, 1b\n"
                        : "=&r" (ret), "=&r" (tmp), "+Q" (*(u16 *)ptr)
                        : "r" (x)
-                       : "cc", "memory");
+                       : "memory");
                break;
        case 4:
                asm volatile("//        __xchg4\n"
-               "1:     ldaxr   %w0, %2\n"
+               "1:     ldxr    %w0, %2\n"
                "       stlxr   %w1, %w3, %2\n"
                "       cbnz    %w1, 1b\n"
                        : "=&r" (ret), "=&r" (tmp), "+Q" (*(u32 *)ptr)
                        : "r" (x)
-                       : "cc", "memory");
+                       : "memory");
                break;
        case 8:
                asm volatile("//        __xchg8\n"
-               "1:     ldaxr   %0, %2\n"
+               "1:     ldxr    %0, %2\n"
                "       stlxr   %w1, %3, %2\n"
                "       cbnz    %w1, 1b\n"
                        : "=&r" (ret), "=&r" (tmp), "+Q" (*(u64 *)ptr)
                        : "r" (x)
-                       : "cc", "memory");
+                       : "memory");
                break;
        default:
                BUILD_BUG();
        }
 
+       smp_mb();
        return ret;
 }
 
index fda2704b3f9f9a49354e12dc6b55aaa81638cd5a..e71f81fe127a504838ba86c5290d99ce10b5411f 100644 (file)
@@ -228,7 +228,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-#define compat_user_stack_pointer() (current_pt_regs()->compat_sp)
+#define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs()))
 
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
new file mode 100644 (file)
index 0000000..cd4ac05
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * 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 __ASM_CPUFEATURE_H
+#define __ASM_CPUFEATURE_H
+
+#include <asm/hwcap.h>
+
+/*
+ * In the arm64 world (as in the ARM world), elf_hwcap is used both internally
+ * in the kernel and for user space to keep track of which optional features
+ * are supported by the current system. So let's map feature 'x' to HWCAP_x.
+ * Note that HWCAP_x constants are bit fields so we need to take the log.
+ */
+
+#define MAX_CPU_FEATURES       (8 * sizeof(elf_hwcap))
+#define cpu_feature(x)         ilog2(HWCAP_ ## x)
+
+static inline bool cpu_have_feature(unsigned int num)
+{
+       return elf_hwcap & (1UL << num);
+}
+
+#endif
index 62314791570cbdda16b7e575c2aa7fc48ed5d45a..6e9b5b36921cce2d26276d12c5379514b420f2ff 100644 (file)
 #define DBG_ESR_EVT_HWWP       0x2
 #define DBG_ESR_EVT_BRK                0x6
 
+/*
+ * Break point instruction encoding
+ */
+#define BREAK_INSTR_SIZE               4
+
+/*
+ * ESR values expected for dynamic and compile time BRK instruction
+ */
+#define DBG_ESR_VAL_BRK(x)     (0xf2000000 | ((x) & 0xfffff))
+
+/*
+ * #imm16 values used for BRK instruction generation
+ * Allowed values for kgbd are 0x400 - 0x7ff
+ * 0x400: for dynamic BRK instruction
+ * 0x401: for compile time BRK instruction
+ */
+#define KGDB_DYN_DGB_BRK_IMM           0x400
+#define KDBG_COMPILED_DBG_BRK_IMM      0x401
+
+/*
+ * BRK instruction encoding
+ * The #imm16 value should be placed at bits[20:5] within BRK ins
+ */
+#define AARCH64_BREAK_MON      0xd4200000
+
+/*
+ * Extract byte from BRK instruction
+ */
+#define KGDB_DYN_DGB_BRK_INS_BYTE(x) \
+       ((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff)
+
+/*
+ * Extract byte from BRK #imm16
+ */
+#define KGBD_DYN_DGB_BRK_IMM_BYTE(x) \
+       (((((KGDB_DYN_DGB_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff)
+
+#define KGDB_DYN_DGB_BRK_BYTE(x) \
+       (KGDB_DYN_DGB_BRK_INS_BYTE(x) | KGBD_DYN_DGB_BRK_IMM_BYTE(x))
+
+#define  KGDB_DYN_BRK_INS_BYTE0  KGDB_DYN_DGB_BRK_BYTE(0)
+#define  KGDB_DYN_BRK_INS_BYTE1  KGDB_DYN_DGB_BRK_BYTE(1)
+#define  KGDB_DYN_BRK_INS_BYTE2  KGDB_DYN_DGB_BRK_BYTE(2)
+#define  KGDB_DYN_BRK_INS_BYTE3  KGDB_DYN_DGB_BRK_BYTE(3)
+
+#define CACHE_FLUSH_IS_SAFE            1
+
 enum debug_el {
        DBG_ACTIVE_EL0 = 0,
        DBG_ACTIVE_EL1,
@@ -43,23 +90,6 @@ enum debug_el {
 #ifndef __ASSEMBLY__
 struct task_struct;
 
-#define local_dbg_save(flags)                                                  \
-       do {                                                                    \
-               typecheck(unsigned long, flags);                                \
-               asm volatile(                                                   \
-               "mrs    %0, daif                        // local_dbg_save\n"    \
-               "msr    daifset, #8"                                            \
-               : "=r" (flags) : : "memory");                                   \
-       } while (0)
-
-#define local_dbg_restore(flags)                                               \
-       do {                                                                    \
-               typecheck(unsigned long, flags);                                \
-               asm volatile(                                                   \
-               "msr    daif, %0                        // local_dbg_restore\n" \
-               : : "r" (flags) : "memory");                                    \
-       } while (0)
-
 #define DBG_ARCH_ID_RESERVED   0       /* In case of ptrace ABI updates. */
 
 #define DBG_HOOK_HANDLED       0
index fd0c0c0e447a657115c116f45bf9edd693b339a3..3a4572ec3273267c04334057b944739fe56d73e2 100644 (file)
@@ -30,6 +30,8 @@
 
 #define DMA_ERROR_CODE (~(dma_addr_t)0)
 extern struct dma_map_ops *dma_ops;
+extern struct dma_map_ops coherent_swiotlb_dma_ops;
+extern struct dma_map_ops noncoherent_swiotlb_dma_ops;
 
 static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
 {
@@ -47,6 +49,11 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
                return __generic_dma_ops(dev);
 }
 
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+       dev->archdata.dma_ops = ops;
+}
+
 #include <asm-generic/dma-mapping-common.h>
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
index 78834123a32ef0f21c7cfe65f89d12e8392767f1..c4a7f940b3870c13fbeb0f3f63a191e44a6c5657 100644 (file)
@@ -42,7 +42,7 @@
 #define ESR_EL1_EC_SP_ALIGN    (0x26)
 #define ESR_EL1_EC_FP_EXC32    (0x28)
 #define ESR_EL1_EC_FP_EXC64    (0x2C)
-#define ESR_EL1_EC_SERRROR     (0x2F)
+#define ESR_EL1_EC_SERROR      (0x2F)
 #define ESR_EL1_EC_BREAKPT_EL0 (0x30)
 #define ESR_EL1_EC_BREAKPT_EL1 (0x31)
 #define ESR_EL1_EC_SOFTSTP_EL0 (0x32)
index 78cc3aba5d69e9ff976be9226cd975860b0a31a0..5f750dc96e0fd64123851ac787659f5953bc71e5 100644 (file)
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg)                \
        asm volatile(                                                   \
-"1:    ldaxr   %w1, %2\n"                                              \
+"1:    ldxr    %w1, %2\n"                                              \
        insn "\n"                                                       \
 "2:    stlxr   %w3, %w0, %2\n"                                         \
 "      cbnz    %w3, 1b\n"                                              \
+"      dmb     ish\n"                                                  \
 "3:\n"                                                                 \
 "      .pushsection .fixup,\"ax\"\n"                                   \
 "      .align  2\n"                                                    \
@@ -40,7 +41,7 @@
 "      .popsection\n"                                                  \
        : "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp)       \
        : "r" (oparg), "Ir" (-EFAULT)                                   \
-       : "cc", "memory")
+       : "memory")
 
 static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
@@ -111,11 +112,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                return -EFAULT;
 
        asm volatile("// futex_atomic_cmpxchg_inatomic\n"
-"1:    ldaxr   %w1, %2\n"
+"1:    ldxr    %w1, %2\n"
 "      sub     %w3, %w1, %w4\n"
 "      cbnz    %w3, 3f\n"
 "2:    stlxr   %w3, %w5, %2\n"
 "      cbnz    %w3, 1b\n"
+"      dmb     ish\n"
 "3:\n"
 "      .pushsection .fixup,\"ax\"\n"
 "4:    mov     %w0, %w6\n"
@@ -127,7 +129,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 "      .popsection\n"
        : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
        : "r" (oldval), "r" (newval), "Ir" (-EFAULT)
-       : "cc", "memory");
+       : "memory");
 
        *uval = val;
        return ret;
index 6cddbb0c9f5459cff851101fd3010ad74882a1ef..024c46183c3cc4bac07977ffcdade60c2567ea98 100644 (file)
 #define COMPAT_HWCAP_IDIV      (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
 #define COMPAT_HWCAP_EVTSTRM   (1 << 21)
 
+#define COMPAT_HWCAP2_AES      (1 << 0)
+#define COMPAT_HWCAP2_PMULL    (1 << 1)
+#define COMPAT_HWCAP2_SHA1     (1 << 2)
+#define COMPAT_HWCAP2_SHA2     (1 << 3)
+#define COMPAT_HWCAP2_CRC32    (1 << 4)
+
 #ifndef __ASSEMBLY__
 /*
  * This yields a mask that user programs can use to figure out what
@@ -41,7 +47,8 @@
 
 #ifdef CONFIG_COMPAT
 #define COMPAT_ELF_HWCAP       (compat_elf_hwcap)
-extern unsigned int compat_elf_hwcap;
+#define COMPAT_ELF_HWCAP2      (compat_elf_hwcap2)
+extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
 #endif
 
 extern unsigned long elf_hwcap;
index 4cc813eddacbebee4c84f864f103bb6492d7c193..7846a6bb08334dec2833ef8c09d60373a55fe3fa 100644 (file)
@@ -121,7 +121,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 *)(MODULES_VADDR - SZ_2M))
+#define PCI_IOBASE             ((void __iomem *)(MODULES_VADDR - SZ_32M))
 
 static inline u8 inb(unsigned long addr)
 {
index b2fcfbc51ecc4b0eaef6e4b20efd0f7afd2a9efd..11cc941bd107b5cb2457101ea15ac772e2eb699a 100644 (file)
@@ -90,5 +90,28 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
        return flags & PSR_I_BIT;
 }
 
+/*
+ * save and restore debug state
+ */
+#define local_dbg_save(flags)                                          \
+       do {                                                            \
+               typecheck(unsigned long, flags);                        \
+               asm volatile(                                           \
+               "mrs    %0, daif                // local_dbg_save\n"    \
+               "msr    daifset, #8"                                    \
+               : "=r" (flags) : : "memory");                           \
+       } while (0)
+
+#define local_dbg_restore(flags)                                       \
+       do {                                                            \
+               typecheck(unsigned long, flags);                        \
+               asm volatile(                                           \
+               "msr    daif, %0                // local_dbg_restore\n" \
+               : : "r" (flags) : "memory");                            \
+       } while (0)
+
+#define local_dbg_enable()     asm("msr        daifclr, #8" : : : "memory")
+#define local_dbg_disable()    asm("msr        daifset, #8" : : : "memory")
+
 #endif
 #endif
diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
new file mode 100644 (file)
index 0000000..3c8aafc
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * AArch64 KGDB support
+ *
+ * Based on arch/arm/include/kgdb.h
+ *
+ * Copyright (C) 2013 Cavium Inc.
+ * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_KGDB_H
+#define __ARM_KGDB_H
+
+#include <linux/ptrace.h>
+#include <asm/debug-monitors.h>
+
+#ifndef        __ASSEMBLY__
+
+static inline void arch_kgdb_breakpoint(void)
+{
+       asm ("brk %0" : : "I" (KDBG_COMPILED_DBG_BRK_IMM));
+}
+
+extern void kgdb_handle_bus_error(void);
+extern int kgdb_fault_expected;
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * gdb is expecting the following registers layout.
+ *
+ * General purpose regs:
+ *     r0-r30: 64 bit
+ *     sp,pc : 64 bit
+ *     pstate  : 64 bit
+ *     Total: 34
+ * FPU regs:
+ *     f0-f31: 128 bit
+ *     Total: 32
+ * Extra regs
+ *     fpsr & fpcr: 32 bit
+ *     Total: 2
+ *
+ */
+
+#define _GP_REGS               34
+#define _FP_REGS               32
+#define _EXTRA_REGS            2
+/*
+ * general purpose registers size in bytes.
+ * pstate is only 4 bytes. subtract 4 bytes
+ */
+#define GP_REG_BYTES           (_GP_REGS * 8)
+#define DBG_MAX_REG_NUM                (_GP_REGS + _FP_REGS + _EXTRA_REGS)
+
+/*
+ * Size of I/O buffer for gdb packet.
+ * considering to hold all register contents, size is set
+ */
+
+#define BUFMAX                 2048
+
+/*
+ * Number of bytes required for gdb_regs buffer.
+ * _GP_REGS: 8 bytes, _FP_REGS: 16 bytes and _EXTRA_REGS: 4 bytes each
+ * GDB fails to connect for size beyond this with error
+ * "'g' packet reply is too long"
+ */
+
+#define NUMREGBYTES    ((_GP_REGS * 8) + (_FP_REGS * 16) + \
+                       (_EXTRA_REGS * 4))
+
+#endif /* __ASM_KGDB_H */
index c98ef4771c7389b989d073b7a933047908fcf0a2..21ef48d32ff271fbdccba7f2df710b021f9db7e0 100644 (file)
 
 /* VTCR_EL2 Registers bits */
 #define VTCR_EL2_PS_MASK       (7 << 16)
-#define VTCR_EL2_PS_40B                (2 << 16)
 #define VTCR_EL2_TG0_MASK      (1 << 14)
 #define VTCR_EL2_TG0_4K                (0 << 14)
 #define VTCR_EL2_TG0_64K       (1 << 14)
  * 64kB pages (TG0 = 1)
  * 2 level page tables (SL = 1)
  */
-#define VTCR_EL2_FLAGS         (VTCR_EL2_PS_40B | VTCR_EL2_TG0_64K | \
-                                VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \
-                                VTCR_EL2_IRGN0_WBWA | VTCR_EL2_SL0_LVL1 | \
-                                VTCR_EL2_T0SZ_40B)
+#define VTCR_EL2_FLAGS         (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \
+                                VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
+                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B)
 #define VTTBR_X                (38 - VTCR_EL2_T0SZ_40B)
 #else
 /*
  * 4kB pages (TG0 = 0)
  * 3 level page tables (SL = 1)
  */
-#define VTCR_EL2_FLAGS         (VTCR_EL2_PS_40B | VTCR_EL2_TG0_4K | \
-                                VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \
-                                VTCR_EL2_IRGN0_WBWA | VTCR_EL2_SL0_LVL1 | \
-                                VTCR_EL2_T0SZ_40B)
+#define VTCR_EL2_FLAGS         (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \
+                                VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
+                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B)
 #define VTTBR_X                (37 - VTCR_EL2_T0SZ_40B)
 #endif
 
 #define ESR_EL2_EC_SP_ALIGN    (0x26)
 #define ESR_EL2_EC_FP_EXC32    (0x28)
 #define ESR_EL2_EC_FP_EXC64    (0x2C)
-#define ESR_EL2_EC_SERRROR     (0x2F)
+#define ESR_EL2_EC_SERROR      (0x2F)
 #define ESR_EL2_EC_BREAKPT     (0x30)
 #define ESR_EL2_EC_BREAKPT_HYP (0x31)
 #define ESR_EL2_EC_SOFTSTP     (0x32)
index 13fb0b3efc5f7206bb8e187ea07ff6c3337ff2be..453a179469a34fd9ffa72ec723a6bada988d4e73 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __ASM_PERCPU_H
 #define __ASM_PERCPU_H
 
+#ifdef CONFIG_SMP
+
 static inline void set_my_cpu_offset(unsigned long off)
 {
        asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
@@ -36,6 +38,12 @@ static inline unsigned long __my_cpu_offset(void)
 }
 #define __my_cpu_offset __my_cpu_offset()
 
+#else  /* !CONFIG_SMP */
+
+#define set_my_cpu_offset(x)   do { } while (0)
+
+#endif /* CONFIG_SMP */
+
 #include <asm-generic/percpu.h>
 
 #endif /* __ASM_PERCPU_H */
index b1d2e26c3c883e7259f0ab679efe33ffe2935429..f7af66b54cb216931f23718cc75754d269acefc4 100644 (file)
 #define PTE_HYP                        PTE_USER
 
 /*
- * 40-bit physical address supported.
+ * Highest possible physical address supported.
  */
-#define PHYS_MASK_SHIFT                (40)
+#define PHYS_MASK_SHIFT                (48)
 #define PHYS_MASK              ((UL(1) << PHYS_MASK_SHIFT) - 1)
 
 /*
 #define TCR_SHARED             ((UL(3) << 12) | (UL(3) << 28))
 #define TCR_TG0_64K            (UL(1) << 14)
 #define TCR_TG1_64K            (UL(1) << 30)
-#define TCR_IPS_40BIT          (UL(2) << 32)
 #define TCR_ASID16             (UL(1) << 36)
 #define TCR_TBI0               (UL(1) << 37)
 
index b524dcd17243d712b4d461cf77d4dd56ed04c8bb..90c811f05a2e3279a8709211a770725141491dd7 100644 (file)
@@ -136,11 +136,11 @@ extern struct page *empty_zero_page;
 /*
  * The following only work if pte_present(). Undefined behaviour otherwise.
  */
-#define pte_present(pte)       (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
-#define pte_dirty(pte)         (pte_val(pte) & PTE_DIRTY)
-#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_WRITE)
+#define pte_present(pte)       (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
+#define pte_dirty(pte)         (!!(pte_val(pte) & PTE_DIRTY))
+#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_WRITE))
 #define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #define pte_valid_user(pte) \
@@ -199,7 +199,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t pte)
 {
        if (pte_valid_user(pte)) {
-               if (pte_exec(pte))
+               if (!pte_special(pte) && pte_exec(pte))
                        __sync_icache_dcache(pte, addr);
                if (pte_dirty(pte) && pte_write(pte))
                        pte_val(pte) &= ~PTE_RDONLY;
@@ -227,36 +227,36 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 
 #define __HAVE_ARCH_PTE_SPECIAL
 
-/*
- * Software PMD bits for THP
- */
+static inline pte_t pmd_pte(pmd_t pmd)
+{
+       return __pte(pmd_val(pmd));
+}
 
-#define PMD_SECT_DIRTY         (_AT(pmdval_t, 1) << 55)
-#define PMD_SECT_SPLITTING     (_AT(pmdval_t, 1) << 57)
+static inline pmd_t pte_pmd(pte_t pte)
+{
+       return __pmd(pte_val(pte));
+}
 
 /*
  * THP definitions.
  */
-#define pmd_young(pmd)         (pmd_val(pmd) & PMD_SECT_AF)
-
-#define __HAVE_ARCH_PMD_WRITE
-#define pmd_write(pmd)         (!(pmd_val(pmd) & PMD_SECT_RDONLY))
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_trans_huge(pmd)    (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
-#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+#define pmd_trans_splitting(pmd)       pte_special(pmd_pte(pmd))
 #endif
 
-#define PMD_BIT_FUNC(fn,op) \
-static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+#define pmd_young(pmd)         pte_young(pmd_pte(pmd))
+#define pmd_wrprotect(pmd)     pte_pmd(pte_wrprotect(pmd_pte(pmd)))
+#define pmd_mksplitting(pmd)   pte_pmd(pte_mkspecial(pmd_pte(pmd)))
+#define pmd_mkold(pmd)         pte_pmd(pte_mkold(pmd_pte(pmd)))
+#define pmd_mkwrite(pmd)       pte_pmd(pte_mkwrite(pmd_pte(pmd)))
+#define pmd_mkdirty(pmd)       pte_pmd(pte_mkdirty(pmd_pte(pmd)))
+#define pmd_mkyoung(pmd)       pte_pmd(pte_mkyoung(pmd_pte(pmd)))
+#define pmd_mknotpresent(pmd)  (__pmd(pmd_val(pmd) &= ~PMD_TYPE_MASK))
 
-PMD_BIT_FUNC(wrprotect,        |= PMD_SECT_RDONLY);
-PMD_BIT_FUNC(mkold,    &= ~PMD_SECT_AF);
-PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
-PMD_BIT_FUNC(mkwrite,   &= ~PMD_SECT_RDONLY);
-PMD_BIT_FUNC(mkdirty,   |= PMD_SECT_DIRTY);
-PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
-PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+#define __HAVE_ARCH_PMD_WRITE
+#define pmd_write(pmd)         pte_write(pmd_pte(pmd))
 
 #define pmd_mkhuge(pmd)                (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
 
@@ -266,15 +266,6 @@ PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
 
 #define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
 
-static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
-{
-       const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN |
-                             PMD_SECT_RDONLY | PMD_SECT_PROT_NONE |
-                             PMD_SECT_VALID;
-       pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
-       return pmd;
-}
-
 #define set_pmd_at(mm, addr, pmdp, pmd)        set_pmd(pmdp, pmd)
 
 static inline int has_transparent_hugepage(void)
@@ -286,11 +277,9 @@ static inline int has_transparent_hugepage(void)
  * Mark the prot value as uncacheable and unbufferable.
  */
 #define pgprot_noncached(prot) \
-       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE))
+       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
 #define pgprot_writecombine(prot) \
-       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
-#define pgprot_dmacoherent(prot) \
-       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
+       __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
 #define __HAVE_PHYS_MEM_ACCESS_PROT
 struct file;
 extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
@@ -383,6 +372,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
        return pte;
 }
 
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+       return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
+}
+
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
 
index e5312ea0ec1a59bdd92934926da81155a6ce3e12..d15ab8b463360869553f4ecfa4cc255d4c8455e3 100644 (file)
@@ -14,6 +14,6 @@
 #ifndef __ASM_PSCI_H
 #define __ASM_PSCI_H
 
-int psci_init(void);
+void psci_init(void);
 
 #endif /* __ASM_PSCI_H */
index 0e7fa49637359ab3cd4757565174d4e63f191cf0..c7ba261dd4b37b8b1ecb1a06d5a4fe7b583a3d92 100644 (file)
@@ -68,6 +68,7 @@
 
 /* Architecturally defined mapping between AArch32 and AArch64 registers */
 #define compat_usr(x)  regs[(x)]
+#define compat_fp      regs[11]
 #define compat_sp      regs[13]
 #define compat_lr      regs[14]
 #define compat_sp_hyp  regs[15]
@@ -132,7 +133,7 @@ struct pt_regs {
        (!((regs)->pstate & PSR_F_BIT))
 
 #define user_stack_pointer(regs) \
-       ((regs)->sp)
+       (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
 
 /*
  * Are the current registers suitable for user mode? (used to maintain
@@ -164,7 +165,7 @@ static inline int valid_user_regs(struct user_pt_regs *regs)
        return 0;
 }
 
-#define instruction_pointer(regs)      (regs)->pc
+#define instruction_pointer(regs)      ((unsigned long)(regs)->pc)
 
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *regs);
index 3d5cf064d7a1702992cb89d0fe0914475ae4b1ee..c45b7b1b71978c6a71b58ef623c30c4e3f652393 100644 (file)
@@ -132,7 +132,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
        "       cbnz    %w0, 2b\n"
        : "=&r" (tmp), "+Q" (rw->lock)
        : "r" (0x80000000)
-       : "cc", "memory");
+       : "memory");
 }
 
 static inline int arch_write_trylock(arch_rwlock_t *rw)
@@ -146,7 +146,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
        "1:\n"
        : "=&r" (tmp), "+Q" (rw->lock)
        : "r" (0x80000000)
-       : "cc", "memory");
+       : "memory");
 
        return !tmp;
 }
@@ -187,7 +187,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
        "       cbnz    %w1, 2b\n"
        : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
        :
-       : "cc", "memory");
+       : "memory");
 }
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
@@ -201,7 +201,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
        "       cbnz    %w1, 1b\n"
        : "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
        :
-       : "cc", "memory");
+       : "memory");
 }
 
 static inline int arch_read_trylock(arch_rwlock_t *rw)
@@ -216,7 +216,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
        "1:\n"
        : "=&r" (tmp), "+r" (tmp2), "+Q" (rw->lock)
        :
-       : "cc", "memory");
+       : "memory");
 
        return !tmp2;
 }
index 717031a762c27966aabc7786f6d2a900034b0b08..72cadf52ca807f181261b1599b25944374de5544 100644 (file)
 #ifndef __ASM_TLB_H
 #define __ASM_TLB_H
 
-#include <linux/pagemap.h>
-#include <linux/swap.h>
 
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-
-#define MMU_GATHER_BUNDLE      8
-
-/*
- * TLB handling.  This allows us to remove pages from the page
- * tables, and efficiently handle the TLB issues.
- */
-struct mmu_gather {
-       struct mm_struct        *mm;
-       unsigned int            fullmm;
-       struct vm_area_struct   *vma;
-       unsigned long           start, end;
-       unsigned long           range_start;
-       unsigned long           range_end;
-       unsigned int            nr;
-       unsigned int            max;
-       struct page             **pages;
-       struct page             *local[MMU_GATHER_BUNDLE];
-};
+#include <asm-generic/tlb.h>
 
 /*
- * This is unnecessarily complex.  There's three ways the TLB shootdown
- * code is used:
+ * There's three ways the TLB shootdown code is used:
  *  1. Unmapping a range of vmas.  See zap_page_range(), unmap_region().
  *     tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called.
- *     tlb->vma will be non-NULL.
  *  2. Unmapping all vmas.  See exit_mmap().
  *     tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called.
- *     tlb->vma will be non-NULL.  Additionally, page tables will be freed.
+ *     Page tables will be freed.
  *  3. Unmapping argument pages.  See shift_arg_pages().
  *     tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called.
- *     tlb->vma will be NULL.
  */
 static inline void tlb_flush(struct mmu_gather *tlb)
 {
-       if (tlb->fullmm || !tlb->vma)
+       if (tlb->fullmm) {
                flush_tlb_mm(tlb->mm);
-       else if (tlb->range_end > 0) {
-               flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end);
-               tlb->range_start = TASK_SIZE;
-               tlb->range_end = 0;
+       } else if (tlb->end > 0) {
+               struct vm_area_struct vma = { .vm_mm = tlb->mm, };
+               flush_tlb_range(&vma, tlb->start, tlb->end);
+               tlb->start = TASK_SIZE;
+               tlb->end = 0;
        }
 }
 
 static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr)
 {
        if (!tlb->fullmm) {
-               if (addr < tlb->range_start)
-                       tlb->range_start = addr;
-               if (addr + PAGE_SIZE > tlb->range_end)
-                       tlb->range_end = addr + PAGE_SIZE;
-       }
-}
-
-static inline void __tlb_alloc_page(struct mmu_gather *tlb)
-{
-       unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
-
-       if (addr) {
-               tlb->pages = (void *)addr;
-               tlb->max = PAGE_SIZE / sizeof(struct page *);
+               tlb->start = min(tlb->start, addr);
+               tlb->end = max(tlb->end, addr + PAGE_SIZE);
        }
 }
 
-static inline void tlb_flush_mmu(struct mmu_gather *tlb)
-{
-       tlb_flush(tlb);
-       free_pages_and_swap_cache(tlb->pages, tlb->nr);
-       tlb->nr = 0;
-       if (tlb->pages == tlb->local)
-               __tlb_alloc_page(tlb);
-}
-
-static inline void
-tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-       tlb->mm = mm;
-       tlb->fullmm = !(start | (end+1));
-       tlb->start = start;
-       tlb->end = end;
-       tlb->vma = NULL;
-       tlb->max = ARRAY_SIZE(tlb->local);
-       tlb->pages = tlb->local;
-       tlb->nr = 0;
-       __tlb_alloc_page(tlb);
-}
-
-static inline void
-tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
-{
-       tlb_flush_mmu(tlb);
-
-       /* keep the page table cache within bounds */
-       check_pgt_cache();
-
-       if (tlb->pages != tlb->local)
-               free_pages((unsigned long)tlb->pages, 0);
-}
-
 /*
  * Memorize the range for the TLB flush.
  */
-static inline void
-tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
+static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
+                                         unsigned long addr)
 {
        tlb_add_flush(tlb, addr);
 }
@@ -137,38 +66,24 @@ tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
  * case where we're doing a full MM flush.  When we're doing a munmap,
  * the vmas are adjusted to only cover the region to be torn down.
  */
-static inline void
-tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+static inline void tlb_start_vma(struct mmu_gather *tlb,
+                                struct vm_area_struct *vma)
 {
        if (!tlb->fullmm) {
-               tlb->vma = vma;
-               tlb->range_start = TASK_SIZE;
-               tlb->range_end = 0;
+               tlb->start = TASK_SIZE;
+               tlb->end = 0;
        }
 }
 
-static inline void
-tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+static inline void tlb_end_vma(struct mmu_gather *tlb,
+                              struct vm_area_struct *vma)
 {
        if (!tlb->fullmm)
                tlb_flush(tlb);
 }
 
-static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
-{
-       tlb->pages[tlb->nr++] = page;
-       VM_BUG_ON(tlb->nr > tlb->max);
-       return tlb->max - tlb->nr;
-}
-
-static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
-{
-       if (!__tlb_remove_page(tlb, page))
-               tlb_flush_mmu(tlb);
-}
-
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
-       unsigned long addr)
+                                 unsigned long addr)
 {
        pgtable_page_dtor(pte);
        tlb_add_flush(tlb, addr);
@@ -184,16 +99,5 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
 }
 #endif
 
-#define pte_free_tlb(tlb, ptep, addr)  __pte_free_tlb(tlb, ptep, addr)
-#define pmd_free_tlb(tlb, pmdp, addr)  __pmd_free_tlb(tlb, pmdp, addr)
-#define pud_free_tlb(tlb, pudp, addr)  pud_free((tlb)->mm, pudp)
-
-#define tlb_migrate_finish(mm)         do { } while (0)
-
-static inline void
-tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
-{
-       tlb_add_flush(tlb, addr);
-}
 
 #endif
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
new file mode 100644 (file)
index 0000000..0172e6d
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __ASM_TOPOLOGY_H
+#define __ASM_TOPOLOGY_H
+
+#ifdef CONFIG_SMP
+
+#include <linux/cpumask.h>
+
+struct cpu_topology {
+       int thread_id;
+       int core_id;
+       int cluster_id;
+       cpumask_t thread_sibling;
+       cpumask_t core_sibling;
+};
+
+extern struct cpu_topology cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu)      (cpu_topology[cpu].cluster_id)
+#define topology_core_id(cpu)          (cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu)     (&cpu_topology[cpu].core_sibling)
+#define topology_thread_cpumask(cpu)   (&cpu_topology[cpu].thread_sibling)
+
+#define mc_capable()   (cpu_topology[0].cluster_id != -1)
+#define smt_capable()  (cpu_topology[0].thread_id != -1)
+
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(int cpu);
+
+#else
+
+static inline void init_cpu_topology(void) { }
+static inline void store_cpu_topology(unsigned int cpuid) { }
+
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_ARM_TOPOLOGY_H */
index 6c0f684aca81ce2da8b71c18cf2fb659c62ceaab..3bf8f4e99a511c67a3a2d9c4a739929cedd5889f 100644 (file)
@@ -83,7 +83,7 @@ static inline void set_fs(mm_segment_t fs)
  * Returns 1 if the range is valid, 0 otherwise.
  *
  * This is equivalent to the following test:
- * (u65)addr + (u65)size < (u65)current->addr_limit
+ * (u65)addr + (u65)size <current->addr_limit
  *
  * This needs 65-bit arithmetic.
  */
@@ -91,7 +91,7 @@ static inline void set_fs(mm_segment_t fs)
 ({                                                                     \
        unsigned long flag, roksum;                                     \
        __chk_user_ptr(addr);                                           \
-       asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, cc"         \
+       asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls"         \
                : "=&r" (flag), "=&r" (roksum)                          \
                : "1" (addr), "Ir" (size),                              \
                  "r" (current_thread_info()->addr_limit)               \
index 82ce217e94cf07228e52ebbfae9e9bcdeb751de1..a4654c656a1eda3c07f682a8eda7acdfd8e18a31 100644 (file)
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifdef CONFIG_COMPAT
+#define __ARCH_WANT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
index 58125bf008d3e647e5c89e6ba534827f0a0d5629..bb8eb8a78e67d2c7906f40aa0f4db2ef0c4ef5f5 100644 (file)
@@ -399,7 +399,10 @@ __SYSCALL(374, compat_sys_sendmmsg)
 __SYSCALL(375, sys_setns)
 __SYSCALL(376, compat_sys_process_vm_readv)
 __SYSCALL(377, compat_sys_process_vm_writev)
-__SYSCALL(378, sys_ni_syscall)                 /* 378 for kcmp */
+__SYSCALL(378, sys_kcmp)
+__SYSCALL(379, sys_finit_module)
+__SYSCALL(380, sys_sched_setattr)
+__SYSCALL(381, sys_sched_getattr)
 
 #define __NR_compat_syscalls           379
 
index e4b78bdca19e81b373251cf228917d3a8eab0a60..942376d37d220fc359c6afc35ef3004c9a2074a2 100644 (file)
@@ -9,6 +9,7 @@ header-y += byteorder.h
 header-y += fcntl.h
 header-y += hwcap.h
 header-y += kvm_para.h
+header-y += perf_regs.h
 header-y += param.h
 header-y += ptrace.h
 header-y += setup.h
index 495ab6f84a6117a43344a49707bd400698bcf737..eaf54a30bedcef3ee1b88b93e2e0f4741f0ef10d 100644 (file)
@@ -148,6 +148,15 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_TIMER_CNT          ARM64_SYS_REG(3, 3, 14, 3, 2)
 #define KVM_REG_ARM_TIMER_CVAL         ARM64_SYS_REG(3, 3, 14, 0, 2)
 
+/* Device Control API: ARM VGIC */
+#define KVM_DEV_ARM_VGIC_GRP_ADDR      0
+#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
+#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS  2
+#define   KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
+#define   KVM_DEV_ARM_VGIC_CPUID_MASK  (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT        0
+#define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_TYPE_SHIFT         24
 #define KVM_ARM_IRQ_TYPE_MASK          0xff
diff --git a/arch/arm64/include/uapi/asm/perf_regs.h b/arch/arm64/include/uapi/asm/perf_regs.h
new file mode 100644 (file)
index 0000000..172b831
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _ASM_ARM64_PERF_REGS_H
+#define _ASM_ARM64_PERF_REGS_H
+
+enum perf_event_arm_regs {
+       PERF_REG_ARM64_X0,
+       PERF_REG_ARM64_X1,
+       PERF_REG_ARM64_X2,
+       PERF_REG_ARM64_X3,
+       PERF_REG_ARM64_X4,
+       PERF_REG_ARM64_X5,
+       PERF_REG_ARM64_X6,
+       PERF_REG_ARM64_X7,
+       PERF_REG_ARM64_X8,
+       PERF_REG_ARM64_X9,
+       PERF_REG_ARM64_X10,
+       PERF_REG_ARM64_X11,
+       PERF_REG_ARM64_X12,
+       PERF_REG_ARM64_X13,
+       PERF_REG_ARM64_X14,
+       PERF_REG_ARM64_X15,
+       PERF_REG_ARM64_X16,
+       PERF_REG_ARM64_X17,
+       PERF_REG_ARM64_X18,
+       PERF_REG_ARM64_X19,
+       PERF_REG_ARM64_X20,
+       PERF_REG_ARM64_X21,
+       PERF_REG_ARM64_X22,
+       PERF_REG_ARM64_X23,
+       PERF_REG_ARM64_X24,
+       PERF_REG_ARM64_X25,
+       PERF_REG_ARM64_X26,
+       PERF_REG_ARM64_X27,
+       PERF_REG_ARM64_X28,
+       PERF_REG_ARM64_X29,
+       PERF_REG_ARM64_LR,
+       PERF_REG_ARM64_SP,
+       PERF_REG_ARM64_PC,
+       PERF_REG_ARM64_MAX,
+};
+#endif /* _ASM_ARM64_PERF_REGS_H */
index 2d4554b134100acbb6dab937326bdabcb12cd73e..7d811d9522bc4fca5e12b035460a56337b68f13e 100644 (file)
@@ -14,12 +14,14 @@ arm64-obj-y         := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
 arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
                                           sys_compat.o
 arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
-arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o
+arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o topology.o
+arm64-obj-$(CONFIG_PERF_EVENTS)                += perf_regs.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
-arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
+arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
 arm64-obj-$(CONFIG_EARLY_PRINTK)       += early_printk.o
 arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND)  += sleep.o suspend.o
 arm64-obj-$(CONFIG_JUMP_LABEL)         += jump_label.o
+arm64-obj-$(CONFIG_KGDB)               += kgdb.o
 
 obj-y                                  += $(arm64-obj-y) vdso/
 obj-m                                  += $(arm64-obj-m)
index 636ba8b6240b8042e9c49622297bbca74e140181..14ba23c6115367b962922e5decd3afabb59e789e 100644 (file)
@@ -137,7 +137,6 @@ void disable_debug_monitors(enum debug_el el)
 static void clear_os_lock(void *unused)
 {
        asm volatile("msr oslar_el1, %0" : : "r" (0));
-       isb();
 }
 
 static int os_lock_notify(struct notifier_block *self,
@@ -156,8 +155,9 @@ static struct notifier_block os_lock_nb = {
 static int debug_monitors_init(void)
 {
        /* Clear the OS lock. */
-       smp_call_function(clear_os_lock, NULL, 1);
-       clear_os_lock(NULL);
+       on_each_cpu(clear_os_lock, NULL, 1);
+       isb();
+       local_dbg_enable();
 
        /* Register hotplug handler. */
        register_cpu_notifier(&os_lock_nb);
@@ -189,7 +189,7 @@ static void clear_regs_spsr_ss(struct pt_regs *regs)
 
 /* EL1 Single Step Handler hooks */
 static LIST_HEAD(step_hook);
-DEFINE_RWLOCK(step_hook_lock);
+static DEFINE_RWLOCK(step_hook_lock);
 
 void register_step_hook(struct step_hook *hook)
 {
@@ -276,7 +276,7 @@ static int single_step_handler(unsigned long addr, unsigned int esr,
  * Use reader/writer locks instead of plain spinlock.
  */
 static LIST_HEAD(break_hook);
-DEFINE_RWLOCK(break_hook_lock);
+static DEFINE_RWLOCK(break_hook_lock);
 
 void register_break_hook(struct break_hook *hook)
 {
index 0b281fffda5199dab76eeaa8f729609570fe6310..61035d6814cbcca9a7bb9be06e92e44446256f25 100644 (file)
@@ -384,26 +384,18 @@ ENDPROC(__calc_phys_offset)
  * Preserves:  tbl, flags
  * Corrupts:   phys, start, end, pstate
  */
-       .macro  create_block_map, tbl, flags, phys, start, end, idmap=0
+       .macro  create_block_map, tbl, flags, phys, start, end
        lsr     \phys, \phys, #BLOCK_SHIFT
-       .if     \idmap
-       and     \start, \phys, #PTRS_PER_PTE - 1        // table index
-       .else
        lsr     \start, \start, #BLOCK_SHIFT
        and     \start, \start, #PTRS_PER_PTE - 1       // table index
-       .endif
        orr     \phys, \flags, \phys, lsl #BLOCK_SHIFT  // table entry
-       .ifnc   \start,\end
        lsr     \end, \end, #BLOCK_SHIFT
        and     \end, \end, #PTRS_PER_PTE - 1           // table end index
-       .endif
 9999:  str     \phys, [\tbl, \start, lsl #3]           // store the entry
-       .ifnc   \start,\end
        add     \start, \start, #1                      // next entry
        add     \phys, \phys, #BLOCK_SIZE               // next block
        cmp     \start, \end
        b.ls    9999b
-       .endif
        .endm
 
 /*
@@ -435,9 +427,13 @@ __create_page_tables:
         * Create the identity mapping.
         */
        add     x0, x25, #PAGE_SIZE             // section table address
-       adr     x3, __turn_mmu_on               // virtual/physical address
+       ldr     x3, =KERNEL_START
+       add     x3, x3, x28                     // __pa(KERNEL_START)
        create_pgd_entry x25, x0, x3, x5, x6
-       create_block_map x0, x7, x3, x5, x5, idmap=1
+       ldr     x6, =KERNEL_END
+       mov     x5, x3                          // __pa(KERNEL_START)
+       add     x6, x6, x28                     // __pa(KERNEL_END)
+       create_block_map x0, x7, x3, x5, x6
 
        /*
         * Map the kernel image (starting with PHYS_OFFSET).
@@ -445,7 +441,7 @@ __create_page_tables:
        add     x0, x26, #PAGE_SIZE             // section table address
        mov     x5, #PAGE_OFFSET
        create_pgd_entry x26, x0, x5, x3, x6
-       ldr     x6, =KERNEL_END - 1
+       ldr     x6, =KERNEL_END
        mov     x3, x24                         // phys offset
        create_block_map x0, x7, x3, x5, x6
 
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
new file mode 100644 (file)
index 0000000..75c9cf1
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * AArch64 KGDB support
+ *
+ * Based on arch/arm/kernel/kgdb.c
+ *
+ * Copyright (C) 2013 Cavium Inc.
+ * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irq.h>
+#include <linux/kdebug.h>
+#include <linux/kgdb.h>
+#include <asm/traps.h>
+
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
+       { "x0", 8, offsetof(struct pt_regs, regs[0])},
+       { "x1", 8, offsetof(struct pt_regs, regs[1])},
+       { "x2", 8, offsetof(struct pt_regs, regs[2])},
+       { "x3", 8, offsetof(struct pt_regs, regs[3])},
+       { "x4", 8, offsetof(struct pt_regs, regs[4])},
+       { "x5", 8, offsetof(struct pt_regs, regs[5])},
+       { "x6", 8, offsetof(struct pt_regs, regs[6])},
+       { "x7", 8, offsetof(struct pt_regs, regs[7])},
+       { "x8", 8, offsetof(struct pt_regs, regs[8])},
+       { "x9", 8, offsetof(struct pt_regs, regs[9])},
+       { "x10", 8, offsetof(struct pt_regs, regs[10])},
+       { "x11", 8, offsetof(struct pt_regs, regs[11])},
+       { "x12", 8, offsetof(struct pt_regs, regs[12])},
+       { "x13", 8, offsetof(struct pt_regs, regs[13])},
+       { "x14", 8, offsetof(struct pt_regs, regs[14])},
+       { "x15", 8, offsetof(struct pt_regs, regs[15])},
+       { "x16", 8, offsetof(struct pt_regs, regs[16])},
+       { "x17", 8, offsetof(struct pt_regs, regs[17])},
+       { "x18", 8, offsetof(struct pt_regs, regs[18])},
+       { "x19", 8, offsetof(struct pt_regs, regs[19])},
+       { "x20", 8, offsetof(struct pt_regs, regs[20])},
+       { "x21", 8, offsetof(struct pt_regs, regs[21])},
+       { "x22", 8, offsetof(struct pt_regs, regs[22])},
+       { "x23", 8, offsetof(struct pt_regs, regs[23])},
+       { "x24", 8, offsetof(struct pt_regs, regs[24])},
+       { "x25", 8, offsetof(struct pt_regs, regs[25])},
+       { "x26", 8, offsetof(struct pt_regs, regs[26])},
+       { "x27", 8, offsetof(struct pt_regs, regs[27])},
+       { "x28", 8, offsetof(struct pt_regs, regs[28])},
+       { "x29", 8, offsetof(struct pt_regs, regs[29])},
+       { "x30", 8, offsetof(struct pt_regs, regs[30])},
+       { "sp", 8, offsetof(struct pt_regs, sp)},
+       { "pc", 8, offsetof(struct pt_regs, pc)},
+       { "pstate", 8, offsetof(struct pt_regs, pstate)},
+       { "v0", 16, -1 },
+       { "v1", 16, -1 },
+       { "v2", 16, -1 },
+       { "v3", 16, -1 },
+       { "v4", 16, -1 },
+       { "v5", 16, -1 },
+       { "v6", 16, -1 },
+       { "v7", 16, -1 },
+       { "v8", 16, -1 },
+       { "v9", 16, -1 },
+       { "v10", 16, -1 },
+       { "v11", 16, -1 },
+       { "v12", 16, -1 },
+       { "v13", 16, -1 },
+       { "v14", 16, -1 },
+       { "v15", 16, -1 },
+       { "v16", 16, -1 },
+       { "v17", 16, -1 },
+       { "v18", 16, -1 },
+       { "v19", 16, -1 },
+       { "v20", 16, -1 },
+       { "v21", 16, -1 },
+       { "v22", 16, -1 },
+       { "v23", 16, -1 },
+       { "v24", 16, -1 },
+       { "v25", 16, -1 },
+       { "v26", 16, -1 },
+       { "v27", 16, -1 },
+       { "v28", 16, -1 },
+       { "v29", 16, -1 },
+       { "v30", 16, -1 },
+       { "v31", 16, -1 },
+       { "fpsr", 4, -1 },
+       { "fpcr", 4, -1 },
+};
+
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+       if (regno >= DBG_MAX_REG_NUM || regno < 0)
+               return NULL;
+
+       if (dbg_reg_def[regno].offset != -1)
+               memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
+                      dbg_reg_def[regno].size);
+       else
+               memset(mem, 0, dbg_reg_def[regno].size);
+       return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+       if (regno >= DBG_MAX_REG_NUM || regno < 0)
+               return -EINVAL;
+
+       if (dbg_reg_def[regno].offset != -1)
+               memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
+                      dbg_reg_def[regno].size);
+       return 0;
+}
+
+void
+sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
+{
+       struct pt_regs *thread_regs;
+
+       /* Initialize to zero */
+       memset((char *)gdb_regs, 0, NUMREGBYTES);
+       thread_regs = task_pt_regs(task);
+       memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES);
+}
+
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+       regs->pc = pc;
+}
+
+static int compiled_break;
+
+static void kgdb_arch_update_addr(struct pt_regs *regs,
+                               char *remcom_in_buffer)
+{
+       unsigned long addr;
+       char *ptr;
+
+       ptr = &remcom_in_buffer[1];
+       if (kgdb_hex2long(&ptr, &addr))
+               kgdb_arch_set_pc(regs, addr);
+       else if (compiled_break == 1)
+               kgdb_arch_set_pc(regs, regs->pc + 4);
+
+       compiled_break = 0;
+}
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+                              int err_code, char *remcom_in_buffer,
+                              char *remcom_out_buffer,
+                              struct pt_regs *linux_regs)
+{
+       int err;
+
+       switch (remcom_in_buffer[0]) {
+       case 'D':
+       case 'k':
+               /*
+                * Packet D (Detach), k (kill). No special handling
+                * is required here. Handle same as c packet.
+                */
+       case 'c':
+               /*
+                * Packet c (Continue) to continue executing.
+                * Set pc to required address.
+                * Try to read optional parameter and set pc.
+                * If this was a compiled breakpoint, we need to move
+                * to the next instruction else we will just breakpoint
+                * over and over again.
+                */
+               kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
+               atomic_set(&kgdb_cpu_doing_single_step, -1);
+               kgdb_single_step =  0;
+
+               /*
+                * Received continue command, disable single step
+                */
+               if (kernel_active_single_step())
+                       kernel_disable_single_step();
+
+               err = 0;
+               break;
+       case 's':
+               /*
+                * Update step address value with address passed
+                * with step packet.
+                * On debug exception return PC is copied to ELR
+                * So just update PC.
+                * If no step address is passed, resume from the address
+                * pointed by PC. Do not update PC
+                */
+               kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
+               atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
+               kgdb_single_step =  1;
+
+               /*
+                * Enable single step handling
+                */
+               if (!kernel_active_single_step())
+                       kernel_enable_single_step(linux_regs);
+               err = 0;
+               break;
+       default:
+               err = -1;
+       }
+       return err;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr)
+{
+       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+       return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr)
+{
+       compiled_break = 1;
+       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+       return 0;
+}
+
+static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
+{
+       kgdb_handle_exception(1, SIGTRAP, 0, regs);
+       return 0;
+}
+
+static struct break_hook kgdb_brkpt_hook = {
+       .esr_mask       = 0xffffffff,
+       .esr_val        = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM),
+       .fn             = kgdb_brk_fn
+};
+
+static struct break_hook kgdb_compiled_brkpt_hook = {
+       .esr_mask       = 0xffffffff,
+       .esr_val        = DBG_ESR_VAL_BRK(KDBG_COMPILED_DBG_BRK_IMM),
+       .fn             = kgdb_compiled_brk_fn
+};
+
+static struct step_hook kgdb_step_hook = {
+       .fn             = kgdb_step_brk_fn
+};
+
+static void kgdb_call_nmi_hook(void *ignored)
+{
+       kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+       local_irq_enable();
+       smp_call_function(kgdb_call_nmi_hook, NULL, 0);
+       local_irq_disable();
+}
+
+static int __kgdb_notify(struct die_args *args, unsigned long cmd)
+{
+       struct pt_regs *regs = args->regs;
+
+       if (kgdb_handle_exception(1, args->signr, cmd, regs))
+               return NOTIFY_DONE;
+       return NOTIFY_STOP;
+}
+
+static int
+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
+{
+       unsigned long flags;
+       int ret;
+
+       local_irq_save(flags);
+       ret = __kgdb_notify(ptr, cmd);
+       local_irq_restore(flags);
+
+       return ret;
+}
+
+static struct notifier_block kgdb_notifier = {
+       .notifier_call  = kgdb_notify,
+       /*
+        * Want to be lowest priority
+        */
+       .priority       = -INT_MAX,
+};
+
+/*
+ * kgdb_arch_init - Perform any architecture specific initalization.
+ * This function will handle the initalization of any architecture
+ * specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+       int ret = register_die_notifier(&kgdb_notifier);
+
+       if (ret != 0)
+               return ret;
+
+       register_break_hook(&kgdb_brkpt_hook);
+       register_break_hook(&kgdb_compiled_brkpt_hook);
+       register_step_hook(&kgdb_step_hook);
+       return 0;
+}
+
+/*
+ * kgdb_arch_exit - Perform any architecture specific uninitalization.
+ * This function will handle the uninitalization of any architecture
+ * specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+       unregister_break_hook(&kgdb_brkpt_hook);
+       unregister_break_hook(&kgdb_compiled_brkpt_hook);
+       unregister_step_hook(&kgdb_step_hook);
+       unregister_die_notifier(&kgdb_notifier);
+}
+
+/*
+ * ARM instructions are always in LE.
+ * Break instruction is encoded in LE format
+ */
+struct kgdb_arch arch_kgdb_ops = {
+       .gdb_bpt_instr = {
+               KGDB_DYN_BRK_INS_BYTE0,
+               KGDB_DYN_BRK_INS_BYTE1,
+               KGDB_DYN_BRK_INS_BYTE2,
+               KGDB_DYN_BRK_INS_BYTE3,
+       }
+};
index 63c48ffdf230125dedea62d631b3067f4d7a28e1..7787208e8cc6af3a4ff55226fb85ef6b8f8d30ba 100644 (file)
@@ -38,12 +38,13 @@ __kuser_cmpxchg64:                  // 0xffff0f60
        .inst   0xe92d00f0              //      push            {r4, r5, r6, r7}
        .inst   0xe1c040d0              //      ldrd            r4, r5, [r0]
        .inst   0xe1c160d0              //      ldrd            r6, r7, [r1]
-       .inst   0xe1b20e9f              // 1:   ldaexd          r0, r1, [r2]
+       .inst   0xe1b20f9f              // 1:   ldrexd          r0, r1, [r2]
        .inst   0xe0303004              //      eors            r3, r0, r4
        .inst   0x00313005              //      eoreqs          r3, r1, r5
        .inst   0x01a23e96              //      stlexdeq        r3, r6, [r2]
        .inst   0x03330001              //      teqeq           r3, #1
        .inst   0x0afffff9              //      beq             1b
+       .inst   0xf57ff05b              //      dmb             ish
        .inst   0xe2730000              //      rsbs            r0, r3, #0
        .inst   0xe8bd00f0              //      pop             {r4, r5, r6, r7}
        .inst   0xe12fff1e              //      bx              lr
@@ -55,11 +56,12 @@ __kuser_memory_barrier:                     // 0xffff0fa0
 
        .align  5
 __kuser_cmpxchg:                       // 0xffff0fc0
-       .inst   0xe1923e9f              // 1:   ldaex           r3, [r2]
+       .inst   0xe1923f9f              // 1:   ldrex           r3, [r2]
        .inst   0xe0533000              //      subs            r3, r3, r0
        .inst   0x01823e91              //      stlexeq         r3, r1, [r2]
        .inst   0x03330001              //      teqeq           r3, #1
        .inst   0x0afffffa              //      beq             1b
+       .inst   0xf57ff05b              //      dmb             ish
        .inst   0xe2730000              //      rsbs            r0, r3, #0
        .inst   0xe12fff1e              //      bx              lr
 
index 5b1cd792274a34cc620933e2258530b20cfdfa40..e868c72a79389c133559fc4c1599a197a33c195b 100644 (file)
@@ -1348,8 +1348,8 @@ early_initcall(init_hw_perf_events);
  * Callchain handling code.
  */
 struct frame_tail {
-       struct frame_tail   __user *fp;
-       unsigned long       lr;
+       struct frame_tail       __user *fp;
+       unsigned long           lr;
 } __attribute__((packed));
 
 /*
@@ -1386,22 +1386,80 @@ user_backtrace(struct frame_tail __user *tail,
        return buftail.fp;
 }
 
+/*
+ * The registers we're interested in are at the end of the variable
+ * length saved register structure. The fp points at the end of this
+ * structure so the address of this struct is:
+ * (struct compat_frame_tail *)(xxx->fp)-1
+ *
+ * This code has been adapted from the ARM OProfile support.
+ */
+struct compat_frame_tail {
+       compat_uptr_t   fp; /* a (struct compat_frame_tail *) in compat mode */
+       u32             sp;
+       u32             lr;
+} __attribute__((packed));
+
+static struct compat_frame_tail __user *
+compat_user_backtrace(struct compat_frame_tail __user *tail,
+                     struct perf_callchain_entry *entry)
+{
+       struct compat_frame_tail buftail;
+       unsigned long err;
+
+       /* Also check accessibility of one struct frame_tail beyond */
+       if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
+               return NULL;
+
+       pagefault_disable();
+       err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
+       pagefault_enable();
+
+       if (err)
+               return NULL;
+
+       perf_callchain_store(entry, buftail.lr);
+
+       /*
+        * Frame pointers should strictly progress back up the stack
+        * (towards higher addresses).
+        */
+       if (tail + 1 >= (struct compat_frame_tail __user *)
+                       compat_ptr(buftail.fp))
+               return NULL;
+
+       return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
+}
+
 void perf_callchain_user(struct perf_callchain_entry *entry,
                         struct pt_regs *regs)
 {
-       struct frame_tail __user *tail;
-
        if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
                /* We don't support guest os callchain now */
                return;
        }
 
        perf_callchain_store(entry, regs->pc);
-       tail = (struct frame_tail __user *)regs->regs[29];
 
-       while (entry->nr < PERF_MAX_STACK_DEPTH &&
-              tail && !((unsigned long)tail & 0xf))
-               tail = user_backtrace(tail, entry);
+       if (!compat_user_mode(regs)) {
+               /* AARCH64 mode */
+               struct frame_tail __user *tail;
+
+               tail = (struct frame_tail __user *)regs->regs[29];
+
+               while (entry->nr < PERF_MAX_STACK_DEPTH &&
+                      tail && !((unsigned long)tail & 0xf))
+                       tail = user_backtrace(tail, entry);
+       } else {
+               /* AARCH32 compat mode */
+               struct compat_frame_tail __user *tail;
+
+               tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
+
+               while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+                       tail && !((unsigned long)tail & 0x3))
+                       tail = compat_user_backtrace(tail, entry);
+       }
 }
 
 /*
@@ -1429,6 +1487,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
        frame.fp = regs->regs[29];
        frame.sp = regs->sp;
        frame.pc = regs->pc;
+
        walk_stackframe(&frame, callchain_trace, entry);
 }
 
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
new file mode 100644 (file)
index 0000000..f2d6f0a
--- /dev/null
@@ -0,0 +1,44 @@
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <asm/perf_regs.h>
+#include <asm/ptrace.h>
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+       if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX))
+               return 0;
+
+       /*
+        * Compat (i.e. 32 bit) mode:
+        * - PC has been set in the pt_regs struct in kernel_entry,
+        * - Handle SP and LR here.
+        */
+       if (compat_user_mode(regs)) {
+               if ((u32)idx == PERF_REG_ARM64_SP)
+                       return regs->compat_sp;
+               if ((u32)idx == PERF_REG_ARM64_LR)
+                       return regs->compat_lr;
+       }
+
+       return regs->regs[idx];
+}
+
+#define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1))
+
+int perf_reg_validate(u64 mask)
+{
+       if (!mask || mask & REG_RESERVED)
+               return -EINVAL;
+
+       return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+       if (is_compat_thread(task_thread_info(task)))
+               return PERF_SAMPLE_REGS_ABI_32;
+       else
+               return PERF_SAMPLE_REGS_ABI_64;
+}
index 1c0a9be2ffa85ad87245ac5837c94149e246533a..6391485f342daaac57e207f129a62e28d169b114 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kallsyms.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
-#include <linux/cpuidle.h>
 #include <linux/elfcore.h>
 #include <linux/pm.h>
 #include <linux/tick.h>
@@ -72,8 +71,17 @@ static void setup_restart(void)
 
 void soft_restart(unsigned long addr)
 {
+       typedef void (*phys_reset_t)(unsigned long);
+       phys_reset_t phys_reset;
+
        setup_restart();
-       cpu_reset(addr);
+
+       /* Switch to the identity mapping */
+       phys_reset = (phys_reset_t)virt_to_phys(cpu_reset);
+       phys_reset(addr);
+
+       /* Should never get here */
+       BUG();
 }
 
 /*
@@ -94,10 +102,8 @@ void arch_cpu_idle(void)
         * This should do all the clock switching and wait for interrupt
         * tricks
         */
-       if (cpuidle_idle_call()) {
-               cpu_do_idle();
-               local_irq_enable();
-       }
+       cpu_do_idle();
+       local_irq_enable();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index 4f97db3d73633294f6a6310e54e626972debc9a2..ea4828a4aa96729993d85145603ed45afba7ac03 100644 (file)
@@ -176,22 +176,20 @@ static const struct of_device_id psci_of_match[] __initconst = {
        {},
 };
 
-int __init psci_init(void)
+void __init psci_init(void)
 {
        struct device_node *np;
        const char *method;
        u32 id;
-       int err = 0;
 
        np = of_find_matching_node(NULL, psci_of_match);
        if (!np)
-               return -ENODEV;
+               return;
 
        pr_info("probing function IDs from device-tree\n");
 
        if (of_property_read_string(np, "method", &method)) {
                pr_warning("missing \"method\" property\n");
-               err = -ENXIO;
                goto out_put_node;
        }
 
@@ -201,7 +199,6 @@ int __init psci_init(void)
                invoke_psci_fn = __invoke_psci_fn_smc;
        } else {
                pr_warning("invalid \"method\" property: %s\n", method);
-               err = -EINVAL;
                goto out_put_node;
        }
 
@@ -227,7 +224,7 @@ int __init psci_init(void)
 
 out_put_node:
        of_node_put(np);
-       return err;
+       return;
 }
 
 #ifdef CONFIG_SMP
@@ -251,7 +248,7 @@ static int cpu_psci_cpu_boot(unsigned int cpu)
 {
        int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry));
        if (err)
-               pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
+               pr_err("failed to boot CPU%d (%d)\n", cpu, err);
 
        return err;
 }
@@ -278,7 +275,7 @@ static void cpu_psci_cpu_die(unsigned int cpu)
 
        ret = psci_ops.cpu_off(state);
 
-       pr_crit("psci: unable to power off CPU%u (%d)\n", cpu, ret);
+       pr_crit("unable to power off CPU%u (%d)\n", cpu, ret);
 }
 #endif
 
index c8e9effe52e10f6b59d39de293aca7607f7d5bce..67da30741a1b64a73ce085739209d7bf085ac2e9 100644 (file)
@@ -69,6 +69,7 @@ EXPORT_SYMBOL_GPL(elf_hwcap);
                                 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
                                 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
 unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
+unsigned int compat_elf_hwcap2 __read_mostly;
 #endif
 
 static const char *cpu_name;
@@ -242,6 +243,38 @@ static void __init setup_processor(void)
        block = (features >> 16) & 0xf;
        if (block && !(block & 0x8))
                elf_hwcap |= HWCAP_CRC32;
+
+#ifdef CONFIG_COMPAT
+       /*
+        * ID_ISAR5_EL1 carries similar information as above, but pertaining to
+        * the Aarch32 32-bit execution state.
+        */
+       features = read_cpuid(ID_ISAR5_EL1);
+       block = (features >> 4) & 0xf;
+       if (!(block & 0x8)) {
+               switch (block) {
+               default:
+               case 2:
+                       compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL;
+               case 1:
+                       compat_elf_hwcap2 |= COMPAT_HWCAP2_AES;
+               case 0:
+                       break;
+               }
+       }
+
+       block = (features >> 8) & 0xf;
+       if (block && !(block & 0x8))
+               compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1;
+
+       block = (features >> 12) & 0xf;
+       if (block && !(block & 0x8))
+               compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2;
+
+       block = (features >> 16) & 0xf;
+       if (block && !(block & 0x8))
+               compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32;
+#endif
 }
 
 static void __init setup_machine_fdt(phys_addr_t dt_phys)
index 7cfb92a4ab66523212ec91392b6ee269fa0d97a9..f0a141dd5655817171605293d45429c740495661 100644 (file)
@@ -114,6 +114,11 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        return ret;
 }
 
+static void smp_store_cpu_info(unsigned int cpuid)
+{
+       store_cpu_topology(cpuid);
+}
+
 /*
  * This is the secondary CPU boot entry.  We're using this CPUs
  * idle thread stack, but a set of temporary page tables.
@@ -152,6 +157,8 @@ asmlinkage void secondary_start_kernel(void)
         */
        notify_cpu_starting(cpu);
 
+       smp_store_cpu_info(cpu);
+
        /*
         * OK, now it's safe to let the boot CPU continue.  Wait for
         * the CPU migration code to notice that the CPU is online
@@ -160,6 +167,7 @@ asmlinkage void secondary_start_kernel(void)
        set_cpu_online(cpu, true);
        complete(&cpu_running);
 
+       local_dbg_enable();
        local_irq_enable();
        local_async_enable();
 
@@ -390,6 +398,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        int err;
        unsigned int cpu, ncores = num_possible_cpus();
 
+       init_cpu_topology();
+
+       smp_store_cpu_info(smp_processor_id());
+
        /*
         * are we trying to boot more cores than exist?
         */
index 44c22805d2e2ad7e16895dc248bb9e861105fe07..7a530d2cc8077e7973938d1610d654644ae0ef1a 100644 (file)
@@ -128,7 +128,7 @@ static int smp_spin_table_cpu_boot(unsigned int cpu)
        return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0;
 }
 
-void smp_spin_table_cpu_postboot(void)
+static void smp_spin_table_cpu_postboot(void)
 {
        /*
         * Let the primary processor know we're out of the pen.
index c3b6c63ea5fb3abe0f154544aee2eb09063c0eb8..38f0558f0c0a56a7a57fe9bb12d08eb01dea7cdc 100644 (file)
@@ -48,7 +48,11 @@ int unwind_frame(struct stackframe *frame)
 
        frame->sp = fp + 0x10;
        frame->fp = *(unsigned long *)(fp);
-       frame->pc = *(unsigned long *)(fp + 8);
+       /*
+        * -4 here because we care about the PC at time of bl,
+        * not where the return will go.
+        */
+       frame->pc = *(unsigned long *)(fp + 8) - 4;
 
        return 0;
 }
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
new file mode 100644 (file)
index 0000000..3e06b0b
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * arch/arm64/kernel/topology.c
+ *
+ * Copyright (C) 2011,2013,2014 Linaro Limited.
+ *
+ * Based on the arm32 version written by Vincent Guittot in turn based on
+ * arch/sh/kernel/topology.c
+ *
+ * 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.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+
+#include <asm/topology.h>
+
+/*
+ * cpu topology table
+ */
+struct cpu_topology cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+       return &cpu_topology[cpu].core_sibling;
+}
+
+static void update_siblings_masks(unsigned int cpuid)
+{
+       struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
+       int cpu;
+
+       if (cpuid_topo->cluster_id == -1) {
+               /*
+                * DT does not contain topology information for this cpu
+                * reset it to default behaviour
+                */
+               pr_debug("CPU%u: No topology information configured\n", cpuid);
+               cpuid_topo->core_id = 0;
+               cpumask_set_cpu(cpuid, &cpuid_topo->core_sibling);
+               cpumask_set_cpu(cpuid, &cpuid_topo->thread_sibling);
+               return;
+       }
+
+       /* update core and thread sibling masks */
+       for_each_possible_cpu(cpu) {
+               cpu_topo = &cpu_topology[cpu];
+
+               if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
+                       continue;
+
+               cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+               if (cpu != cpuid)
+                       cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
+
+               if (cpuid_topo->core_id != cpu_topo->core_id)
+                       continue;
+
+               cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
+               if (cpu != cpuid)
+                       cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
+       }
+}
+
+void store_cpu_topology(unsigned int cpuid)
+{
+       update_siblings_masks(cpuid);
+}
+
+/*
+ * init_cpu_topology is called at boot when only one cpu is running
+ * which prevent simultaneous write access to cpu_topology array
+ */
+void __init init_cpu_topology(void)
+{
+       unsigned int cpu;
+
+       /* init core mask and power*/
+       for_each_possible_cpu(cpu) {
+               struct cpu_topology *cpu_topo = &cpu_topology[cpu];
+
+               cpu_topo->thread_id = -1;
+               cpu_topo->core_id =  -1;
+               cpu_topo->cluster_id = -1;
+               cpumask_clear(&cpu_topo->core_sibling);
+               cpumask_clear(&cpu_topo->thread_sibling);
+       }
+}
index 65d40cf6945ac20bb501ca65e95450d0458e78ff..50384fec56c469b296dc5737bdf2733d2febb321 100644 (file)
@@ -106,49 +106,31 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 
 static int __init vdso_init(void)
 {
-       struct page *pg;
-       char *vbase;
-       int i, ret = 0;
+       int i;
+
+       if (memcmp(&vdso_start, "\177ELF", 4)) {
+               pr_err("vDSO is not a valid ELF object!\n");
+               return -EINVAL;
+       }
 
        vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
        pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n",
                vdso_pages + 1, vdso_pages, 1L, &vdso_start);
 
        /* Allocate the vDSO pagelist, plus a page for the data. */
-       vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1),
+       vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
                                GFP_KERNEL);
-       if (vdso_pagelist == NULL) {
-               pr_err("Failed to allocate vDSO pagelist!\n");
+       if (vdso_pagelist == NULL)
                return -ENOMEM;
-       }
 
        /* Grab the vDSO code pages. */
-       for (i = 0; i < vdso_pages; i++) {
-               pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
-               ClearPageReserved(pg);
-               get_page(pg);
-               vdso_pagelist[i] = pg;
-       }
-
-       /* Sanity check the shared object header. */
-       vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
-       if (vbase == NULL) {
-               pr_err("Failed to map vDSO pagelist!\n");
-               return -ENOMEM;
-       } else if (memcmp(vbase, "\177ELF", 4)) {
-               pr_err("vDSO is not a valid ELF object!\n");
-               ret = -EINVAL;
-               goto unmap;
-       }
+       for (i = 0; i < vdso_pages; i++)
+               vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
 
        /* Grab the vDSO data page. */
-       pg = virt_to_page(vdso_data);
-       get_page(pg);
-       vdso_pagelist[i] = pg;
+       vdso_pagelist[i] = virt_to_page(vdso_data);
 
-unmap:
-       vunmap(vbase);
-       return ret;
+       return 0;
 }
 arch_initcall(vdso_init);
 
@@ -238,6 +220,8 @@ void update_vsyscall(struct timekeeper *tk)
        vdso_data->use_syscall                  = use_syscall;
        vdso_data->xtime_coarse_sec             = xtime_coarse.tv_sec;
        vdso_data->xtime_coarse_nsec            = xtime_coarse.tv_nsec;
+       vdso_data->wtm_clock_sec                = tk->wall_to_monotonic.tv_sec;
+       vdso_data->wtm_clock_nsec               = tk->wall_to_monotonic.tv_nsec;
 
        if (!use_syscall) {
                vdso_data->cs_cycle_last        = tk->clock->cycle_last;
@@ -245,8 +229,6 @@ void update_vsyscall(struct timekeeper *tk)
                vdso_data->xtime_clock_nsec     = tk->xtime_nsec;
                vdso_data->cs_mult              = tk->mult;
                vdso_data->cs_shift             = tk->shift;
-               vdso_data->wtm_clock_sec        = tk->wall_to_monotonic.tv_sec;
-               vdso_data->wtm_clock_nsec       = tk->wall_to_monotonic.tv_nsec;
        }
 
        smp_wmb();
index d8064af42e6217ba173d559ec72999181c83776a..6d20b7d162d834da4f9364e340e81d6014ec566a 100644 (file)
@@ -48,7 +48,7 @@ $(obj-vdso): %.o: %.S
 
 # Actual build commands
 quiet_cmd_vdsold = VDSOL $@
-      cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@
+      cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
 quiet_cmd_vdsoas = VDSOA $@
       cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
 
index f0a6d10b52114953dcfd818c66ad85f6cccccbd8..fe652ffd34c28090076b8d8358c6e40f7d77034d 100644 (file)
@@ -103,6 +103,8 @@ ENTRY(__kernel_clock_gettime)
        bl      __do_get_tspec
        seqcnt_check w9, 1b
 
+       mov     x30, x2
+
        cmp     w0, #CLOCK_MONOTONIC
        b.ne    6f
 
@@ -118,6 +120,9 @@ ENTRY(__kernel_clock_gettime)
        ccmp    w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
        b.ne    8f
 
+       /* xtime_coarse_nsec is already right-shifted */
+       mov     x12, #0
+
        /* Get coarse timespec. */
        adr     vdso_data, _vdso_data
 3:     seqcnt_acquire
@@ -156,7 +161,7 @@ ENTRY(__kernel_clock_gettime)
        lsr     x11, x11, x12
        stp     x10, x11, [x1, #TSPEC_TV_SEC]
        mov     x0, xzr
-       ret     x2
+       ret
 7:
        mov     x30, x2
 8:     /* Syscall fallback. */
index 2b0244d65c16f5c68dde0770f555bbadf4a5b073..d968796f4b2d7a88dda3605f0f16b9777879052b 100644 (file)
@@ -68,6 +68,12 @@ __do_hyp_init:
        msr     tcr_el2, x4
 
        ldr     x4, =VTCR_EL2_FLAGS
+       /*
+        * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in
+        * VTCR_EL2.
+        */
+       mrs     x5, ID_AA64MMFR0_EL1
+       bfi     x4, x5, #16, #3
        msr     vtcr_el2, x4
 
        mrs     x4, mair_el1
index 3b47c36e10ffcdac920a08277ee9e3e1df00a211..2c56012cb2d2c8d82588063058f4444e188d13f6 100644 (file)
@@ -694,6 +694,24 @@ __hyp_panic_str:
 
        .align  2
 
+/*
+ * u64 kvm_call_hyp(void *hypfn, ...);
+ *
+ * This is not really a variadic function in the classic C-way and care must
+ * be taken when calling this to ensure parameters are passed in registers
+ * only, since the stack will change between the caller and the callee.
+ *
+ * Call the function with the first argument containing a pointer to the
+ * function you wish to call in Hyp mode, and subsequent arguments will be
+ * passed as x0, x1, and x2 (a maximum of 3 arguments in addition to the
+ * function pointer can be passed).  The function being called must be mapped
+ * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
+ * passed in r0 and r1.
+ *
+ * A function pointer with a value of 0 has a special meaning, and is
+ * used to implement __hyp_get_vectors in the same way as in
+ * arch/arm64/kernel/hyp_stub.S.
+ */
 ENTRY(kvm_call_hyp)
        hvc     #0
        ret
@@ -737,7 +755,12 @@ el1_sync:                                  // Guest trapped into EL2
        pop     x2, x3
        pop     x0, x1
 
-       push    lr, xzr
+       /* Check for __hyp_get_vectors */
+       cbnz    x0, 1f
+       mrs     x0, vbar_el2
+       b       2f
+
+1:     push    lr, xzr
 
        /*
         * Compute the function address in EL2, and shuffle the parameters.
@@ -750,7 +773,7 @@ el1_sync:                                   // Guest trapped into EL2
        blr     lr
 
        pop     lr, xzr
-       eret
+2:     eret
 
 el1_trap:
        /*
index e5db797790d3265c5418d749b7537c494ddeb250..7dac371cc9a2f8c817d895d1be0103db9a009ec9 100644 (file)
@@ -46,11 +46,12 @@ ENTRY(      \name   )
        mov     x2, #1
        add     x1, x1, x0, lsr #3      // Get word offset
        lsl     x4, x2, x3              // Create mask
-1:     ldaxr   x2, [x1]
+1:     ldxr    x2, [x1]
        lsr     x0, x2, x3              // Save old value of bit
        \instr  x2, x2, x4              // toggle bit
        stlxr   w5, x2, [x1]
        cbnz    w5, 1b
+       dmb     ish
        and     x0, x0, #1
 3:     ret
 ENDPROC(\name  )
index 1ea9f26d1b703585537d82cf30aa44ddbe879917..c46f48b33c1409d8ea6dfe3c48327a00b6376a06 100644 (file)
@@ -30,7 +30,7 @@
  *
  *     Corrupted registers: x0-x7, x9-x11
  */
-ENTRY(__flush_dcache_all)
+__flush_dcache_all:
        dsb     sy                              // ensure ordering with previous memory accesses
        mrs     x0, clidr_el1                   // read clidr
        and     x3, x0, #0x7000000              // extract loc from clidr
@@ -166,3 +166,81 @@ ENTRY(__flush_dcache_area)
        dsb     sy
        ret
 ENDPROC(__flush_dcache_area)
+
+/*
+ *     __dma_inv_range(start, end)
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+__dma_inv_range:
+       dcache_line_size x2, x3
+       sub     x3, x2, #1
+       bic     x0, x0, x3
+       bic     x1, x1, x3
+1:     dc      ivac, x0                        // invalidate D / U line
+       add     x0, x0, x2
+       cmp     x0, x1
+       b.lo    1b
+       dsb     sy
+       ret
+ENDPROC(__dma_inv_range)
+
+/*
+ *     __dma_clean_range(start, end)
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+__dma_clean_range:
+       dcache_line_size x2, x3
+       sub     x3, x2, #1
+       bic     x0, x0, x3
+1:     dc      cvac, x0                        // clean D / U line
+       add     x0, x0, x2
+       cmp     x0, x1
+       b.lo    1b
+       dsb     sy
+       ret
+ENDPROC(__dma_clean_range)
+
+/*
+ *     __dma_flush_range(start, end)
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+ENTRY(__dma_flush_range)
+       dcache_line_size x2, x3
+       sub     x3, x2, #1
+       bic     x0, x0, x3
+1:     dc      civac, x0                       // clean & invalidate D / U line
+       add     x0, x0, x2
+       cmp     x0, x1
+       b.lo    1b
+       dsb     sy
+       ret
+ENDPROC(__dma_flush_range)
+
+/*
+ *     __dma_map_area(start, size, dir)
+ *     - start - kernel virtual start address
+ *     - size  - size of region
+ *     - dir   - DMA direction
+ */
+ENTRY(__dma_map_area)
+       add     x1, x1, x0
+       cmp     w2, #DMA_FROM_DEVICE
+       b.eq    __dma_inv_range
+       b       __dma_clean_range
+ENDPROC(__dma_map_area)
+
+/*
+ *     __dma_unmap_area(start, size, dir)
+ *     - start - kernel virtual start address
+ *     - size  - size of region
+ *     - dir   - DMA direction
+ */
+ENTRY(__dma_unmap_area)
+       add     x1, x1, x0
+       cmp     w2, #DMA_TO_DEVICE
+       b.ne    __dma_inv_range
+       ret
+ENDPROC(__dma_unmap_area)
index 45b5ab54c9eeb04730d363d13fc43a40d138aabe..0ba347e59f06a7dbfe3fe7dcc884f9435c791d6e 100644 (file)
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
-static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
-                                         dma_addr_t *dma_handle, gfp_t flags,
-                                         struct dma_attrs *attrs)
+static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
+                                bool coherent)
+{
+       if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+               return pgprot_writecombine(prot);
+       return prot;
+}
+
+static void *__dma_alloc_coherent(struct device *dev, size_t size,
+                                 dma_addr_t *dma_handle, gfp_t flags,
+                                 struct dma_attrs *attrs)
 {
        if (dev == NULL) {
                WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
                return NULL;
        }
 
-       if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
+       if (IS_ENABLED(CONFIG_ZONE_DMA) &&
            dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-               flags |= GFP_DMA32;
+               flags |= GFP_DMA;
        if (IS_ENABLED(CONFIG_DMA_CMA)) {
                struct page *page;
 
+               size = PAGE_ALIGN(size);
                page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
                                                        get_order(size));
                if (!page)
@@ -57,9 +66,9 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
        }
 }
 
-static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
-                                       void *vaddr, dma_addr_t dma_handle,
-                                       struct dma_attrs *attrs)
+static void __dma_free_coherent(struct device *dev, size_t size,
+                               void *vaddr, dma_addr_t dma_handle,
+                               struct dma_attrs *attrs)
 {
        if (dev == NULL) {
                WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
@@ -77,9 +86,212 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
        }
 }
 
-static struct dma_map_ops arm64_swiotlb_dma_ops = {
-       .alloc = arm64_swiotlb_alloc_coherent,
-       .free = arm64_swiotlb_free_coherent,
+static void *__dma_alloc_noncoherent(struct device *dev, size_t size,
+                                    dma_addr_t *dma_handle, gfp_t flags,
+                                    struct dma_attrs *attrs)
+{
+       struct page *page, **map;
+       void *ptr, *coherent_ptr;
+       int order, i;
+
+       size = PAGE_ALIGN(size);
+       order = get_order(size);
+
+       ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);
+       if (!ptr)
+               goto no_mem;
+       map = kmalloc(sizeof(struct page *) << order, flags & ~GFP_DMA);
+       if (!map)
+               goto no_map;
+
+       /* remove any dirty cache lines on the kernel alias */
+       __dma_flush_range(ptr, ptr + size);
+
+       /* create a coherent mapping */
+       page = virt_to_page(ptr);
+       for (i = 0; i < (size >> PAGE_SHIFT); i++)
+               map[i] = page + i;
+       coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP,
+                           __get_dma_pgprot(attrs, pgprot_default, false));
+       kfree(map);
+       if (!coherent_ptr)
+               goto no_map;
+
+       return coherent_ptr;
+
+no_map:
+       __dma_free_coherent(dev, size, ptr, *dma_handle, attrs);
+no_mem:
+       *dma_handle = ~0;
+       return NULL;
+}
+
+static void __dma_free_noncoherent(struct device *dev, size_t size,
+                                  void *vaddr, dma_addr_t dma_handle,
+                                  struct dma_attrs *attrs)
+{
+       void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
+
+       vunmap(vaddr);
+       __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
+}
+
+static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
+                                    unsigned long offset, size_t size,
+                                    enum dma_data_direction dir,
+                                    struct dma_attrs *attrs)
+{
+       dma_addr_t dev_addr;
+
+       dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
+       __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+
+       return dev_addr;
+}
+
+
+static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
+                                size_t size, enum dma_data_direction dir,
+                                struct dma_attrs *attrs)
+{
+       __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+       swiotlb_unmap_page(dev, dev_addr, size, dir, attrs);
+}
+
+static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+                                 int nelems, enum dma_data_direction dir,
+                                 struct dma_attrs *attrs)
+{
+       struct scatterlist *sg;
+       int i, ret;
+
+       ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs);
+       for_each_sg(sgl, sg, ret, i)
+               __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+                              sg->length, dir);
+
+       return ret;
+}
+
+static void __swiotlb_unmap_sg_attrs(struct device *dev,
+                                    struct scatterlist *sgl, int nelems,
+                                    enum dma_data_direction dir,
+                                    struct dma_attrs *attrs)
+{
+       struct scatterlist *sg;
+       int i;
+
+       for_each_sg(sgl, sg, nelems, i)
+               __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+                                sg->length, dir);
+       swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs);
+}
+
+static void __swiotlb_sync_single_for_cpu(struct device *dev,
+                                         dma_addr_t dev_addr, size_t size,
+                                         enum dma_data_direction dir)
+{
+       __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+       swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir);
+}
+
+static void __swiotlb_sync_single_for_device(struct device *dev,
+                                            dma_addr_t dev_addr, size_t size,
+                                            enum dma_data_direction dir)
+{
+       swiotlb_sync_single_for_device(dev, dev_addr, size, dir);
+       __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
+}
+
+static void __swiotlb_sync_sg_for_cpu(struct device *dev,
+                                     struct scatterlist *sgl, int nelems,
+                                     enum dma_data_direction dir)
+{
+       struct scatterlist *sg;
+       int i;
+
+       for_each_sg(sgl, sg, nelems, i)
+               __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+                                sg->length, dir);
+       swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir);
+}
+
+static void __swiotlb_sync_sg_for_device(struct device *dev,
+                                        struct scatterlist *sgl, int nelems,
+                                        enum dma_data_direction dir)
+{
+       struct scatterlist *sg;
+       int i;
+
+       swiotlb_sync_sg_for_device(dev, sgl, nelems, dir);
+       for_each_sg(sgl, sg, nelems, i)
+               __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)),
+                              sg->length, dir);
+}
+
+/* vma->vm_page_prot must be set appropriately before calling this function */
+static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                            void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+       int ret = -ENXIO;
+       unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
+                                       PAGE_SHIFT;
+       unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+       unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT;
+       unsigned long off = vma->vm_pgoff;
+
+       if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
+               return ret;
+
+       if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) {
+               ret = remap_pfn_range(vma, vma->vm_start,
+                                     pfn + off,
+                                     vma->vm_end - vma->vm_start,
+                                     vma->vm_page_prot);
+       }
+
+       return ret;
+}
+
+static int __swiotlb_mmap_noncoherent(struct device *dev,
+               struct vm_area_struct *vma,
+               void *cpu_addr, dma_addr_t dma_addr, size_t size,
+               struct dma_attrs *attrs)
+{
+       vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false);
+       return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
+}
+
+static int __swiotlb_mmap_coherent(struct device *dev,
+               struct vm_area_struct *vma,
+               void *cpu_addr, dma_addr_t dma_addr, size_t size,
+               struct dma_attrs *attrs)
+{
+       /* Just use whatever page_prot attributes were specified */
+       return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
+}
+
+struct dma_map_ops noncoherent_swiotlb_dma_ops = {
+       .alloc = __dma_alloc_noncoherent,
+       .free = __dma_free_noncoherent,
+       .mmap = __swiotlb_mmap_noncoherent,
+       .map_page = __swiotlb_map_page,
+       .unmap_page = __swiotlb_unmap_page,
+       .map_sg = __swiotlb_map_sg_attrs,
+       .unmap_sg = __swiotlb_unmap_sg_attrs,
+       .sync_single_for_cpu = __swiotlb_sync_single_for_cpu,
+       .sync_single_for_device = __swiotlb_sync_single_for_device,
+       .sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu,
+       .sync_sg_for_device = __swiotlb_sync_sg_for_device,
+       .dma_supported = swiotlb_dma_supported,
+       .mapping_error = swiotlb_dma_mapping_error,
+};
+EXPORT_SYMBOL(noncoherent_swiotlb_dma_ops);
+
+struct dma_map_ops coherent_swiotlb_dma_ops = {
+       .alloc = __dma_alloc_coherent,
+       .free = __dma_free_coherent,
+       .mmap = __swiotlb_mmap_coherent,
        .map_page = swiotlb_map_page,
        .unmap_page = swiotlb_unmap_page,
        .map_sg = swiotlb_map_sg_attrs,
@@ -91,12 +303,19 @@ static struct dma_map_ops arm64_swiotlb_dma_ops = {
        .dma_supported = swiotlb_dma_supported,
        .mapping_error = swiotlb_dma_mapping_error,
 };
+EXPORT_SYMBOL(coherent_swiotlb_dma_ops);
+
+extern int swiotlb_late_init_with_default_size(size_t default_size);
 
-void __init arm64_swiotlb_init(void)
+static int __init swiotlb_late_init(void)
 {
-       dma_ops = &arm64_swiotlb_dma_ops;
-       swiotlb_init(1);
+       size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
+
+       dma_ops = &coherent_swiotlb_dma_ops;
+
+       return swiotlb_late_init_with_default_size(swiotlb_size);
 }
+subsys_initcall(swiotlb_late_init);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES     4096
 
index d0b4c2efda90aa1ba8eaf2eabe8a977cb0fe2c9c..88627c450a6cbd3f5cdd0eb7056eeecaac76b6f2 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/memblock.h>
 #include <linux/sort.h>
 #include <linux/of_fdt.h>
+#include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 
 #include <asm/sections.h>
@@ -59,22 +60,22 @@ static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
-#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
-
 static void __init zone_sizes_init(unsigned long min, unsigned long max)
 {
        struct memblock_region *reg;
        unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
-       unsigned long max_dma32 = min;
+       unsigned long max_dma = min;
 
        memset(zone_size, 0, sizeof(zone_size));
 
-#ifdef CONFIG_ZONE_DMA32
        /* 4GB maximum for 32-bit only capable devices */
-       max_dma32 = max(min, min(max, MAX_DMA32_PFN));
-       zone_size[ZONE_DMA32] = max_dma32 - min;
-#endif
-       zone_size[ZONE_NORMAL] = max - max_dma32;
+       if (IS_ENABLED(CONFIG_ZONE_DMA)) {
+               unsigned long max_dma_phys =
+                       (unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1);
+               max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT));
+               zone_size[ZONE_DMA] = max_dma - min;
+       }
+       zone_size[ZONE_NORMAL] = max - max_dma;
 
        memcpy(zhole_size, zone_size, sizeof(zhole_size));
 
@@ -84,15 +85,15 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 
                if (start >= max)
                        continue;
-#ifdef CONFIG_ZONE_DMA32
-               if (start < max_dma32) {
-                       unsigned long dma_end = min(end, max_dma32);
-                       zhole_size[ZONE_DMA32] -= dma_end - start;
+
+               if (IS_ENABLED(CONFIG_ZONE_DMA) && start < max_dma) {
+                       unsigned long dma_end = min(end, max_dma);
+                       zhole_size[ZONE_DMA] -= dma_end - start;
                }
-#endif
-               if (end > max_dma32) {
+
+               if (end > max_dma) {
                        unsigned long normal_end = min(end, max);
-                       unsigned long normal_start = max(start, max_dma32);
+                       unsigned long normal_start = max(start, max_dma);
                        zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
                }
        }
@@ -261,8 +262,6 @@ static void __init free_unused_memmap(void)
  */
 void __init mem_init(void)
 {
-       arm64_swiotlb_init();
-
        max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
index f557ebbe7013edb71599570f0e4904a318b9dafc..f8dc7e8fce6fea147a9842824a8046822b70b180 100644 (file)
@@ -203,10 +203,18 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
        do {
                next = pmd_addr_end(addr, end);
                /* try section mapping first */
-               if (((addr | next | phys) & ~SECTION_MASK) == 0)
+               if (((addr | next | phys) & ~SECTION_MASK) == 0) {
+                       pmd_t old_pmd =*pmd;
                        set_pmd(pmd, __pmd(phys | prot_sect_kernel));
-               else
+                       /*
+                        * Check for previous table entries created during
+                        * boot (__create_page_tables) and flush them.
+                        */
+                       if (!pmd_none(old_pmd))
+                               flush_tlb_all();
+               } else {
                        alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys));
+               }
                phys += next - addr;
        } while (pmd++, addr = next, addr != end);
 }
index 7083cdada657f21ab4e5aa7d4a9397d212b62e0e..62c6101df260e60ddd1084804383d2831de67ba4 100644 (file)
 
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       pgd_t *new_pgd;
-
        if (PGD_SIZE == PAGE_SIZE)
-               new_pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL);
+               return (pgd_t *)get_zeroed_page(GFP_KERNEL);
        else
-               new_pgd = kzalloc(PGD_SIZE, GFP_KERNEL);
-
-       if (!new_pgd)
-               return NULL;
-
-       return new_pgd;
+               return kzalloc(PGD_SIZE, GFP_KERNEL);
 }
 
 void pgd_free(struct mm_struct *mm, pgd_t *pgd)
index 1333e6f9a8e50bd7e8996a67a392feaa4aaf95e0..e085ee6ef4e23c146627798b9c7b98411a719f36 100644 (file)
@@ -173,12 +173,6 @@ ENDPROC(cpu_do_switch_mm)
  *     value of the SCTLR_EL1 register.
  */
 ENTRY(__cpu_setup)
-       /*
-        * Preserve the link register across the function call.
-        */
-       mov     x28, lr
-       bl      __flush_dcache_all
-       mov     lr, x28
        ic      iallu                           // I+BTB cache invalidate
        tlbi    vmalle1is                       // invalidate I + D TLBs
        dsb     sy
@@ -215,8 +209,14 @@ ENTRY(__cpu_setup)
         * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for
         * both user and kernel.
         */
-       ldr     x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | TCR_IPS_40BIT | \
+       ldr     x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | \
                      TCR_ASID16 | TCR_TBI0 | (1 << 31)
+       /*
+        * Read the PARange bits from ID_AA64MMFR0_EL1 and set the IPS bits in
+        * TCR_EL1.
+        */
+       mrs     x9, ID_AA64MMFR0_EL1
+       bfi     x10, x9, #32, #3
 #ifdef CONFIG_ARM64_64K_PAGES
        orr     x10, x10, TCR_TG0_64K
        orr     x10, x10, TCR_TG1_64K
index 22fb66590dcd0e6f7339c9723a9128eb078cdb06..dba48a5d5bb9db351ff62bafc23a62a7047b42b5 100644 (file)
@@ -11,7 +11,7 @@ all: uImage vmlinux.elf
 
 KBUILD_DEFCONFIG       := atstk1002_defconfig
 
-KBUILD_CFLAGS  += -pipe -fno-builtin -mno-pic
+KBUILD_CFLAGS  += -pipe -fno-builtin -mno-pic -D__linux__
 KBUILD_AFLAGS  += -mrelax -mno-pic
 KBUILD_CFLAGS_MODULE += -mno-relax
 LDFLAGS_vmlinux        += --relax
index 9764a1a1073e933aa1c2d6a73e51483553da2dfa..c1466a872b9c8598ca184f65eb32f3320669f4b1 100644 (file)
@@ -11,6 +11,7 @@
 #define FRAM_VERSION   "1.0"
 
 #include <linux/miscdevice.h>
+#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/io.h>
index cfb9fe1b8df9528b8bdbf8d2570b860af3fd4a4b..00a0f3ccd6eb994a67071d8e544762475f1ca792 100644 (file)
@@ -1,21 +1,23 @@
 
-generic-y      += clkdev.h
-generic-y       += cputime.h
-generic-y       += delay.h
-generic-y       += device.h
-generic-y       += div64.h
-generic-y       += emergency-restart.h
-generic-y      += exec.h
-generic-y       += futex.h
-generic-y      += preempt.h
-generic-y       += irq_regs.h
-generic-y      += param.h
-generic-y       += local.h
-generic-y       += local64.h
-generic-y       += percpu.h
-generic-y       += scatterlist.h
-generic-y       += sections.h
-generic-y       += topology.h
-generic-y      += trace_clock.h
-generic-y       += xor.h
-generic-y      += hash.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += exec.h
+generic-y += futex.h
+generic-y += hash.h
+generic-y += irq_regs.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += param.h
+generic-y += percpu.h
+generic-y += preempt.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += vga.h
+generic-y += xor.h
index 7635e770622ee32dafb27f6368a588542791d51f..278661bbd1b0aefb081be0bdb7d15423cd27f3f3 100644 (file)
@@ -9,7 +9,7 @@
 
 static void __init check_bugs(void)
 {
-       cpu_data->loops_per_jiffy = loops_per_jiffy;
+       boot_cpu_data.loops_per_jiffy = loops_per_jiffy;
 }
 
 #endif /* __ASM_AVR32_BUGS_H */
index fc6483f83ccca748a3dc4319bb1ee849f8435654..4f5ec2bb71727279a952843051f44e3297c7b222 100644 (file)
@@ -295,6 +295,8 @@ extern void __iounmap(void __iomem *addr);
 #define iounmap(addr)                          \
        __iounmap(addr)
 
+#define ioremap_wc ioremap_nocache
+
 #define cached(addr) P1SEGADDR(addr)
 #define uncached(addr) P2SEGADDR(addr)
 
index 48d71c5c898a18d083f8a55da807c103d7515458..972adcc1e8f40179d06a4062d2adf63416f36452 100644 (file)
@@ -83,13 +83,8 @@ static inline unsigned int avr32_get_chip_revision(struct avr32_cpuinfo *cpu)
 
 extern struct avr32_cpuinfo boot_cpu_data;
 
-#ifdef CONFIG_SMP
-extern struct avr32_cpuinfo cpu_data[];
-#define current_cpu_data cpu_data[smp_processor_id()]
-#else
-#define cpu_data (&boot_cpu_data)
+/* No SMP support so far */
 #define current_cpu_data boot_cpu_data
-#endif
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's
index 2233be71e2e8cf7e8b62789eb6a5a7ba864d001e..0341ae27c9ec57fd06eaf88776db6ae83444c96e 100644 (file)
@@ -39,10 +39,12 @@ static ssize_t store_pc0event(struct device *dev,
                              size_t count)
 {
        unsigned long val;
-       char *endp;
+       int ret;
 
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf || val > 0x3f)
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+       if (val > 0x3f)
                return -EINVAL;
        val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff);
        sysreg_write(PCCR, val);
@@ -61,11 +63,11 @@ static ssize_t store_pc0count(struct device *dev,
                                const char *buf, size_t count)
 {
        unsigned long val;
-       char *endp;
+       int ret;
 
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf)
-               return -EINVAL;
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
        sysreg_write(PCNT0, val);
 
        return count;
@@ -84,10 +86,12 @@ static ssize_t store_pc1event(struct device *dev,
                              size_t count)
 {
        unsigned long val;
-       char *endp;
+       int ret;
 
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf || val > 0x3f)
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+       if (val > 0x3f)
                return -EINVAL;
        val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff);
        sysreg_write(PCCR, val);
@@ -106,11 +110,11 @@ static ssize_t store_pc1count(struct device *dev,
                              size_t count)
 {
        unsigned long val;
-       char *endp;
+       int ret;
 
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf)
-               return -EINVAL;
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
        sysreg_write(PCNT1, val);
 
        return count;
@@ -129,11 +133,11 @@ static ssize_t store_pccycles(struct device *dev,
                              size_t count)
 {
        unsigned long val;
-       char *endp;
+       int ret;
 
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf)
-               return -EINVAL;
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
        sysreg_write(PCCNT, val);
 
        return count;
@@ -152,11 +156,11 @@ static ssize_t store_pcenable(struct device *dev,
                              size_t count)
 {
        unsigned long pccr, val;
-       char *endp;
+       int ret;
 
-       val = simple_strtoul(buf, &endp, 0);
-       if (endp == buf)
-               return -EINVAL;
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
        if (val)
                val = 1;
 
index 6a46ecd56cfd538c7fe070b641fad3e68ffc3d1f..85d635cd7b28f84045e5bf29e62e4aab53196f85 100644 (file)
@@ -111,6 +111,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
        __flush_icache_range(start & ~(linesz - 1),
                             (end + linesz - 1) & ~(linesz - 1));
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 /*
  * This one is called from __do_fault() and do_swap_page().
index 359d36fdc2471f987ff561104e9dcb2723fdcf99..0d93b9a79ca9561399a152d25a3545a09496b858 100644 (file)
@@ -10,6 +10,7 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += fb.h
 generic-y += futex.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
@@ -17,14 +18,16 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += kvm_para.h
-generic-y += local64.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += param.h
 generic-y += percpu.h
 generic-y += pgalloc.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -44,5 +47,3 @@ generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index d73bb85ccdd3e9f7dbc49c5a3c67944f250c82a6..8dbdce8421b08c0e58322db87002ef314778cd1b 100644 (file)
@@ -15,6 +15,7 @@ generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += futex.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += io.h
 generic-y += ioctl.h
@@ -24,6 +25,7 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += local.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += mmu.h
 generic-y += mmu_context.h
@@ -34,6 +36,7 @@ generic-y += percpu.h
 generic-y += pgalloc.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += segment.h
@@ -56,5 +59,3 @@ generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 09c5a0f5f4d1778156a5ee83715e6a2aec7f0441..86648c083bb4b1297275dc2bc4ceb3ecd949aa5b 100644 (file)
@@ -12,6 +12,7 @@
 #define _ASM_C6X_CACHE_H
 
 #include <linux/irqflags.h>
+#include <linux/init.h>
 
 /*
  * Cache line size
index f3fd8768f095cc55c606d22bf5281042a31234c2..afff5105909d953af7ca3667c773350fb4bc434d 100644 (file)
@@ -5,12 +5,14 @@ header-y += arch-v32/
 
 generic-y += barrier.h
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += exec.h
 generic-y += hash.h
 generic-y += kvm_para.h
 generic-y += linkage.h
+generic-y += mcs_spinlock.h
 generic-y += module.h
+generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
index 184066ceb1f6146c9254a778c8e9c7f6b9656668..053c17b3655926ed97427a927a83081ec289d224 100644 (file)
@@ -144,7 +144,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
  * definition, which doesn't have the same semantics.  We don't want to
  * use -fno-builtin, so just hide the name ffs.
  */
-#define ffs kernel_ffs
+#define ffs(x) kernel_ffs(x)
 
 #include <asm-generic/bitops/fls.h>
 #include <asm-generic/bitops/__fls.h>
diff --git a/arch/cris/include/asm/cputime.h b/arch/cris/include/asm/cputime.h
deleted file mode 100644 (file)
index 4446a65..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __CRIS_CPUTIME_H
-#define __CRIS_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __CRIS_CPUTIME_H */
index bc42f14c9c2e706081c66b3805a9369d65e4bce9..87b95eb8aee53e3f5280f3b985da8b0c6cc75192 100644 (file)
@@ -1,6 +1,8 @@
 
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += exec.h
-generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/frv/include/asm/cputime.h b/arch/frv/include/asm/cputime.h
deleted file mode 100644 (file)
index f6c373a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_CPUTIME_H
-#define _ASM_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* _ASM_CPUTIME_H */
index 38ca45d3df1e4d88230d1ab8f991510efb983450..eadcc118f9506d8fbfddfd5b0dc7e65c6f3f9673 100644 (file)
@@ -25,14 +25,16 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
-generic-y += local64.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += rwsem.h
 generic-y += scatterlist.h
@@ -45,8 +47,8 @@ generic-y += siginfo.h
 generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += statfs.h
 generic-y += stat.h
+generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
@@ -55,4 +57,3 @@ generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += xor.h
-generic-y += preempt.h
index efbd2929aeb75c563b5ccbf4b267be596ce921e2..6404acbb84b295e57274a9bbc24d433238386901 100644 (file)
@@ -30,9 +30,9 @@ CONFIG_ACPI_BUTTON=m
 CONFIG_ACPI_FAN=m
 CONFIG_ACPI_DOCK=y
 CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_CONTAINER=m
+CONFIG_ACPI_CONTAINER=y
 CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
index 8e858b593e4f13cf79fb34fda2903531e02fd1dc..30c43d39dede068c9f54448bc8e1f90917fe0c84 100644 (file)
@@ -1596,7 +1596,7 @@ static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
 *
 ***************************************************************/
 
-static void __init
+static void
 ioc_iova_init(struct ioc *ioc)
 {
        int tcnfg;
@@ -1807,7 +1807,7 @@ static struct ioc_iommu ioc_iommu_info[] __initdata = {
        { SX2000_IOC_ID, "sx2000", NULL },
 };
 
-static struct ioc * __init
+static struct ioc *
 ioc_init(unsigned long hpa, void *handle)
 {
        struct ioc *ioc;
@@ -2041,7 +2041,7 @@ sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 #define sba_map_ioc_to_node(ioc, handle)
 #endif
 
-static int __init
+static int
 acpi_sba_ioc_add(struct acpi_device *device,
                 const struct acpi_device_id *not_used)
 {
index 283a83154b5eaaab7f8dc5474f0ec722e970a1de..0da4aa2602ae01d9badaca0f960e8d6b4c16ae2b 100644 (file)
@@ -1,8 +1,9 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += kvm_para.h
-generic-y += trace_clock.h
+generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += trace_clock.h
 generic-y += vtime.h
-generic-y += hash.h
index a2496e449b75452038ab7e7b14e4bd2c796fd458..5cb55a1e606b0b5cbed352f1e7187c41d31371de 100644 (file)
@@ -77,7 +77,6 @@ void build_cpu_to_node_map(void);
 #define topology_core_id(cpu)                  (cpu_data(cpu)->core_id)
 #define topology_core_cpumask(cpu)             (&cpu_core_map[cpu])
 #define topology_thread_cpumask(cpu)           (&per_cpu(cpu_sibling_map, cpu))
-#define smt_capable()                          (smp_num_siblings > 1)
 #endif
 
 extern void arch_fix_phys_package_id(int num, u32 slot);
index afd45e0d552e1301536f2f8a21beea440c1ad6c5..ae763d8bf55acff94a8c611893e2a103f3156f33 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    312 /* length of syscall table */
+#define NR_syscalls                    314 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 34fd6fe46da1e6e1659b347481f2a93ec2b5ca11..715e85f858de5ea34e7f581b38bc5d9a60ec1304 100644 (file)
 #define __NR_process_vm_writev         1333
 #define __NR_accept4                   1334
 #define __NR_finit_module              1335
+#define __NR_sched_setattr             1336
+#define __NR_sched_getattr             1337
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index da5b462e6de6c9e91c18d42756ff482bb9f70505..741b99c1a0b1483b153be8823ae681a141d71bf5 100644 (file)
@@ -477,6 +477,9 @@ efi_init (void)
        char *cp, vendor[100] = "unknown";
        int i;
 
+       set_bit(EFI_BOOT, &efi.flags);
+       set_bit(EFI_64BIT, &efi.flags);
+
        /*
         * It's too early to be able to use the standard kernel command line
         * support...
@@ -529,6 +532,8 @@ efi_init (void)
               efi.systab->hdr.revision >> 16,
               efi.systab->hdr.revision & 0xffff, vendor);
 
+       set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
        palo_phys      = EFI_INVALID_TABLE_ADDR;
 
        if (efi_config_init(arch_tables) != 0)
@@ -657,6 +662,8 @@ efi_enter_virtual_mode (void)
                return;
        }
 
+       set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
        /*
         * Now that EFI is in virtual mode, we call the EFI functions more
         * efficiently:
index ddea607f948aaa61932b022a14a390df9e816f8c..fa8d61a312a7ee818a300522d9f029c9534d78f6 100644 (file)
@@ -1773,6 +1773,8 @@ sys_call_table:
        data8 sys_process_vm_writev
        data8 sys_accept4
        data8 sys_finit_module                  // 1335
+       data8 sys_sched_setattr
+       data8 sys_sched_getattr
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
index b8edfa75a83f9cd8bce4469d1d1c97b93b02d371..601502ab71414ddf578d4bb1af24659aed04cf3f 100644 (file)
@@ -217,7 +217,7 @@ void ia64_mca_printk(const char *fmt, ...)
        /* Copy the output into mlogbuf */
        if (oops_in_progress) {
                /* mlogbuf was abandoned, use printk directly instead. */
-               printk(temp_buf);
+               printk("%s", temp_buf);
        } else {
                spin_lock(&mlogbuf_wlock);
                for (p = temp_buf; *p; p++) {
@@ -268,7 +268,7 @@ void ia64_mlogbuf_dump(void)
                }
                *p = '\0';
                if (temp_buf[0])
-                       printk(temp_buf);
+                       printk("%s", temp_buf);
                mlogbuf_start = index;
 
                mlogbuf_timestamp = 0;
index a96bcf83a735dae2f812f81e0fc54635bb3de072..20e8a9b21d7519ebf7d506e4825d83c05629ba37 100644 (file)
@@ -98,7 +98,7 @@ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
        /* attempt to allocate a granule's worth of cached memory pages */
 
        page = alloc_pages_exact_node(nid,
-                               GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+                               GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
                                IA64_GRANULE_SHIFT-PAGE_SHIFT);
        if (!page) {
                mutex_unlock(&uc_pool->add_chunk_mutex);
index 932435ac4e5ce4ff721b2c455de567c5c7603861..67779a74b62dbbe2e5841253acf145867b67c9ae 100644 (file)
@@ -1,7 +1,9 @@
 
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += exec.h
+generic-y += hash.h
+generic-y += mcs_spinlock.h
 generic-y += module.h
-generic-y += trace_clock.h
 generic-y += preempt.h
-generic-y += hash.h
+generic-y += trace_clock.h
diff --git a/arch/m32r/include/asm/cputime.h b/arch/m32r/include/asm/cputime.h
deleted file mode 100644 (file)
index 0a47550..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __M32R_CPUTIME_H
-#define __M32R_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __M32R_CPUTIME_H */
index dbdd2231c75ddc9fab61fd1b2dca7c1cc60a3e3e..b2e322939256f528bfeb042bc420cd0de2efc1a3 100644 (file)
@@ -17,6 +17,7 @@ config M68K
        select FPU if MMU
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
+       select HAVE_FUTEX_CMPXCHG if MMU && FUTEX
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_REL
        select MODULES_USE_ELF_RELA
index 559ff3af8ff7b1e8dd4a738eebe6321f1dc3ddd9..96da4963d14b21ef0b5daa023b4d16425eaebeaf 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
@@ -85,6 +87,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -94,6 +97,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -126,6 +131,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -163,8 +169,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -190,7 +194,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -512,7 +515,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index cb1f55df69b6c87b03dc2c1598b43fdbfd3fcfa0..1b8739f50cbf77631d0eb5fb25d22941c7233aad 100644 (file)
@@ -25,6 +25,8 @@ CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
@@ -83,6 +85,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -92,6 +95,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -124,6 +129,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -161,8 +167,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -188,7 +192,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -470,7 +473,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index e880cfbb62d9e419bcbf4a4d006ffd420939b4f1..6ea4e91f0caabed1a806afbaab092744f23c0c98 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
@@ -82,6 +84,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -91,6 +94,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -123,6 +128,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -160,8 +166,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -187,7 +191,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -487,7 +490,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 4aa4f45e52a8708853925fb678a19d4889f632f3..e5a12739ff2d3535e8d9ed0dc22df8720eb4689e 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68040=y
 CONFIG_M68060=y
 CONFIG_VME=y
@@ -81,6 +83,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -90,6 +93,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -122,6 +127,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -159,8 +165,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -186,7 +190,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -463,7 +466,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 7cd9d9f456fb61ab3619641b81ee8dbfbd975acf..8936d7fb0f0f15a983dcd6d0262301a7447e10b9 100644 (file)
@@ -25,6 +25,8 @@ CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
@@ -83,6 +85,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -92,6 +95,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -124,6 +129,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -161,8 +167,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -188,7 +192,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -472,7 +475,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 31f5bd061d1466f5367fa0b0dafc1ecaa8f4d521..be5342cca25b36180991f88a49d2bfe80f49ff2f 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68020=y
 CONFIG_M68030=y
 CONFIG_M68040=y
@@ -82,6 +84,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -91,6 +94,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -123,6 +128,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -160,8 +166,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -187,7 +191,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -495,7 +498,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 4e5adff326eec88bccff93bf83933f518b94328b..f27194ade167d96fb949b1e2a42e7e74a75f6e79 100644 (file)
@@ -20,6 +20,8 @@ CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68020=y
 CONFIG_M68040=y
 CONFIG_M68060=y
@@ -91,6 +93,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -100,6 +103,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -132,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -169,8 +175,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -196,7 +200,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -571,7 +574,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 02cdbac5565e5153f0970409e8247535bf818fd7..c3887603c1db4a49196af9a52c2dc85efdc641be 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68030=y
 CONFIG_VME=y
 CONFIG_MVME147=y
@@ -80,6 +82,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -89,6 +92,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -121,6 +126,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -158,8 +164,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -185,7 +189,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -463,7 +466,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 05a990a9dbd46994c60488c6eefeb807aa19f287..f7ff784d05aca2498040a3b47ea477c5793ac22d 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68040=y
 CONFIG_M68060=y
 CONFIG_VME=y
@@ -81,6 +83,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -90,6 +93,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -122,6 +127,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -159,8 +165,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -186,7 +190,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -464,7 +467,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 568e2a98f976ee3c91900734df88e5d675c83811..f0c72ab037be1b268abcc720be5dda97fb128323 100644 (file)
@@ -25,6 +25,8 @@ CONFIG_SUN_PARTITION=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_M68040=y
 CONFIG_M68060=y
 CONFIG_Q40=y
@@ -81,6 +83,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -90,6 +93,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -122,6 +127,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -159,8 +165,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -186,7 +190,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -485,7 +488,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 60b0aeac5742e80f28c8345a856070638252897b..7bca0f464521707451d41686040fac2dfc4b2070 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_UNIXWARE_DISKLABEL=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_SUN3=y
 # CONFIG_COMPACTION is not set
 CONFIG_CLEANCACHE=y
@@ -78,6 +80,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -87,6 +90,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -119,6 +124,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -156,8 +162,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -183,7 +187,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -464,7 +467,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 21bda331eebb04cfae90c5b94d869b18c9097d95..317f3e1fec954285880d0268bce5af93cc23be1e 100644 (file)
@@ -24,6 +24,8 @@ CONFIG_UNIXWARE_DISKLABEL=y
 # CONFIG_EFI_PARTITION is not set
 CONFIG_SYSV68_PARTITION=y
 CONFIG_IOSCHED_DEADLINE=m
+CONFIG_KEXEC=y
+CONFIG_BOOTINFO_PROC=y
 CONFIG_SUN3X=y
 # CONFIG_COMPACTION is not set
 CONFIG_CLEANCACHE=y
@@ -78,6 +80,7 @@ CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
@@ -87,6 +90,8 @@ CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -119,6 +124,7 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=m
 CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
@@ -156,8 +162,6 @@ CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_REJECT_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -183,7 +187,6 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -464,7 +467,6 @@ CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 # CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_T10DIF=y
 CONFIG_XZ_DEC_X86=y
 CONFIG_XZ_DEC_POWERPC=y
 CONFIG_XZ_DEC_IA64=y
index 7cc8c364924dff8e8529be82406f0acfb7dfe0f2..c67c94a2d67229a461239a4335def5d90d597abe 100644 (file)
@@ -1,4 +1,4 @@
-
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += clkdev.h
 generic-y += cputime.h
@@ -6,6 +6,7 @@ generic-y += device.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
@@ -13,11 +14,13 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += kvm_para.h
-generic-y += local64.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += mutex.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -31,5 +34,3 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
diff --git a/arch/m68k/include/asm/barrier.h b/arch/m68k/include/asm/barrier.h
deleted file mode 100644 (file)
index 15c5f77..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _M68K_BARRIER_H
-#define _M68K_BARRIER_H
-
-#define nop()          do { asm volatile ("nop"); barrier(); } while (0)
-
-#include <asm-generic/barrier.h>
-
-#endif /* _M68K_BARRIER_H */
index 014f288fc81354e0eb088e500184e7e032ea6ba3..9d38b73989eb597d677acd95ea53cf0ddb99b624 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            349
+#define NR_syscalls            351
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index 625f321001dc077fe13da02eb0844a50099653dc..b932dd470041c2c5130dfcc44448c80033525259 100644 (file)
 #define __NR_process_vm_writev 346
 #define __NR_kcmp              347
 #define __NR_finit_module      348
+#define __NR_sched_setattr     349
+#define __NR_sched_getattr     350
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 4c99bab7e6647c0709ebacbff38b42f01ab24449..3ab329b8852173694bac06c2559841fed73d95ac 100644 (file)
 
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
 #define CONSOLE
-#define CONSOLE_PENGUIN
 #endif
 
 #ifdef CONFIG_EARLY_PRINTK
@@ -658,27 +657,6 @@ ENTRY(__start)
        movel   %a0@,%a1@
 #endif
 
-#if 0
-       /*
-        * Clear the screen
-        */
-       lea     %pc@(L(mac_videobase)),%a0
-       movel   %a0@,%a1
-       lea     %pc@(L(mac_dimensions)),%a0
-       movel   %a0@,%d1
-       swap    %d1             /* #rows is high bytes */
-       andl    #0xFFFF,%d1     /* rows */
-       subl    #10,%d1
-       lea     %pc@(L(mac_rowbytes)),%a0
-loopy2:
-       movel   %a0@,%d0
-       subql   #1,%d0
-loopx2:
-       moveb   #0x55, %a1@+
-       dbra    %d0,loopx2
-       dbra    %d1,loopy2
-#endif
-
 L(test_notmac):
 #endif /* CONFIG_MAC */
 
@@ -907,15 +885,15 @@ L(nothp):
  */
 #ifdef CONFIG_MAC
        is_not_mac(L(nocon))
-#ifdef CONSOLE
+#  ifdef CONSOLE
        console_init
-#ifdef CONSOLE_PENGUIN
+#    ifdef CONFIG_LOGO
        console_put_penguin
-#endif /* CONSOLE_PENGUIN */
+#    endif /* CONFIG_LOGO */
        console_put_stats
-#endif /* CONSOLE */
+#  endif /* CONSOLE */
 L(nocon):
-#endif /* CONFIG_MAC */
+#endif /* CONFIG_MAC */
 
 
        putc    '\n'
@@ -3324,14 +3302,13 @@ func_return     set_leds
 #define Lconsole_struct_num_columns    8
 #define Lconsole_struct_num_rows       12
 #define Lconsole_struct_left_edge      16
-#define Lconsole_struct_penguin_putc   20
 
 func_start     console_init,%a0-%a4/%d0-%d7
        /*
         *      Some of the register usage that follows
         *              a0 = pointer to boot_info
         *              a1 = pointer to screen
-        *              a2 = pointer to Lconsole_globals
+        *              a2 = pointer to console_globals
         *              d3 = pixel width of screen
         *              d4 = pixel height of screen
         *              (d3,d4) ~= (x,y) of a point just below
@@ -3456,7 +3433,7 @@ func_start        console_put_stats,%a0/%d7
 
 func_return    console_put_stats
 
-#ifdef CONSOLE_PENGUIN
+#ifdef CONFIG_LOGO
 func_start     console_put_penguin,%a0-%a1/%d0-%d7
        /*
         *      Get 'that_penguin' onto the screen in the upper right corner
@@ -3799,38 +3776,6 @@ L(console_plot_pixel_exit):
 func_return    console_plot_pixel
 #endif /* CONSOLE */
 
-#if 0
-/*
- * This is some old code lying around.  I don't believe
- * it's used or important anymore.  My guess is it contributed
- * to getting to this point, but it's done for now.
- * It was still in the 2.1.77 head.S, so it's still here.
- * (And still not used!)
- */
-L(showtest):
-       moveml  %a0/%d7,%sp@-
-       puts    "A="
-       putn    %a1
-
-       .long   0xf0119f15              | ptestr        #5,%a1@,#7,%a0
-
-       puts    "DA="
-       putn    %a0
-
-       puts    "D="
-       putn    %a0@
-
-       puts    "S="
-       lea     %pc@(L(mmu)),%a0
-       .long   0xf0106200              | pmove         %psr,%a0@
-       clrl    %d7
-       movew   %a0@,%d7
-       putn    %d7
-
-       putc    '\n'
-       moveml  %sp@+,%a0/%d7
-       rts
-#endif /* 0 */
 
 __INITDATA
        .align  4
@@ -3849,7 +3794,6 @@ L(console_globals):
        .long   0               /* max num columns */
        .long   0               /* max num rows */
        .long   0               /* left edge */
-       .long   0               /* mac putc */
 L(console_font):
        .long   0               /* pointer to console font (struct font_desc) */
 L(console_font_data):
index 3f04ea0ab802750866835fcd9c3aa75ac7b28282..b6223dc41d82870953be64b35fc409c4b5634070 100644 (file)
@@ -369,4 +369,6 @@ ENTRY(sys_call_table)
        .long sys_process_vm_writev
        .long sys_kcmp
        .long sys_finit_module
+       .long sys_sched_setattr
+       .long sys_sched_getattr         /* 350 */
 
index b716d807c2ece0b222da935b6796f789b2486c97..c29ead89a31778da9d5f217b6cc984c1176a6772 100644 (file)
@@ -13,6 +13,7 @@ generic-y += fb.h
 generic-y += fcntl.h
 generic-y += futex.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -23,6 +24,7 @@ generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += param.h
@@ -30,6 +32,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += sembuf.h
@@ -52,5 +55,3 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 2b98bc73642afb4cd07c7c412c416c9a87cb69de..c98ed95c054185913aa3fb63dbf641d6984ba2d8 100644 (file)
@@ -1,8 +1,10 @@
 
 generic-y += barrier.h
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += exec.h
 generic-y += hash.h
-generic-y += trace_clock.h
-generic-y += syscalls.h
+generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += syscalls.h
+generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/cputime.h b/arch/microblaze/include/asm/cputime.h
deleted file mode 100644 (file)
index 6d68ad7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/cputime.h>
index 05b7d39e4391218775b701c12d5138b25ca2ca34..66fc24c24238f64cac057fa33e9b330af10867e3 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _ASM_MICROBLAZE_DELAY_H
 #define _ASM_MICROBLAZE_DELAY_H
 
+#include <linux/param.h>
+
 extern inline void __delay(unsigned long loops)
 {
        asm volatile ("# __delay                \n\t"           \
index a2cea72060777a5df8fd1065f80e627d56a29787..3fbb7f1db3bcdcfbe867c9e6ab7ce3189d0a74c0 100644 (file)
@@ -89,6 +89,11 @@ static inline unsigned int readl(const volatile void __iomem *addr)
 {
        return le32_to_cpu(*(volatile unsigned int __force *)addr);
 }
+#define readq readq
+static inline u64 readq(const volatile void __iomem *addr)
+{
+       return le64_to_cpu(__raw_readq(addr));
+}
 static inline void writeb(unsigned char v, volatile void __iomem *addr)
 {
        *(volatile unsigned char __force *)addr = v;
@@ -101,6 +106,7 @@ static inline void writel(unsigned int v, volatile void __iomem *addr)
 {
        *(volatile unsigned int __force *)addr = cpu_to_le32(v);
 }
+#define writeq(b, addr) __raw_writeq(cpu_to_le64(b), addr)
 
 /* ioread and iowrite variants. thease are for now same as __raw_
  * variants of accessors. we might check for endianess in the feature
index b7fb0438458ca8960bd0a730ec9c0da520112136..17645b2e2f075d69a41fb4a4fcee7ba468c76c36 100644 (file)
@@ -66,7 +66,7 @@ real_start:
        mts     rmsr, r0
 /* Disable stack protection from bootloader */
        mts     rslr, r0
-       addi    r8, r0, 0xFFFFFFF
+       addi    r8, r0, 0xFFFFFFFF
        mts     rshr, r8
 /*
  * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc'
index dcae3a7035db55a278b1a8cac80faa5ac2199003..95fa1f1d5c8b4a70d3ee991e7a5bb32b5db22740 100644 (file)
@@ -1776,12 +1776,12 @@ endchoice
 
 config FORCE_MAX_ZONEORDER
        int "Maximum zone order"
-       range 14 64 if HUGETLB_PAGE && PAGE_SIZE_64KB
-       default "14" if HUGETLB_PAGE && PAGE_SIZE_64KB
-       range 13 64 if HUGETLB_PAGE && PAGE_SIZE_32KB
-       default "13" if HUGETLB_PAGE && PAGE_SIZE_32KB
-       range 12 64 if HUGETLB_PAGE && PAGE_SIZE_16KB
-       default "12" if HUGETLB_PAGE && PAGE_SIZE_16KB
+       range 14 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_64KB
+       default "14" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_64KB
+       range 13 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_32KB
+       default "13" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_32KB
+       range 12 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_16KB
+       default "12" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_16KB
        range 11 64
        default "11"
        help
@@ -2353,9 +2353,8 @@ config SECCOMP
          If unsure, say Y. Only embedded should say N here.
 
 config MIPS_O32_FP64_SUPPORT
-       bool "Support for O32 binaries using 64-bit FP"
+       bool "Support for O32 binaries using 64-bit FP (EXPERIMENTAL)"
        depends on 32BIT || MIPS32_O32
-       default y
        help
          When this is enabled, the kernel will support use of 64-bit floating
          point registers with binaries using the O32 ABI along with the
@@ -2367,7 +2366,14 @@ config MIPS_O32_FP64_SUPPORT
          of your kernel & potentially improve FP emulation performance by
          saying N here.
 
-         If unsure, say Y.
+         Although binutils currently supports use of this flag the details
+         concerning its effect upon the O32 ABI in userland are still being
+         worked on. In order to avoid userland becoming dependant upon current
+         behaviour before the details have been finalised, this option should
+         be considered experimental and only enabled by those working upon
+         said details.
+
+         If unsure, say N.
 
 config USE_OF
        bool
index 9edc35ff8cf1420e9576f195f92658e71517c073..acf9a2a37f5a055a0c794d7aa62a46e75527f6a4 100644 (file)
@@ -53,10 +53,8 @@ void __init prom_init(void)
        prom_init_cmdline();
 
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
                memsize = 0x04000000;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
index 9969dbab19e36e3f2bd1210c93840bc85bfd7f16..25a59a23547e392b593a140d4f9bac3f2e882831 100644 (file)
@@ -52,10 +52,8 @@ void __init prom_init(void)
        prom_init_cmdline();
 
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
                memsize = 0x04000000;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
index 11f3ad20321ca64a1c5d6bf98b4d6d8a141cc92d..5483906e0f86d19acafb160596c673e83481e8ff 100644 (file)
@@ -534,13 +534,10 @@ static int __init db1000_dev_init(void)
                s0 = AU1100_GPIO1_INT;
                s1 = AU1100_GPIO4_INT;
 
+               gpio_request(19, "sd0_cd");
+               gpio_request(20, "sd1_cd");
                gpio_direction_input(19);       /* sd0 cd# */
                gpio_direction_input(20);       /* sd1 cd# */
-               gpio_direction_input(21);       /* touch pendown# */
-               gpio_direction_input(207);      /* SPI MISO */
-               gpio_direction_output(208, 0);  /* SPI MOSI */
-               gpio_direction_output(209, 1);  /* SPI SCK */
-               gpio_direction_output(210, 1);  /* SPI CS# */
 
                /* spi_gpio on SSI0 pins */
                pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
index 6d612e2b949b20f3875f7993b29de8e77435194c..cdd8246f92b33f8494712247a16348a8b41f27f1 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/errno.h>
 #include <linux/export.h>
 #include <linux/string.h>
 #include <bcm47xx_board.h>
index 6decb27cf48b4343e9358283775f82df82ed0aa5..2bed73a684aea021b4a296076880fed6a2ec489b 100644 (file)
@@ -196,7 +196,7 @@ int bcm47xx_nvram_gpio_pin(const char *name)
        char nvram_var[10];
        char buf[30];
 
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < 32; i++) {
                err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
                if (err <= 0)
                        continue;
index 25fbfae06c1f8585359c65d975bfc3240e00faa8..c2bb4f896ce788cbba4b6c48cd18ef875e5bdfd6 100644 (file)
@@ -975,10 +975,6 @@ static int octeon_irq_ciu_xlat(struct irq_domain *d,
        if (ciu > 1 || bit > 63)
                return -EINVAL;
 
-       /* These are the GPIO lines */
-       if (ciu == 0 && bit >= 16 && bit < 32)
-               return -EINVAL;
-
        *out_hwirq = (ciu << 6) | bit;
        *out_type = 0;
 
@@ -1007,6 +1003,10 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
        if (!octeon_irq_virq_in_range(virq))
                return -EINVAL;
 
+       /* Don't map irq if it is reserved for GPIO. */
+       if (line == 0 && bit >= 16 && bit <32)
+               return 0;
+
        if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
                return -EINVAL;
 
@@ -1525,10 +1525,6 @@ static int octeon_irq_ciu2_xlat(struct irq_domain *d,
        ciu = intspec[0];
        bit = intspec[1];
 
-       /* Line 7  are the GPIO lines */
-       if (ciu > 6 || bit > 63)
-               return -EINVAL;
-
        *out_hwirq = (ciu << 6) | bit;
        *out_type = 0;
 
@@ -1570,8 +1566,14 @@ static int octeon_irq_ciu2_map(struct irq_domain *d,
        if (!octeon_irq_virq_in_range(virq))
                return -EINVAL;
 
-       /* Line 7  are the GPIO lines */
-       if (line > 6 || octeon_irq_ciu_to_irq[line][bit] != 0)
+       /*
+        * Don't map irq if it is reserved for GPIO.
+        * (Line 7 are the GPIO lines.)
+        */
+       if (line == 7)
+               return 0;
+
+       if (line > 7 || octeon_irq_ciu_to_irq[line][bit] != 0)
                return -EINVAL;
 
        if (octeon_irq_ciu2_is_edge(line, bit))
index 2d7f65052c1f3ffe9c9f191539a196dff97339f0..05439187891dfa02e582dc1caa2b6abbbfb8395b 100644 (file)
@@ -2,16 +2,17 @@
 generic-y += cputime.h
 generic-y += current.h
 generic-y += emergency-restart.h
+generic-y += hash.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += mutex.h
 generic-y += parport.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += ucontext.h
 generic-y += xor.h
-generic-y += hash.h
index 3220c93ea981da828e94820bb6ec7c9a570db70f..4225e99bd7bfdbe75b0e47cd8b974c2dd92e1ddc 100644 (file)
@@ -9,6 +9,7 @@
 #define _ASM_ASMMACRO_H
 
 #include <asm/hazards.h>
+#include <asm/asm-offsets.h>
 
 #ifdef CONFIG_32BIT
 #include <asm/asmmacro-32.h>
        .endm
 
        .macro  local_irq_disable reg=t0
+#ifdef CONFIG_PREEMPT
+       lw      \reg, TI_PRE_COUNT($28)
+       addi    \reg, \reg, 1
+       sw      \reg, TI_PRE_COUNT($28)
+#endif
        mfc0    \reg, CP0_STATUS
        ori     \reg, \reg, 1
        xori    \reg, \reg, 1
        mtc0    \reg, CP0_STATUS
        irq_disable_hazard
+#ifdef CONFIG_PREEMPT
+       lw      \reg, TI_PRE_COUNT($28)
+       addi    \reg, \reg, -1
+       sw      \reg, TI_PRE_COUNT($28)
+#endif
        .endm
 #endif /* CONFIG_MIPS_MT_SMTC */
 
        .endm
 
        .macro  fpu_save_double thread status tmp
-#if defined(CONFIG_MIPS64) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
        sll     \tmp, \status, 5
        bgez    \tmp, 10f
        fpu_save_16odd \thread
        .endm
 
        .macro  fpu_restore_double thread status tmp
-#if defined(CONFIG_MIPS64) || defined(CONFIG_CPU_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
        sll     \tmp, \status, 5
        bgez    \tmp, 10f                               # 16 register mode?
 
index cfe092fc720d021ab7636276e2f0ea9eb4a4507c..58e50cbdb1a6d577ef6ffbac115efcd593b6dedc 100644 (file)
@@ -57,7 +57,7 @@ static inline int __enable_fpu(enum fpu_mode mode)
                return 0;
 
        case FPU_64BIT:
-#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_MIPS64))
+#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
                /* we only have a 32-bit FPU */
                return SIGFPE;
 #endif
@@ -74,6 +74,8 @@ static inline int __enable_fpu(enum fpu_mode mode)
        default:
                BUG();
        }
+
+       return SIGFPE;
 }
 
 #define __disable_fpu()                                                        \
index ce35c9af0c28b2dd8d179e1f5ad75d9fc610ba4c..992aaba603b5ca24da6242c5aebef4ea80aeb0e2 100644 (file)
@@ -22,12 +22,12 @@ extern void _mcount(void);
 #define safe_load(load, src, dst, error)               \
 do {                                                   \
        asm volatile (                                  \
-               "1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
-               "   li %[" STR(error) "], 0\n"          \
+               "1: " load " %[tmp_dst], 0(%[tmp_src])\n"       \
+               "   li %[tmp_err], 0\n"                 \
                "2:\n"                                  \
                                                        \
                ".section .fixup, \"ax\"\n"             \
-               "3: li %[" STR(error) "], 1\n"          \
+               "3: li %[tmp_err], 1\n"                 \
                "   j 2b\n"                             \
                ".previous\n"                           \
                                                        \
@@ -35,8 +35,8 @@ do {                                                  \
                STR(PTR) "\t1b, 3b\n\t"                 \
                ".previous\n"                           \
                                                        \
-               : [dst] "=&r" (dst), [error] "=r" (error)\
-               : [src] "r" (src)                       \
+               : [tmp_dst] "=&r" (dst), [tmp_err] "=r" (error)\
+               : [tmp_src] "r" (src)                   \
                : "memory"                              \
        );                                              \
 } while (0)
@@ -44,12 +44,12 @@ do {                                                        \
 #define safe_store(store, src, dst, error)     \
 do {                                           \
        asm volatile (                          \
-               "1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
-               "   li %[" STR(error) "], 0\n"  \
+               "1: " store " %[tmp_src], 0(%[tmp_dst])\n"\
+               "   li %[tmp_err], 0\n"         \
                "2:\n"                          \
                                                \
                ".section .fixup, \"ax\"\n"     \
-               "3: li %[" STR(error) "], 1\n"  \
+               "3: li %[tmp_err], 1\n"         \
                "   j 2b\n"                     \
                ".previous\n"                   \
                                                \
@@ -57,8 +57,8 @@ do {                                          \
                STR(PTR) "\t1b, 3b\n\t"         \
                ".previous\n"                   \
                                                \
-               : [error] "=r" (error)          \
-               : [dst] "r" (dst), [src] "r" (src)\
+               : [tmp_err] "=r" (error)        \
+               : [tmp_dst] "r" (dst), [tmp_src] "r" (src)\
                : "memory"                      \
        );                                      \
 } while (0)
index 33e8dbfc1b631626b3f52dd9c60d27957ae0f364..f35b131977e62a3ef0d81c47da6827f47d527b71 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __ASM_MIPS_SYSCALL_H
 #define __ASM_MIPS_SYSCALL_H
 
+#include <linux/compiler.h>
 #include <linux/audit.h>
 #include <linux/elf-em.h>
 #include <linux/kernel.h>
@@ -39,14 +40,14 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
 
 #ifdef CONFIG_32BIT
        case 4: case 5: case 6: case 7:
-               return get_user(*arg, (int *)usp + 4 * n);
+               return get_user(*arg, (int *)usp + n);
 #endif
 
 #ifdef CONFIG_64BIT
        case 4: case 5: case 6: case 7:
 #ifdef CONFIG_MIPS32_O32
                if (test_thread_flag(TIF_32BIT_REGS))
-                       return get_user(*arg, (int *)usp + 4 * n);
+                       return get_user(*arg, (int *)usp + n);
                else
 #endif
                        *arg = regs->regs[4 + n];
@@ -57,6 +58,8 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
        default:
                BUG();
        }
+
+       unreachable();
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -83,11 +86,10 @@ static inline void syscall_get_arguments(struct task_struct *task,
                                         unsigned int i, unsigned int n,
                                         unsigned long *args)
 {
-       unsigned long arg;
        int ret;
 
        while (n--)
-               ret |= mips_get_syscall_arg(&arg, task, regs, i++);
+               ret |= mips_get_syscall_arg(args++, task, regs, i++);
 
        /*
         * No way to communicate an error because this is a void function.
index 12609a17dc8b5893faacf8df47b954b10a140664..20ea4859c82259534425ceb3833aa098f7400cf2 100644 (file)
@@ -10,8 +10,4 @@
 
 #include <topology.h>
 
-#ifdef CONFIG_SMP
-#define smt_capable()  (smp_num_siblings > 1)
-#endif
-
 #endif /* __ASM_TOPOLOGY_H */
index 4d3b92886665799d2ca2b746d8efc310cc0c1168..413d6c612bec059e0e5579d3167d67e6bb8e7ad0 100644 (file)
@@ -24,7 +24,6 @@
 
 #ifndef __ASSEMBLY__
 
-#define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
index b39ba25b41ccd2db0ae723ba01c4fab3a82621a6..f25181b19941db0544dc8e98187827343df99238 100644 (file)
@@ -163,8 +163,8 @@ enum cop1_sdw_func {
  */
 enum cop1x_func {
        lwxc1_op     =  0x00, ldxc1_op     =  0x01,
-       pfetch_op    =  0x07, swxc1_op     =  0x08,
-       sdxc1_op     =  0x09, madd_s_op    =  0x20,
+       swxc1_op     =  0x08, sdxc1_op     =  0x09,
+       pfetch_op    =  0x0f, madd_s_op    =  0x20,
        madd_d_op    =  0x21, madd_e_op    =  0x22,
        msub_s_op    =  0x28, msub_d_op    =  0x29,
        msub_e_op    =  0x2a, nmadd_s_op   =  0x30,
index 1dee279f96659c6ae2d2ac6d42af77483454076d..d6e154a9e6a55ef98d964f71629a129f6fd04d27 100644 (file)
 #define __NR_process_vm_writev         (__NR_Linux + 346)
 #define __NR_kcmp                      (__NR_Linux + 347)
 #define __NR_finit_module              (__NR_Linux + 348)
+#define __NR_sched_setattr             (__NR_Linux + 349)
+#define __NR_sched_getattr             (__NR_Linux + 350)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            348
+#define __NR_Linux_syscalls            350
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                348
+#define __NR_O32_Linux_syscalls                350
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_kcmp                      (__NR_Linux + 306)
 #define __NR_finit_module              (__NR_Linux + 307)
 #define __NR_getdents64                        (__NR_Linux + 308)
+#define __NR_sched_setattr             (__NR_Linux + 309)
+#define __NR_sched_getattr             (__NR_Linux + 310)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            308
+#define __NR_Linux_syscalls            310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         308
+#define __NR_64_Linux_syscalls         310
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_process_vm_writev         (__NR_Linux + 310)
 #define __NR_kcmp                      (__NR_Linux + 311)
 #define __NR_finit_module              (__NR_Linux + 312)
+#define __NR_sched_setattr             (__NR_Linux + 313)
+#define __NR_sched_getattr             (__NR_Linux + 314)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            312
+#define __NR_Linux_syscalls            314
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                312
+#define __NR_N32_Linux_syscalls                314
 
 #endif /* _UAPI_ASM_UNISTD_H */
index 185ba258361b979ee9531bd18d38b0242e1de979..374ed74cd516d91e27638ce12e4c3c731a191ef4 100644 (file)
@@ -111,11 +111,10 @@ static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
        safe_store_code(new_code1, ip, faulted);
        if (unlikely(faulted))
                return -EFAULT;
-       ip += 4;
-       safe_store_code(new_code2, ip, faulted);
+       safe_store_code(new_code2, ip + 4, faulted);
        if (unlikely(faulted))
                return -EFAULT;
-       flush_icache_range(ip, ip + 8); /* original ip + 12 */
+       flush_icache_range(ip, ip + 8);
        return 0;
 }
 #endif
index 253b2fb520267fb3536584df6d395a6b860392f1..73b0ddf910d41b08dd1bacd97f862e97f94f4c95 100644 (file)
@@ -35,9 +35,9 @@
 LEAF(_save_fp_context)
        cfc1    t1, fcr31
 
-#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
        .set    push
-#ifdef CONFIG_MIPS32_R2
+#ifdef CONFIG_CPU_MIPS32_R2
        .set    mips64r2
        mfc0    t0, CP0_STATUS
        sll     t0, t0, 5
@@ -146,11 +146,11 @@ LEAF(_save_fp_context32)
  *  - cp1 status/control register
  */
 LEAF(_restore_fp_context)
-       EX      lw t0, SC_FPC_CSR(a0)
+       EX      lw t1, SC_FPC_CSR(a0)
 
-#if defined(CONFIG_64BIT) || defined(CONFIG_MIPS32_R2)
+#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
        .set    push
-#ifdef CONFIG_MIPS32_R2
+#ifdef CONFIG_CPU_MIPS32_R2
        .set    mips64r2
        mfc0    t0, CP0_STATUS
        sll     t0, t0, 5
@@ -191,7 +191,7 @@ LEAF(_restore_fp_context)
        EX      ldc1 $f26, SC_FPREGS+208(a0)
        EX      ldc1 $f28, SC_FPREGS+224(a0)
        EX      ldc1 $f30, SC_FPREGS+240(a0)
-       ctc1    t0, fcr31
+       ctc1    t1, fcr31
        jr      ra
         li     v0, 0                                   # success
        END(_restore_fp_context)
@@ -199,7 +199,7 @@ LEAF(_restore_fp_context)
 #ifdef CONFIG_MIPS32_COMPAT
 LEAF(_restore_fp_context32)
        /* Restore an o32 sigcontext.  */
-       EX      lw t0, SC32_FPC_CSR(a0)
+       EX      lw t1, SC32_FPC_CSR(a0)
 
        mfc0    t0, CP0_STATUS
        sll     t0, t0, 5
@@ -239,7 +239,7 @@ LEAF(_restore_fp_context32)
        EX      ldc1 $f26, SC32_FPREGS+208(a0)
        EX      ldc1 $f28, SC32_FPREGS+224(a0)
        EX      ldc1 $f30, SC32_FPREGS+240(a0)
-       ctc1    t0, fcr31
+       ctc1    t1, fcr31
        jr      ra
         li     v0, 0                                   # success
        END(_restore_fp_context32)
index 56dc6963515314962ad22ee0a5676edf87937122..758fb3cd2326c34dd119d86d1c3ee5c5d148ee29 100644 (file)
@@ -112,5 +112,8 @@ void __exit rtlx_module_exit(void)
 
        for (i = 0; i < RTLX_CHANNELS; i++)
                device_destroy(mt_class, MKDEV(major, i));
+
        unregister_chrdev(major, RTLX_MODULE_NAME);
+
+       aprp_hook = NULL;
 }
index 91d61ba422b4677fdc956b0a5707ddb58740212a..9c1aca00fd5442e8b44a259ad99e2c328718b600 100644 (file)
@@ -144,5 +144,8 @@ void __exit rtlx_module_exit(void)
 
        for (i = 0; i < RTLX_CHANNELS; i++)
                device_destroy(mt_class, MKDEV(major, i));
+
        unregister_chrdev(major, RTLX_MODULE_NAME);
+
+       aprp_hook = NULL;
 }
index e8e541b40d86be37a2e1fe9c693bbfe912581bfb..a5b14f48e1af805af4aaff1b4d6f17fff0beffe9 100644 (file)
@@ -563,3 +563,5 @@ EXPORT(sys_call_table)
        PTR     sys_process_vm_writev
        PTR     sys_kcmp
        PTR     sys_finit_module
+       PTR     sys_sched_setattr
+       PTR     sys_sched_getattr               /* 4350 */
index 57e3742fec59a19083eb3cb5f802b9e43a90b66b..b56e254beb15b6bb91078b43e1c13b4ea5b83bd3 100644 (file)
@@ -425,4 +425,6 @@ EXPORT(sys_call_table)
        PTR     sys_kcmp
        PTR     sys_finit_module
        PTR     sys_getdents64
+       PTR     sys_sched_setattr
+       PTR     sys_sched_getattr               /* 5310 */
        .size   sys_call_table,.-sys_call_table
index 2f48f5934399e3b48a14cd88f2bf84fba0d46894..f7e5b72cf481256103919641267714e6c9e59742 100644 (file)
@@ -418,4 +418,6 @@ EXPORT(sysn32_call_table)
        PTR     compat_sys_process_vm_writev    /* 6310 */
        PTR     sys_kcmp
        PTR     sys_finit_module
+       PTR     sys_sched_setattr
+       PTR     sys_sched_getattr
        .size   sysn32_call_table,.-sysn32_call_table
index f1acdb429f4fa1d89ee8db664f5fd25005c978a1..6788727d91af1f79da1af76fbb0e7c3cc99ec600 100644 (file)
@@ -541,4 +541,6 @@ EXPORT(sys32_call_table)
        PTR     compat_sys_process_vm_writev
        PTR     sys_kcmp
        PTR     sys_finit_module
+       PTR     sys_sched_setattr
+       PTR     sys_sched_getattr               /* 4350 */
        .size   sys32_call_table,.-sys32_call_table
index 506925b2c3f366a12aecfb8ecc3cf6d69274654d..0b4e2e38294bf174132fcb4036cc958a370cfbec 100644 (file)
@@ -1538,10 +1538,10 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                break;
        }
 
-       case 0x7:               /* 7 */
-               if (MIPSInst_FUNC(ir) != pfetch_op) {
+       case 0x3:
+               if (MIPSInst_FUNC(ir) != pfetch_op)
                        return SIGILL;
-               }
+
                /* ignore prefx operation */
                break;
 
index 592ac0427426acd4b83d1272f4e8c43c7716bca1..84ac523b0ce08675ecd102a2beeda2b66ce92f11 100644 (file)
@@ -72,7 +72,7 @@ int amon_cpu_start(int cpu,
        return 0;
 }
 
-#ifdef CONFIG_MIPS_VPE_LOADER
+#ifdef CONFIG_MIPS_VPE_LOADER_CMP
 int vpe_run(struct vpe *v)
 {
        struct vpe_notifications *n;
index ca3e3a46a42f90dedc359c1729d7b3c55365fc92..2242181a62841e2c86cd87ab3859bee35ca91099 100644 (file)
@@ -119,7 +119,7 @@ static void malta_hw0_irqdispatch(void)
 
        do_IRQ(MALTA_INT_BASE + irq);
 
-#ifdef MIPS_VPE_APSP_API
+#ifdef CONFIG_MIPS_VPE_APSP_API_MT
        if (aprp_hook)
                aprp_hook();
 #endif
@@ -310,7 +310,7 @@ static void ipi_call_dispatch(void)
 
 static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
 {
-#ifdef MIPS_VPE_APSP_API
+#ifdef CONFIG_MIPS_VPE_APSP_API_CMP
        if (aprp_hook)
                aprp_hook();
 #endif
index d37be36dc659b4df1f3b22787f84c6908bc5eb45..2b91b0e6156670a723c4cd46749065a0f798d347 100644 (file)
@@ -150,6 +150,7 @@ msi_irq_allocated:
                msg.address_lo =
                        ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff;
                msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32;
+               break;
        case OCTEON_DMA_BAR_TYPE_BIG:
                /* When using big bar, Bar 0 is based at 0 */
                msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff;
index 992e989ab7853d3f3e1be4bbb432cf4c2de8c7a2..654d5ba6e31077354f130f22a198c7b6adb45743 100644 (file)
@@ -1,7 +1,9 @@
 
 generic-y += barrier.h
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += exec.h
 generic-y += hash.h
-generic-y += trace_clock.h
+generic-y += mcs_spinlock.h
 generic-y += preempt.h
+generic-y += trace_clock.h
diff --git a/arch/mn10300/include/asm/cputime.h b/arch/mn10300/include/asm/cputime.h
deleted file mode 100644 (file)
index 6d68ad7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/cputime.h>
index 2e40f1ca86677ecff7f232beb909128aa509e9d3..480af0d9c2f5dbe20fb39dc6331648dacb043a97 100644 (file)
@@ -10,8 +10,8 @@ generic-y += bugs.h
 generic-y += cacheflush.h
 generic-y += checksum.h
 generic-y += clkdev.h
-generic-y += cmpxchg.h
 generic-y += cmpxchg-local.h
+generic-y += cmpxchg.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += device.h
@@ -25,6 +25,7 @@ generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += futex.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -34,6 +35,7 @@ generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += local.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += module.h
 generic-y += msgbuf.h
@@ -41,6 +43,7 @@ generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -53,11 +56,11 @@ generic-y += siginfo.h
 generic-y += signal.h
 generic-y += socket.h
 generic-y += sockios.h
-generic-y += statfs.h
 generic-y += stat.h
+generic-y += statfs.h
 generic-y += string.h
-generic-y += switch_to.h
 generic-y += swab.h
+generic-y += switch_to.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
@@ -68,5 +71,3 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 88d0962de65a8ca97c877b90dfb0b9ac59b0bfac..2bedafea3d94c13c7215a4be242f12e7a2f185f1 100644 (file)
 
 int hpux_execve(struct pt_regs *regs)
 {
-       int error;
-       struct filename *filename;
-
-       filename = getname((const char __user *) regs->gr[26]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-
-       error = do_execve(filename->name,
+       return  do_execve(getname((const char __user *) regs->gr[26]),
                          (const char __user *const __user *) regs->gr[25],
                          (const char __user *const __user *) regs->gr[24]);
-
-       putname(filename);
-
-out:
-       return error;
 }
 
 struct hpux_dirent {
index 752c981bc3c7fc36dbd0fb01705f4c691e7ee6bd..ecf25e6678ad5a2f0e2bd63761699e85c9d2d759 100644 (file)
@@ -1,9 +1,29 @@
 
+generic-y += auxvec.h
 generic-y += barrier.h
-generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
-         segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \
-         div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
-         poll.h xor.h clkdev.h exec.h
-generic-y += trace_clock.h
-generic-y += preempt.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += exec.h
 generic-y += hash.h
+generic-y += hw_irq.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kvm_para.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += preempt.h
+generic-y += segment.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += user.h
+generic-y += vga.h
+generic-y += word-at-a-time.h
+generic-y += xor.h
index 637fe031aa8476d743a8141ca9b549019985a0c6..60d5d174dfe413e14cb5117a04536ce7948d937d 100644 (file)
@@ -32,17 +32,6 @@ void copy_page_asm(void *to, void *from);
 void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
                        struct page *pg);
 
-/* #define CONFIG_PARISC_TMPALIAS */
-
-#ifdef CONFIG_PARISC_TMPALIAS
-void clear_user_highpage(struct page *page, unsigned long vaddr);
-#define clear_user_highpage clear_user_highpage
-struct vm_area_struct;
-void copy_user_highpage(struct page *to, struct page *from,
-       unsigned long vaddr, struct vm_area_struct *vma);
-#define __HAVE_ARCH_COPY_USER_HIGHPAGE
-#endif
-
 /*
  * These are used to make use of C type-checking..
  */
index 3516e0b27044d5e5cf987cf53acf735059a5b016..64f2992e439fcd81811e7a44d322bdc5aafd9ff1 100644 (file)
@@ -191,8 +191,4 @@ static __inline__ int arch_write_can_lock(arch_rwlock_t *rw)
 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
 
-#define arch_spin_relax(lock)  cpu_relax()
-#define arch_read_relax(lock)  cpu_relax()
-#define arch_write_relax(lock) cpu_relax()
-
 #endif /* __ASM_SPINLOCK_H */
index 42706794a36f34d12fa598df238ade3db602e9c6..265ae5190b0a70e4dc2539d9a661e1e3d2deda05 100644 (file)
 #define __NR_finit_module      (__NR_Linux + 333)
 #define __NR_sched_setattr     (__NR_Linux + 334)
 #define __NR_sched_getattr     (__NR_Linux + 335)
+#define __NR_utimes            (__NR_Linux + 336)
 
-#define __NR_Linux_syscalls    (__NR_sched_getattr + 1)
+#define __NR_Linux_syscalls    (__NR_utimes + 1)
 
 
 #define __IGNORE_select                /* newselect */
 #define __IGNORE_fadvise64     /* fadvise64_64 */
-#define __IGNORE_utimes                /* utime */
 
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
index ac87a40502e6f6a0e11d21eaf6789259859ad092..a6ffc775a9f8105381b3da46214290a421a79c6c 100644 (file)
@@ -581,67 +581,3 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
                __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
        }
 }
-
-#ifdef CONFIG_PARISC_TMPALIAS
-
-void clear_user_highpage(struct page *page, unsigned long vaddr)
-{
-       void *vto;
-       unsigned long flags;
-
-       /* Clear using TMPALIAS region.  The page doesn't need to
-          be flushed but the kernel mapping needs to be purged.  */
-
-       vto = kmap_atomic(page);
-
-       /* The PA-RISC 2.0 Architecture book states on page F-6:
-          "Before a write-capable translation is enabled, *all*
-          non-equivalently-aliased translations must be removed
-          from the page table and purged from the TLB.  (Note
-          that the caches are not required to be flushed at this
-          time.)  Before any non-equivalent aliased translation
-          is re-enabled, the virtual address range for the writeable
-          page (the entire page) must be flushed from the cache,
-          and the write-capable translation removed from the page
-          table and purged from the TLB."  */
-
-       purge_kernel_dcache_page_asm((unsigned long)vto);
-       purge_tlb_start(flags);
-       pdtlb_kernel(vto);
-       purge_tlb_end(flags);
-       preempt_disable();
-       clear_user_page_asm(vto, vaddr);
-       preempt_enable();
-
-       pagefault_enable();             /* kunmap_atomic(addr, KM_USER0); */
-}
-
-void copy_user_highpage(struct page *to, struct page *from,
-       unsigned long vaddr, struct vm_area_struct *vma)
-{
-       void *vfrom, *vto;
-       unsigned long flags;
-
-       /* Copy using TMPALIAS region.  This has the advantage
-          that the `from' page doesn't need to be flushed.  However,
-          the `to' page must be flushed in copy_user_page_asm since
-          it can be used to bring in executable code.  */
-
-       vfrom = kmap_atomic(from);
-       vto = kmap_atomic(to);
-
-       purge_kernel_dcache_page_asm((unsigned long)vto);
-       purge_tlb_start(flags);
-       pdtlb_kernel(vto);
-       pdtlb_kernel(vfrom);
-       purge_tlb_end(flags);
-       preempt_disable();
-       copy_user_page_asm(vto, vfrom, vaddr);
-       flush_dcache_page_asm(__pa(vto), vaddr);
-       preempt_enable();
-
-       pagefault_enable();             /* kunmap_atomic(addr, KM_USER1); */
-       pagefault_enable();             /* kunmap_atomic(addr, KM_USER0); */
-}
-
-#endif /* CONFIG_PARISC_TMPALIAS */
index 8fa3fbb3e4d3806f15ab0d98543a35d8b18155ce..80e5dd248934e26ca94916c1e1f7c2cd6cffbefd 100644 (file)
        ENTRY_SAME(finit_module)
        ENTRY_SAME(sched_setattr)
        ENTRY_SAME(sched_getattr)       /* 335 */
+       ENTRY_COMP(utimes)
 
        /* Nothing yet */
 
index 6c0a955a1b06277d05b7bf159da202279b2038e9..3fb1bc432f4f6106f1a892ce02113ec68970af6a 100644 (file)
@@ -1,7 +1,8 @@
 
 generic-y += clkdev.h
+generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += vtime.h
-generic-y += hash.h
index 84fdf6857c31d1ccf878911b416f32e104eba8fb..a613d2c82fd9e7cbb024a28f493c0be54748d7e0 100644 (file)
@@ -200,10 +200,11 @@ static inline void __user *arch_compat_alloc_user_space(long len)
 
        /*
         * We can't access below the stack pointer in the 32bit ABI and
-        * can access 288 bytes in the 64bit ABI
+        * can access 288 bytes in the 64bit big-endian ABI,
+        * or 512 bytes with the new ELFv2 little-endian ABI.
         */
        if (!is_32bit_task())
-               usp -= 288;
+               usp -= USER_REDZONE_SIZE;
 
        return (void __user *) (usp - len);
 }
index e27e9ad6818ea815164734711e1eb048e52ab5a2..150866b2a3fe07337f38905511a73cd726e07689 100644 (file)
@@ -134,6 +134,7 @@ static inline int dma_supported(struct device *dev, u64 mask)
 }
 
 extern int dma_set_mask(struct device *dev, u64 dma_mask);
+extern int __dma_set_mask(struct device *dev, u64 dma_mask);
 
 #define dma_alloc_coherent(d,s,h,f)    dma_alloc_attrs(d,s,h,f,NULL)
 
index 9e39ceb1d19fd706014794a6918f671ef12a5a58..d4dd41fb951b343918dda3db91399702d0e86423 100644 (file)
@@ -172,10 +172,20 @@ struct eeh_ops {
 };
 
 extern struct eeh_ops *eeh_ops;
-extern int eeh_subsystem_enabled;
+extern bool eeh_subsystem_enabled;
 extern raw_spinlock_t confirm_error_lock;
 extern int eeh_probe_mode;
 
+static inline bool eeh_enabled(void)
+{
+       return eeh_subsystem_enabled;
+}
+
+static inline void eeh_set_enable(bool mode)
+{
+       eeh_subsystem_enabled = mode;
+}
+
 #define EEH_PROBE_MODE_DEV     (1<<0)  /* From PCI device      */
 #define EEH_PROBE_MODE_DEVTREE (1<<1)  /* From device tree     */
 
@@ -246,7 +256,7 @@ void eeh_remove_device(struct pci_dev *);
  * If this macro yields TRUE, the caller relays to eeh_check_failure()
  * which does further tests out of line.
  */
-#define EEH_POSSIBLE_ERROR(val, type)  ((val) == (type)~0 && eeh_subsystem_enabled)
+#define EEH_POSSIBLE_ERROR(val, type)  ((val) == (type)~0 && eeh_enabled())
 
 /*
  * Reads from a device which has been isolated by EEH will return
@@ -257,6 +267,13 @@ void eeh_remove_device(struct pci_dev *);
 
 #else /* !CONFIG_EEH */
 
+static inline bool eeh_enabled(void)
+{
+        return false;
+}
+
+static inline void eeh_set_enable(bool mode) { }
+
 static inline int eeh_init(void)
 {
        return 0;
index d750336b171db4cf2c75f7e1fb95cbf6bcba8d74..623f2971ce0ed8d4d947642c862d4dce7640d28d 100644 (file)
@@ -127,7 +127,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
                                            unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_PPC64
-       return __pte(pte_update(mm, addr, ptep, ~0UL, 1));
+       return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 1));
 #else
        return __pte(pte_update(ptep, ~0UL, 0));
 #endif
index f7a8036579b5a43d19ea0730b7e541b61272ab13..42632c7a2a4e77e86fa0768646f30b7508365fd9 100644 (file)
@@ -77,6 +77,7 @@ struct iommu_table {
 #ifdef CONFIG_IOMMU_API
        struct iommu_group *it_group;
 #endif
+       void (*set_bypass)(struct iommu_table *tbl, bool enable);
 };
 
 /* Pure 2^n version of get_order */
index 40157e2ca6914467cddae0225070d8582ad0861c..ed82142a325111ca18ecbc5ad05ec5760cb03a87 100644 (file)
@@ -816,8 +816,8 @@ int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe,
 int64_t opal_pci_poll(uint64_t phb_id);
 int64_t opal_return_cpu(void);
 
-int64_t opal_xscom_read(uint32_t gcid, uint32_t pcb_addr, __be64 *val);
-int64_t opal_xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val);
+int64_t opal_xscom_read(uint32_t gcid, uint64_t pcb_addr, __be64 *val);
+int64_t opal_xscom_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val);
 
 int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
                       uint32_t addr, uint32_t data, uint32_t sz);
index bc141c950b1e6c8128769b786df189eb275f583f..eb9261024f5192386dec97bff1ee10e62da4b7c3 100644 (file)
@@ -195,6 +195,7 @@ extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 static inline unsigned long pte_update(struct mm_struct *mm,
                                       unsigned long addr,
                                       pte_t *ptep, unsigned long clr,
+                                      unsigned long set,
                                       int huge)
 {
 #ifdef PTE_ATOMIC_UPDATES
@@ -205,14 +206,15 @@ static inline unsigned long pte_update(struct mm_struct *mm,
        andi.   %1,%0,%6\n\
        bne-    1b \n\
        andc    %1,%0,%4 \n\
+       or      %1,%1,%7\n\
        stdcx.  %1,0,%3 \n\
        bne-    1b"
        : "=&r" (old), "=&r" (tmp), "=m" (*ptep)
-       : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY)
+       : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set)
        : "cc" );
 #else
        unsigned long old = pte_val(*ptep);
-       *ptep = __pte(old & ~clr);
+       *ptep = __pte((old & ~clr) | set);
 #endif
        /* huge pages use the old page table lock */
        if (!huge)
@@ -231,9 +233,9 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
 {
        unsigned long old;
 
-               if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
+       if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
                return 0;
-       old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0);
+       old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
        return (old & _PAGE_ACCESSED) != 0;
 }
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -252,7 +254,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
        if ((pte_val(*ptep) & _PAGE_RW) == 0)
                return;
 
-       pte_update(mm, addr, ptep, _PAGE_RW, 0);
+       pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
 }
 
 static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
@@ -261,7 +263,7 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
        if ((pte_val(*ptep) & _PAGE_RW) == 0)
                return;
 
-       pte_update(mm, addr, ptep, _PAGE_RW, 1);
+       pte_update(mm, addr, ptep, _PAGE_RW, 0, 1);
 }
 
 /*
@@ -284,14 +286,14 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
                                       unsigned long addr, pte_t *ptep)
 {
-       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0);
+       unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
        return __pte(old);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
                             pte_t * ptep)
 {
-       pte_update(mm, addr, ptep, ~0UL, 0);
+       pte_update(mm, addr, ptep, ~0UL, 0, 0);
 }
 
 
@@ -506,7 +508,9 @@ extern int pmdp_set_access_flags(struct vm_area_struct *vma,
 
 extern unsigned long pmd_hugepage_update(struct mm_struct *mm,
                                         unsigned long addr,
-                                        pmd_t *pmdp, unsigned long clr);
+                                        pmd_t *pmdp,
+                                        unsigned long clr,
+                                        unsigned long set);
 
 static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
                                              unsigned long addr, pmd_t *pmdp)
@@ -515,7 +519,7 @@ static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
 
        if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
                return 0;
-       old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED);
+       old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
        return ((old & _PAGE_ACCESSED) != 0);
 }
 
@@ -542,7 +546,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
        if ((pmd_val(*pmdp) & _PAGE_RW) == 0)
                return;
 
-       pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW);
+       pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0);
 }
 
 #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
index f83b6f3e1b39b68c5b25f8df6a107f59bf20ae1b..3ebb188c3ff51a5ec0d55c31ce26601354a1bef7 100644 (file)
@@ -75,12 +75,34 @@ static inline pte_t pte_mknuma(pte_t pte)
        return pte;
 }
 
+#define ptep_set_numa ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pte_t *ptep)
+{
+       if ((pte_val(*ptep) & _PAGE_PRESENT) == 0)
+               VM_BUG_ON(1);
+
+       pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0);
+       return;
+}
+
 #define pmd_numa pmd_numa
 static inline int pmd_numa(pmd_t pmd)
 {
        return pte_numa(pmd_pte(pmd));
 }
 
+#define pmdp_set_numa pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pmd_t *pmdp)
+{
+       if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0)
+               VM_BUG_ON(1);
+
+       pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA);
+       return;
+}
+
 #define pmd_mknonnuma pmd_mknonnuma
 static inline pmd_t pmd_mknonnuma(pmd_t pmd)
 {
index becc08e6a65c585e0b6bc995f7699d74e2c36338..279b80f3bb293d0bceceecb9eb38ff344e26b8fb 100644 (file)
 
 #ifdef __powerpc64__
 
+/*
+ * Size of redzone that userspace is allowed to use below the stack
+ * pointer.  This is 288 in the 64-bit big-endian ELF ABI, and 512 in
+ * the new ELFv2 little-endian ABI, so we allow the larger amount.
+ *
+ * For kernel code we allow a 288-byte redzone, in order to conserve
+ * kernel stack space; gcc currently only uses 288 bytes, and will
+ * hopefully allow explicit control of the redzone size in future.
+ */
+#define USER_REDZONE_SIZE      512
+#define KERNEL_REDZONE_SIZE    288
+
 #define STACK_FRAME_OVERHEAD   112     /* size of minimum stack frame */
 #define STACK_FRAME_LR_SAVE    2       /* Location of LR in stack frame */
 #define STACK_FRAME_REGS_MARKER        ASM_CONST(0x7265677368657265)
 #define STACK_INT_FRAME_SIZE   (sizeof(struct pt_regs) + \
-                                       STACK_FRAME_OVERHEAD + 288)
+                                STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
 #define STACK_FRAME_MARKER     12
 
 /* Size of dummy stack frame allocated when calling signal handler. */
@@ -41,6 +53,8 @@
 
 #else /* __powerpc64__ */
 
+#define USER_REDZONE_SIZE      0
+#define KERNEL_REDZONE_SIZE    0
 #define STACK_FRAME_OVERHEAD   16      /* size of minimum stack frame */
 #define STACK_FRAME_LR_SAVE    1       /* Location of LR in stack frame */
 #define STACK_FRAME_REGS_MARKER        ASM_CONST(0x72656773)
index 4ee06fe15de41d11e77f7c7c44d2daaea8d10ed2..d0e784e0ff484f0053f807e081a4c89fec13dee6 100644 (file)
@@ -8,6 +8,7 @@
 
 #ifdef __powerpc64__
 
+extern char __start_interrupts[];
 extern char __end_interrupts[];
 
 extern char __prom_init_toc_start[];
@@ -21,6 +22,17 @@ static inline int in_kernel_text(unsigned long addr)
        return 0;
 }
 
+static inline int overlaps_interrupt_vector_text(unsigned long start,
+                                                       unsigned long end)
+{
+       unsigned long real_start, real_end;
+       real_start = __start_interrupts - _stext;
+       real_end = __end_interrupts - _stext;
+
+       return start < (unsigned long)__va(real_end) &&
+               (unsigned long)__va(real_start) < end;
+}
+
 static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
 {
        return start < (unsigned long)__init_end &&
index d0b5fca6b0776fc8ef220483b91b1557c73a0835..c9202151079f2b1d6e99af4569b82ce68c785573 100644 (file)
@@ -99,7 +99,6 @@ static inline int prrn_is_enabled(void)
 
 #ifdef CONFIG_SMP
 #include <asm/cputable.h>
-#define smt_capable()          (cpu_has_feature(CPU_FTR_SMT))
 
 #ifdef CONFIG_PPC64
 #include <asm/smp.h>
index 0d9cecddf8a4f5ae133415f5e0bd49d780318e01..c53f5f6d1761f711b280c9e29509da15e6f1f4b8 100644 (file)
@@ -4,11 +4,11 @@
 #ifdef __KERNEL__
 
 /* Default link addresses for the vDSOs */
-#define VDSO32_LBASE   0x100000
-#define VDSO64_LBASE   0x100000
+#define VDSO32_LBASE   0x0
+#define VDSO64_LBASE   0x0
 
 /* Default map addresses for 32bit vDSO */
-#define VDSO32_MBASE   VDSO32_LBASE
+#define VDSO32_MBASE   0x100000
 
 #define VDSO_VERSION_STRING    LINUX_2.6.15
 
index 11c1d069d920a1fc97ec601ab0542c41708d7cc1..7a13f378ca2c7b1c715b9719e01329f99bf2ef2e 100644 (file)
@@ -98,17 +98,19 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
                        size_t csize, unsigned long offset, int userbuf)
 {
        void  *vaddr;
+       phys_addr_t paddr;
 
        if (!csize)
                return 0;
 
        csize = min_t(size_t, csize, PAGE_SIZE);
+       paddr = pfn << PAGE_SHIFT;
 
-       if ((min_low_pfn < pfn) && (pfn < max_pfn)) {
-               vaddr = __va(pfn << PAGE_SHIFT);
+       if (memblock_is_region_memory(paddr, csize)) {
+               vaddr = __va(paddr);
                csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
        } else {
-               vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
+               vaddr = __ioremap(paddr, PAGE_SIZE, 0);
                csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
                iounmap(vaddr);
        }
index 8032b97ccdcb6668f01dc9c2026c0080f0a14449..ee78f6e49d64bddc78d58382b73008841896b38a 100644 (file)
@@ -191,12 +191,10 @@ EXPORT_SYMBOL(dma_direct_ops);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 
-int dma_set_mask(struct device *dev, u64 dma_mask)
+int __dma_set_mask(struct device *dev, u64 dma_mask)
 {
        struct dma_map_ops *dma_ops = get_dma_ops(dev);
 
-       if (ppc_md.dma_set_mask)
-               return ppc_md.dma_set_mask(dev, dma_mask);
        if ((dma_ops != NULL) && (dma_ops->set_dma_mask != NULL))
                return dma_ops->set_dma_mask(dev, dma_mask);
        if (!dev->dma_mask || !dma_supported(dev, dma_mask))
@@ -204,6 +202,12 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
        *dev->dma_mask = dma_mask;
        return 0;
 }
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+       if (ppc_md.dma_set_mask)
+               return ppc_md.dma_set_mask(dev, dma_mask);
+       return __dma_set_mask(dev, dma_mask);
+}
 EXPORT_SYMBOL(dma_set_mask);
 
 u64 dma_get_required_mask(struct device *dev)
index 148db72a8c4371e69f79009683eb8b3baf12c3d6..e7b76a6bf15083704136459dc1dc69f2c6c9183e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/rbtree.h>
+#include <linux/reboot.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/export.h>
@@ -89,7 +90,7 @@
 /* Platform dependent EEH operations */
 struct eeh_ops *eeh_ops = NULL;
 
-int eeh_subsystem_enabled;
+bool eeh_subsystem_enabled = false;
 EXPORT_SYMBOL(eeh_subsystem_enabled);
 
 /*
@@ -364,7 +365,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
 
        eeh_stats.total_mmio_ffs++;
 
-       if (!eeh_subsystem_enabled)
+       if (!eeh_enabled())
                return 0;
 
        if (!edev) {
@@ -747,6 +748,17 @@ int __exit eeh_ops_unregister(const char *name)
        return -EEXIST;
 }
 
+static int eeh_reboot_notifier(struct notifier_block *nb,
+                              unsigned long action, void *unused)
+{
+       eeh_set_enable(false);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block eeh_reboot_nb = {
+       .notifier_call = eeh_reboot_notifier,
+};
+
 /**
  * eeh_init - EEH initialization
  *
@@ -778,6 +790,14 @@ int eeh_init(void)
        if (machine_is(powernv) && cnt++ <= 0)
                return ret;
 
+       /* Register reboot notifier */
+       ret = register_reboot_notifier(&eeh_reboot_nb);
+       if (ret) {
+               pr_warn("%s: Failed to register notifier (%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
        /* call platform initialization function */
        if (!eeh_ops) {
                pr_warning("%s: Platform EEH operation not found\n",
@@ -822,7 +842,7 @@ int eeh_init(void)
                        return ret;
        }
 
-       if (eeh_subsystem_enabled)
+       if (eeh_enabled())
                pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
        else
                pr_warning("EEH: No capable adapters found\n");
@@ -897,7 +917,7 @@ void eeh_add_device_late(struct pci_dev *dev)
        struct device_node *dn;
        struct eeh_dev *edev;
 
-       if (!dev || !eeh_subsystem_enabled)
+       if (!dev || !eeh_enabled())
                return;
 
        pr_debug("EEH: Adding device %s\n", pci_name(dev));
@@ -1005,7 +1025,7 @@ void eeh_remove_device(struct pci_dev *dev)
 {
        struct eeh_dev *edev;
 
-       if (!dev || !eeh_subsystem_enabled)
+       if (!dev || !eeh_enabled())
                return;
        edev = pci_dev_to_eeh_dev(dev);
 
@@ -1045,7 +1065,7 @@ void eeh_remove_device(struct pci_dev *dev)
 
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
-       if (0 == eeh_subsystem_enabled) {
+       if (!eeh_enabled()) {
                seq_printf(m, "EEH Subsystem is globally disabled\n");
                seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs);
        } else {
index 7bb30dca4e192f55ca689319eefdc2a50646ff3a..fdc679d309ec4c030d6f407d35675fb1b2527473 100644 (file)
@@ -362,9 +362,13 @@ static void *eeh_rmv_device(void *data, void *userdata)
         */
        if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
                return NULL;
+
        driver = eeh_pcid_get(dev);
-       if (driver && driver->err_handler)
-               return NULL;
+       if (driver) {
+               eeh_pcid_put(dev);
+               if (driver->err_handler)
+                       return NULL;
+       }
 
        /* Remove it from PCI subsystem */
        pr_debug("EEH: Removing %s without EEH sensitive driver\n",
index 9b27b293a9226903c81529a4f01aee64a7f07d23..b0ded97ee4e11148cd436809aaab2c36c106893a 100644 (file)
@@ -74,6 +74,7 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
  */
 static int test_24bit_addr(unsigned long ip, unsigned long addr)
 {
+       addr = ppc_function_entry((void *)addr);
 
        /* use the create_branch to verify that this offset can be branched */
        return create_branch((unsigned int *)ip, addr, 0);
index d773dd440a45a32560fed0176120709ff5ea860d..88e3ec6e1d965a38ade11ecff745e8c029e84ced 100644 (file)
@@ -1088,6 +1088,14 @@ int iommu_take_ownership(struct iommu_table *tbl)
        memset(tbl->it_map, 0xff, sz);
        iommu_clear_tces_and_put_pages(tbl, tbl->it_offset, tbl->it_size);
 
+       /*
+        * Disable iommu bypass, otherwise the user can DMA to all of
+        * our physical memory via the bypass window instead of just
+        * the pages that has been explicitly mapped into the iommu
+        */
+       if (tbl->set_bypass)
+               tbl->set_bypass(tbl, false);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_take_ownership);
@@ -1102,6 +1110,10 @@ void iommu_release_ownership(struct iommu_table *tbl)
        /* Restore bit#0 set by iommu_init_table() */
        if (tbl->it_offset == 0)
                set_bit(0, tbl->it_map);
+
+       /* The kernel owns the device now, we can restore the iommu bypass */
+       if (tbl->set_bypass)
+               tbl->set_bypass(tbl, true);
 }
 EXPORT_SYMBOL_GPL(iommu_release_ownership);
 
index 9729b23bfb0a2deebf0e5157accb2d68541b6bf0..1d0848bba049bf2c97bd09d9d86864857af128a7 100644 (file)
@@ -559,8 +559,13 @@ void exc_lvl_ctx_init(void)
 #ifdef CONFIG_PPC64
                cpu_nr = i;
 #else
+#ifdef CONFIG_SMP
                cpu_nr = get_hard_smp_processor_id(i);
+#else
+               cpu_nr = 0;
 #endif
+#endif
+
                memset((void *)critirq_ctx[cpu_nr], 0, THREAD_SIZE);
                tp = critirq_ctx[cpu_nr];
                tp->cpu = cpu_nr;
index 75d4f7340da893bc2825f97dda750409d8963323..015ae55c18686ffb794938531aa52692e0843b0e 100644 (file)
@@ -196,7 +196,9 @@ int overlaps_crashkernel(unsigned long start, unsigned long size)
 
 /* Values we need to export to the second kernel via the device tree. */
 static phys_addr_t kernel_end;
+static phys_addr_t crashk_base;
 static phys_addr_t crashk_size;
+static unsigned long long mem_limit;
 
 static struct property kernel_end_prop = {
        .name = "linux,kernel-end",
@@ -207,7 +209,7 @@ static struct property kernel_end_prop = {
 static struct property crashk_base_prop = {
        .name = "linux,crashkernel-base",
        .length = sizeof(phys_addr_t),
-       .value = &crashk_res.start,
+       .value = &crashk_base
 };
 
 static struct property crashk_size_prop = {
@@ -219,9 +221,11 @@ static struct property crashk_size_prop = {
 static struct property memory_limit_prop = {
        .name = "linux,memory-limit",
        .length = sizeof(unsigned long long),
-       .value = &memory_limit,
+       .value = &mem_limit,
 };
 
+#define cpu_to_be_ulong        __PASTE(cpu_to_be, BITS_PER_LONG)
+
 static void __init export_crashk_values(struct device_node *node)
 {
        struct property *prop;
@@ -237,8 +241,9 @@ static void __init export_crashk_values(struct device_node *node)
                of_remove_property(node, prop);
 
        if (crashk_res.start != 0) {
+               crashk_base = cpu_to_be_ulong(crashk_res.start),
                of_add_property(node, &crashk_base_prop);
-               crashk_size = resource_size(&crashk_res);
+               crashk_size = cpu_to_be_ulong(resource_size(&crashk_res));
                of_add_property(node, &crashk_size_prop);
        }
 
@@ -246,6 +251,7 @@ static void __init export_crashk_values(struct device_node *node)
         * memory_limit is required by the kexec-tools to limit the
         * crash regions to the actual memory used.
         */
+       mem_limit = cpu_to_be_ulong(memory_limit);
        of_update_property(node, &memory_limit_prop);
 }
 
@@ -264,7 +270,7 @@ static int __init kexec_setup(void)
                of_remove_property(node, prop);
 
        /* information needed by userspace when using default_machine_kexec */
-       kernel_end = __pa(_end);
+       kernel_end = cpu_to_be_ulong(__pa(_end));
        of_add_property(node, &kernel_end_prop);
 
        export_crashk_values(node);
index be4e6d648f6093d4efe7fe84155ebe9653a3baea..59d229a2a3e08dfcd1f18ca94e56cd00e787c987 100644 (file)
@@ -369,6 +369,7 @@ void default_machine_kexec(struct kimage *image)
 
 /* Values we need to export to the second kernel via the device tree. */
 static unsigned long htab_base;
+static unsigned long htab_size;
 
 static struct property htab_base_prop = {
        .name = "linux,htab-base",
@@ -379,7 +380,7 @@ static struct property htab_base_prop = {
 static struct property htab_size_prop = {
        .name = "linux,htab-size",
        .length = sizeof(unsigned long),
-       .value = &htab_size_bytes,
+       .value = &htab_size,
 };
 
 static int __init export_htab_values(void)
@@ -403,8 +404,9 @@ static int __init export_htab_values(void)
        if (prop)
                of_remove_property(node, prop);
 
-       htab_base = __pa(htab_address);
+       htab_base = cpu_to_be64(__pa(htab_address));
        of_add_property(node, &htab_base_prop);
+       htab_size = cpu_to_be64(htab_size_bytes);
        of_add_property(node, &htab_size_prop);
 
        of_node_put(node);
index 879f09620f8341e27dbfd1ed6be47fe242eab812..7c6bb4b17b4960d111f29bc7f37632f9026d944c 100644 (file)
@@ -57,11 +57,14 @@ _GLOBAL(call_do_softirq)
        mtlr    r0
        blr
 
+/*
+ * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
+ */
 _GLOBAL(call_do_irq)
        mflr    r0
        stw     r0,4(r1)
        lwz     r10,THREAD+KSP_LIMIT(r2)
-       addi    r11,r3,THREAD_INFO_GAP
+       addi    r11,r4,THREAD_INFO_GAP
        stwu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
        mr      r1,r4
        stw     r10,8(r1)
index 8d4c247f17389f283d02bc48dba044ff077e3ffe..af064d28b36524c5ce9c8fc982a58eec65ebbfc7 100644 (file)
@@ -1048,6 +1048,15 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
        flush_altivec_to_thread(src);
        flush_vsx_to_thread(src);
        flush_spe_to_thread(src);
+       /*
+        * Flush TM state out so we can copy it.  __switch_to_tm() does this
+        * flush but it removes the checkpointed state from the current CPU and
+        * transitions the CPU out of TM mode.  Hence we need to call
+        * tm_recheckpoint_new_task() (on the same task) to restore the
+        * checkpointed state back and the TM mode.
+        */
+       __switch_to_tm(src);
+       tm_recheckpoint_new_task(src);
 
        *dst = *src;
 
index b47a0e1ab00150926df137b68d79684050f13b26..d88736fbece67c6627e6f33a9c4fd3e31ee2b533 100644 (file)
@@ -69,8 +69,8 @@ _GLOBAL(relocate)
         * R_PPC64_RELATIVE ones.
         */
        mtctr   r8
-5:     lwz     r0,12(9)        /* ELF64_R_TYPE(reloc->r_info) */
-       cmpwi   r0,R_PPC64_RELATIVE
+5:     ld      r0,8(9)         /* ELF64_R_TYPE(reloc->r_info) */
+       cmpdi   r0,R_PPC64_RELATIVE
        bne     6f
        ld      r6,0(r9)        /* reloc->r_offset */
        ld      r0,16(r9)       /* reloc->r_addend */
@@ -81,6 +81,7 @@ _GLOBAL(relocate)
 
 6:     blr
 
+.balign 8
 p_dyn: .llong  __dynamic_start - 0b
 p_rela:        .llong  __rela_dyn_start - 0b
 p_st:  .llong  _stext - 0b
index 2b0da27eaee4242f156d37bfbb4efa06bad334df..04cc4fcca78b690f86c089708745e6c4cc0f5939 100644 (file)
@@ -247,7 +247,12 @@ static void __init exc_lvl_early_init(void)
        /* interrupt stacks must be in lowmem, we get that for free on ppc32
         * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
        for_each_possible_cpu(i) {
+#ifdef CONFIG_SMP
                hw_cpu = get_hard_smp_processor_id(i);
+#else
+               hw_cpu = 0;
+#endif
+
                critirq_ctx[hw_cpu] = (struct thread_info *)
                        __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
 #ifdef CONFIG_BOOKE
index e35bf773df7a8d972990374cbb1507db261ccea2..8d253c29649b514e6f12694a5794329e008f1ea2 100644 (file)
@@ -65,8 +65,8 @@ struct rt_sigframe {
        struct siginfo __user *pinfo;
        void __user *puc;
        struct siginfo info;
-       /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
-       char abigap[288];
+       /* New 64 bit little-endian ABI allows redzone of 512 bytes below sp */
+       char abigap[USER_REDZONE_SIZE];
 } __attribute__ ((aligned (16)));
 
 static const char fmt32[] = KERN_INFO \
index 79683d0393f5d01577503b02d7d298018647a758..6ac107ac402a93ffcabb5f0cd365132f922fe88d 100644 (file)
@@ -6,7 +6,7 @@
        .globl vdso32_start, vdso32_end
        .balign PAGE_SIZE
 vdso32_start:
-       .incbin "arch/powerpc/kernel/vdso32/vdso32.so"
+       .incbin "arch/powerpc/kernel/vdso32/vdso32.so.dbg"
        .balign PAGE_SIZE
 vdso32_end:
 
index 8df9e2463007c1601012aae7062c6a8896ebf9ef..df60fca6a13d1eb745612e78c0be86a32fb78c45 100644 (file)
@@ -6,7 +6,7 @@
        .globl vdso64_start, vdso64_end
        .balign PAGE_SIZE
 vdso64_start:
-       .incbin "arch/powerpc/kernel/vdso64/vdso64.so"
+       .incbin "arch/powerpc/kernel/vdso64/vdso64.so.dbg"
        .balign PAGE_SIZE
 vdso64_end:
 
index e66d4ec04d953a78a314b43a3a07f47ca27f5ae7..818dce344e82a0fa0a94fe7f21eefdb2483fbc68 100644 (file)
@@ -1504,73 +1504,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 1:     addi    r8,r8,16
        .endr
 
-       /* Save DEC */
-       mfspr   r5,SPRN_DEC
-       mftb    r6
-       extsw   r5,r5
-       add     r5,r5,r6
-       std     r5,VCPU_DEC_EXPIRES(r9)
-
-BEGIN_FTR_SECTION
-       b       8f
-END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
-       /* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
-       mfmsr   r8
-       li      r0, 1
-       rldimi  r8, r0, MSR_TM_LG, 63-MSR_TM_LG
-       mtmsrd  r8
-
-       /* Save POWER8-specific registers */
-       mfspr   r5, SPRN_IAMR
-       mfspr   r6, SPRN_PSPB
-       mfspr   r7, SPRN_FSCR
-       std     r5, VCPU_IAMR(r9)
-       stw     r6, VCPU_PSPB(r9)
-       std     r7, VCPU_FSCR(r9)
-       mfspr   r5, SPRN_IC
-       mfspr   r6, SPRN_VTB
-       mfspr   r7, SPRN_TAR
-       std     r5, VCPU_IC(r9)
-       std     r6, VCPU_VTB(r9)
-       std     r7, VCPU_TAR(r9)
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       mfspr   r5, SPRN_TFHAR
-       mfspr   r6, SPRN_TFIAR
-       mfspr   r7, SPRN_TEXASR
-       std     r5, VCPU_TFHAR(r9)
-       std     r6, VCPU_TFIAR(r9)
-       std     r7, VCPU_TEXASR(r9)
-#endif
-       mfspr   r8, SPRN_EBBHR
-       std     r8, VCPU_EBBHR(r9)
-       mfspr   r5, SPRN_EBBRR
-       mfspr   r6, SPRN_BESCR
-       mfspr   r7, SPRN_CSIGR
-       mfspr   r8, SPRN_TACR
-       std     r5, VCPU_EBBRR(r9)
-       std     r6, VCPU_BESCR(r9)
-       std     r7, VCPU_CSIGR(r9)
-       std     r8, VCPU_TACR(r9)
-       mfspr   r5, SPRN_TCSCR
-       mfspr   r6, SPRN_ACOP
-       mfspr   r7, SPRN_PID
-       mfspr   r8, SPRN_WORT
-       std     r5, VCPU_TCSCR(r9)
-       std     r6, VCPU_ACOP(r9)
-       stw     r7, VCPU_GUEST_PID(r9)
-       std     r8, VCPU_WORT(r9)
-8:
-
-       /* Save and reset AMR and UAMOR before turning on the MMU */
-BEGIN_FTR_SECTION
-       mfspr   r5,SPRN_AMR
-       mfspr   r6,SPRN_UAMOR
-       std     r5,VCPU_AMR(r9)
-       std     r6,VCPU_UAMOR(r9)
-       li      r6,0
-       mtspr   SPRN_AMR,r6
-END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
-
        /* Unset guest mode */
        li      r0, KVM_GUEST_MODE_NONE
        stb     r0, HSTATE_IN_GUEST(r13)
@@ -2203,7 +2136,7 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
        mfspr   r6,SPRN_VRSAVE
-       stw     r6,VCPU_VRSAVE(r3)
+       stw     r6,VCPU_VRSAVE(r31)
        mtlr    r30
        mtmsrd  r5
        isync
@@ -2240,7 +2173,7 @@ BEGIN_FTR_SECTION
        bl      .load_vr_state
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
-       lwz     r7,VCPU_VRSAVE(r4)
+       lwz     r7,VCPU_VRSAVE(r31)
        mtspr   SPRN_VRSAVE,r7
        mtlr    r30
        mr      r4,r31
index de6881259aef3bd552c53ea77751093336e2e5be..d766d6ee33fe6889e5a96b3898f8c47b0050fc14 100644 (file)
@@ -207,6 +207,20 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
 
+               /*
+                * If relocatable, check if it overlaps interrupt vectors that
+                * are copied down to real 0. For relocatable kernel
+                * (e.g. kdump case) we copy interrupt vectors down to real
+                * address 0. Mark that region as executable. This is
+                * because on p8 system with relocation on exception feature
+                * enabled, exceptions are raised with MMU (IR=DR=1) ON. Hence
+                * in order to execute the interrupt handlers in virtual
+                * mode the vector region need to be marked as executable.
+                */
+               if ((PHYSICAL_START > MEMORY_START) &&
+                       overlaps_interrupt_vector_text(vaddr, vaddr + step))
+                               tprot &= ~HPTE_R_N;
+
                hash = hpt_hash(vpn, shift, ssize);
                hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
index 65b7b65e8708bd1867861f4b519d207b25beb5a7..62bf5e8e78daaaf5051fb6e5727bfd99be81a088 100644 (file)
@@ -510,7 +510,8 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
 }
 
 unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
-                                 pmd_t *pmdp, unsigned long clr)
+                                 pmd_t *pmdp, unsigned long clr,
+                                 unsigned long set)
 {
 
        unsigned long old, tmp;
@@ -526,14 +527,15 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
                andi.   %1,%0,%6\n\
                bne-    1b \n\
                andc    %1,%0,%4 \n\
+               or      %1,%1,%7\n\
                stdcx.  %1,0,%3 \n\
                bne-    1b"
        : "=&r" (old), "=&r" (tmp), "=m" (*pmdp)
-       : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY)
+       : "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set)
        : "cc" );
 #else
        old = pmd_val(*pmdp);
-       *pmdp = __pmd(old & ~clr);
+       *pmdp = __pmd((old & ~clr) | set);
 #endif
        if (old & _PAGE_HASHPTE)
                hpte_do_hugepage_flush(mm, addr, pmdp);
@@ -708,7 +710,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
-       pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT);
+       pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
 }
 
 /*
@@ -835,7 +837,7 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm,
        unsigned long old;
        pgtable_t *pgtable_slot;
 
-       old = pmd_hugepage_update(mm, addr, pmdp, ~0UL);
+       old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
        old_pmd = __pmd(old);
        /*
         * We have pmd == none and we are holding page_table_lock.
index a770df2dae7050bafd28daf1c354165113e378f9..6c0b1f5f8d2ccef746ccddfed70684c45f3adec2 100644 (file)
@@ -78,7 +78,7 @@ static void hpte_flush_range(struct mm_struct *mm, unsigned long addr,
        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
        arch_enter_lazy_mmu_mode();
        for (; npages > 0; --npages) {
-               pte_update(mm, addr, pte, 0, 0);
+               pte_update(mm, addr, pte, 0, 0, 0);
                addr += PAGE_SIZE;
                ++pte;
        }
index 29b89e863d7cc11328cb2d93e08f4b4598ec47a2..67cf22083f4c2cfd6175c91ce416efb68ae1a6e6 100644 (file)
@@ -1147,6 +1147,9 @@ static void power_pmu_enable(struct pmu *pmu)
        mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]);
 
        mb();
+       if (cpuhw->bhrb_users)
+               ppmu->config_bhrb(cpuhw->bhrb_filter);
+
        write_mmcr0(cpuhw, mmcr0);
 
        /*
@@ -1158,8 +1161,6 @@ static void power_pmu_enable(struct pmu *pmu)
        }
 
  out:
-       if (cpuhw->bhrb_users)
-               ppmu->config_bhrb(cpuhw->bhrb_filter);
 
        local_irq_restore(flags);
 }
index a3f7abd2f13f7a0793ce4e2bdb00855f9724d108..96cee20dcd34ec2cf33f6d836d4f4fd49b7848c6 100644 (file)
 #define PM_BRU_FIN                     0x10068
 #define PM_BR_MPRED_CMPL               0x400f6
 
+/* All L1 D cache load references counted at finish, gated by reject */
+#define PM_LD_REF_L1                   0x100ee
+/* Load Missed L1 */
+#define PM_LD_MISS_L1                  0x3e054
+/* Store Missed L1 */
+#define PM_ST_MISS_L1                  0x300f0
+/* L1 cache data prefetches */
+#define PM_L1_PREF                     0x0d8b8
+/* Instruction fetches from L1 */
+#define PM_INST_FROM_L1                        0x04080
+/* Demand iCache Miss */
+#define PM_L1_ICACHE_MISS              0x200fd
+/* Instruction Demand sectors wriittent into IL1 */
+#define PM_L1_DEMAND_WRITE             0x0408c
+/* Instruction prefetch written into IL1 */
+#define PM_IC_PREF_WRITE               0x0408e
+/* The data cache was reloaded from local core's L3 due to a demand load */
+#define PM_DATA_FROM_L3                        0x4c042
+/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
+#define PM_DATA_FROM_L3MISS            0x300fe
+/* All successful D-side store dispatches for this thread */
+#define PM_L2_ST                       0x17080
+/* All successful D-side store dispatches for this thread that were L2 Miss */
+#define PM_L2_ST_MISS                  0x17082
+/* Total HW L3 prefetches(Load+store) */
+#define PM_L3_PREF_ALL                 0x4e052
+/* Data PTEG reload */
+#define PM_DTLB_MISS                   0x300fc
+/* ITLB Reloaded */
+#define PM_ITLB_MISS                   0x400fc
+
 
 /*
  * Raw event encoding for POWER8:
@@ -557,6 +588,8 @@ static int power8_generic_events[] = {
        [PERF_COUNT_HW_INSTRUCTIONS] =                  PM_INST_CMPL,
        [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =           PM_BRU_FIN,
        [PERF_COUNT_HW_BRANCH_MISSES] =                 PM_BR_MPRED_CMPL,
+       [PERF_COUNT_HW_CACHE_REFERENCES] =              PM_LD_REF_L1,
+       [PERF_COUNT_HW_CACHE_MISSES] =                  PM_LD_MISS_L1,
 };
 
 static u64 power8_bhrb_filter_map(u64 branch_sample_type)
@@ -596,6 +629,116 @@ static void power8_config_bhrb(u64 pmu_bhrb_filter)
        mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
 }
 
+#define C(x)   PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int power8_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+       [ C(L1D) ] = {
+               [ C(OP_READ) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_LD_REF_L1,
+                       [ C(RESULT_MISS)   ] = PM_LD_MISS_L1,
+               },
+               [ C(OP_WRITE) ] = {
+                       [ C(RESULT_ACCESS) ] = 0,
+                       [ C(RESULT_MISS)   ] = PM_ST_MISS_L1,
+               },
+               [ C(OP_PREFETCH) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_L1_PREF,
+                       [ C(RESULT_MISS)   ] = 0,
+               },
+       },
+       [ C(L1I) ] = {
+               [ C(OP_READ) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_INST_FROM_L1,
+                       [ C(RESULT_MISS)   ] = PM_L1_ICACHE_MISS,
+               },
+               [ C(OP_WRITE) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_L1_DEMAND_WRITE,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+               [ C(OP_PREFETCH) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_IC_PREF_WRITE,
+                       [ C(RESULT_MISS)   ] = 0,
+               },
+       },
+       [ C(LL) ] = {
+               [ C(OP_READ) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_DATA_FROM_L3,
+                       [ C(RESULT_MISS)   ] = PM_DATA_FROM_L3MISS,
+               },
+               [ C(OP_WRITE) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_L2_ST,
+                       [ C(RESULT_MISS)   ] = PM_L2_ST_MISS,
+               },
+               [ C(OP_PREFETCH) ] = {
+                       [ C(RESULT_ACCESS) ] = PM_L3_PREF_ALL,
+                       [ C(RESULT_MISS)   ] = 0,
+               },
+       },
+       [ C(DTLB) ] = {
+               [ C(OP_READ) ] = {
+                       [ C(RESULT_ACCESS) ] = 0,
+                       [ C(RESULT_MISS)   ] = PM_DTLB_MISS,
+               },
+               [ C(OP_WRITE) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+               [ C(OP_PREFETCH) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+       },
+       [ C(ITLB) ] = {
+               [ C(OP_READ) ] = {
+                       [ C(RESULT_ACCESS) ] = 0,
+                       [ C(RESULT_MISS)   ] = PM_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) ] = PM_BRU_FIN,
+                       [ C(RESULT_MISS)   ] = PM_BR_MPRED_CMPL,
+               },
+               [ C(OP_WRITE) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+               [ C(OP_PREFETCH) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+       },
+       [ C(NODE) ] = {
+               [ C(OP_READ) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+               [ C(OP_WRITE) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+               [ C(OP_PREFETCH) ] = {
+                       [ C(RESULT_ACCESS) ] = -1,
+                       [ C(RESULT_MISS)   ] = -1,
+               },
+       },
+};
+
+#undef C
+
 static struct power_pmu power8_pmu = {
        .name                   = "POWER8",
        .n_counter              = 6,
@@ -611,6 +754,7 @@ static struct power_pmu power8_pmu = {
        .flags                  = PPMU_HAS_SSLOT | PPMU_HAS_SIER | PPMU_BHRB | PPMU_EBB,
        .n_generic              = ARRAY_SIZE(power8_generic_events),
        .generic_events         = power8_generic_events,
+       .cache_events           = &power8_cache_events,
        .attr_groups            = power8_pmu_attr_groups,
        .bhrb_nr                = 32,
 };
index 5ec1e47a0d771eba56e8b8c42111a19aed7df25a..e865d748179b2ac1b0b7550c1d3bebbcae71e049 100644 (file)
@@ -123,7 +123,8 @@ static int __init cbe_ptcal_enable_on_node(int nid, int order)
 
        area->nid = nid;
        area->order = order;
-       area->pages = alloc_pages_exact_node(area->nid, GFP_KERNEL|GFP_THISNODE,
+       area->pages = alloc_pages_exact_node(area->nid,
+                                               GFP_KERNEL|__GFP_THISNODE,
                                                area->order);
 
        if (!area->pages) {
index 49318385d4fac71e6122588da95c895a18d9198d..4a0a64fe25df274a16051b668a3497b4632e8bf1 100644 (file)
@@ -83,7 +83,6 @@ static struct timer_list spuloadavg_timer;
 #define MIN_SPU_TIMESLICE      max(5 * HZ / (1000 * SPUSCHED_TICK), 1)
 #define DEF_SPU_TIMESLICE      (100 * HZ / (1000 * SPUSCHED_TICK))
 
-#define MAX_USER_PRIO          (MAX_PRIO - MAX_RT_PRIO)
 #define SCALE_PRIO(x, prio) \
        max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE)
 
index e1e71618b70cfe5d4caa7d15e30bc42a37361c56..253fefe3d1a0e76fd4ed3996711b6f1784725d6c 100644 (file)
@@ -44,7 +44,8 @@ static int ioda_eeh_event(struct notifier_block *nb,
 
        /* We simply send special EEH event */
        if ((changed_evts & OPAL_EVENT_PCI_ERROR) &&
-           (events & OPAL_EVENT_PCI_ERROR))
+           (events & OPAL_EVENT_PCI_ERROR) &&
+           eeh_enabled())
                eeh_send_failure_event(NULL);
 
        return 0;
@@ -113,6 +114,7 @@ DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get,
                        ioda_eeh_inbB_dbgfs_set, "0x%llx\n");
 #endif /* CONFIG_DEBUG_FS */
 
+
 /**
  * ioda_eeh_post_init - Chip dependent post initialization
  * @hose: PCI controller
@@ -220,6 +222,22 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
        return ret;
 }
 
+static void ioda_eeh_phb_diag(struct pci_controller *hose)
+{
+       struct pnv_phb *phb = hose->private_data;
+       long rc;
+
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
+       if (rc != OPAL_SUCCESS) {
+               pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
+                           __func__, hose->global_number, rc);
+               return;
+       }
+
+       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+}
+
 /**
  * ioda_eeh_get_state - Retrieve the state of PE
  * @pe: EEH PE
@@ -271,6 +289,9 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
                        result |= EEH_STATE_DMA_ACTIVE;
                        result |= EEH_STATE_MMIO_ENABLED;
                        result |= EEH_STATE_DMA_ENABLED;
+               } else if (!(pe->state & EEH_PE_ISOLATED)) {
+                       eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+                       ioda_eeh_phb_diag(hose);
                }
 
                return result;
@@ -314,6 +335,15 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
                           __func__, fstate, hose->global_number, pe_no);
        }
 
+       /* Dump PHB diag-data for frozen PE */
+       if (result != EEH_STATE_NOT_SUPPORT &&
+           (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) !=
+           (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
+           !(pe->state & EEH_PE_ISOLATED)) {
+               eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
+               ioda_eeh_phb_diag(hose);
+       }
+
        return result;
 }
 
@@ -489,8 +519,7 @@ static int ioda_eeh_bridge_reset(struct pci_controller *hose,
 static int ioda_eeh_reset(struct eeh_pe *pe, int option)
 {
        struct pci_controller *hose = pe->phb;
-       struct eeh_dev *edev;
-       struct pci_dev *dev;
+       struct pci_bus *bus;
        int ret;
 
        /*
@@ -519,72 +548,16 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
        if (pe->type & EEH_PE_PHB) {
                ret = ioda_eeh_phb_reset(hose, option);
        } else {
-               if (pe->type & EEH_PE_DEVICE) {
-                       /*
-                        * If it's device PE, we didn't refer to the parent
-                        * PCI bus yet. So we have to figure it out indirectly.
-                        */
-                       edev = list_first_entry(&pe->edevs,
-                                       struct eeh_dev, list);
-                       dev = eeh_dev_to_pci_dev(edev);
-                       dev = dev->bus->self;
-               } else {
-                       /*
-                        * If it's bus PE, the parent PCI bus is already there
-                        * and just pick it up.
-                        */
-                       dev = pe->bus->self;
-               }
-
-               /*
-                * Do reset based on the fact that the direct upstream bridge
-                * is root bridge (port) or not.
-                */
-               if (dev->bus->number == 0)
+               bus = eeh_pe_bus_get(pe);
+               if (pci_is_root_bus(bus))
                        ret = ioda_eeh_root_reset(hose, option);
                else
-                       ret = ioda_eeh_bridge_reset(hose, dev, option);
+                       ret = ioda_eeh_bridge_reset(hose, bus->self, option);
        }
 
        return ret;
 }
 
-/**
- * ioda_eeh_get_log - Retrieve error log
- * @pe: EEH PE
- * @severity: Severity level of the log
- * @drv_log: buffer to store the log
- * @len: space of the log buffer
- *
- * The function is used to retrieve error log from P7IOC.
- */
-static int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
-                           char *drv_log, unsigned long len)
-{
-       s64 ret;
-       unsigned long flags;
-       struct pci_controller *hose = pe->phb;
-       struct pnv_phb *phb = hose->private_data;
-
-       spin_lock_irqsave(&phb->lock, flags);
-
-       ret = opal_pci_get_phb_diag_data2(phb->opal_id,
-                       phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
-       if (ret) {
-               spin_unlock_irqrestore(&phb->lock, flags);
-               pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n",
-                          __func__, hose->global_number, pe->addr, ret);
-               return -EIO;
-       }
-
-       /* The PHB diag-data is always indicative */
-       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
-
-       spin_unlock_irqrestore(&phb->lock, flags);
-
-       return 0;
-}
-
 /**
  * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
  * @pe: EEH PE
@@ -666,22 +639,6 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
        }
 }
 
-static void ioda_eeh_phb_diag(struct pci_controller *hose)
-{
-       struct pnv_phb *phb = hose->private_data;
-       long rc;
-
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
-                                        PNV_PCI_DIAG_BUF_SIZE);
-       if (rc != OPAL_SUCCESS) {
-               pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
-                           __func__, hose->global_number, rc);
-               return;
-       }
-
-       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
-}
-
 static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
                               struct eeh_pe **pe)
 {
@@ -854,6 +811,20 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
                                __func__, err_type);
                }
 
+               /*
+                * EEH core will try recover from fenced PHB or
+                * frozen PE. In the time for frozen PE, EEH core
+                * enable IO path for that before collecting logs,
+                * but it ruins the site. So we have to dump the
+                * log in advance here.
+                */
+               if ((ret == EEH_NEXT_ERR_FROZEN_PE  ||
+                   ret == EEH_NEXT_ERR_FENCED_PHB) &&
+                   !((*pe)->state & EEH_PE_ISOLATED)) {
+                       eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
+                       ioda_eeh_phb_diag(hose);
+               }
+
                /*
                 * If we have no errors on the specific PHB or only
                 * informative error there, we continue poking it.
@@ -872,7 +843,6 @@ struct pnv_eeh_ops ioda_eeh_ops = {
        .set_option             = ioda_eeh_set_option,
        .get_state              = ioda_eeh_get_state,
        .reset                  = ioda_eeh_reset,
-       .get_log                = ioda_eeh_get_log,
        .configure_bridge       = ioda_eeh_configure_bridge,
        .next_error             = ioda_eeh_next_error
 };
index a79fddc5e74e58ac0a0b18fc1b7cb5db607095b2..a59788e83b8b377152ed5d70db86fbb7bc9fb805 100644 (file)
@@ -145,7 +145,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
         * Enable EEH explicitly so that we will do EEH check
         * while accessing I/O stuff
         */
-       eeh_subsystem_enabled = 1;
+       eeh_set_enable(true);
 
        /* Save memory bars */
        eeh_save_bars(edev);
index 4fbf276ac99eeb4e2900196e3905a3343bedc988..4cd2ea6c0dbe13ecf2fb7926838cfeac9277730c 100644 (file)
@@ -71,11 +71,11 @@ static int opal_xscom_err_xlate(int64_t rc)
        }
 }
 
-static u64 opal_scom_unmangle(u64 reg)
+static u64 opal_scom_unmangle(u64 addr)
 {
        /*
         * XSCOM indirect addresses have the top bit set. Additionally
-        * the reset of the top 3 nibbles is always 0.
+        * the rest of the top 3 nibbles is always 0.
         *
         * Because the debugfs interface uses signed offsets and shifts
         * the address left by 3, we basically cannot use the top 4 bits
@@ -86,10 +86,13 @@ static u64 opal_scom_unmangle(u64 reg)
         * conversion here. To leave room for further xscom address
         * expansion, we only clear out the top byte
         *
+        * For in-kernel use, we also support the real indirect bit, so
+        * we test for any of the top 5 bits
+        *
         */
-       if (reg & (1ull << 59))
-               reg = (reg & ~(0xffull << 56)) | (1ull << 63);
-       return reg;
+       if (addr & (0x1full << 59))
+               addr = (addr & ~(0xffull << 56)) | (1ull << 63);
+       return addr;
 }
 
 static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
@@ -98,8 +101,8 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
        int64_t rc;
        __be64 v;
 
-       reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v));
+       reg = opal_scom_unmangle(m->addr + reg);
+       rc = opal_xscom_read(m->chip, reg, (__be64 *)__pa(&v));
        *value = be64_to_cpu(v);
        return opal_xscom_err_xlate(rc);
 }
@@ -109,8 +112,8 @@ static int opal_scom_write(scom_map_t map, u64 reg, u64 value)
        struct opal_scom_map *m = map;
        int64_t rc;
 
-       reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_write(m->chip, m->addr + reg, value);
+       reg = opal_scom_unmangle(m->addr + reg);
+       rc = opal_xscom_write(m->chip, reg, value);
        return opal_xscom_err_xlate(rc);
 }
 
index 7d6dcc6d5fa9a6551c2465285cc1886242cc0125..3b2b4fb3585b6b9fac45878041772285591d1d63 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/msi.h>
+#include <linux/memblock.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
@@ -460,9 +461,39 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
                return;
 
        pe = &phb->ioda.pe_array[pdn->pe_number];
+       WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops);
        set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table);
 }
 
+static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb,
+                                    struct pci_dev *pdev, u64 dma_mask)
+{
+       struct pci_dn *pdn = pci_get_pdn(pdev);
+       struct pnv_ioda_pe *pe;
+       uint64_t top;
+       bool bypass = false;
+
+       if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
+               return -ENODEV;;
+
+       pe = &phb->ioda.pe_array[pdn->pe_number];
+       if (pe->tce_bypass_enabled) {
+               top = pe->tce_bypass_base + memblock_end_of_DRAM() - 1;
+               bypass = (dma_mask >= top);
+       }
+
+       if (bypass) {
+               dev_info(&pdev->dev, "Using 64-bit DMA iommu bypass\n");
+               set_dma_ops(&pdev->dev, &dma_direct_ops);
+               set_dma_offset(&pdev->dev, pe->tce_bypass_base);
+       } else {
+               dev_info(&pdev->dev, "Using 32-bit DMA via iommu\n");
+               set_dma_ops(&pdev->dev, &dma_iommu_ops);
+               set_iommu_table_base(&pdev->dev, &pe->tce32_table);
+       }
+       return 0;
+}
+
 static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
 {
        struct pci_dev *dev;
@@ -657,6 +688,56 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
                __free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs));
 }
 
+static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable)
+{
+       struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe,
+                                             tce32_table);
+       uint16_t window_id = (pe->pe_number << 1 ) + 1;
+       int64_t rc;
+
+       pe_info(pe, "%sabling 64-bit DMA bypass\n", enable ? "En" : "Dis");
+       if (enable) {
+               phys_addr_t top = memblock_end_of_DRAM();
+
+               top = roundup_pow_of_two(top);
+               rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id,
+                                                    pe->pe_number,
+                                                    window_id,
+                                                    pe->tce_bypass_base,
+                                                    top);
+       } else {
+               rc = opal_pci_map_pe_dma_window_real(pe->phb->opal_id,
+                                                    pe->pe_number,
+                                                    window_id,
+                                                    pe->tce_bypass_base,
+                                                    0);
+
+               /*
+                * We might want to reset the DMA ops of all devices on
+                * this PE. However in theory, that shouldn't be necessary
+                * as this is used for VFIO/KVM pass-through and the device
+                * hasn't yet been returned to its kernel driver
+                */
+       }
+       if (rc)
+               pe_err(pe, "OPAL error %lld configuring bypass window\n", rc);
+       else
+               pe->tce_bypass_enabled = enable;
+}
+
+static void pnv_pci_ioda2_setup_bypass_pe(struct pnv_phb *phb,
+                                         struct pnv_ioda_pe *pe)
+{
+       /* TVE #1 is selected by PCI address bit 59 */
+       pe->tce_bypass_base = 1ull << 59;
+
+       /* Install set_bypass callback for VFIO */
+       pe->tce32_table.set_bypass = pnv_pci_ioda2_set_bypass;
+
+       /* Enable bypass by default */
+       pnv_pci_ioda2_set_bypass(&pe->tce32_table, true);
+}
+
 static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
                                       struct pnv_ioda_pe *pe)
 {
@@ -727,6 +808,8 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
        else
                pnv_ioda_setup_bus_dma(pe, pe->pbus);
 
+       /* Also create a bypass window */
+       pnv_pci_ioda2_setup_bypass_pe(phb, pe);
        return;
 fail:
        if (pe->tce32_seg >= 0)
@@ -1286,6 +1369,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
 
        /* Setup TCEs */
        phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup;
+       phb->dma_set_mask = pnv_pci_ioda_dma_set_mask;
 
        /* Setup shutdown function for kexec */
        phb->shutdown = pnv_pci_ioda_shutdown;
index b555ebc57ef5a33010ea4becbf992d3deb2dcbad..8518817dcdfdc95d04e3b1fc10bfe54432330079 100644 (file)
@@ -134,57 +134,72 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose,
        pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
                hose->global_number, common->version);
 
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-       pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
-       pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+       if (data->brdgCtl)
+               pr_info("  brdgCtl:     %08x\n",
+                       data->brdgCtl);
+       if (data->portStatusReg || data->rootCmplxStatus ||
+           data->busAgentStatus)
+               pr_info("  UtlSts:      %08x %08x %08x\n",
+                       data->portStatusReg, data->rootCmplxStatus,
+                       data->busAgentStatus);
+       if (data->deviceStatus || data->slotStatus   ||
+           data->linkStatus   || data->devCmdStatus ||
+           data->devSecStatus)
+               pr_info("  RootSts:     %08x %08x %08x %08x %08x\n",
+                       data->deviceStatus, data->slotStatus,
+                       data->linkStatus, data->devCmdStatus,
+                       data->devSecStatus);
+       if (data->rootErrorStatus   || data->uncorrErrorStatus ||
+           data->corrErrorStatus)
+               pr_info("  RootErrSts:  %08x %08x %08x\n",
+                       data->rootErrorStatus, data->uncorrErrorStatus,
+                       data->corrErrorStatus);
+       if (data->tlpHdr1 || data->tlpHdr2 ||
+           data->tlpHdr3 || data->tlpHdr4)
+               pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+                       data->tlpHdr1, data->tlpHdr2,
+                       data->tlpHdr3, data->tlpHdr4);
+       if (data->sourceId || data->errorClass ||
+           data->correlator)
+               pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+                       data->sourceId, data->errorClass,
+                       data->correlator);
+       if (data->p7iocPlssr || data->p7iocCsr)
+               pr_info("  PhbSts:      %016llx %016llx\n",
+                       data->p7iocPlssr, data->p7iocCsr);
+       if (data->lemFir || data->lemErrorMask ||
+           data->lemWOF)
+               pr_info("  Lem:         %016llx %016llx %016llx\n",
+                       data->lemFir, data->lemErrorMask,
+                       data->lemWOF);
+       if (data->phbErrorStatus || data->phbFirstErrorStatus ||
+           data->phbErrorLog0   || data->phbErrorLog1)
+               pr_info("  PhbErr:      %016llx %016llx %016llx %016llx\n",
+                       data->phbErrorStatus, data->phbFirstErrorStatus,
+                       data->phbErrorLog0, data->phbErrorLog1);
+       if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
+           data->mmioErrorLog0   || data->mmioErrorLog1)
+               pr_info("  OutErr:      %016llx %016llx %016llx %016llx\n",
+                       data->mmioErrorStatus, data->mmioFirstErrorStatus,
+                       data->mmioErrorLog0, data->mmioErrorLog1);
+       if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
+           data->dma0ErrorLog0   || data->dma0ErrorLog1)
+               pr_info("  InAErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma0ErrorStatus, data->dma0FirstErrorStatus,
+                       data->dma0ErrorLog0, data->dma0ErrorLog1);
+       if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
+           data->dma1ErrorLog0   || data->dma1ErrorLog1)
+               pr_info("  InBErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma1ErrorStatus, data->dma1FirstErrorStatus,
+                       data->dma1ErrorLog0, data->dma1ErrorLog1);
 
        for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
                if ((data->pestA[i] >> 63) == 0 &&
                    (data->pestB[i] >> 63) == 0)
                        continue;
 
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+               pr_info("  PE[%3d] A/B: %016llx %016llx\n",
+                       i, data->pestA[i], data->pestB[i]);
        }
 }
 
@@ -197,62 +212,77 @@ static void pnv_pci_dump_phb3_diag_data(struct pci_controller *hose,
        data = (struct OpalIoPhb3ErrorData*)common;
        pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n",
                hose->global_number, common->version);
-
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-
-       pr_info("  nFir:                 %016llx\n", data->nFir);
-       pr_info("  nFirMask:             %016llx\n", data->nFirMask);
-       pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
-       pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
-       pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+       if (data->brdgCtl)
+               pr_info("  brdgCtl:     %08x\n",
+                       data->brdgCtl);
+       if (data->portStatusReg || data->rootCmplxStatus ||
+           data->busAgentStatus)
+               pr_info("  UtlSts:      %08x %08x %08x\n",
+                       data->portStatusReg, data->rootCmplxStatus,
+                       data->busAgentStatus);
+       if (data->deviceStatus || data->slotStatus   ||
+           data->linkStatus   || data->devCmdStatus ||
+           data->devSecStatus)
+               pr_info("  RootSts:     %08x %08x %08x %08x %08x\n",
+                       data->deviceStatus, data->slotStatus,
+                       data->linkStatus, data->devCmdStatus,
+                       data->devSecStatus);
+       if (data->rootErrorStatus || data->uncorrErrorStatus ||
+           data->corrErrorStatus)
+               pr_info("  RootErrSts:  %08x %08x %08x\n",
+                       data->rootErrorStatus, data->uncorrErrorStatus,
+                       data->corrErrorStatus);
+       if (data->tlpHdr1 || data->tlpHdr2 ||
+           data->tlpHdr3 || data->tlpHdr4)
+               pr_info("  RootErrLog:  %08x %08x %08x %08x\n",
+                       data->tlpHdr1, data->tlpHdr2,
+                       data->tlpHdr3, data->tlpHdr4);
+       if (data->sourceId || data->errorClass ||
+           data->correlator)
+               pr_info("  RootErrLog1: %08x %016llx %016llx\n",
+                       data->sourceId, data->errorClass,
+                       data->correlator);
+       if (data->nFir || data->nFirMask ||
+           data->nFirWOF)
+               pr_info("  nFir:        %016llx %016llx %016llx\n",
+                       data->nFir, data->nFirMask,
+                       data->nFirWOF);
+       if (data->phbPlssr || data->phbCsr)
+               pr_info("  PhbSts:      %016llx %016llx\n",
+                       data->phbPlssr, data->phbCsr);
+       if (data->lemFir || data->lemErrorMask ||
+           data->lemWOF)
+               pr_info("  Lem:         %016llx %016llx %016llx\n",
+                       data->lemFir, data->lemErrorMask,
+                       data->lemWOF);
+       if (data->phbErrorStatus || data->phbFirstErrorStatus ||
+           data->phbErrorLog0   || data->phbErrorLog1)
+               pr_info("  PhbErr:      %016llx %016llx %016llx %016llx\n",
+                       data->phbErrorStatus, data->phbFirstErrorStatus,
+                       data->phbErrorLog0, data->phbErrorLog1);
+       if (data->mmioErrorStatus || data->mmioFirstErrorStatus ||
+           data->mmioErrorLog0   || data->mmioErrorLog1)
+               pr_info("  OutErr:      %016llx %016llx %016llx %016llx\n",
+                       data->mmioErrorStatus, data->mmioFirstErrorStatus,
+                       data->mmioErrorLog0, data->mmioErrorLog1);
+       if (data->dma0ErrorStatus || data->dma0FirstErrorStatus ||
+           data->dma0ErrorLog0   || data->dma0ErrorLog1)
+               pr_info("  InAErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma0ErrorStatus, data->dma0FirstErrorStatus,
+                       data->dma0ErrorLog0, data->dma0ErrorLog1);
+       if (data->dma1ErrorStatus || data->dma1FirstErrorStatus ||
+           data->dma1ErrorLog0   || data->dma1ErrorLog1)
+               pr_info("  InBErr:      %016llx %016llx %016llx %016llx\n",
+                       data->dma1ErrorStatus, data->dma1FirstErrorStatus,
+                       data->dma1ErrorLog0, data->dma1ErrorLog1);
 
        for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
                if ((data->pestA[i] >> 63) == 0 &&
                    (data->pestB[i] >> 63) == 0)
                        continue;
 
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+               pr_info("  PE[%3d] A/B: %016llx %016llx\n",
+                       i, data->pestA[i], data->pestB[i]);
        }
 }
 
@@ -634,6 +664,16 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
                pnv_pci_dma_fallback_setup(hose, pdev);
 }
 
+int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
+{
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+
+       if (phb && phb->dma_set_mask)
+               return phb->dma_set_mask(phb, pdev, dma_mask);
+       return __dma_set_mask(&pdev->dev, dma_mask);
+}
+
 void pnv_pci_shutdown(void)
 {
        struct pci_controller *hose;
index 13f1942a9a5f98708038808a2d816f2bec0d6e1a..cde169442775c1684f0cd9f2db799d17c685deb3 100644 (file)
@@ -54,7 +54,9 @@ struct pnv_ioda_pe {
        struct iommu_table      tce32_table;
        phys_addr_t             tce_inval_reg_phys;
 
-       /* XXX TODO: Add support for additional 64-bit iommus */
+       /* 64-bit TCE bypass region */
+       bool                    tce_bypass_enabled;
+       uint64_t                tce_bypass_base;
 
        /* MSIs. MVE index is identical for for 32 and 64 bit MSI
         * and -1 if not supported. (It's actually identical to the
@@ -113,6 +115,8 @@ struct pnv_phb {
                         unsigned int hwirq, unsigned int virq,
                         unsigned int is_64, struct msi_msg *msg);
        void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
+       int (*dma_set_mask)(struct pnv_phb *phb, struct pci_dev *pdev,
+                           u64 dma_mask);
        void (*fixup_phb)(struct pci_controller *hose);
        u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
        void (*shutdown)(struct pnv_phb *phb);
index de6819be1f95ea11911bbadd5080fb05db66e884..0051e108ef0f86bd971e212db24c3110cfbf8993 100644 (file)
@@ -7,12 +7,20 @@ extern void pnv_smp_init(void);
 static inline void pnv_smp_init(void) { }
 #endif
 
+struct pci_dev;
+
 #ifdef CONFIG_PCI
 extern void pnv_pci_init(void);
 extern void pnv_pci_shutdown(void);
+extern int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask);
 #else
 static inline void pnv_pci_init(void) { }
 static inline void pnv_pci_shutdown(void) { }
+
+static inline int pnv_pci_dma_set_mask(struct pci_dev *pdev, u64 dma_mask)
+{
+       return -ENODEV;
+}
 #endif
 
 extern void pnv_lpc_init(void);
index 21166f65c97c37df19e48a938c33c49d5bad845e..81a7a0a79be75e0c8035baa992a6a674546c94eb 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/of_fdt.h>
 #include <linux/interrupt.h>
 #include <linux/bug.h>
-#include <linux/cpuidle.h>
+#include <linux/pci.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
@@ -141,6 +141,13 @@ static void pnv_progress(char *s, unsigned short hex)
 {
 }
 
+static int pnv_dma_set_mask(struct device *dev, u64 dma_mask)
+{
+       if (dev_is_pci(dev))
+               return pnv_pci_dma_set_mask(to_pci_dev(dev), dma_mask);
+       return __dma_set_mask(dev, dma_mask);
+}
+
 static void pnv_shutdown(void)
 {
        /* Let the PCI code clear up IODA tables */
@@ -217,16 +224,6 @@ static int __init pnv_probe(void)
        return 1;
 }
 
-void powernv_idle(void)
-{
-       /* Hook to cpuidle framework if available, else
-        * call on default platform idle code
-        */
-       if (cpuidle_idle_call()) {
-               power7_idle();
-       }
-}
-
 define_machine(powernv) {
        .name                   = "PowerNV",
        .probe                  = pnv_probe,
@@ -236,8 +233,9 @@ define_machine(powernv) {
        .show_cpuinfo           = pnv_show_cpuinfo,
        .progress               = pnv_progress,
        .machine_shutdown       = pnv_shutdown,
-       .power_save             = powernv_idle,
+       .power_save             = power7_idle,
        .calibrate_decr         = generic_calibrate_decr,
+       .dma_set_mask           = pnv_dma_set_mask,
 #ifdef CONFIG_KEXEC
        .kexec_cpu_down         = pnv_kexec_cpu_down,
 #endif
index 37300f6ee244edeb96f7ebbf86c2b476d3dfbb23..80b1d57c306a997e9b3c0a2933efa00ed1ac946e 100644 (file)
@@ -20,6 +20,7 @@ config PPC_PSERIES
        select PPC_DOORBELL
        select HAVE_CONTEXT_TRACKING
        select HOTPLUG_CPU if SMP
+       select ARCH_RANDOM
        default y
 
 config PPC_SPLPAR
index 9ef3cc8ebc11c7f533a3bc966d90bd6c085d891d..8a8f0472d98fd0e56d9c199c85c4d513e04f8d9a 100644 (file)
@@ -265,7 +265,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
                        enable = 1;
 
                if (enable) {
-                       eeh_subsystem_enabled = 1;
+                       eeh_set_enable(true);
                        eeh_add_to_parent_pe(edev);
 
                        pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
index 82789e79e53985cf2b6c856f313628ff1eb0ca3e..0ea99e3d4815733a74b8098864f3594839ed97eb 100644 (file)
 #include "offline_states.h"
 
 /* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
-       .token = RTAS_UNKNOWN_SERVICE,
-       .nargs = 0,
-       .nret = 1,
-       .rets = &rtas_stop_self_args.args[0],
-};
+static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
 
 static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) =
                                                        CPU_STATE_OFFLINE;
@@ -93,15 +88,20 @@ void set_default_offline_state(int cpu)
 
 static void rtas_stop_self(void)
 {
-       struct rtas_args *args = &rtas_stop_self_args;
+       struct rtas_args args = {
+               .token = cpu_to_be32(rtas_stop_self_token),
+               .nargs = 0,
+               .nret = 1,
+               .rets = &args.args[0],
+       };
 
        local_irq_disable();
 
-       BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+       BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
 
        printk("cpu %u (hwid %u) Ready to die...\n",
               smp_processor_id(), hard_smp_processor_id());
-       enter_rtas(__pa(args));
+       enter_rtas(__pa(&args));
 
        panic("Alas, I survived.\n");
 }
@@ -392,10 +392,10 @@ static int __init pseries_cpu_hotplug_init(void)
                }
        }
 
-       rtas_stop_self_args.token = rtas_token("stop-self");
+       rtas_stop_self_token = rtas_token("stop-self");
        qcss_tok = rtas_token("query-cpu-stopped-state");
 
-       if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+       if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE ||
                        qcss_tok == RTAS_UNKNOWN_SERVICE) {
                printk(KERN_INFO "CPU Hotplug not supported by firmware "
                                "- disabling.\n");
index 70670a2d9cf2ddd691a936dbe489d8e338ed4029..c413ec158ff5a6587e7c611659f817dc33d9c7e4 100644 (file)
@@ -113,7 +113,8 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
        struct device_node *dn, *pdn;
        struct pci_bus *bus;
-       const __be32 *pcie_link_speed_stats;
+       u32 pcie_link_speed_stats[2];
+       int rc;
 
        bus = bridge->bus;
 
@@ -122,38 +123,45 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
 
        for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) {
-               pcie_link_speed_stats = of_get_property(pdn,
-                       "ibm,pcie-link-speed-stats", NULL);
-               if (pcie_link_speed_stats)
+               rc = of_property_read_u32_array(pdn,
+                               "ibm,pcie-link-speed-stats",
+                               &pcie_link_speed_stats[0], 2);
+               if (!rc)
                        break;
        }
 
        of_node_put(pdn);
 
-       if (!pcie_link_speed_stats) {
+       if (rc) {
                pr_err("no ibm,pcie-link-speed-stats property\n");
                return 0;
        }
 
-       switch (be32_to_cpup(pcie_link_speed_stats)) {
+       switch (pcie_link_speed_stats[0]) {
        case 0x01:
                bus->max_bus_speed = PCIE_SPEED_2_5GT;
                break;
        case 0x02:
                bus->max_bus_speed = PCIE_SPEED_5_0GT;
                break;
+       case 0x04:
+               bus->max_bus_speed = PCIE_SPEED_8_0GT;
+               break;
        default:
                bus->max_bus_speed = PCI_SPEED_UNKNOWN;
                break;
        }
 
-       switch (be32_to_cpup(pcie_link_speed_stats)) {
+       switch (pcie_link_speed_stats[1]) {
        case 0x01:
                bus->cur_bus_speed = PCIE_SPEED_2_5GT;
                break;
        case 0x02:
                bus->cur_bus_speed = PCIE_SPEED_5_0GT;
                break;
+       case 0x04:
+               bus->cur_bus_speed = PCIE_SPEED_8_0GT;
+               break;
        default:
                bus->cur_bus_speed = PCI_SPEED_UNKNOWN;
                break;
index 8e639d7cbda72e057ab535083e29ef03f8d7f369..2db8cc691bf49dcd5b72b150c48bde8ec440f841 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
-#include <linux/cpuidle.h>
 #include <linux/of.h>
 #include <linux/kexec.h>
 
@@ -356,29 +355,24 @@ early_initcall(alloc_dispatch_log_kmem_cache);
 
 static void pseries_lpar_idle(void)
 {
-       /* This would call on the cpuidle framework, and the back-end pseries
-        * driver to  go to idle states
+       /*
+        * Default handler to go into low thread priority and possibly
+        * low power mode by cedeing processor to hypervisor
         */
-       if (cpuidle_idle_call()) {
-               /* On error, execute default handler
-                * to go into low thread priority and possibly
-                * low power mode by cedeing processor to hypervisor
-                */
 
-               /* Indicate to hypervisor that we are idle. */
-               get_lppaca()->idle = 1;
+       /* Indicate to hypervisor that we are idle. */
+       get_lppaca()->idle = 1;
 
-               /*
-                * Yield the processor to the hypervisor.  We return if
-                * an external interrupt occurs (which are driven prior
-                * to returning here) or if a prod occurs from another
-                * processor. When returning here, external interrupts
-                * are enabled.
-                */
-               cede_processor();
+       /*
+        * Yield the processor to the hypervisor.  We return if
+        * an external interrupt occurs (which are driven prior
+        * to returning here) or if a prod occurs from another
+        * processor. When returning here, external interrupts
+        * are enabled.
+        */
+       cede_processor();
 
-               get_lppaca()->idle = 0;
-       }
+       get_lppaca()->idle = 0;
 }
 
 /*
@@ -430,8 +424,7 @@ static void pSeries_machine_kexec(struct kimage *image)
 {
        long rc;
 
-       if (firmware_has_feature(FW_FEATURE_SET_MODE) &&
-           (image->type != KEXEC_TYPE_CRASH)) {
+       if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
                rc = pSeries_disable_reloc_on_exc();
                if (rc != H_SUCCESS)
                        pr_warning("Warning: Failed to disable relocation on "
index 0e166ed4cd16b7452f2656501de27c4f085e02da..8209744b28290b8a2466cf2a8600f0f34d920708 100644 (file)
@@ -886,25 +886,25 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 
        /* Default: read HW settings */
        if (flow_type == IRQ_TYPE_DEFAULT) {
-               switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
-                              MPIC_INFO(VECPRI_SENSE_MASK))) {
-                       case MPIC_INFO(VECPRI_SENSE_EDGE) |
-                            MPIC_INFO(VECPRI_POLARITY_POSITIVE):
-                               flow_type = IRQ_TYPE_EDGE_RISING;
-                               break;
-                       case MPIC_INFO(VECPRI_SENSE_EDGE) |
-                            MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
-                               flow_type = IRQ_TYPE_EDGE_FALLING;
-                               break;
-                       case MPIC_INFO(VECPRI_SENSE_LEVEL) |
-                            MPIC_INFO(VECPRI_POLARITY_POSITIVE):
-                               flow_type = IRQ_TYPE_LEVEL_HIGH;
-                               break;
-                       case MPIC_INFO(VECPRI_SENSE_LEVEL) |
-                            MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
-                               flow_type = IRQ_TYPE_LEVEL_LOW;
-                               break;
-               }
+               int vold_ps;
+
+               vold_ps = vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
+                                 MPIC_INFO(VECPRI_SENSE_MASK));
+
+               if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) |
+                               MPIC_INFO(VECPRI_POLARITY_POSITIVE)))
+                       flow_type = IRQ_TYPE_EDGE_RISING;
+               else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) |
+                                    MPIC_INFO(VECPRI_POLARITY_NEGATIVE)))
+                       flow_type = IRQ_TYPE_EDGE_FALLING;
+               else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) |
+                                    MPIC_INFO(VECPRI_POLARITY_POSITIVE)))
+                       flow_type = IRQ_TYPE_LEVEL_HIGH;
+               else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) |
+                                    MPIC_INFO(VECPRI_POLARITY_NEGATIVE)))
+                       flow_type = IRQ_TYPE_LEVEL_LOW;
+               else
+                       WARN_ONCE(1, "mpic: unknown IRQ type %d\n", vold);
        }
 
        /* Apply to irq desc */
index a90731b3d44a3ea41052690975aefcd8b3ce2db7..b07909850f77151b393f73a30bac727a79ea9921 100644 (file)
@@ -309,16 +309,23 @@ static void get_output_lock(void)
 
        if (xmon_speaker == me)
                return;
+
        for (;;) {
-               if (xmon_speaker == 0) {
-                       last_speaker = cmpxchg(&xmon_speaker, 0, me);
-                       if (last_speaker == 0)
-                               return;
-               }
-               timeout = 10000000;
+               last_speaker = cmpxchg(&xmon_speaker, 0, me);
+               if (last_speaker == 0)
+                       return;
+
+               /*
+                * Wait a full second for the lock, we might be on a slow
+                * console, but check every 100us.
+                */
+               timeout = 10000;
                while (xmon_speaker == last_speaker) {
-                       if (--timeout > 0)
+                       if (--timeout > 0) {
+                               udelay(100);
                                continue;
+                       }
+
                        /* hostile takeover */
                        prev = cmpxchg(&xmon_speaker, last_speaker, me);
                        if (prev == last_speaker)
@@ -397,7 +404,6 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
        }
 
        xmon_fault_jmp[cpu] = recurse_jmp;
-       cpumask_set_cpu(cpu, &cpus_in_xmon);
 
        bp = NULL;
        if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
@@ -419,6 +425,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
                release_output_lock();
        }
 
+       cpumask_set_cpu(cpu, &cpus_in_xmon);
+
  waiting:
        secondary = 1;
        while (secondary && !xmon_gate) {
index 65a07750f4f946f038bb2e2a4e13f9f6d05dce83..953f17c8d17cde75f73ef78ebc59aa0235e9fde0 100644 (file)
@@ -117,6 +117,7 @@ config S390
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZ4
@@ -140,6 +141,7 @@ config S390
        select OLD_SIGACTION
        select OLD_SIGSUSPEND3
        select SYSCTL_EXCEPTION_TRACE
+       select TTY
        select VIRT_CPU_ACCOUNTING
        select VIRT_TO_BUS
 
@@ -415,6 +417,10 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
 config ARCH_ENABLE_MEMORY_HOTREMOVE
        def_bool y
 
+config ARCH_ENABLE_SPLIT_PMD_PTLOCK
+       def_bool y
+       depends on 64BIT
+
 config FORCE_MAX_ZONEORDER
        int
        default "9"
index 4c4a1cef52087bf359c28d9077e315196f7630eb..47c8630c93cdd6c6a3f55d78798c32f7defa9f03 100644 (file)
@@ -529,6 +529,7 @@ static int __init appldata_init(void)
 {
        int rc;
 
+       init_virt_timer(&appldata_timer);
        appldata_timer.function = appldata_timer_function;
        appldata_timer.data = (unsigned long) &appldata_work;
 
index de8e2b3b0180e0650dd5a100f9e57a9b89e99359..69b23b25ac34a4f3f6c6faeb305648ef5a7e5b63 100644 (file)
@@ -171,7 +171,7 @@ static int __init appldata_os_init(void)
        int rc, max_size;
 
        max_size = sizeof(struct appldata_os_data) +
-                  (NR_CPUS * sizeof(struct appldata_os_per_cpu));
+                  (num_possible_cpus() * sizeof(struct appldata_os_per_cpu));
        if (max_size > APPLDATA_MAX_REC_SIZE) {
                pr_err("Maximum OS record size %i exceeds the maximum "
                       "record size %i\n", max_size, APPLDATA_MAX_REC_SIZE);
index e0af2ee587511d023abf72a35b3353668da921ca..ddaae2f5c9137d0155ef5d5e943b40d097471881 100644 (file)
@@ -46,6 +46,7 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_MARCH_Z9_109=y
+CONFIG_NR_CPUS=256
 CONFIG_PREEMPT=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
@@ -58,7 +59,6 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_CHSC_SCH=y
 CONFIG_CRASH_DUMP=y
-CONFIG_ZFCPDUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
@@ -101,7 +101,6 @@ CONFIG_TCP_CONG_VENO=m
 CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
@@ -111,6 +110,7 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
@@ -135,7 +135,17 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
 CONFIG_NF_CT_NETLINK_TIMEOUT=m
-CONFIG_NETFILTER_TPROXY=m
+CONFIG_NF_TABLES=m
+CONFIG_NFT_EXTHDR=m
+CONFIG_NFT_META=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_RBTREE=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -204,7 +214,9 @@ CONFIG_IP_SET_HASH_IP=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
 CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
 CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
@@ -227,6 +239,11 @@ CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
 # CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_NF_TABLES_IPV4=m
+CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_CHAIN_NAT_IPV4=m
+CONFIG_NF_TABLES_ARP=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -249,6 +266,9 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_NF_TABLES_IPV6=m
+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -268,6 +288,7 @@ CONFIG_IP6_NF_SECURITY=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_NET_SCTPPROBE=m
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
@@ -314,6 +335,7 @@ CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_FLOW=m
 CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_BPF=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
 CONFIG_NET_ACT_GACT=m
@@ -381,8 +403,8 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
-CONFIG_DM_RAID=m
 CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_QL=m
@@ -434,7 +456,6 @@ CONFIG_TN3270_FS=y
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
-CONFIG_ZVM_WATCHDOG=m
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_INFINIBAND=m
@@ -534,13 +555,23 @@ CONFIG_UNUSED_SYMBOLS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_SELFTEST=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
 CONFIG_SLUB_DEBUG_ON=y
 CONFIG_SLUB_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_VM_RB=y
 CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_DEBUG_PER_CPU_MAPS=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_RT_MUTEX_TESTER=y
@@ -573,9 +604,11 @@ CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
 CONFIG_BLK_DEV_IO_TRACE=y
 # CONFIG_KPROBE_EVENT is not set
 CONFIG_LKDTM=m
+CONFIG_TEST_LIST_SORT=y
 CONFIG_KPROBES_SANITY_TEST=y
-CONFIG_RBTREE_TEST=m
+CONFIG_RBTREE_TEST=y
 CONFIG_INTERVAL_TREE_TEST=m
+CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_DMA_API_DEBUG=y
 # CONFIG_STRICT_DEVMEM is not set
@@ -638,7 +671,6 @@ CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_ASYMMETRIC_KEY_TYPE=m
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_PUBLIC_KEY_ALGO_RSA=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
index b9f6b4cab927e79618600f806351441083e89428..c81a74e3e25a698340a3fae730ec3a5c27324508 100644 (file)
@@ -46,6 +46,7 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_MARCH_Z9_109=y
+CONFIG_NR_CPUS=256
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -56,7 +57,6 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_CHSC_SCH=y
 CONFIG_CRASH_DUMP=y
-CONFIG_ZFCPDUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
@@ -99,7 +99,6 @@ CONFIG_TCP_CONG_VENO=m
 CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
@@ -109,6 +108,7 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
@@ -133,7 +133,17 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
 CONFIG_NF_CT_NETLINK_TIMEOUT=m
-CONFIG_NETFILTER_TPROXY=m
+CONFIG_NF_TABLES=m
+CONFIG_NFT_EXTHDR=m
+CONFIG_NFT_META=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_RBTREE=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -202,7 +212,9 @@ CONFIG_IP_SET_HASH_IP=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
 CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
 CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
@@ -225,6 +237,11 @@ CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
 # CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_NF_TABLES_IPV4=m
+CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_CHAIN_NAT_IPV4=m
+CONFIG_NF_TABLES_ARP=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -247,6 +264,9 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_NF_TABLES_IPV6=m
+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -266,6 +286,7 @@ CONFIG_IP6_NF_SECURITY=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_NET_SCTPPROBE=m
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
@@ -311,6 +332,7 @@ CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_FLOW=m
 CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_BPF=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
 CONFIG_NET_ACT_GACT=m
@@ -378,8 +400,8 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
-CONFIG_DM_RAID=m
 CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_QL=m
@@ -431,7 +453,6 @@ CONFIG_TN3270_FS=y
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
-CONFIG_ZVM_WATCHDOG=m
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_INFINIBAND=m
@@ -540,6 +561,7 @@ CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_LKDTM=m
 CONFIG_RBTREE_TEST=m
 CONFIG_INTERVAL_TREE_TEST=m
+CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 # CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
@@ -601,7 +623,6 @@ CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_ASYMMETRIC_KEY_TYPE=m
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_PUBLIC_KEY_ALGO_RSA=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
index 91087b43e8fa3d1016f5cd27fb5e10caa03483e2..b5ba8fe1cc6487c7cb67a6948b3d23895888950d 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_MARCH_Z9_109=y
+CONFIG_NR_CPUS=256
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -54,7 +55,6 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_CHSC_SCH=y
 CONFIG_CRASH_DUMP=y
-CONFIG_ZFCPDUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
@@ -97,7 +97,6 @@ CONFIG_TCP_CONG_VENO=m
 CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
@@ -107,6 +106,7 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=m
 CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_INET6_XFRM_MODE_BEET=m
 CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_GRE=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
@@ -131,7 +131,17 @@ CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
 CONFIG_NF_CT_NETLINK_TIMEOUT=m
-CONFIG_NETFILTER_TPROXY=m
+CONFIG_NF_TABLES=m
+CONFIG_NFT_EXTHDR=m
+CONFIG_NFT_META=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_RBTREE=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_COMPAT=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -200,7 +210,9 @@ CONFIG_IP_SET_HASH_IP=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
 CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
 CONFIG_IP_SET_HASH_NETPORT=m
 CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
@@ -223,6 +235,11 @@ CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
 # CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_NF_TABLES_IPV4=m
+CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_CHAIN_NAT_IPV4=m
+CONFIG_NF_TABLES_ARP=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -245,6 +262,9 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_NF_TABLES_IPV6=m
+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -264,6 +284,7 @@ CONFIG_IP6_NF_SECURITY=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_NET_SCTPPROBE=m
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
@@ -309,6 +330,7 @@ CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_FLOW=m
 CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_BPF=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
 CONFIG_NET_ACT_GACT=m
@@ -376,8 +398,8 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
-CONFIG_DM_RAID=m
 CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
 CONFIG_DM_MULTIPATH_QL=m
@@ -429,7 +451,6 @@ CONFIG_TN3270_FS=y
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
-CONFIG_ZVM_WATCHDOG=m
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_INFINIBAND=m
@@ -532,6 +553,7 @@ CONFIG_LATENCYTOP=y
 CONFIG_BLK_DEV_IO_TRACE=y
 # CONFIG_KPROBE_EVENT is not set
 CONFIG_LKDTM=m
+CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 # CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
@@ -593,7 +615,6 @@ CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_ASYMMETRIC_KEY_TYPE=m
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_PUBLIC_KEY_ALGO_RSA=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
index d725c4d956e4551aecfdba78d0c02e857e7ad7b4..cef073ca1f07f2aca39ece9e52f4ce16468ee0b4 100644 (file)
@@ -19,7 +19,6 @@ CONFIG_HZ_100=y
 # CONFIG_CHSC_SCH is not set
 # CONFIG_SCM_BUS is not set
 CONFIG_CRASH_DUMP=y
-CONFIG_ZFCPDUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_IUCV is not set
index b3feabd39f31f8eead0a69f4340a8abc0ea17da6..cf3c0089bef253d7817a604f9a7f195a4ffd9bc0 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
 #include "crypt_s390.h"
 
 #define AES_KEYLEN_128         1
@@ -32,6 +33,7 @@
 #define AES_KEYLEN_256         4
 
 static u8 *ctrblk;
+static DEFINE_SPINLOCK(ctrblk_lock);
 static char keylen_flag;
 
 struct s390_aes_ctx {
@@ -758,43 +760,67 @@ static int ctr_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        return aes_set_key(tfm, in_key, key_len);
 }
 
+static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
+{
+       unsigned int i, n;
+
+       /* only use complete blocks, max. PAGE_SIZE */
+       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(AES_BLOCK_SIZE - 1);
+       for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
+               memcpy(ctrptr + i, ctrptr + i - AES_BLOCK_SIZE,
+                      AES_BLOCK_SIZE);
+               crypto_inc(ctrptr + i, AES_BLOCK_SIZE);
+       }
+       return n;
+}
+
 static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                         struct s390_aes_ctx *sctx, struct blkcipher_walk *walk)
 {
        int ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
-       unsigned int i, n, nbytes;
-       u8 buf[AES_BLOCK_SIZE];
-       u8 *out, *in;
+       unsigned int n, nbytes;
+       u8 buf[AES_BLOCK_SIZE], ctrbuf[AES_BLOCK_SIZE];
+       u8 *out, *in, *ctrptr = ctrbuf;
 
        if (!walk->nbytes)
                return ret;
 
-       memcpy(ctrblk, walk->iv, AES_BLOCK_SIZE);
+       if (spin_trylock(&ctrblk_lock))
+               ctrptr = ctrblk;
+
+       memcpy(ctrptr, walk->iv, AES_BLOCK_SIZE);
        while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                while (nbytes >= AES_BLOCK_SIZE) {
-                       /* only use complete blocks, max. PAGE_SIZE */
-                       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
-                                                nbytes & ~(AES_BLOCK_SIZE - 1);
-                       for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
-                               memcpy(ctrblk + i, ctrblk + i - AES_BLOCK_SIZE,
-                                      AES_BLOCK_SIZE);
-                               crypto_inc(ctrblk + i, AES_BLOCK_SIZE);
-                       }
-                       ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk);
-                       if (ret < 0 || ret != n)
+                       if (ctrptr == ctrblk)
+                               n = __ctrblk_init(ctrptr, nbytes);
+                       else
+                               n = AES_BLOCK_SIZE;
+                       ret = crypt_s390_kmctr(func, sctx->key, out, in,
+                                              n, ctrptr);
+                       if (ret < 0 || ret != n) {
+                               if (ctrptr == ctrblk)
+                                       spin_unlock(&ctrblk_lock);
                                return -EIO;
+                       }
                        if (n > AES_BLOCK_SIZE)
-                               memcpy(ctrblk, ctrblk + n - AES_BLOCK_SIZE,
+                               memcpy(ctrptr, ctrptr + n - AES_BLOCK_SIZE,
                                       AES_BLOCK_SIZE);
-                       crypto_inc(ctrblk, AES_BLOCK_SIZE);
+                       crypto_inc(ctrptr, AES_BLOCK_SIZE);
                        out += n;
                        in += n;
                        nbytes -= n;
                }
                ret = blkcipher_walk_done(desc, walk, nbytes);
        }
+       if (ctrptr == ctrblk) {
+               if (nbytes)
+                       memcpy(ctrbuf, ctrptr, AES_BLOCK_SIZE);
+               else
+                       memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
+               spin_unlock(&ctrblk_lock);
+       }
        /*
         * final block may be < AES_BLOCK_SIZE, copy only nbytes
         */
@@ -802,14 +828,15 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                ret = crypt_s390_kmctr(func, sctx->key, buf, in,
-                                      AES_BLOCK_SIZE, ctrblk);
+                                      AES_BLOCK_SIZE, ctrbuf);
                if (ret < 0 || ret != AES_BLOCK_SIZE)
                        return -EIO;
                memcpy(out, buf, nbytes);
-               crypto_inc(ctrblk, AES_BLOCK_SIZE);
+               crypto_inc(ctrbuf, AES_BLOCK_SIZE);
                ret = blkcipher_walk_done(desc, walk, 0);
+               memcpy(walk->iv, ctrbuf, AES_BLOCK_SIZE);
        }
-       memcpy(walk->iv, ctrblk, AES_BLOCK_SIZE);
+
        return ret;
 }
 
index 200f2a1b599d16badb97d4b292729512602ab59d..0a5aac8a9412b64c4b2c43f9999e0f1e2f3815cb 100644 (file)
@@ -25,6 +25,7 @@
 #define DES3_KEY_SIZE  (3 * DES_KEY_SIZE)
 
 static u8 *ctrblk;
+static DEFINE_SPINLOCK(ctrblk_lock);
 
 struct s390_des_ctx {
        u8 iv[DES_BLOCK_SIZE];
@@ -105,29 +106,35 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
 }
 
 static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
-                           u8 *iv, struct blkcipher_walk *walk)
+                           struct blkcipher_walk *walk)
 {
+       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        int ret = blkcipher_walk_virt(desc, walk);
        unsigned int nbytes = walk->nbytes;
+       struct {
+               u8 iv[DES_BLOCK_SIZE];
+               u8 key[DES3_KEY_SIZE];
+       } param;
 
        if (!nbytes)
                goto out;
 
-       memcpy(iv, walk->iv, DES_BLOCK_SIZE);
+       memcpy(param.iv, walk->iv, DES_BLOCK_SIZE);
+       memcpy(param.key, ctx->key, DES3_KEY_SIZE);
        do {
                /* only use complete blocks */
                unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
                u8 *out = walk->dst.virt.addr;
                u8 *in = walk->src.virt.addr;
 
-               ret = crypt_s390_kmc(func, iv, out, in, n);
+               ret = crypt_s390_kmc(func, &param, out, in, n);
                if (ret < 0 || ret != n)
                        return -EIO;
 
                nbytes &= DES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
        } while ((nbytes = walk->nbytes));
-       memcpy(walk->iv, iv, DES_BLOCK_SIZE);
+       memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
 
 out:
        return ret;
@@ -179,22 +186,20 @@ static int cbc_des_encrypt(struct blkcipher_desc *desc,
                           struct scatterlist *dst, struct scatterlist *src,
                           unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk);
 }
 
 static int cbc_des_decrypt(struct blkcipher_desc *desc,
                           struct scatterlist *dst, struct scatterlist *src,
                           unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk);
 }
 
 static struct crypto_alg cbc_des_alg = {
@@ -327,22 +332,20 @@ static int cbc_des3_encrypt(struct blkcipher_desc *desc,
                            struct scatterlist *dst, struct scatterlist *src,
                            unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk);
 }
 
 static int cbc_des3_decrypt(struct blkcipher_desc *desc,
                            struct scatterlist *dst, struct scatterlist *src,
                            unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk);
 }
 
 static struct crypto_alg cbc_des3_alg = {
@@ -366,54 +369,80 @@ static struct crypto_alg cbc_des3_alg = {
        }
 };
 
+static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
+{
+       unsigned int i, n;
+
+       /* align to block size, max. PAGE_SIZE */
+       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
+       for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
+               memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+               crypto_inc(ctrptr + i, DES_BLOCK_SIZE);
+       }
+       return n;
+}
+
 static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
-                           struct s390_des_ctx *ctx, struct blkcipher_walk *walk)
+                           struct s390_des_ctx *ctx,
+                           struct blkcipher_walk *walk)
 {
        int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
-       unsigned int i, n, nbytes;
-       u8 buf[DES_BLOCK_SIZE];
-       u8 *out, *in;
+       unsigned int n, nbytes;
+       u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE];
+       u8 *out, *in, *ctrptr = ctrbuf;
+
+       if (!walk->nbytes)
+               return ret;
 
-       memcpy(ctrblk, walk->iv, DES_BLOCK_SIZE);
+       if (spin_trylock(&ctrblk_lock))
+               ctrptr = ctrblk;
+
+       memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
        while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                while (nbytes >= DES_BLOCK_SIZE) {
-                       /* align to block size, max. PAGE_SIZE */
-                       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
-                               nbytes & ~(DES_BLOCK_SIZE - 1);
-                       for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
-                               memcpy(ctrblk + i, ctrblk + i - DES_BLOCK_SIZE,
-                                      DES_BLOCK_SIZE);
-                               crypto_inc(ctrblk + i, DES_BLOCK_SIZE);
-                       }
-                       ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk);
-                       if (ret < 0 || ret != n)
+                       if (ctrptr == ctrblk)
+                               n = __ctrblk_init(ctrptr, nbytes);
+                       else
+                               n = DES_BLOCK_SIZE;
+                       ret = crypt_s390_kmctr(func, ctx->key, out, in,
+                                              n, ctrptr);
+                       if (ret < 0 || ret != n) {
+                               if (ctrptr == ctrblk)
+                                       spin_unlock(&ctrblk_lock);
                                return -EIO;
+                       }
                        if (n > DES_BLOCK_SIZE)
-                               memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE,
+                               memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE,
                                       DES_BLOCK_SIZE);
-                       crypto_inc(ctrblk, DES_BLOCK_SIZE);
+                       crypto_inc(ctrptr, DES_BLOCK_SIZE);
                        out += n;
                        in += n;
                        nbytes -= n;
                }
                ret = blkcipher_walk_done(desc, walk, nbytes);
        }
-
+       if (ctrptr == ctrblk) {
+               if (nbytes)
+                       memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
+               else
+                       memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
+               spin_unlock(&ctrblk_lock);
+       }
        /* final block may be < DES_BLOCK_SIZE, copy only nbytes */
        if (nbytes) {
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                ret = crypt_s390_kmctr(func, ctx->key, buf, in,
-                                      DES_BLOCK_SIZE, ctrblk);
+                                      DES_BLOCK_SIZE, ctrbuf);
                if (ret < 0 || ret != DES_BLOCK_SIZE)
                        return -EIO;
                memcpy(out, buf, nbytes);
-               crypto_inc(ctrblk, DES_BLOCK_SIZE);
+               crypto_inc(ctrbuf, DES_BLOCK_SIZE);
                ret = blkcipher_walk_done(desc, walk, 0);
+               memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE);
        }
-       memcpy(walk->iv, ctrblk, DES_BLOCK_SIZE);
        return ret;
 }
 
index 33f57514f4245a3835438801c99e11c749ac33a3..4557cb7ffddf80bda691e9254a831f275220473c 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_MARCH_Z196=y
+CONFIG_NR_CPUS=256
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -122,22 +123,31 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_WRITECOUNT=y
 CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_PROVE_RCU=y
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_RCU_TRACE=y
 CONFIG_LATENCYTOP=y
+CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_KPROBES_SANITY_TEST=y
 # CONFIG_STRICT_DEVMEM is not set
+CONFIG_S390_PTDUMP=y
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_AUTHENC=m
 CONFIG_CRYPTO_TEST=m
index 24908ce149f15c89f1fbf5f4c8cc0b09b8a9ec13..32040ace00ea2431a18428dca5c34c0c4ebde10c 100644 (file)
@@ -32,7 +32,7 @@ struct diag2fc_data {
        __u32 pcpus;
        __u32 lcpus;
        __u32 vcpus;
-       __u32 cpu_min;
+       __u32 ocpus;
        __u32 cpu_max;
        __u32 cpu_shares;
        __u32 cpu_use_samp;
@@ -142,7 +142,12 @@ static int hpyfs_vm_create_guest(struct dentry *systems_dir,
        ATTRIBUTE(cpus_dir, "capped", capped_value);
        ATTRIBUTE(cpus_dir, "dedicated", dedicated_flag);
        ATTRIBUTE(cpus_dir, "count", data->vcpus);
-       ATTRIBUTE(cpus_dir, "weight_min", data->cpu_min);
+       /*
+        * Note: The "weight_min" attribute got the wrong name.
+        * The value represents the number of non-stopped (operating)
+        * CPUS.
+        */
+       ATTRIBUTE(cpus_dir, "weight_min", data->ocpus);
        ATTRIBUTE(cpus_dir, "weight_max", data->cpu_max);
        ATTRIBUTE(cpus_dir, "weight_cur", data->cpu_shares);
 
index 8386a4a1f19a35ba4cf1e93259b3bca911928408..57892a8a905584d79fd112a7c2e67a319a3f9e45 100644 (file)
@@ -1,6 +1,7 @@
 
 
 generic-y += clkdev.h
-generic-y += trace_clock.h
-generic-y += preempt.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
+generic-y += trace_clock.h
index 4bbb5957ed1b6db504cec7328100af49d70607e3..bd93ff6661b809643e4dcd3e94747c4464a763a2 100644 (file)
@@ -44,11 +44,21 @@ struct airq_iv {
 
 struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags);
 void airq_iv_release(struct airq_iv *iv);
-unsigned long airq_iv_alloc_bit(struct airq_iv *iv);
-void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit);
+unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num);
+void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num);
 unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
                           unsigned long end);
 
+static inline unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
+{
+       return airq_iv_alloc(iv, 1);
+}
+
+static inline void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
+{
+       airq_iv_free(iv, bit, 1);
+}
+
 static inline unsigned long airq_iv_end(struct airq_iv *iv)
 {
        return iv->end;
index 6e6ad06808293b7e88949351f647e516af8f16b2..ec5ef891db6bb8f159bc25a8c98679ea27fb4cb8 100644 (file)
@@ -13,9 +13,9 @@
  *
  * The bitop functions are defined to work on unsigned longs, so for an
  * s390x system the bits end up numbered:
- *   |63..............0|127............64|191...........128|255...........196|
+ *   |63..............0|127............64|191...........128|255...........192|
  * and on s390:
- *   |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
+ *   |31.....0|63....32|95....64|127...96|159..128|191..160|223..192|255..224|
  *
  * There are a few little-endian macros used mostly for filesystem
  * bitmaps, these work on similar bit arrays layouts, but
@@ -30,7 +30,7 @@
  * on an s390x system the bits are numbered:
  *   |0..............63|64............127|128...........191|192...........255|
  * and on s390:
- *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|
  *
  * The main difference is that bit 0-63 (64b) or 0-31 (32b) in the bit
  * number field needs to be reversed compared to the LSB0 encoded bit
@@ -304,7 +304,7 @@ static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
  * On an s390x system the bits are numbered:
  *   |0..............63|64............127|128...........191|192...........255|
  * and on s390:
- *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|
  */
 unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size);
 unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
index f201af8be580ddc876de2f5de96952aaaf493cb5..a9c2c06861772f63b52988cc98afa80058fc0f22 100644 (file)
@@ -219,7 +219,9 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);
 #define to_ccwdev(n) container_of(n, struct ccw_device, dev)
 #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
 
-extern struct ccw_device *ccw_device_probe_console(void);
+extern struct ccw_device *ccw_device_create_console(struct ccw_driver *);
+extern void ccw_device_destroy_console(struct ccw_device *);
+extern int ccw_device_enable_console(struct ccw_device *);
 extern void ccw_device_wait_idle(struct ccw_device *);
 extern int ccw_device_force_console(struct ccw_device *);
 
index 4f57a4f3909a1682822a61976cbc4e01f417dda5..7403648563554604e19b6cfbd0873bee868c7644 100644 (file)
@@ -44,22 +44,15 @@ csum_partial(const void *buff, int len, __wsum sum)
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  *
- * Copy from userspace and compute checksum.  If we catch an exception
- * then zero the rest of the buffer.
+ * Copy from userspace and compute checksum.
  */
 static inline __wsum
 csum_partial_copy_from_user(const void __user *src, void *dst,
                                           int len, __wsum sum,
                                           int *err_ptr)
 {
-       int missing;
-
-       missing = copy_from_user(dst, src, len);
-       if (missing) {
-               memset(dst + len - missing, 0, missing);
+       if (unlikely(copy_from_user(dst, src, len)))
                *err_ptr = -EFAULT;
-       }
-               
        return csum_partial(dst, len, sum);
 }
 
index 5d7e8cf83bd6c7d53b5f2a34fc2120add4cfa2d8..d350ed9d0fbb2e2955cade45aea5d7632716bfb9 100644 (file)
@@ -8,7 +8,11 @@
 #include <linux/thread_info.h>
 
 #define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p(typeof(0?(t)0:0ULL), u64))
-#define __SC_DELOUSE(t,v) (t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v))
+
+#define __SC_DELOUSE(t,v) ({ \
+       BUILD_BUG_ON(sizeof(t) > 4 && !__TYPE_IS_PTR(t)); \
+       (t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v)); \
+})
 
 #define PSW32_MASK_PER         0x40000000UL
 #define PSW32_MASK_DAT         0x04000000UL
index 51bcaa0fdeefaa33b289a521b6cd95be411ada27..fda46bd38c99a7b529ce71925e862efdc3c88a5d 100644 (file)
@@ -5,7 +5,10 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newval);
+int __futex_atomic_op_inuser(int op, u32 __user *uaddr, int oparg, int *old);
+
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
        int op = (encoded_op >> 28) & 7;
        int cmp = (encoded_op >> 24) & 15;
@@ -17,7 +20,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
                oparg = 1 << oparg;
 
        pagefault_disable();
-       ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval);
+       ret = __futex_atomic_op_inuser(op, uaddr, oparg, &oldval);
        pagefault_enable();
 
        if (!ret) {
@@ -34,10 +37,4 @@ static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
        return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
-                                               u32 oldval, u32 newval)
-{
-       return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
-}
-
 #endif /* _ASM_S390_FUTEX_H */
index eef3dd3fd9a9f76d105b2c92d266dc5079c7833f..9bf95bb30f1a6cf27d0494396168f87e23cf8a65 100644 (file)
@@ -106,7 +106,9 @@ struct kvm_s390_sie_block {
        __u64   gbea;                   /* 0x0180 */
        __u8    reserved188[24];        /* 0x0188 */
        __u32   fac;                    /* 0x01a0 */
-       __u8    reserved1a4[68];        /* 0x01a4 */
+       __u8    reserved1a4[20];        /* 0x01a4 */
+       __u64   cbrlo;                  /* 0x01b8 */
+       __u8    reserved1c0[40];        /* 0x01c0 */
        __u64   itdba;                  /* 0x01e8 */
        __u8    reserved1f0[16];        /* 0x01f0 */
 } __attribute__((packed));
@@ -155,6 +157,7 @@ struct kvm_vcpu_stat {
        u32 instruction_stsi;
        u32 instruction_stfl;
        u32 instruction_tprot;
+       u32 instruction_essa;
        u32 instruction_sigp_sense;
        u32 instruction_sigp_sense_running;
        u32 instruction_sigp_external_call;
index 5d1f950704dc6272ec368279b2a01f82274fe220..38149b63dc44a360ab3b0db2dfca4f23e64cc63a 100644 (file)
@@ -48,13 +48,42 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                             struct task_struct *tsk)
 {
-       cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
-       update_mm(next, tsk);
+       int cpu = smp_processor_id();
+
+       if (prev == next)
+               return;
+       if (atomic_inc_return(&next->context.attach_count) >> 16) {
+               /* Delay update_mm until all TLB flushes are done. */
+               set_tsk_thread_flag(tsk, TIF_TLB_WAIT);
+       } else {
+               cpumask_set_cpu(cpu, mm_cpumask(next));
+               update_mm(next, tsk);
+               if (next->context.flush_mm)
+                       /* Flush pending TLBs */
+                       __tlb_flush_mm(next);
+       }
        atomic_dec(&prev->context.attach_count);
        WARN_ON(atomic_read(&prev->context.attach_count) < 0);
-       atomic_inc(&next->context.attach_count);
-       /* Check for TLBs not flushed yet */
-       __tlb_flush_mm_lazy(next);
+}
+
+#define finish_arch_post_lock_switch finish_arch_post_lock_switch
+static inline void finish_arch_post_lock_switch(void)
+{
+       struct task_struct *tsk = current;
+       struct mm_struct *mm = tsk->mm;
+
+       if (!test_tsk_thread_flag(tsk, TIF_TLB_WAIT))
+               return;
+       preempt_disable();
+       clear_tsk_thread_flag(tsk, TIF_TLB_WAIT);
+       while (atomic_read(&mm->context.attach_count) >> 16)
+               cpu_relax();
+
+       cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
+       update_mm(mm, tsk);
+       if (mm->context.flush_mm)
+               __tlb_flush_mm(mm);
+       preempt_enable();
 }
 
 #define enter_lazy_tlb(mm,tsk) do { } while (0)
index e1408ddb94f8d6d5107561374bb759a37c5d8eb1..884017cbfa9fade412372f7f781e503b3f39513b 100644 (file)
@@ -22,6 +22,7 @@ unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
 void page_table_free(struct mm_struct *, unsigned long *);
 void page_table_free_rcu(struct mmu_gather *, unsigned long *);
 
+void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long);
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
                          unsigned long key, bool nq);
 
@@ -91,11 +92,22 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
        unsigned long *table = crst_table_alloc(mm);
-       if (table)
-               crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
+
+       if (!table)
+               return NULL;
+       crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
+       if (!pgtable_pmd_page_ctor(virt_to_page(table))) {
+               crst_table_free(mm, table);
+               return NULL;
+       }
        return (pmd_t *) table;
 }
-#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+       pgtable_pmd_page_dtor(virt_to_page(pmd));
+       crst_table_free(mm, (unsigned long *) pmd);
+}
 
 static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 {
index 2204400d0bd58d4a1e45c82394ff5cbd100aa2cc..1ab75eaacbd417079d3e6de25e8401c87e24a1d7 100644 (file)
@@ -229,6 +229,7 @@ extern unsigned long MODULES_END;
 #define _PAGE_READ     0x010           /* SW pte read bit */
 #define _PAGE_WRITE    0x020           /* SW pte write bit */
 #define _PAGE_SPECIAL  0x040           /* SW associated with special page */
+#define _PAGE_UNUSED   0x080           /* SW bit for pgste usage state */
 #define __HAVE_ARCH_PTE_SPECIAL
 
 /* Set of bits not changed in pte_modify */
@@ -394,6 +395,12 @@ extern unsigned long MODULES_END;
 
 #endif /* CONFIG_64BIT */
 
+/* Guest Page State used for virtualization */
+#define _PGSTE_GPS_ZERO                0x0000000080000000UL
+#define _PGSTE_GPS_USAGE_MASK  0x0000000003000000UL
+#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL
+#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL
+
 /*
  * A user page table pointer has the space-switch-event bit, the
  * private-space-control bit and the storage-alteration-event-control
@@ -617,6 +624,14 @@ static inline int pte_none(pte_t pte)
        return pte_val(pte) == _PAGE_INVALID;
 }
 
+static inline int pte_swap(pte_t pte)
+{
+       /* Bit pattern: (pte & 0x603) == 0x402 */
+       return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT |
+                               _PAGE_TYPE | _PAGE_PRESENT))
+               == (_PAGE_INVALID | _PAGE_TYPE);
+}
+
 static inline int pte_file(pte_t pte)
 {
        /* Bit pattern: (pte & 0x601) == 0x600 */
@@ -821,20 +836,20 @@ unsigned long gmap_translate(unsigned long address, struct gmap *);
 unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
+void __gmap_zap(unsigned long address, struct gmap *);
 
 void gmap_register_ipte_notifier(struct gmap_notifier *);
 void gmap_unregister_ipte_notifier(struct gmap_notifier *);
 int gmap_ipte_notify(struct gmap *, unsigned long start, unsigned long len);
-void gmap_do_ipte_notify(struct mm_struct *, unsigned long addr, pte_t *);
+void gmap_do_ipte_notify(struct mm_struct *, pte_t *);
 
 static inline pgste_t pgste_ipte_notify(struct mm_struct *mm,
-                                       unsigned long addr,
                                        pte_t *ptep, pgste_t pgste)
 {
 #ifdef CONFIG_PGSTE
        if (pgste_val(pgste) & PGSTE_IN_BIT) {
                pgste_val(pgste) &= ~PGSTE_IN_BIT;
-               gmap_do_ipte_notify(mm, addr, ptep);
+               gmap_do_ipte_notify(mm, ptep);
        }
 #endif
        return pgste;
@@ -852,6 +867,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
+               pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
                pgste_set_key(ptep, pgste, entry);
                pgste_set_pte(ptep, entry);
                pgste_set_unlock(ptep, pgste);
@@ -881,6 +897,12 @@ static inline int pte_young(pte_t pte)
        return (pte_val(pte) & _PAGE_YOUNG) != 0;
 }
 
+#define __HAVE_ARCH_PTE_UNUSED
+static inline int pte_unused(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_UNUSED;
+}
+
 /*
  * pgd/pmd/pte modification functions
  */
@@ -1034,30 +1056,41 @@ static inline int ptep_test_and_clear_user_young(struct mm_struct *mm,
 
 static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
 {
-       if (!(pte_val(*ptep) & _PAGE_INVALID)) {
+       unsigned long pto = (unsigned long) ptep;
+
 #ifndef CONFIG_64BIT
-               /* pto must point to the start of the segment table */
-               pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00);
-#else
-               /* ipte in zarch mode can do the math */
-               pte_t *pto = ptep;
+       /* pto in ESA mode must point to the start of the segment table */
+       pto &= 0x7ffffc00;
 #endif
-               asm volatile(
-                       "       ipte    %2,%3"
-                       : "=m" (*ptep) : "m" (*ptep),
-                         "a" (pto), "a" (address));
-       }
+       /* Invalidation + global TLB flush for the pte */
+       asm volatile(
+               "       ipte    %2,%3"
+               : "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address));
+}
+
+static inline void ptep_flush_direct(struct mm_struct *mm,
+                                    unsigned long address, pte_t *ptep)
+{
+       if (pte_val(*ptep) & _PAGE_INVALID)
+               return;
+       __ptep_ipte(address, ptep);
 }
 
 static inline void ptep_flush_lazy(struct mm_struct *mm,
                                   unsigned long address, pte_t *ptep)
 {
-       int active = (mm == current->active_mm) ? 1 : 0;
+       int active, count;
 
-       if (atomic_read(&mm->context.attach_count) > active)
-               __ptep_ipte(address, ptep);
-       else
+       if (pte_val(*ptep) & _PAGE_INVALID)
+               return;
+       active = (mm == current->active_mm) ? 1 : 0;
+       count = atomic_add_return(0x10000, &mm->context.attach_count);
+       if ((count & 0xffff) <= active) {
+               pte_val(*ptep) |= _PAGE_INVALID;
                mm->context.flush_mm = 1;
+       } else
+               __ptep_ipte(address, ptep);
+       atomic_sub(0x10000, &mm->context.attach_count);
 }
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -1070,11 +1103,11 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
 
        if (mm_has_pgste(vma->vm_mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(vma->vm_mm, addr, ptep, pgste);
+               pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste);
        }
 
        pte = *ptep;
-       __ptep_ipte(addr, ptep);
+       ptep_flush_direct(vma->vm_mm, addr, ptep);
        young = pte_young(pte);
        pte = pte_mkold(pte);
 
@@ -1116,7 +1149,7 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(mm, address, ptep, pgste);
+               pgste = pgste_ipte_notify(mm, ptep, pgste);
        }
 
        pte = *ptep;
@@ -1140,12 +1173,11 @@ static inline pte_t ptep_modify_prot_start(struct mm_struct *mm,
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste_ipte_notify(mm, address, ptep, pgste);
+               pgste_ipte_notify(mm, ptep, pgste);
        }
 
        pte = *ptep;
        ptep_flush_lazy(mm, address, ptep);
-       pte_val(*ptep) |= _PAGE_INVALID;
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_update_all(&pte, pgste);
@@ -1178,14 +1210,17 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
 
        if (mm_has_pgste(vma->vm_mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
+               pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste);
        }
 
        pte = *ptep;
-       __ptep_ipte(address, ptep);
+       ptep_flush_direct(vma->vm_mm, address, ptep);
        pte_val(*ptep) = _PAGE_INVALID;
 
        if (mm_has_pgste(vma->vm_mm)) {
+               if ((pgste_val(pgste) & _PGSTE_GPS_USAGE_MASK) ==
+                   _PGSTE_GPS_USAGE_UNUSED)
+                       pte_val(pte) |= _PAGE_UNUSED;
                pgste = pgste_update_all(&pte, pgste);
                pgste_set_unlock(ptep, pgste);
        }
@@ -1209,7 +1244,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
 
        if (!full && mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(mm, address, ptep, pgste);
+               pgste = pgste_ipte_notify(mm, ptep, pgste);
        }
 
        pte = *ptep;
@@ -1234,7 +1269,7 @@ static inline pte_t ptep_set_wrprotect(struct mm_struct *mm,
        if (pte_write(pte)) {
                if (mm_has_pgste(mm)) {
                        pgste = pgste_get_lock(ptep);
-                       pgste = pgste_ipte_notify(mm, address, ptep, pgste);
+                       pgste = pgste_ipte_notify(mm, ptep, pgste);
                }
 
                ptep_flush_lazy(mm, address, ptep);
@@ -1260,10 +1295,10 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
                return 0;
        if (mm_has_pgste(vma->vm_mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
+               pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste);
        }
 
-       __ptep_ipte(address, ptep);
+       ptep_flush_direct(vma->vm_mm, address, ptep);
 
        if (mm_has_pgste(vma->vm_mm)) {
                pgste_set_pte(ptep, entry);
@@ -1447,12 +1482,16 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd)
 static inline void pmdp_flush_lazy(struct mm_struct *mm,
                                   unsigned long address, pmd_t *pmdp)
 {
-       int active = (mm == current->active_mm) ? 1 : 0;
+       int active, count;
 
-       if ((atomic_read(&mm->context.attach_count) & 0xffff) > active)
-               __pmd_idte(address, pmdp);
-       else
+       active = (mm == current->active_mm) ? 1 : 0;
+       count = atomic_add_return(0x10000, &mm->context.attach_count);
+       if ((count & 0xffff) <= active) {
+               pmd_val(*pmdp) |= _SEGMENT_ENTRY_INVALID;
                mm->context.flush_mm = 1;
+       } else
+               __pmd_idte(address, pmdp);
+       atomic_sub(0x10000, &mm->context.attach_count);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
index 9c82cebddabd78938b1d66baef004c74f3bd97ec..f4783c0b7b43cfd4e58c2c4bfed19013f465fb1b 100644 (file)
@@ -83,6 +83,7 @@ struct per_struct_kernel {
  * These are defined as per linux/ptrace.h, which see.
  */
 #define arch_has_single_step() (1)
+#define arch_has_block_step()  (1)
 
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
index abaca2275c7a5acb3f0f730539e4d8d5fd6cd19f..2f5e9932b4defddda4587c6593492712f2fb85c1 100644 (file)
@@ -46,6 +46,7 @@ int sclp_cpu_configure(u8 cpu);
 int sclp_cpu_deconfigure(u8 cpu);
 unsigned long long sclp_get_rnmax(void);
 unsigned long long sclp_get_rzm(void);
+unsigned int sclp_get_max_cpu(void);
 int sclp_sdias_blk_count(void);
 int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
 int sclp_chp_configure(struct chp_id chpid);
index 94cfbe442f124cc720f2436c7e3c34d485cf0139..406f3a1e63efcce54ccbe6c409d6246bbdb7a887 100644 (file)
@@ -59,7 +59,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 #define MACHINE_FLAG_DIAG44    (1UL << 4)
 #define MACHINE_FLAG_IDTE      (1UL << 5)
 #define MACHINE_FLAG_DIAG9C    (1UL << 6)
-#define MACHINE_FLAG_MVCOS     (1UL << 7)
 #define MACHINE_FLAG_KVM       (1UL << 8)
 #define MACHINE_FLAG_ESOP      (1UL << 9)
 #define MACHINE_FLAG_EDAT1     (1UL << 10)
@@ -85,7 +84,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 #define MACHINE_HAS_IDTE       (0)
 #define MACHINE_HAS_DIAG44     (1)
 #define MACHINE_HAS_MVPG       (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG)
-#define MACHINE_HAS_MVCOS      (0)
 #define MACHINE_HAS_EDAT1      (0)
 #define MACHINE_HAS_EDAT2      (0)
 #define MACHINE_HAS_LPP                (0)
@@ -98,7 +96,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 #define MACHINE_HAS_IDTE       (S390_lowcore.machine_flags & MACHINE_FLAG_IDTE)
 #define MACHINE_HAS_DIAG44     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
 #define MACHINE_HAS_MVPG       (1)
-#define MACHINE_HAS_MVCOS      (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS)
 #define MACHINE_HAS_EDAT1      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1)
 #define MACHINE_HAS_EDAT2      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2)
 #define MACHINE_HAS_LPP                (S390_lowcore.machine_flags & MACHINE_FLAG_LPP)
index 10e0fcd3633d178f25b299a709b9c80706f05818..3ccd71b903454a667ec116a21fa0678a6f80dafe 100644 (file)
@@ -81,6 +81,7 @@ static inline struct thread_info *current_thread_info(void)
 #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_TLB_WAIT           4       /* wait for TLB flush completion */
 #define TIF_PER_TRAP           6       /* deliver sigtrap on return to user */
 #define TIF_MCCK_PENDING       7       /* machine check handling is pending */
 #define TIF_SYSCALL_TRACE      8       /* syscall trace active */
@@ -91,11 +92,13 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_MEMDIE             18      /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    19      /* restore signal mask in do_signal() */
 #define TIF_SINGLE_STEP                20      /* This task is single stepped */
+#define TIF_BLOCK_STEP         21      /* This task is block stepped */
 
 #define _TIF_SYSCALL           (1<<TIF_SYSCALL)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_TLB_WAIT          (1<<TIF_TLB_WAIT)
 #define _TIF_PER_TRAP          (1<<TIF_PER_TRAP)
 #define _TIF_MCCK_PENDING      (1<<TIF_MCCK_PENDING)
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
index 79330af9a5f85442745110001defbaa2a1964bb8..4133b3f72fb09a04c9f640cd214ef4a21a69c9db 100644 (file)
@@ -92,33 +92,58 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x)
 #define ARCH_HAS_SORT_EXTABLE
 #define ARCH_HAS_SEARCH_EXTABLE
 
-struct uaccess_ops {
-       size_t (*copy_from_user)(size_t, const void __user *, void *);
-       size_t (*copy_to_user)(size_t, void __user *, const void *);
-       size_t (*copy_in_user)(size_t, void __user *, const void __user *);
-       size_t (*clear_user)(size_t, void __user *);
-       size_t (*strnlen_user)(size_t, const char __user *);
-       size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-       int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
-       int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
-};
+int __handle_fault(unsigned long, unsigned long, int);
 
-extern struct uaccess_ops uaccess;
-extern struct uaccess_ops uaccess_mvcos;
-extern struct uaccess_ops uaccess_pt;
+/**
+ * __copy_from_user: - Copy a block of data from user space, with less checking.
+ * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:   Number of bytes to copy.
+ *
+ * Context: User context only. This function may sleep.
+ *
+ * Copy data from user space to kernel space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+unsigned long __must_check __copy_from_user(void *to, const void __user *from,
+                                           unsigned long n);
+
+/**
+ * __copy_to_user: - Copy a block of data into user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:   Number of bytes to copy.
+ *
+ * Context: User context only. This function may sleep.
+ *
+ * Copy data from kernel space to user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long __must_check __copy_to_user(void __user *to, const void *from,
+                                         unsigned long n);
 
-extern int __handle_fault(unsigned long, unsigned long, int);
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
-static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
+static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
 {
-       size = uaccess.copy_to_user(size, ptr, x);
-       return size ? -EFAULT : size;
+       size = __copy_to_user(ptr, x, size);
+       return size ? -EFAULT : 0;
 }
 
-static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
+static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 {
-       size = uaccess.copy_from_user(size, ptr, x);
-       return size ? -EFAULT : size;
+       size = __copy_from_user(x, ptr, size);
+       return size ? -EFAULT : 0;
 }
 
 /*
@@ -135,8 +160,8 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
        case 2:                                                 \
        case 4:                                                 \
        case 8:                                                 \
-               __pu_err = __put_user_fn(sizeof (*(ptr)),       \
-                                        ptr, &__x);            \
+               __pu_err = __put_user_fn(&__x, ptr,             \
+                                        sizeof(*(ptr)));       \
                break;                                          \
        default:                                                \
                __put_user_bad();                               \
@@ -152,7 +177,7 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 })
 
 
-extern int __put_user_bad(void) __attribute__((noreturn));
+int __put_user_bad(void) __attribute__((noreturn));
 
 #define __get_user(x, ptr)                                     \
 ({                                                             \
@@ -161,29 +186,29 @@ extern int __put_user_bad(void) __attribute__((noreturn));
        switch (sizeof(*(ptr))) {                               \
        case 1: {                                               \
                unsigned char __x;                              \
-               __gu_err = __get_user_fn(sizeof (*(ptr)),       \
-                                        ptr, &__x);            \
+               __gu_err = __get_user_fn(&__x, ptr,             \
+                                        sizeof(*(ptr)));       \
                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
                break;                                          \
        };                                                      \
        case 2: {                                               \
                unsigned short __x;                             \
-               __gu_err = __get_user_fn(sizeof (*(ptr)),       \
-                                        ptr, &__x);            \
+               __gu_err = __get_user_fn(&__x, ptr,             \
+                                        sizeof(*(ptr)));       \
                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
                break;                                          \
        };                                                      \
        case 4: {                                               \
                unsigned int __x;                               \
-               __gu_err = __get_user_fn(sizeof (*(ptr)),       \
-                                        ptr, &__x);            \
+               __gu_err = __get_user_fn(&__x, ptr,             \
+                                        sizeof(*(ptr)));       \
                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
                break;                                          \
        };                                                      \
        case 8: {                                               \
                unsigned long long __x;                         \
-               __gu_err = __get_user_fn(sizeof (*(ptr)),       \
-                                        ptr, &__x);            \
+               __gu_err = __get_user_fn(&__x, ptr,             \
+                                        sizeof(*(ptr)));       \
                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
                break;                                          \
        };                                                      \
@@ -200,34 +225,11 @@ extern int __put_user_bad(void) __attribute__((noreturn));
        __get_user(x, ptr);                                     \
 })
 
-extern int __get_user_bad(void) __attribute__((noreturn));
+int __get_user_bad(void) __attribute__((noreturn));
 
 #define __put_user_unaligned __put_user
 #define __get_user_unaligned __get_user
 
-/**
- * __copy_to_user: - Copy a block of data into user space, with less checking.
- * @to:   Destination address, in user space.
- * @from: Source address, in kernel space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only.  This function may sleep.
- *
- * Copy data from kernel space to user space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
-static inline unsigned long __must_check
-__copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-       return uaccess.copy_to_user(n, to, from);
-}
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
 /**
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
@@ -248,30 +250,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
        return __copy_to_user(to, from, n);
 }
 
-/**
- * __copy_from_user: - Copy a block of data from user space, with less checking.
- * @to:   Destination address, in kernel space.
- * @from: Source address, in user space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only.  This function may sleep.
- *
- * Copy data from user space to kernel space.  Caller must check
- * the specified block with access_ok() before calling this function.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- *
- * If some data could not be copied, this function will pad the copied
- * data to the requested size using zero bytes.
- */
-static inline unsigned long __must_check
-__copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-       return uaccess.copy_from_user(n, from, to);
-}
-
-extern void copy_from_user_overflow(void)
+void copy_from_user_overflow(void)
 #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
 __compiletime_warning("copy_from_user() buffer size is not provably correct")
 #endif
@@ -306,11 +285,8 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
        return __copy_from_user(to, from, n);
 }
 
-static inline unsigned long __must_check
-__copy_in_user(void __user *to, const void __user *from, unsigned long n)
-{
-       return uaccess.copy_in_user(n, to, from);
-}
+unsigned long __must_check
+__copy_in_user(void __user *to, const void __user *from, unsigned long n);
 
 static inline unsigned long __must_check
 copy_in_user(void __user *to, const void __user *from, unsigned long n)
@@ -322,18 +298,22 @@ copy_in_user(void __user *to, const void __user *from, unsigned long n)
 /*
  * Copy a null terminated string from userspace.
  */
+
+long __strncpy_from_user(char *dst, const char __user *src, long count);
+
 static inline long __must_check
 strncpy_from_user(char *dst, const char __user *src, long count)
 {
        might_fault();
-       return uaccess.strncpy_from_user(count, src, dst);
+       return __strncpy_from_user(dst, src, count);
 }
 
-static inline unsigned long
-strnlen_user(const char __user * src, unsigned long n)
+unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
+
+static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
 {
        might_fault();
-       return uaccess.strnlen_user(n, src);
+       return __strnlen_user(src, n);
 }
 
 /**
@@ -355,21 +335,14 @@ strnlen_user(const char __user * src, unsigned long n)
 /*
  * Zero Userspace
  */
+unsigned long __must_check __clear_user(void __user *to, unsigned long size);
 
-static inline unsigned long __must_check
-__clear_user(void __user *to, unsigned long n)
-{
-       return uaccess.clear_user(n, to);
-}
-
-static inline unsigned long __must_check
-clear_user(void __user *to, unsigned long n)
+static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 {
        might_fault();
-       return uaccess.clear_user(n, to);
+       return __clear_user(to, n);
 }
 
-extern int copy_to_user_real(void __user *dest, void *src, size_t count);
-extern int copy_from_user_real(void *dest, void __user *src, size_t count);
+int copy_to_user_real(void __user *dest, void *src, unsigned long count);
 
 #endif /* __S390_UACCESS_H */
index 7e0b498a2c2ba95c8ca56537e673b18c4a0065d3..a150f4fabe437a5f39ddcafb88c598895c909518 100644 (file)
@@ -402,6 +402,12 @@ typedef struct
 #define PTRACE_DISABLE_TE            0x5010
 #define PTRACE_TE_ABORT_RAND         0x5011
 
+/*
+ * The numbers chosen here are somewhat arbitrary but absolutely MUST
+ * not overlap with any of the number assigned in <linux/ptrace.h>.
+ */
+#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+
 /*
  * PT_PROT definition is loosely based on hppa bsd definition in
  * gdb/hppab-nat.c
index 1b3ac09c11b6df2981ca3dbde3cc6df3fba5d2e9..a95c4ca99617e43360fb3b867ac3aefb92b374d6 100644 (file)
@@ -47,9 +47,8 @@ obj-$(CONFIG_SCHED_BOOK)      += topology.o
 obj-$(CONFIG_HIBERNATION)      += suspend.o swsusp_asm64.o
 obj-$(CONFIG_AUDIT)            += audit.o
 compat-obj-$(CONFIG_AUDIT)     += compat_audit.o
-obj-$(CONFIG_COMPAT)           += compat_linux.o compat_signal.o \
-                                       compat_wrapper.o compat_exec_domain.o \
-                                       $(compat-obj-y)
+obj-$(CONFIG_COMPAT)           += compat_linux.o compat_signal.o
+obj-$(CONFIG_COMPAT)           += compat_wrapper.o $(compat-obj-y)
 
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
diff --git a/arch/s390/kernel/compat_exec_domain.c b/arch/s390/kernel/compat_exec_domain.c
deleted file mode 100644 (file)
index 765fabd..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Support for 32-bit Linux for S390 personality.
- *
- * Copyright IBM Corp. 2000
- * Author(s): Gerhard Tonn (ton@de.ibm.com)
- *
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/personality.h>
-#include <linux/sched.h>
-
-static struct exec_domain s390_exec_domain;
-
-static int __init s390_init (void)
-{
-       s390_exec_domain.name = "Linux/s390";
-       s390_exec_domain.handler = NULL;
-       s390_exec_domain.pers_low = PER_LINUX32;
-       s390_exec_domain.pers_high = PER_LINUX32;
-       s390_exec_domain.signal_map = default_exec_domain.signal_map;
-       s390_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
-       register_exec_domain(&s390_exec_domain);
-       return 0;
-}
-
-__initcall(s390_init);
index db02052bd137254c1c6d46314005ed4fce1a6204..ca38139423ae7f22e3a4d5e33d4990d9f4bc5daa 100644 (file)
 #define SET_STAT_UID(stat, uid)                (stat).st_uid = high2lowuid(uid)
 #define SET_STAT_GID(stat, gid)                (stat).st_gid = high2lowgid(gid)
 
-asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
+COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename,
+                      u16, user, u16, group)
 {
        return sys_chown(filename, low2highuid(user), low2highgid(group));
 }
 
-asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
+COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *,
+                      filename, u16, user, u16, group)
 {
        return sys_lchown(filename, low2highuid(user), low2highgid(group));
 }
 
-asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
+COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group)
 {
        return sys_fchown(fd, low2highuid(user), low2highgid(group));
 }
 
-asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
+COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid)
 {
        return sys_setregid(low2highgid(rgid), low2highgid(egid));
 }
 
-asmlinkage long sys32_setgid16(u16 gid)
+COMPAT_SYSCALL_DEFINE1(s390_setgid16, u16, gid)
 {
        return sys_setgid((gid_t)gid);
 }
 
-asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
+COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid)
 {
        return sys_setreuid(low2highuid(ruid), low2highuid(euid));
 }
 
-asmlinkage long sys32_setuid16(u16 uid)
+COMPAT_SYSCALL_DEFINE1(s390_setuid16, u16, uid)
 {
        return sys_setuid((uid_t)uid);
 }
 
-asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
+COMPAT_SYSCALL_DEFINE3(s390_setresuid16, u16, ruid, u16, euid, u16, suid)
 {
        return sys_setresuid(low2highuid(ruid), low2highuid(euid),
-               low2highuid(suid));
+                            low2highuid(suid));
 }
 
-asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp)
+COMPAT_SYSCALL_DEFINE3(s390_getresuid16, u16 __user *, ruidp,
+                      u16 __user *, euidp, u16 __user *, suidp)
 {
        const struct cred *cred = current_cred();
        int retval;
@@ -144,13 +147,14 @@ asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __us
        return retval;
 }
 
-asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
+COMPAT_SYSCALL_DEFINE3(s390_setresgid16, u16, rgid, u16, egid, u16, sgid)
 {
        return sys_setresgid(low2highgid(rgid), low2highgid(egid),
-               low2highgid(sgid));
+                            low2highgid(sgid));
 }
 
-asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp)
+COMPAT_SYSCALL_DEFINE3(s390_getresgid16, u16 __user *, rgidp,
+                      u16 __user *, egidp, u16 __user *, sgidp)
 {
        const struct cred *cred = current_cred();
        int retval;
@@ -167,12 +171,12 @@ asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __us
        return retval;
 }
 
-asmlinkage long sys32_setfsuid16(u16 uid)
+COMPAT_SYSCALL_DEFINE1(s390_setfsuid16, u16, uid)
 {
        return sys_setfsuid((uid_t)uid);
 }
 
-asmlinkage long sys32_setfsgid16(u16 gid)
+COMPAT_SYSCALL_DEFINE1(s390_setfsgid16, u16, gid)
 {
        return sys_setfsgid((gid_t)gid);
 }
@@ -215,7 +219,7 @@ static int groups16_from_user(struct group_info *group_info, u16 __user *groupli
        return 0;
 }
 
-asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
+COMPAT_SYSCALL_DEFINE2(s390_getgroups16, int, gidsetsize, u16 __user *, grouplist)
 {
        const struct cred *cred = current_cred();
        int i;
@@ -240,7 +244,7 @@ out:
        return i;
 }
 
-asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
+COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplist)
 {
        struct group_info *group_info;
        int retval;
@@ -265,22 +269,22 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
        return retval;
 }
 
-asmlinkage long sys32_getuid16(void)
+COMPAT_SYSCALL_DEFINE0(s390_getuid16)
 {
        return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
 }
 
-asmlinkage long sys32_geteuid16(void)
+COMPAT_SYSCALL_DEFINE0(s390_geteuid16)
 {
        return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
 }
 
-asmlinkage long sys32_getgid16(void)
+COMPAT_SYSCALL_DEFINE0(s390_getgid16)
 {
        return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
 }
 
-asmlinkage long sys32_getegid16(void)
+COMPAT_SYSCALL_DEFINE0(s390_getegid16)
 {
        return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
 }
@@ -295,41 +299,35 @@ COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
 }
 #endif
 
-asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
+COMPAT_SYSCALL_DEFINE3(s390_truncate64, const char __user *, path, u32, high, u32, low)
 {
-       if ((int)high < 0)
-               return -EINVAL;
-       else
-               return sys_truncate(path, (high << 32) | low);
+       return sys_truncate(path, (unsigned long)high << 32 | low);
 }
 
-asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
+COMPAT_SYSCALL_DEFINE3(s390_ftruncate64, unsigned int, fd, u32, high, u32, low)
 {
-       if ((int)high < 0)
-               return -EINVAL;
-       else
-               return sys_ftruncate(fd, (high << 32) | low);
+       return sys_ftruncate(fd, (unsigned long)high << 32 | low);
 }
 
-asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
-                               size_t count, u32 poshi, u32 poslo)
+COMPAT_SYSCALL_DEFINE5(s390_pread64, unsigned int, fd, char __user *, ubuf,
+                      compat_size_t, count, u32, high, u32, low)
 {
        if ((compat_ssize_t) count < 0)
                return -EINVAL;
-       return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+       return sys_pread64(fd, ubuf, count, (unsigned long)high << 32 | low);
 }
 
-asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
-                               size_t count, u32 poshi, u32 poslo)
+COMPAT_SYSCALL_DEFINE5(s390_pwrite64, unsigned int, fd, const char __user *, ubuf,
+                      compat_size_t, count, u32, high, u32, low)
 {
        if ((compat_ssize_t) count < 0)
                return -EINVAL;
-       return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+       return sys_pwrite64(fd, ubuf, count, (unsigned long)high << 32 | low);
 }
 
-asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
+COMPAT_SYSCALL_DEFINE4(s390_readahead, int, fd, u32, high, u32, low, s32, count)
 {
-       return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
+       return sys_readahead(fd, (unsigned long)high << 32 | low, count);
 }
 
 struct stat64_emu31 {
@@ -381,7 +379,7 @@ static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
        return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 
 }
 
-asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
+COMPAT_SYSCALL_DEFINE2(s390_stat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)
 {
        struct kstat stat;
        int ret = vfs_stat(filename, &stat);
@@ -390,7 +388,7 @@ asmlinkage long sys32_stat64(const char __user * filename, struct stat64_emu31 _
        return ret;
 }
 
-asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31 __user * statbuf)
+COMPAT_SYSCALL_DEFINE2(s390_lstat64, const char __user *, filename, struct stat64_emu31 __user *, statbuf)
 {
        struct kstat stat;
        int ret = vfs_lstat(filename, &stat);
@@ -399,7 +397,7 @@ asmlinkage long sys32_lstat64(const char __user * filename, struct stat64_emu31
        return ret;
 }
 
-asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
+COMPAT_SYSCALL_DEFINE2(s390_fstat64, unsigned int, fd, struct stat64_emu31 __user *, statbuf)
 {
        struct kstat stat;
        int ret = vfs_fstat(fd, &stat);
@@ -408,8 +406,8 @@ asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * sta
        return ret;
 }
 
-asmlinkage long sys32_fstatat64(unsigned int dfd, const char __user *filename,
-                               struct stat64_emu31 __user* statbuf, int flag)
+COMPAT_SYSCALL_DEFINE4(s390_fstatat64, unsigned int, dfd, const char __user *, filename,
+                      struct stat64_emu31 __user *, statbuf, int, flag)
 {
        struct kstat stat;
        int error;
@@ -435,7 +433,7 @@ struct mmap_arg_struct_emu31 {
        compat_ulong_t offset;
 };
 
-asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
+COMPAT_SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct_emu31 __user *, arg)
 {
        struct mmap_arg_struct_emu31 a;
 
@@ -447,7 +445,7 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
                              a.offset >> PAGE_SHIFT);
 }
 
-asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
+COMPAT_SYSCALL_DEFINE1(s390_mmap2, struct mmap_arg_struct_emu31 __user *, arg)
 {
        struct mmap_arg_struct_emu31 a;
 
@@ -456,7 +454,7 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
        return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
 }
 
-asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
+COMPAT_SYSCALL_DEFINE3(s390_read, unsigned int, fd, char __user *, buf, compat_size_t, count)
 {
        if ((compat_ssize_t) count < 0)
                return -EINVAL; 
@@ -464,7 +462,7 @@ asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
        return sys_read(fd, buf, count);
 }
 
-asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t count)
+COMPAT_SYSCALL_DEFINE3(s390_write, unsigned int, fd, const char __user *, buf, compat_size_t, count)
 {
        if ((compat_ssize_t) count < 0)
                return -EINVAL; 
@@ -478,14 +476,13 @@ asmlinkage long sys32_write(unsigned int fd, const char __user * buf, size_t cou
  * because the 31 bit values differ from the 64 bit values.
  */
 
-asmlinkage long
-sys32_fadvise64(int fd, loff_t offset, size_t len, int advise)
+COMPAT_SYSCALL_DEFINE5(s390_fadvise64, int, fd, u32, high, u32, low, compat_size_t, len, int, advise)
 {
        if (advise == 4)
                advise = POSIX_FADV_DONTNEED;
        else if (advise == 5)
                advise = POSIX_FADV_NOREUSE;
-       return sys_fadvise64(fd, offset, len, advise);
+       return sys_fadvise64(fd, (unsigned long)high << 32 | low, len, advise);
 }
 
 struct fadvise64_64_args {
@@ -495,8 +492,7 @@ struct fadvise64_64_args {
        int advice;
 };
 
-asmlinkage long
-sys32_fadvise64_64(struct fadvise64_64_args __user *args)
+COMPAT_SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)
 {
        struct fadvise64_64_args a;
 
@@ -508,3 +504,17 @@ sys32_fadvise64_64(struct fadvise64_64_args __user *args)
                a.advice = POSIX_FADV_NOREUSE;
        return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
 }
+
+COMPAT_SYSCALL_DEFINE6(s390_sync_file_range, int, fd, u32, offhigh, u32, offlow,
+                      u32, nhigh, u32, nlow, unsigned int, flags)
+{
+       return sys_sync_file_range(fd, ((loff_t)offhigh << 32) + offlow,
+                                  ((u64)nhigh << 32) + nlow, flags);
+}
+
+COMPAT_SYSCALL_DEFINE6(s390_fallocate, int, fd, int, mode, u32, offhigh, u32, offlow,
+                      u32, lenhigh, u32, lenlow)
+{
+       return sys_fallocate(fd, mode, ((loff_t)offhigh << 32) + offlow,
+                            ((u64)lenhigh << 32) + lenlow);
+}
index 1bfda3eca37909988c26564b11398b6b75302c50..39ddfdb40ae86228c89f126b02e6f488ca1ae57e 100644 (file)
@@ -76,46 +76,43 @@ struct stat64_emu31;
 struct mmap_arg_struct_emu31;
 struct fadvise64_64_args;
 
-long sys32_chown16(const char __user * filename, u16 user, u16 group);
-long sys32_lchown16(const char __user * filename, u16 user, u16 group);
-long sys32_fchown16(unsigned int fd, u16 user, u16 group);
-long sys32_setregid16(u16 rgid, u16 egid);
-long sys32_setgid16(u16 gid);
-long sys32_setreuid16(u16 ruid, u16 euid);
-long sys32_setuid16(u16 uid);
-long sys32_setresuid16(u16 ruid, u16 euid, u16 suid);
-long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid);
-long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid);
-long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid);
-long sys32_setfsuid16(u16 uid);
-long sys32_setfsgid16(u16 gid);
-long sys32_getgroups16(int gidsetsize, u16 __user *grouplist);
-long sys32_setgroups16(int gidsetsize, u16 __user *grouplist);
-long sys32_getuid16(void);
-long sys32_geteuid16(void);
-long sys32_getgid16(void);
-long sys32_getegid16(void);
-long sys32_truncate64(const char __user * path, unsigned long high,
-                     unsigned long low);
-long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low);
-long sys32_init_module(void __user *umod, unsigned long len,
-                      const char __user *uargs);
-long sys32_delete_module(const char __user *name_user, unsigned int flags);
-long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
-                  u32 poshi, u32 poslo);
-long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
-                   size_t count, u32 poshi, u32 poslo);
-compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count);
-long sys32_stat64(const char __user * filename, struct stat64_emu31 __user * statbuf);
-long sys32_lstat64(const char __user * filename,
-                  struct stat64_emu31 __user * statbuf);
-long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf);
-long sys32_fstatat64(unsigned int dfd, const char __user *filename,
-                    struct stat64_emu31 __user* statbuf, int flag);
-unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg);
-long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg);
-long sys32_read(unsigned int fd, char __user * buf, size_t count);
-long sys32_write(unsigned int fd, const char __user * buf, size_t count);
-long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise);
-long sys32_fadvise64_64(struct fadvise64_64_args __user *args);
+long compat_sys_s390_chown16(const char __user *filename, u16 user, u16 group);
+long compat_sys_s390_lchown16(const char __user *filename, u16 user, u16 group);
+long compat_sys_s390_fchown16(unsigned int fd, u16 user, u16 group);
+long compat_sys_s390_setregid16(u16 rgid, u16 egid);
+long compat_sys_s390_setgid16(u16 gid);
+long compat_sys_s390_setreuid16(u16 ruid, u16 euid);
+long compat_sys_s390_setuid16(u16 uid);
+long compat_sys_s390_setresuid16(u16 ruid, u16 euid, u16 suid);
+long compat_sys_s390_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid);
+long compat_sys_s390_setresgid16(u16 rgid, u16 egid, u16 sgid);
+long compat_sys_s390_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid);
+long compat_sys_s390_setfsuid16(u16 uid);
+long compat_sys_s390_setfsgid16(u16 gid);
+long compat_sys_s390_getgroups16(int gidsetsize, u16 __user *grouplist);
+long compat_sys_s390_setgroups16(int gidsetsize, u16 __user *grouplist);
+long compat_sys_s390_getuid16(void);
+long compat_sys_s390_geteuid16(void);
+long compat_sys_s390_getgid16(void);
+long compat_sys_s390_getegid16(void);
+long compat_sys_s390_truncate64(const char __user *path, u32 high, u32 low);
+long compat_sys_s390_ftruncate64(unsigned int fd, u32 high, u32 low);
+long compat_sys_s390_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, u32 high, u32 low);
+long compat_sys_s390_pwrite64(unsigned int fd, const char __user *ubuf, compat_size_t count, u32 high, u32 low);
+long compat_sys_s390_readahead(int fd, u32 high, u32 low, s32 count);
+long compat_sys_s390_stat64(const char __user *filename, struct stat64_emu31 __user *statbuf);
+long compat_sys_s390_lstat64(const char __user *filename, struct stat64_emu31 __user *statbuf);
+long compat_sys_s390_fstat64(unsigned int fd, struct stat64_emu31 __user *statbuf);
+long compat_sys_s390_fstatat64(unsigned int dfd, const char __user *filename, struct stat64_emu31 __user *statbuf, int flag);
+long compat_sys_s390_old_mmap(struct mmap_arg_struct_emu31 __user *arg);
+long compat_sys_s390_mmap2(struct mmap_arg_struct_emu31 __user *arg);
+long compat_sys_s390_read(unsigned int fd, char __user * buf, compat_size_t count);
+long compat_sys_s390_write(unsigned int fd, const char __user * buf, compat_size_t count);
+long compat_sys_s390_fadvise64(int fd, u32 high, u32 low, compat_size_t len, int advise);
+long compat_sys_s390_fadvise64_64(struct fadvise64_64_args __user *args);
+long compat_sys_s390_sync_file_range(int fd, u32 offhigh, u32 offlow, u32 nhigh, u32 nlow, unsigned int flags);
+long compat_sys_s390_fallocate(int fd, int mode, u32 offhigh, u32 offlow, u32 lenhigh, u32 lenlow);
+long compat_sys_sigreturn(void);
+long compat_sys_rt_sigreturn(void);
+
 #endif /* _ASM_S390X_S390_H */
index 8b84bc373e945bbb2edaba876addbbf5a850fcdd..7df5ed9f44d7c2d471e99bd3f21195d958638c3d 100644 (file)
@@ -241,7 +241,7 @@ static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
        return 0;
 }
 
-asmlinkage long sys32_sigreturn(void)
+COMPAT_SYSCALL_DEFINE0(sigreturn)
 {
        struct pt_regs *regs = task_pt_regs(current);
        sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
@@ -260,7 +260,7 @@ badframe:
        return 0;
 }
 
-asmlinkage long sys32_rt_sigreturn(void)
+COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
 {
        struct pt_regs *regs = task_pt_regs(current);
        rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
deleted file mode 100644 (file)
index 59c8efc..0000000
+++ /dev/null
@@ -1,1425 +0,0 @@
-/*
-*    wrapper for 31 bit compatible system calls.
-*
-*    Copyright IBM Corp. 2000, 2006
-*    Author(s): Gerhard Tonn (ton@de.ibm.com),
-*              Thomas Spatzier (tspat@de.ibm.com)
-*/
-
-#include <linux/linkage.h>
-
-ENTRY(sys32_exit_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_exit                # branch to sys_exit
-
-ENTRY(sys32_read_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # char *
-       llgfr   %r4,%r4                 # size_t
-       jg      sys32_read              # branch to sys_read
-
-ENTRY(sys32_write_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # size_t
-       jg      sys32_write             # branch to system call
-
-ENTRY(sys32_close_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_close               # branch to system call
-
-ENTRY(sys32_creat_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_creat               # branch to system call
-
-ENTRY(sys32_link_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # const char *
-       jg      sys_link                # branch to system call
-
-ENTRY(sys32_unlink_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       jg      sys_unlink              # branch to system call
-
-ENTRY(sys32_chdir_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       jg      sys_chdir               # branch to system call
-
-ENTRY(sys32_time_wrapper)
-       llgtr   %r2,%r2                 # int *
-       jg      compat_sys_time         # branch to system call
-
-ENTRY(sys32_mknod_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       llgfr   %r4,%r4                 # dev
-       jg      sys_mknod               # branch to system call
-
-ENTRY(sys32_chmod_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # mode_t
-       jg      sys_chmod               # branch to system call
-
-ENTRY(sys32_lchown16_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
-       llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t
-       jg      sys32_lchown16          # branch to system call
-
-#sys32_getpid_wrapper                          # void
-
-ENTRY(sys32_mount_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # char *
-       llgfr   %r5,%r5                 # unsigned long
-       llgtr   %r6,%r6                 # void *
-       jg      compat_sys_mount        # branch to system call
-
-ENTRY(sys32_oldumount_wrapper)
-       llgtr   %r2,%r2                 # char *
-       jg      sys_oldumount           # branch to system call
-
-ENTRY(sys32_setuid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
-       jg      sys32_setuid16          # branch to system call
-
-#sys32_getuid16_wrapper                        # void
-
-ENTRY(sys32_ptrace_wrapper)
-       lgfr    %r2,%r2                 # long
-       lgfr    %r3,%r3                 # long
-       llgtr   %r4,%r4                 # long
-       llgfr   %r5,%r5                 # long
-       jg      compat_sys_ptrace       # branch to system call
-
-ENTRY(sys32_alarm_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_alarm               # branch to system call
-
-ENTRY(compat_sys_utime_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct compat_utimbuf *
-       jg      compat_sys_utime        # branch to system call
-
-ENTRY(sys32_access_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_access              # branch to system call
-
-ENTRY(sys32_nice_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_nice                # branch to system call
-
-#sys32_sync_wrapper                    # void
-
-ENTRY(sys32_kill_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       jg      sys_kill                # branch to system call
-
-ENTRY(sys32_rename_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # const char *
-       jg      sys_rename              # branch to system call
-
-ENTRY(sys32_mkdir_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_mkdir               # branch to system call
-
-ENTRY(sys32_rmdir_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       jg      sys_rmdir               # branch to system call
-
-ENTRY(sys32_dup_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_dup                 # branch to system call
-
-ENTRY(sys32_pipe_wrapper)
-       llgtr   %r2,%r2                 # u32 *
-       jg      sys_pipe                # branch to system call
-
-ENTRY(compat_sys_times_wrapper)
-       llgtr   %r2,%r2                 # struct compat_tms *
-       jg      compat_sys_times        # branch to system call
-
-ENTRY(sys32_brk_wrapper)
-       llgtr   %r2,%r2                 # unsigned long
-       jg      sys_brk                 # branch to system call
-
-ENTRY(sys32_setgid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
-       jg      sys32_setgid16          # branch to system call
-
-#sys32_getgid16_wrapper                        # void
-
-ENTRY(sys32_signal_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # __sighandler_t
-       jg      sys_signal
-
-#sys32_geteuid16_wrapper               # void
-
-#sys32_getegid16_wrapper               # void
-
-ENTRY(sys32_acct_wrapper)
-       llgtr   %r2,%r2                 # char *
-       jg      sys_acct                # branch to system call
-
-ENTRY(sys32_umount_wrapper)
-       llgtr   %r2,%r2                 # char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_umount              # branch to system call
-
-ENTRY(compat_sys_ioctl_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       llgfr   %r4,%r4                 # unsigned int
-       jg      compat_sys_ioctl        # branch to system call
-
-ENTRY(compat_sys_fcntl_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       llgfr   %r4,%r4                 # unsigned long
-       jg      compat_sys_fcntl        # branch to system call
-
-ENTRY(sys32_setpgid_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       lgfr    %r3,%r3                 # pid_t
-       jg      sys_setpgid             # branch to system call
-
-ENTRY(sys32_umask_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_umask               # branch to system call
-
-ENTRY(sys32_chroot_wrapper)
-       llgtr   %r2,%r2                 # char *
-       jg      sys_chroot              # branch to system call
-
-ENTRY(sys32_ustat_wrapper)
-       llgfr   %r2,%r2                 # dev_t
-       llgtr   %r3,%r3                 # struct ustat *
-       jg      compat_sys_ustat
-
-ENTRY(sys32_dup2_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       jg      sys_dup2                # branch to system call
-
-#sys32_getppid_wrapper                 # void
-
-#sys32_getpgrp_wrapper                 # void
-
-#sys32_setsid_wrapper                  # void
-
-ENTRY(sys32_setreuid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
-       jg      sys32_setreuid16        # branch to system call
-
-ENTRY(sys32_setregid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
-       llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
-       jg      sys32_setregid16        # branch to system call
-
-ENTRY(sys_sigsuspend_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       llgfr   %r4,%r4                 # old_sigset_t
-       jg      sys_sigsuspend
-
-ENTRY(compat_sys_sigpending_wrapper)
-       llgtr   %r2,%r2                 # compat_old_sigset_t *
-       jg      compat_sys_sigpending   # branch to system call
-
-ENTRY(sys32_sethostname_wrapper)
-       llgtr   %r2,%r2                 # char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_sethostname         # branch to system call
-
-ENTRY(compat_sys_setrlimit_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # struct rlimit_emu31 *
-       jg      compat_sys_setrlimit    # branch to system call
-
-ENTRY(compat_sys_old_getrlimit_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # struct rlimit_emu31 *
-       jg      compat_sys_old_getrlimit # branch to system call
-
-ENTRY(compat_sys_getrlimit_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # struct rlimit_emu31 *
-       jg      compat_sys_getrlimit    # branch to system call
-
-ENTRY(sys32_mmap2_wrapper)
-       llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
-       jg      sys32_mmap2                     # branch to system call
-
-ENTRY(compat_sys_gettimeofday_wrapper)
-       llgtr   %r2,%r2                 # struct timeval_emu31 *
-       llgtr   %r3,%r3                 # struct timezone *
-       jg      compat_sys_gettimeofday # branch to system call
-
-ENTRY(compat_sys_settimeofday_wrapper)
-       llgtr   %r2,%r2                 # struct timeval_emu31 *
-       llgtr   %r3,%r3                 # struct timezone *
-       jg      compat_sys_settimeofday # branch to system call
-
-ENTRY(sys32_getgroups16_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
-       jg      sys32_getgroups16       # branch to system call
-
-ENTRY(sys32_setgroups16_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
-       jg      sys32_setgroups16       # branch to system call
-
-ENTRY(sys32_symlink_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # const char *
-       jg      sys_symlink             # branch to system call
-
-ENTRY(sys32_readlink_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # char *
-       lgfr    %r4,%r4                 # int
-       jg      sys_readlink            # branch to system call
-
-ENTRY(sys32_uselib_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       jg      sys_uselib              # branch to system call
-
-ENTRY(sys32_swapon_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_swapon              # branch to system call
-
-ENTRY(sys32_reboot_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       llgfr   %r4,%r4                 # unsigned int
-       llgtr   %r5,%r5                 # void *
-       jg      sys_reboot              # branch to system call
-
-ENTRY(old32_readdir_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # void *
-       llgfr   %r4,%r4                 # unsigned int
-       jg      compat_sys_old_readdir  # branch to system call
-
-ENTRY(old32_mmap_wrapper)
-       llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
-       jg      old32_mmap              # branch to system call
-
-ENTRY(sys32_munmap_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t
-       jg      sys_munmap              # branch to system call
-
-ENTRY(sys32_fchmod_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # mode_t
-       jg      sys_fchmod              # branch to system call
-
-ENTRY(sys32_fchown16_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # compat_uid_t
-       llgfr   %r4,%r4                 # compat_uid_t
-       jg      sys32_fchown16          # branch to system call
-
-ENTRY(sys32_getpriority_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       jg      sys_getpriority         # branch to system call
-
-ENTRY(sys32_setpriority_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       lgfr    %r4,%r4                 # int
-       jg      sys_setpriority         # branch to system call
-
-ENTRY(compat_sys_statfs_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct compat_statfs *
-       jg      compat_sys_statfs       # branch to system call
-
-ENTRY(compat_sys_fstatfs_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # struct compat_statfs *
-       jg      compat_sys_fstatfs      # branch to system call
-
-ENTRY(compat_sys_socketcall_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # u32 *
-       jg      compat_sys_socketcall   # branch to system call
-
-ENTRY(sys32_syslog_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # char *
-       lgfr    %r4,%r4                 # int
-       jg      sys_syslog              # branch to system call
-
-ENTRY(compat_sys_newstat_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct stat_emu31 *
-       jg      compat_sys_newstat      # branch to system call
-
-ENTRY(compat_sys_newlstat_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct stat_emu31 *
-       jg      compat_sys_newlstat     # branch to system call
-
-ENTRY(compat_sys_newfstat_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # struct stat_emu31 *
-       jg      compat_sys_newfstat     # branch to system call
-
-#sys32_vhangup_wrapper                 # void
-
-ENTRY(sys32_swapoff_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       jg      sys_swapoff             # branch to system call
-
-ENTRY(compat_sys_sysinfo_wrapper)
-       llgtr   %r2,%r2                 # struct sysinfo_emu31 *
-       jg      compat_sys_sysinfo      # branch to system call
-
-ENTRY(sys32_fsync_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_fsync               # branch to system call
-
-#sys32_sigreturn_wrapper               # done in sigreturn_glue
-
-#sys32_clone_wrapper                   # done in clone_glue
-
-ENTRY(sys32_setdomainname_wrapper)
-       llgtr   %r2,%r2                 # char *
-       lgfr    %r3,%r3                 # int
-       jg      sys_setdomainname       # branch to system call
-
-ENTRY(sys32_newuname_wrapper)
-       llgtr   %r2,%r2                 # struct new_utsname *
-       jg      sys_newuname            # branch to system call
-
-ENTRY(compat_sys_adjtimex_wrapper)
-       llgtr   %r2,%r2                 # struct compat_timex *
-       jg      compat_sys_adjtimex     # branch to system call
-
-ENTRY(sys32_mprotect_wrapper)
-       llgtr   %r2,%r2                 # unsigned long (actually pointer
-       llgfr   %r3,%r3                 # size_t
-       llgfr   %r4,%r4                 # unsigned long
-       jg      sys_mprotect            # branch to system call
-
-ENTRY(sys_init_module_wrapper)
-       llgtr   %r2,%r2                 # void *
-       llgfr   %r3,%r3                 # unsigned long
-       llgtr   %r4,%r4                 # char *
-       jg      sys_init_module         # branch to system call
-
-ENTRY(sys_delete_module_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # unsigned int
-       jg      sys_delete_module       # branch to system call
-
-ENTRY(sys32_quotactl_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # qid_t
-       llgtr   %r5,%r5                 # caddr_t
-       jg      sys_quotactl            # branch to system call
-
-ENTRY(sys32_getpgid_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       jg      sys_getpgid             # branch to system call
-
-ENTRY(sys32_fchdir_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_fchdir              # branch to system call
-
-ENTRY(sys32_bdflush_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # long
-       jg      sys_bdflush             # branch to system call
-
-ENTRY(sys32_sysfs_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       jg      sys_sysfs               # branch to system call
-
-ENTRY(sys32_personality_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_s390_personality    # branch to system call
-
-ENTRY(sys32_setfsuid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
-       jg      sys32_setfsuid16        # branch to system call
-
-ENTRY(sys32_setfsgid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
-       jg      sys32_setfsgid16        # branch to system call
-
-ENTRY(sys32_llseek_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       llgtr   %r5,%r5                 # loff_t *
-       llgfr   %r6,%r6                 # unsigned int
-       jg      sys_llseek              # branch to system call
-
-ENTRY(sys32_getdents_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # void *
-       llgfr   %r4,%r4                 # unsigned int
-       jg      compat_sys_getdents     # branch to system call
-
-ENTRY(compat_sys_select_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # compat_fd_set *
-       llgtr   %r4,%r4                 # compat_fd_set *
-       llgtr   %r5,%r5                 # compat_fd_set *
-       llgtr   %r6,%r6                 # struct compat_timeval *
-       jg      compat_sys_select       # branch to system call
-
-ENTRY(sys32_flock_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       jg      sys_flock               # branch to system call
-
-ENTRY(sys32_msync_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t
-       lgfr    %r4,%r4                 # int
-       jg      sys_msync               # branch to system call
-
-ENTRY(compat_sys_readv_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const struct compat_iovec *
-       llgfr   %r4,%r4                 # unsigned long
-       jg      compat_sys_readv        # branch to system call
-
-ENTRY(compat_sys_writev_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const struct compat_iovec *
-       llgfr   %r4,%r4                 # unsigned long
-       jg      compat_sys_writev       # branch to system call
-
-ENTRY(sys32_getsid_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       jg      sys_getsid              # branch to system call
-
-ENTRY(sys32_fdatasync_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_fdatasync           # branch to system call
-
-ENTRY(sys32_mlock_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t
-       jg      sys_mlock               # branch to system call
-
-ENTRY(sys32_munlock_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t
-       jg      sys_munlock             # branch to system call
-
-ENTRY(sys32_mlockall_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_mlockall            # branch to system call
-
-#sys32_munlockall_wrapper              # void
-
-ENTRY(sys32_sched_setparam_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       llgtr   %r3,%r3                 # struct sched_param *
-       jg      sys_sched_setparam      # branch to system call
-
-ENTRY(sys32_sched_getparam_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       llgtr   %r3,%r3                 # struct sched_param *
-       jg      sys_sched_getparam      # branch to system call
-
-ENTRY(sys32_sched_setscheduler_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       lgfr    %r3,%r3                 # int
-       llgtr   %r4,%r4                 # struct sched_param *
-       jg      sys_sched_setscheduler  # branch to system call
-
-ENTRY(sys32_sched_getscheduler_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       jg      sys_sched_getscheduler  # branch to system call
-
-#sys32_sched_yield_wrapper             # void
-
-ENTRY(sys32_sched_get_priority_max_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_sched_get_priority_max      # branch to system call
-
-ENTRY(sys32_sched_get_priority_min_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_sched_get_priority_min      # branch to system call
-
-ENTRY(compat_sys_nanosleep_wrapper)
-       llgtr   %r2,%r2                 # struct compat_timespec *
-       llgtr   %r3,%r3                 # struct compat_timespec *
-       jg      compat_sys_nanosleep            # branch to system call
-
-ENTRY(sys32_mremap_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # unsigned long
-       llgfr   %r6,%r6                 # unsigned long
-       jg      sys_mremap              # branch to system call
-
-ENTRY(sys32_setresuid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
-       llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t
-       jg      sys32_setresuid16       # branch to system call
-
-ENTRY(sys32_getresuid16_wrapper)
-       llgtr   %r2,%r2                 # __kernel_old_uid_emu31_t *
-       llgtr   %r3,%r3                 # __kernel_old_uid_emu31_t *
-       llgtr   %r4,%r4                 # __kernel_old_uid_emu31_t *
-       jg      sys32_getresuid16       # branch to system call
-
-ENTRY(sys32_poll_wrapper)
-       llgtr   %r2,%r2                 # struct pollfd *
-       llgfr   %r3,%r3                 # unsigned int
-       lgfr    %r4,%r4                 # int
-       jg      sys_poll                # branch to system call
-
-ENTRY(sys32_setresgid16_wrapper)
-       llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
-       llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
-       llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t
-       jg      sys32_setresgid16       # branch to system call
-
-ENTRY(sys32_getresgid16_wrapper)
-       llgtr   %r2,%r2                 # __kernel_old_gid_emu31_t *
-       llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
-       llgtr   %r4,%r4                 # __kernel_old_gid_emu31_t *
-       jg      sys32_getresgid16       # branch to system call
-
-ENTRY(sys32_prctl_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # unsigned long
-       llgfr   %r6,%r6                 # unsigned long
-       jg      sys_prctl               # branch to system call
-
-#sys32_rt_sigreturn_wrapper            # done in rt_sigreturn_glue
-
-ENTRY(sys32_pread64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # char *
-       llgfr   %r4,%r4                 # size_t
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      sys32_pread64           # branch to system call
-
-ENTRY(sys32_pwrite64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # size_t
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      sys32_pwrite64          # branch to system call
-
-ENTRY(sys32_chown16_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
-       llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t
-       jg      sys32_chown16           # branch to system call
-
-ENTRY(sys32_getcwd_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgfr   %r3,%r3                 # unsigned long
-       jg      sys_getcwd              # branch to system call
-
-ENTRY(sys32_capget_wrapper)
-       llgtr   %r2,%r2                 # cap_user_header_t
-       llgtr   %r3,%r3                 # cap_user_data_t
-       jg      sys_capget              # branch to system call
-
-ENTRY(sys32_capset_wrapper)
-       llgtr   %r2,%r2                 # cap_user_header_t
-       llgtr   %r3,%r3                 # const cap_user_data_t
-       jg      sys_capset              # branch to system call
-
-#sys32_vfork_wrapper                   # done in vfork_glue
-
-ENTRY(sys32_truncate64_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       jg      sys32_truncate64        # branch to system call
-
-ENTRY(sys32_ftruncate64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       jg      sys32_ftruncate64       # branch to system call
-
-ENTRY(sys32_lchown_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # uid_t
-       llgfr   %r4,%r4                 # gid_t
-       jg      sys_lchown              # branch to system call
-
-#sys32_getuid_wrapper                  # void
-#sys32_getgid_wrapper                  # void
-#sys32_geteuid_wrapper                 # void
-#sys32_getegid_wrapper                 # void
-
-ENTRY(sys32_setreuid_wrapper)
-       llgfr   %r2,%r2                 # uid_t
-       llgfr   %r3,%r3                 # uid_t
-       jg      sys_setreuid            # branch to system call
-
-ENTRY(sys32_setregid_wrapper)
-       llgfr   %r2,%r2                 # gid_t
-       llgfr   %r3,%r3                 # gid_t
-       jg      sys_setregid            # branch to system call
-
-ENTRY(sys32_getgroups_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # gid_t *
-       jg      sys_getgroups           # branch to system call
-
-ENTRY(sys32_setgroups_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # gid_t *
-       jg      sys_setgroups           # branch to system call
-
-ENTRY(sys32_fchown_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # uid_t
-       llgfr   %r4,%r4                 # gid_t
-       jg      sys_fchown              # branch to system call
-
-ENTRY(sys32_setresuid_wrapper)
-       llgfr   %r2,%r2                 # uid_t
-       llgfr   %r3,%r3                 # uid_t
-       llgfr   %r4,%r4                 # uid_t
-       jg      sys_setresuid           # branch to system call
-
-ENTRY(sys32_getresuid_wrapper)
-       llgtr   %r2,%r2                 # uid_t *
-       llgtr   %r3,%r3                 # uid_t *
-       llgtr   %r4,%r4                 # uid_t *
-       jg      sys_getresuid           # branch to system call
-
-ENTRY(sys32_setresgid_wrapper)
-       llgfr   %r2,%r2                 # gid_t
-       llgfr   %r3,%r3                 # gid_t
-       llgfr   %r4,%r4                 # gid_t
-       jg      sys_setresgid           # branch to system call
-
-ENTRY(sys32_getresgid_wrapper)
-       llgtr   %r2,%r2                 # gid_t *
-       llgtr   %r3,%r3                 # gid_t *
-       llgtr   %r4,%r4                 # gid_t *
-       jg      sys_getresgid           # branch to system call
-
-ENTRY(sys32_chown_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # uid_t
-       llgfr   %r4,%r4                 # gid_t
-       jg      sys_chown               # branch to system call
-
-ENTRY(sys32_setuid_wrapper)
-       llgfr   %r2,%r2                 # uid_t
-       jg      sys_setuid              # branch to system call
-
-ENTRY(sys32_setgid_wrapper)
-       llgfr   %r2,%r2                 # gid_t
-       jg      sys_setgid              # branch to system call
-
-ENTRY(sys32_setfsuid_wrapper)
-       llgfr   %r2,%r2                 # uid_t
-       jg      sys_setfsuid            # branch to system call
-
-ENTRY(sys32_setfsgid_wrapper)
-       llgfr   %r2,%r2                 # gid_t
-       jg      sys_setfsgid            # branch to system call
-
-ENTRY(sys32_pivot_root_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # const char *
-       jg      sys_pivot_root          # branch to system call
-
-ENTRY(sys32_mincore_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t
-       llgtr   %r4,%r4                 # unsigned char *
-       jg      sys_mincore             # branch to system call
-
-ENTRY(sys32_madvise_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # size_t
-       lgfr    %r4,%r4                 # int
-       jg      sys_madvise             # branch to system call
-
-ENTRY(sys32_getdents64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # void *
-       llgfr   %r4,%r4                 # unsigned int
-       jg      sys_getdents64          # branch to system call
-
-ENTRY(compat_sys_fcntl64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       llgfr   %r4,%r4                 # unsigned long
-       jg      compat_sys_fcntl64      # branch to system call
-
-ENTRY(sys32_stat64_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct stat64 *
-       jg      sys32_stat64            # branch to system call
-
-ENTRY(sys32_lstat64_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct stat64 *
-       jg      sys32_lstat64           # branch to system call
-
-ENTRY(sys32_stime_wrapper)
-       llgtr   %r2,%r2                 # long *
-       jg      compat_sys_stime        # branch to system call
-
-ENTRY(sys32_fstat64_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgtr   %r3,%r3                 # struct stat64 *
-       jg      sys32_fstat64           # branch to system call
-
-ENTRY(sys32_setxattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # void *
-       llgfr   %r5,%r5                 # size_t
-       lgfr    %r6,%r6                 # int
-       jg      sys_setxattr
-
-ENTRY(sys32_lsetxattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # void *
-       llgfr   %r5,%r5                 # size_t
-       lgfr    %r6,%r6                 # int
-       jg      sys_lsetxattr
-
-ENTRY(sys32_fsetxattr_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # void *
-       llgfr   %r5,%r5                 # size_t
-       lgfr    %r6,%r6                 # int
-       jg      sys_fsetxattr
-
-ENTRY(sys32_getxattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # void *
-       llgfr   %r5,%r5                 # size_t
-       jg      sys_getxattr
-
-ENTRY(sys32_lgetxattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # void *
-       llgfr   %r5,%r5                 # size_t
-       jg      sys_lgetxattr
-
-ENTRY(sys32_fgetxattr_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # void *
-       llgfr   %r5,%r5                 # size_t
-       jg      sys_fgetxattr
-
-ENTRY(sys32_listxattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgfr   %r4,%r4                 # size_t
-       jg      sys_listxattr
-
-ENTRY(sys32_llistxattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       llgfr   %r4,%r4                 # size_t
-       jg      sys_llistxattr
-
-ENTRY(sys32_flistxattr_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # char *
-       llgfr   %r4,%r4                 # size_t
-       jg      sys_flistxattr
-
-ENTRY(sys32_removexattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       jg      sys_removexattr
-
-ENTRY(sys32_lremovexattr_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # char *
-       jg      sys_lremovexattr
-
-ENTRY(sys32_fremovexattr_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # char *
-       jg      sys_fremovexattr
-
-ENTRY(sys32_sched_setaffinity_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # unsigned int
-       llgtr   %r4,%r4                 # unsigned long *
-       jg      compat_sys_sched_setaffinity
-
-ENTRY(sys32_sched_getaffinity_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # unsigned int
-       llgtr   %r4,%r4                 # unsigned long *
-       jg      compat_sys_sched_getaffinity
-
-ENTRY(sys32_exit_group_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_exit_group          # branch to system call
-
-ENTRY(sys32_set_tid_address_wrapper)
-       llgtr   %r2,%r2                 # int *
-       jg      sys_set_tid_address     # branch to system call
-
-ENTRY(sys_epoll_create_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_epoll_create        # branch to system call
-
-ENTRY(sys_epoll_ctl_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       lgfr    %r4,%r4                 # int
-       llgtr   %r5,%r5                 # struct epoll_event *
-       jg      sys_epoll_ctl           # branch to system call
-
-ENTRY(sys_epoll_wait_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # struct epoll_event *
-       lgfr    %r4,%r4                 # int
-       lgfr    %r5,%r5                 # int
-       jg      sys_epoll_wait          # branch to system call
-
-ENTRY(sys32_fadvise64_wrapper)
-       lgfr    %r2,%r2                 # int
-       sllg    %r3,%r3,32              # get high word of 64bit loff_t
-       or      %r3,%r4                 # get low word of 64bit loff_t
-       llgfr   %r4,%r5                 # size_t (unsigned long)
-       lgfr    %r5,%r6                 # int
-       jg      sys32_fadvise64
-
-ENTRY(sys32_fadvise64_64_wrapper)
-       llgtr   %r2,%r2                 # struct fadvise64_64_args *
-       jg      sys32_fadvise64_64
-
-ENTRY(sys32_clock_settime_wrapper)
-       lgfr    %r2,%r2                 # clockid_t (int)
-       llgtr   %r3,%r3                 # struct compat_timespec *
-       jg      compat_sys_clock_settime
-
-ENTRY(sys32_clock_gettime_wrapper)
-       lgfr    %r2,%r2                 # clockid_t (int)
-       llgtr   %r3,%r3                 # struct compat_timespec *
-       jg      compat_sys_clock_gettime
-
-ENTRY(sys32_clock_getres_wrapper)
-       lgfr    %r2,%r2                 # clockid_t (int)
-       llgtr   %r3,%r3                 # struct compat_timespec *
-       jg      compat_sys_clock_getres
-
-ENTRY(sys32_clock_nanosleep_wrapper)
-       lgfr    %r2,%r2                 # clockid_t (int)
-       lgfr    %r3,%r3                 # int
-       llgtr   %r4,%r4                 # struct compat_timespec *
-       llgtr   %r5,%r5                 # struct compat_timespec *
-       jg      compat_sys_clock_nanosleep
-
-ENTRY(sys32_timer_create_wrapper)
-       lgfr    %r2,%r2                 # timer_t (int)
-       llgtr   %r3,%r3                 # struct compat_sigevent *
-       llgtr   %r4,%r4                 # timer_t *
-       jg      compat_sys_timer_create
-
-ENTRY(sys32_timer_settime_wrapper)
-       lgfr    %r2,%r2                 # timer_t (int)
-       lgfr    %r3,%r3                 # int
-       llgtr   %r4,%r4                 # struct compat_itimerspec *
-       llgtr   %r5,%r5                 # struct compat_itimerspec *
-       jg      compat_sys_timer_settime
-
-ENTRY(sys32_timer_gettime_wrapper)
-       lgfr    %r2,%r2                 # timer_t (int)
-       llgtr   %r3,%r3                 # struct compat_itimerspec *
-       jg      compat_sys_timer_gettime
-
-ENTRY(sys32_timer_getoverrun_wrapper)
-       lgfr    %r2,%r2                 # timer_t (int)
-       jg      sys_timer_getoverrun
-
-ENTRY(sys32_timer_delete_wrapper)
-       lgfr    %r2,%r2                 # timer_t (int)
-       jg      sys_timer_delete
-
-ENTRY(sys32_io_setup_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # u32 *
-       jg      compat_sys_io_setup
-
-ENTRY(sys32_io_destroy_wrapper)
-       llgfr   %r2,%r2                 # (aio_context_t) u32
-       jg      sys_io_destroy
-
-ENTRY(sys32_io_getevents_wrapper)
-       llgfr   %r2,%r2                 # (aio_context_t) u32
-       lgfr    %r3,%r3                 # long
-       lgfr    %r4,%r4                 # long
-       llgtr   %r5,%r5                 # struct io_event *
-       llgtr   %r6,%r6                 # struct compat_timespec *
-       jg      compat_sys_io_getevents
-
-ENTRY(sys32_io_submit_wrapper)
-       llgfr   %r2,%r2                 # (aio_context_t) u32
-       lgfr    %r3,%r3                 # long
-       llgtr   %r4,%r4                 # struct iocb **
-       jg      compat_sys_io_submit
-
-ENTRY(sys32_io_cancel_wrapper)
-       llgfr   %r2,%r2                 # (aio_context_t) u32
-       llgtr   %r3,%r3                 # struct iocb *
-       llgtr   %r4,%r4                 # struct io_event *
-       jg      sys_io_cancel
-
-ENTRY(compat_sys_statfs64_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgfr   %r3,%r3                 # compat_size_t
-       llgtr   %r4,%r4                 # struct compat_statfs64 *
-       jg      compat_sys_statfs64
-
-ENTRY(compat_sys_fstatfs64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int fd
-       llgfr   %r3,%r3                 # compat_size_t
-       llgtr   %r4,%r4                 # struct compat_statfs64 *
-       jg      compat_sys_fstatfs64
-
-ENTRY(compat_sys_mq_open_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       llgfr   %r4,%r4                 # mode_t
-       llgtr   %r5,%r5                 # struct compat_mq_attr *
-       jg      compat_sys_mq_open
-
-ENTRY(sys32_mq_unlink_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       jg      sys_mq_unlink
-
-ENTRY(compat_sys_mq_timedsend_wrapper)
-       lgfr    %r2,%r2                 # mqd_t
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # size_t
-       llgfr   %r5,%r5                 # unsigned int
-       llgtr   %r6,%r6                 # const struct compat_timespec *
-       jg      compat_sys_mq_timedsend
-
-ENTRY(compat_sys_mq_timedreceive_wrapper)
-       lgfr    %r2,%r2                 # mqd_t
-       llgtr   %r3,%r3                 # char *
-       llgfr   %r4,%r4                 # size_t
-       llgtr   %r5,%r5                 # unsigned int *
-       llgtr   %r6,%r6                 # const struct compat_timespec *
-       jg      compat_sys_mq_timedreceive
-
-ENTRY(compat_sys_mq_notify_wrapper)
-       lgfr    %r2,%r2                 # mqd_t
-       llgtr   %r3,%r3                 # struct compat_sigevent *
-       jg      compat_sys_mq_notify
-
-ENTRY(compat_sys_mq_getsetattr_wrapper)
-       lgfr    %r2,%r2                 # mqd_t
-       llgtr   %r3,%r3                 # struct compat_mq_attr *
-       llgtr   %r4,%r4                 # struct compat_mq_attr *
-       jg      compat_sys_mq_getsetattr
-
-ENTRY(compat_sys_add_key_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # const char *
-       llgtr   %r4,%r4                 # const void *
-       llgfr   %r5,%r5                 # size_t
-       llgfr   %r6,%r6                 # (key_serial_t) u32
-       jg      sys_add_key
-
-ENTRY(compat_sys_request_key_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       llgtr   %r3,%r3                 # const char *
-       llgtr   %r4,%r4                 # const void *
-       llgfr   %r5,%r5                 # (key_serial_t) u32
-       jg      sys_request_key
-
-ENTRY(sys32_remap_file_pages_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # unsigned long
-       llgfr   %r4,%r4                 # unsigned long
-       llgfr   %r5,%r5                 # unsigned long
-       llgfr   %r6,%r6                 # unsigned long
-       jg      sys_remap_file_pages
-
-ENTRY(compat_sys_kexec_load_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # unsigned long
-       llgtr   %r4,%r4                 # struct kexec_segment *
-       llgfr   %r5,%r5                 # unsigned long
-       jg      compat_sys_kexec_load
-
-ENTRY(sys_ioprio_set_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       lgfr    %r4,%r4                 # int
-       jg      sys_ioprio_set
-
-ENTRY(sys_ioprio_get_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       jg      sys_ioprio_get
-
-ENTRY(sys_inotify_add_watch_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # u32
-       jg      sys_inotify_add_watch
-
-ENTRY(sys_inotify_rm_watch_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # u32
-       jg      sys_inotify_rm_watch
-
-ENTRY(sys_mkdirat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       lgfr    %r4,%r4                 # int
-       jg      sys_mkdirat
-
-ENTRY(sys_mknodat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       lgfr    %r4,%r4                 # int
-       llgfr   %r5,%r5                 # unsigned int
-       jg      sys_mknodat
-
-ENTRY(sys_fchownat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # uid_t
-       llgfr   %r5,%r5                 # gid_t
-       lgfr    %r6,%r6                 # int
-       jg      sys_fchownat
-
-ENTRY(compat_sys_futimesat_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # struct timeval *
-       jg      compat_sys_futimesat
-
-ENTRY(sys32_fstatat64_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # struct stat64 *
-       lgfr    %r5,%r5                 # int
-       jg      sys32_fstatat64
-
-ENTRY(sys_unlinkat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       lgfr    %r4,%r4                 # int
-       jg      sys_unlinkat
-
-ENTRY(sys_renameat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       lgfr    %r4,%r4                 # int
-       llgtr   %r5,%r5                 # const char *
-       jg      sys_renameat
-
-ENTRY(sys_linkat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       lgfr    %r4,%r4                 # int
-       llgtr   %r5,%r5                 # const char *
-       lgfr    %r6,%r6                 # int
-       jg      sys_linkat
-
-ENTRY(sys_symlinkat_wrapper)
-       llgtr   %r2,%r2                 # const char *
-       lgfr    %r3,%r3                 # int
-       llgtr   %r4,%r4                 # const char *
-       jg      sys_symlinkat
-
-ENTRY(sys_readlinkat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       llgtr   %r4,%r4                 # char *
-       lgfr    %r5,%r5                 # int
-       jg      sys_readlinkat
-
-ENTRY(sys_fchmodat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       llgfr   %r4,%r4                 # mode_t
-       jg      sys_fchmodat
-
-ENTRY(sys_faccessat_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char *
-       lgfr    %r4,%r4                 # int
-       jg      sys_faccessat
-
-ENTRY(compat_sys_pselect6_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # fd_set *
-       llgtr   %r4,%r4                 # fd_set *
-       llgtr   %r5,%r5                 # fd_set *
-       llgtr   %r6,%r6                 # struct timespec *
-       llgt    %r0,164(%r15)           # void *
-       stg     %r0,160(%r15)
-       jg      compat_sys_pselect6
-
-ENTRY(compat_sys_ppoll_wrapper)
-       llgtr   %r2,%r2                 # struct pollfd *
-       llgfr   %r3,%r3                 # unsigned int
-       llgtr   %r4,%r4                 # struct timespec *
-       llgtr   %r5,%r5                 # const sigset_t *
-       llgfr   %r6,%r6                 # size_t
-       jg      compat_sys_ppoll
-
-ENTRY(sys_unshare_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       jg      sys_unshare
-
-ENTRY(sys_splice_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # loff_t *
-       lgfr    %r4,%r4                 # int
-       llgtr   %r5,%r5                 # loff_t *
-       llgfr   %r6,%r6                 # size_t
-       llgf    %r0,164(%r15)           # unsigned int
-       stg     %r0,160(%r15)
-       jg      sys_splice
-
-ENTRY(sys_sync_file_range_wrapper)
-       lgfr    %r2,%r2                 # int
-       sllg    %r3,%r3,32              # get high word of 64bit loff_t
-       or      %r3,%r4                 # get low word of 64bit loff_t
-       sllg    %r4,%r5,32              # get high word of 64bit loff_t
-       or      %r4,%r6                 # get low word of 64bit loff_t
-       llgf    %r5,164(%r15)           # unsigned int
-       jg      sys_sync_file_range
-
-ENTRY(sys_tee_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       llgfr   %r4,%r4                 # size_t
-       llgfr   %r5,%r5                 # unsigned int
-       jg      sys_tee
-
-ENTRY(sys_getcpu_wrapper)
-       llgtr   %r2,%r2                 # unsigned *
-       llgtr   %r3,%r3                 # unsigned *
-       llgtr   %r4,%r4                 # struct getcpu_cache *
-       jg      sys_getcpu
-
-ENTRY(compat_sys_utimes_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # struct compat_timeval *
-       jg      compat_sys_utimes
-
-ENTRY(compat_sys_utimensat_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgtr   %r3,%r3                 # char *
-       llgtr   %r4,%r4                 # struct compat_timespec *
-       lgfr    %r5,%r5                 # int
-       jg      compat_sys_utimensat
-
-ENTRY(sys_eventfd_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       jg      sys_eventfd
-
-ENTRY(sys_fallocate_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       sllg    %r4,%r4,32              # get high word of 64bit loff_t
-       lr      %r4,%r5                 # get low word of 64bit loff_t
-       sllg    %r5,%r6,32              # get high word of 64bit loff_t
-       l       %r5,164(%r15)           # get low word of 64bit loff_t
-       jg      sys_fallocate
-
-ENTRY(sys_timerfd_create_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       jg      sys_timerfd_create
-
-ENTRY(sys_eventfd2_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       lgfr    %r3,%r3                 # int
-       jg      sys_eventfd2
-
-ENTRY(sys_inotify_init1_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_inotify_init1
-
-ENTRY(sys_pipe2_wrapper)
-       llgtr   %r2,%r2                 # u32 *
-       lgfr    %r3,%r3                 # int
-       jg      sys_pipe2               # branch to system call
-
-ENTRY(sys_dup3_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       lgfr    %r4,%r4                 # int
-       jg      sys_dup3                # branch to system call
-
-ENTRY(sys_epoll_create1_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_epoll_create1       # branch to system call
-
-ENTRY(sys32_readahead_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgfr   %r3,%r3                 # u32
-       llgfr   %r4,%r4                 # u32
-       lgfr    %r5,%r5                 # s32
-       jg      sys32_readahead         # branch to system call
-
-ENTRY(sys_tkill_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       lgfr    %r3,%r3                 # int
-       jg      sys_tkill               # branch to system call
-
-ENTRY(sys_tgkill_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       lgfr    %r3,%r3                 # pid_t
-       lgfr    %r4,%r4                 # int
-       jg      sys_tgkill              # branch to system call
-
-ENTRY(compat_sys_keyctl_wrapper)
-       llgfr   %r2,%r2                 # u32
-       llgfr   %r3,%r3                 # u32
-       llgfr   %r4,%r4                 # u32
-       llgfr   %r5,%r5                 # u32
-       llgfr   %r6,%r6                 # u32
-       jg      compat_sys_keyctl       # branch to system call
-
-ENTRY(sys_perf_event_open_wrapper)
-       llgtr   %r2,%r2                 # const struct perf_event_attr *
-       lgfr    %r3,%r3                 # pid_t
-       lgfr    %r4,%r4                 # int
-       lgfr    %r5,%r5                 # int
-       llgfr   %r6,%r6                 # unsigned long
-       jg      sys_perf_event_open     # branch to system call
-
-ENTRY(sys_clone_wrapper)
-       llgfr   %r2,%r2                 # unsigned long
-       llgfr   %r3,%r3                 # unsigned long
-       llgtr   %r4,%r4                 # int *
-       llgtr   %r5,%r5                 # int *
-       jg      sys_clone               # branch to system call
-
-ENTRY(sys32_execve_wrapper)
-       llgtr   %r2,%r2                 # char *
-       llgtr   %r3,%r3                 # compat_uptr_t *
-       llgtr   %r4,%r4                 # compat_uptr_t *
-       jg      compat_sys_execve       # branch to system call
-
-ENTRY(sys_fanotify_init_wrapper)
-       llgfr   %r2,%r2                 # unsigned int
-       llgfr   %r3,%r3                 # unsigned int
-       jg      sys_fanotify_init       # branch to system call
-
-ENTRY(sys_prlimit64_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       llgfr   %r3,%r3                 # unsigned int
-       llgtr   %r4,%r4                 # const struct rlimit64 __user *
-       llgtr   %r5,%r5                 # struct rlimit64 __user *
-       jg      sys_prlimit64           # branch to system call
-
-ENTRY(sys_name_to_handle_at_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char __user *
-       llgtr   %r4,%r4                 # struct file_handle __user *
-       llgtr   %r5,%r5                 # int __user *
-       lgfr    %r6,%r6                 # int
-       jg      sys_name_to_handle_at
-
-ENTRY(compat_sys_clock_adjtime_wrapper)
-       lgfr    %r2,%r2                 # clockid_t (int)
-       llgtr   %r3,%r3                 # struct compat_timex __user *
-       jg      compat_sys_clock_adjtime
-
-ENTRY(sys_syncfs_wrapper)
-       lgfr    %r2,%r2                 # int
-       jg      sys_syncfs
-
-ENTRY(sys_setns_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       jg      sys_setns
-
-ENTRY(compat_sys_process_vm_readv_wrapper)
-       lgfr    %r2,%r2                 # compat_pid_t
-       llgtr   %r3,%r3                 # struct compat_iovec __user *
-       llgfr   %r4,%r4                 # unsigned long
-       llgtr   %r5,%r5                 # struct compat_iovec __user *
-       llgfr   %r6,%r6                 # unsigned long
-       llgf    %r0,164(%r15)           # unsigned long
-       stg     %r0,160(%r15)
-       jg      compat_sys_process_vm_readv
-
-ENTRY(compat_sys_process_vm_writev_wrapper)
-       lgfr    %r2,%r2                 # compat_pid_t
-       llgtr   %r3,%r3                 # struct compat_iovec __user *
-       llgfr   %r4,%r4                 # unsigned long
-       llgtr   %r5,%r5                 # struct compat_iovec __user *
-       llgfr   %r6,%r6                 # unsigned long
-       llgf    %r0,164(%r15)           # unsigned long
-       stg     %r0,160(%r15)
-       jg      compat_sys_process_vm_writev
-
-ENTRY(sys_s390_runtime_instr_wrapper)
-       lgfr    %r2,%r2                 # int
-       lgfr    %r3,%r3                 # int
-       jg      sys_s390_runtime_instr
-
-ENTRY(sys_kcmp_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       lgfr    %r3,%r3                 # pid_t
-       lgfr    %r4,%r4                 # int
-       llgfr   %r5,%r5                 # unsigned long
-       llgfr   %r6,%r6                 # unsigned long
-       jg      sys_kcmp
-
-ENTRY(sys_finit_module_wrapper)
-       lgfr    %r2,%r2                 # int
-       llgtr   %r3,%r3                 # const char __user *
-       lgfr    %r4,%r4                 # int
-       jg      sys_finit_module
-
-ENTRY(sys_sched_setattr_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       llgtr   %r3,%r3                 # struct sched_attr __user *
-       jg      sys_sched_setattr
-
-ENTRY(sys_sched_getattr_wrapper)
-       lgfr    %r2,%r2                 # pid_t
-       llgtr   %r3,%r3                 # const char __user *
-       llgfr   %r3,%r3                 # unsigned int
-       jg      sys_sched_getattr
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
new file mode 100644 (file)
index 0000000..824c39d
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ *  Compat sytem call wrappers.
+ *
+ *    Copyright IBM Corp. 2014
+ */
+
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include "entry.h"
+
+#define COMPAT_SYSCALL_WRAP1(name, ...) \
+       COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP2(name, ...) \
+       COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP3(name, ...) \
+       COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP4(name, ...) \
+       COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP5(name, ...) \
+       COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP6(name, ...) \
+       COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
+
+#define __SC_COMPAT_TYPE(t, a) \
+       __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+
+#define __SC_COMPAT_CAST(t, a)                                         \
+({                                                                     \
+       long __ReS = a;                                                 \
+                                                                       \
+       BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&              \
+                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));            \
+       if (__TYPE_IS_L(t))                                             \
+               __ReS = (s32)a;                                         \
+       if (__TYPE_IS_UL(t))                                            \
+               __ReS = (u32)a;                                         \
+       if (__TYPE_IS_PTR(t))                                           \
+               __ReS = a & 0x7fffffff;                                 \
+       (t)__ReS;                                                       \
+})
+
+/*
+ * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
+ * compat tasks. These wrappers will only be used for system calls where only
+ * the system call arguments need sign or zero extension or zeroing of the upper
+ * 33 bits of pointers.
+ * Note: since the wrapper function will afterwards call a system call which
+ * again performs zero and sign extension for all system call arguments with
+ * a size of less than eight bytes, these compat wrappers only touch those
+ * system call arguments with a size of eight bytes ((unsigned) long and
+ * pointers). Zero and sign extension for e.g. int parameters will be done by
+ * the regular system call wrappers.
+ */
+#define COMPAT_SYSCALL_WRAPx(x, name, ...)                                     \
+       asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));              \
+       asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
+       asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
+       {                                                                       \
+               return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));        \
+       }
+
+COMPAT_SYSCALL_WRAP1(exit, int, error_code);
+COMPAT_SYSCALL_WRAP1(close, unsigned int, fd);
+COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
+COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
+COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
+COMPAT_SYSCALL_WRAP1(alarm, unsigned int, seconds);
+COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
+COMPAT_SYSCALL_WRAP1(nice, int, increment);
+COMPAT_SYSCALL_WRAP2(kill, int, pid, int, sig);
+COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(dup, unsigned int, fildes);
+COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
+COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
+COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
+COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
+COMPAT_SYSCALL_WRAP2(setpgid, pid_t, pid, pid_t, pgid);
+COMPAT_SYSCALL_WRAP1(umask, int, mask);
+COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
+COMPAT_SYSCALL_WRAP2(dup2, unsigned int, oldfd, unsigned int, newfd);
+COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
+COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
+COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
+COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz);
+COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
+COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
+COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
+COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
+COMPAT_SYSCALL_WRAP2(fchmod, unsigned int, fd, umode_t, mode);
+COMPAT_SYSCALL_WRAP2(getpriority, int, which, int, who);
+COMPAT_SYSCALL_WRAP3(setpriority, int, which, int, who, int, niceval);
+COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
+COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
+COMPAT_SYSCALL_WRAP1(fsync, unsigned int, fd);
+COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
+COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
+COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
+COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
+COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
+COMPAT_SYSCALL_WRAP1(getpgid, pid_t, pid);
+COMPAT_SYSCALL_WRAP1(fchdir, unsigned int, fd);
+COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
+COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
+COMPAT_SYSCALL_WRAP1(s390_personality, unsigned int, personality);
+COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
+COMPAT_SYSCALL_WRAP2(flock, unsigned int, fd, unsigned int, cmd);
+COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
+COMPAT_SYSCALL_WRAP1(getsid, pid_t, pid);
+COMPAT_SYSCALL_WRAP1(fdatasync, unsigned int, fd);
+COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
+COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
+COMPAT_SYSCALL_WRAP1(mlockall, int, flags);
+COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP1(sched_getscheduler, pid_t, pid);
+COMPAT_SYSCALL_WRAP1(sched_get_priority_max, int, policy);
+COMPAT_SYSCALL_WRAP1(sched_get_priority_min, int, policy);
+COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
+COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
+COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
+COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
+COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
+COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
+COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP2(setreuid, uid_t, ruid, uid_t, euid);
+COMPAT_SYSCALL_WRAP2(setregid, gid_t, rgid, gid_t, egid);
+COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
+COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
+COMPAT_SYSCALL_WRAP3(fchown, unsigned int, fd, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid);
+COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
+COMPAT_SYSCALL_WRAP3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid);
+COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
+COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP1(setuid, uid_t, uid);
+COMPAT_SYSCALL_WRAP1(setgid, gid_t, gid);
+COMPAT_SYSCALL_WRAP1(setfsuid, uid_t, uid);
+COMPAT_SYSCALL_WRAP1(setfsgid, gid_t, gid);
+COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
+COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
+COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
+COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count);
+COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
+COMPAT_SYSCALL_WRAP1(exit_group, int, error_code);
+COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
+COMPAT_SYSCALL_WRAP1(epoll_create, int, size);
+COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
+COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
+COMPAT_SYSCALL_WRAP1(timer_getoverrun, timer_t, timer_id);
+COMPAT_SYSCALL_WRAP1(timer_delete, compat_timer_t, compat_timer_id);
+COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
+COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
+COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
+COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
+COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
+COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
+COMPAT_SYSCALL_WRAP3(ioprio_set, int, which, int, who, int, ioprio);
+COMPAT_SYSCALL_WRAP2(ioprio_get, int, which, int, who);
+COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
+COMPAT_SYSCALL_WRAP2(inotify_rm_watch, int, fd, __s32, wd);
+COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
+COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag);
+COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname);
+COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags);
+COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname);
+COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz);
+COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode);
+COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode);
+COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
+COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
+COMPAT_SYSCALL_WRAP1(eventfd, unsigned int, count);
+COMPAT_SYSCALL_WRAP2(timerfd_create, int, clockid, int, flags);
+COMPAT_SYSCALL_WRAP2(eventfd2, unsigned int, count, int, flags);
+COMPAT_SYSCALL_WRAP1(inotify_init1, int, flags);
+COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
+COMPAT_SYSCALL_WRAP3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags);
+COMPAT_SYSCALL_WRAP1(epoll_create1, int, flags);
+COMPAT_SYSCALL_WRAP2(tkill, int, pid, int, sig);
+COMPAT_SYSCALL_WRAP3(tgkill, int, tgid, int, pid, int, sig);
+COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
+COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, int, tls_val);
+COMPAT_SYSCALL_WRAP2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags);
+COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
+COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
+COMPAT_SYSCALL_WRAP1(syncfs, int, fd);
+COMPAT_SYSCALL_WRAP2(setns, int, fd, int, nstype);
+COMPAT_SYSCALL_WRAP2(s390_runtime_instr, int, command, int, signum);
+COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
+COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
+COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
index fca20b5fe79e085e4795861edf7f4bb5736c67cb..6b594439cca5a68fa3fd8ece0484cc0f8b9d11bd 100644 (file)
@@ -380,8 +380,6 @@ static __init void detect_machine_facilities(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2;
        if (test_facility(3))
                S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
-       if (test_facility(27))
-               S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
        if (test_facility(40))
                S390_lowcore.machine_flags |= MACHINE_FLAG_LPP;
        if (test_facility(50) && test_facility(73))
index 0dc2b6d0a1ec8557f7450d5fbd255d2758bf8512..526d3735ed29050d317ef1327039397a4594d71f 100644 (file)
@@ -43,6 +43,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
                 _TIF_SYSCALL_TRACEPOINT)
+_TIF_TRANSFER = (_TIF_MCCK_PENDING | _TIF_TLB_WAIT)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -159,10 +160,12 @@ ENTRY(__switch_to)
        lctl    %c4,%c4,__TASK_pid(%r3)         # load pid to control reg. 4
        mvc     __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
        l       %r15,__THREAD_ksp(%r3)          # load kernel stack of next
-       tm      __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
+       lhi     %r6,_TIF_TRANSFER               # transfer TIF bits
+       n       %r6,__TI_flags(%r4)             # isolate TIF bits
        jz      0f
-       ni      __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
-       oi      __TI_flags+3(%r5),_TIF_MCCK_PENDING     # set it in next
+       o       %r6,__TI_flags(%r5)             # set TIF bits of next
+       st      %r6,__TI_flags(%r5)
+       ni      __TI_flags+3(%r4),255-_TIF_TRANSFER # clear TIF bits of prev
 0:     lm      %r6,%r15,__SF_GPRS(%r15)        # load gprs of next task
        br      %r14
 
index cb533f78c09ed5795ee365eec00374c5db662a9c..6ac78192455f386aa72a15bdd2b73c55f844a5b5 100644 (file)
@@ -67,9 +67,7 @@ struct s390_mmap_arg_struct;
 struct fadvise64_64_args;
 struct old_sigaction;
 
-long sys_sigreturn(void);
-long sys_rt_sigreturn(void);
-long sys32_sigreturn(void);
-long sys32_rt_sigreturn(void);
+long sys_s390_personality(unsigned int personality);
+long sys_s390_runtime_instr(int command, int signum);
 
 #endif /* _ENTRY_H */
index 384e609b47110dc59c7a96cfa419e864cca86b2a..e09dbe5f29015a9fc794cddb2f7ff57053594cdc 100644 (file)
@@ -48,6 +48,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
                 _TIF_SYSCALL_TRACEPOINT)
+_TIF_TRANSFER = (_TIF_MCCK_PENDING | _TIF_TLB_WAIT)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -189,10 +190,12 @@ ENTRY(__switch_to)
        lctl    %c4,%c4,__TASK_pid(%r3)         # load pid to control reg. 4
        mvc     __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next
        lg      %r15,__THREAD_ksp(%r3)          # load kernel stack of next
-       tm      __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
+       llill   %r6,_TIF_TRANSFER               # transfer TIF bits
+       ng      %r6,__TI_flags(%r4)             # isolate TIF bits
        jz      0f
-       ni      __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
-       oi      __TI_flags+7(%r5),_TIF_MCCK_PENDING     # set it in next
+       og      %r6,__TI_flags(%r5)             # set TIF bits of next
+       stg     %r6,__TI_flags(%r5)
+       ni      __TI_flags+7(%r4),255-_TIF_TRANSFER # clear TIF bits of prev
 0:     lmg     %r6,%r15,__SF_GPRS(%r15)        # load gprs of next task
        br      %r14
 
index b9e25ae2579c9f04c3d4bb422cab012c943dda58..d7c00507568a73e8f5acb45014f366154f839980 100644 (file)
@@ -59,7 +59,7 @@ ENTRY(startup_continue)
        .quad   0                       # cr12: tracing off
        .quad   0                       # cr13: home space segment table
        .quad   0xc0000000              # cr14: machine check handling off
-       .quad   0                       # cr15: linkage stack operations
+       .quad   .Llinkage_stack         # cr15: linkage stack operations
 .Lpcmsk:.quad  0x0000000180000000
 .L4malign:.quad 0xffffffffffc00000
 .Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
@@ -67,12 +67,15 @@ ENTRY(startup_continue)
 .Lparmaddr:
        .quad   PARMAREA
        .align  64
-.Lduct: .long  0,0,0,0,.Lduald,0,0,0
+.Lduct: .long  0,.Laste,.Laste,0,.Lduald,0,0,0
        .long   0,0,0,0,0,0,0,0
+.Laste:        .quad   0,0xffffffffffffffff,0,0,0,0,0,0
        .align  128
 .Lduald:.rept  8
        .long   0x80000000,0,0,0        # invalid access-list entries
        .endr
+.Llinkage_stack:
+       .long   0,0,0x89000000,0,0,0,0x8a000000,0
 
 ENTRY(_ehead)
 
index 5d2dfa31c4efad44028d41b60b6d43631ecaedc6..61595c1f0a0fe7d502bb6c213519929effe48b02 100644 (file)
@@ -121,7 +121,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
                               : PERF_RECORD_MISC_KERNEL;
 }
 
-void print_debug_cf(void)
+static void print_debug_cf(void)
 {
        struct cpumf_ctr_info cf_info;
        int cpu = smp_processor_id();
index f6be6087a0e98edb3d2917228cb65b4657b61d11..4ac8fafec95fa87d0b680c6222ac3c9e9f06700a 100644 (file)
@@ -85,7 +85,10 @@ void update_cr_regs(struct task_struct *task)
 
        /* merge TIF_SINGLE_STEP into user specified PER registers. */
        if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
-               new.control |= PER_EVENT_IFETCH;
+               if (test_tsk_thread_flag(task, TIF_BLOCK_STEP))
+                       new.control |= PER_EVENT_BRANCH;
+               else
+                       new.control |= PER_EVENT_IFETCH;
 #ifdef CONFIG_64BIT
                new.control |= PER_CONTROL_SUSPENSION;
                new.control |= PER_EVENT_TRANSACTION_END;
@@ -107,14 +110,22 @@ void update_cr_regs(struct task_struct *task)
 
 void user_enable_single_step(struct task_struct *task)
 {
+       clear_tsk_thread_flag(task, TIF_BLOCK_STEP);
        set_tsk_thread_flag(task, TIF_SINGLE_STEP);
 }
 
 void user_disable_single_step(struct task_struct *task)
 {
+       clear_tsk_thread_flag(task, TIF_BLOCK_STEP);
        clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
 }
 
+void user_enable_block_step(struct task_struct *task)
+{
+       set_tsk_thread_flag(task, TIF_SINGLE_STEP);
+       set_tsk_thread_flag(task, TIF_BLOCK_STEP);
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
index 09e2f468f48bc874e61c3d12b9d751b04c5f0126..f70f2489fa5fe241fd107596d2879d0fe331f7bc 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/compat.h>
 
 #include <asm/ipl.h>
-#include <asm/uaccess.h>
 #include <asm/facility.h>
 #include <asm/smp.h>
 #include <asm/mmu_context.h>
 #include <asm/sclp.h>
 #include "entry.h"
 
-/*
- * User copy operations.
- */
-struct uaccess_ops uaccess;
-EXPORT_SYMBOL(uaccess);
-
 /*
  * Machine setup..
  */
@@ -294,14 +287,6 @@ static int __init parse_vmalloc(char *arg)
 }
 early_param("vmalloc", parse_vmalloc);
 
-static int __init early_parse_user_mode(char *p)
-{
-       if (!p || strcmp(p, "primary") == 0)
-               return 0;
-       return 1;
-}
-early_param("user_mode", early_parse_user_mode);
-
 void *restart_stack __attribute__((__section__(".data")));
 
 static void __init setup_lowcore(void)
@@ -1009,8 +994,6 @@ void __init setup_arch(char **cmdline_p)
        init_mm.end_data = (unsigned long) &_edata;
        init_mm.brk = (unsigned long) &_end;
 
-       uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos : uaccess_pt;
-
        parse_early_param();
        detect_memory_layout(memory_chunk, memory_end);
        os_info_init();
index a7125b62a9a6c1f77289a0d834358fea1971cb87..8827883310ddbc05c765f17b2125e804dc2cd85e 100644 (file)
@@ -773,11 +773,11 @@ void __noreturn cpu_die(void)
 
 void __init smp_fill_possible_mask(void)
 {
-       unsigned int possible, cpu;
+       unsigned int possible, sclp, cpu;
 
-       possible = setup_possible_cpus;
-       if (!possible)
-               possible = MACHINE_IS_VM ? 64 : nr_cpu_ids;
+       sclp = sclp_get_max_cpu() ?: nr_cpu_ids;
+       possible = setup_possible_cpus ?: nr_cpu_ids;
+       possible = min(possible, sclp);
        for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++)
                set_cpu_possible(cpu, true);
 }
index 143992152ec95d7c2b96c1978d1bae78da480efb..542ef488bac176fb0b3a1efed9e34e2e2af0c730 100644 (file)
 #define NI_SYSCALL SYSCALL(sys_ni_syscall,sys_ni_syscall,sys_ni_syscall)
 
 NI_SYSCALL                                                     /* 0 */
-SYSCALL(sys_exit,sys_exit,sys32_exit_wrapper)
+SYSCALL(sys_exit,sys_exit,compat_sys_exit)
 SYSCALL(sys_fork,sys_fork,sys_fork)
-SYSCALL(sys_read,sys_read,sys32_read_wrapper)
-SYSCALL(sys_write,sys_write,sys32_write_wrapper)
+SYSCALL(sys_read,sys_read,compat_sys_s390_read)
+SYSCALL(sys_write,sys_write,compat_sys_s390_write)
 SYSCALL(sys_open,sys_open,compat_sys_open)                     /* 5 */
-SYSCALL(sys_close,sys_close,sys32_close_wrapper)
+SYSCALL(sys_close,sys_close,compat_sys_close)
 SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall)
-SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper)
-SYSCALL(sys_link,sys_link,sys32_link_wrapper)
-SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper)            /* 10 */
-SYSCALL(sys_execve,sys_execve,sys32_execve_wrapper)
-SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper)
-SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper)            /* old time syscall */
-SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper)
-SYSCALL(sys_chmod,sys_chmod,sys32_chmod_wrapper)               /* 15 */
-SYSCALL(sys_lchown16,sys_ni_syscall,sys32_lchown16_wrapper)    /* old lchown16 syscall*/
+SYSCALL(sys_creat,sys_creat,compat_sys_creat)
+SYSCALL(sys_link,sys_link,compat_sys_link)
+SYSCALL(sys_unlink,sys_unlink,compat_sys_unlink)               /* 10 */
+SYSCALL(sys_execve,sys_execve,compat_sys_execve)
+SYSCALL(sys_chdir,sys_chdir,compat_sys_chdir)
+SYSCALL(sys_time,sys_ni_syscall,compat_sys_time)               /* old time syscall */
+SYSCALL(sys_mknod,sys_mknod,compat_sys_mknod)
+SYSCALL(sys_chmod,sys_chmod,compat_sys_chmod)                  /* 15 */
+SYSCALL(sys_lchown16,sys_ni_syscall,compat_sys_s390_lchown16)  /* old lchown16 syscall*/
 NI_SYSCALL                                                     /* old break syscall holder */
 NI_SYSCALL                                                     /* old stat syscall holder */
 SYSCALL(sys_lseek,sys_lseek,compat_sys_lseek)
 SYSCALL(sys_getpid,sys_getpid,sys_getpid)                      /* 20 */
-SYSCALL(sys_mount,sys_mount,sys32_mount_wrapper)
-SYSCALL(sys_oldumount,sys_oldumount,sys32_oldumount_wrapper)
-SYSCALL(sys_setuid16,sys_ni_syscall,sys32_setuid16_wrapper)    /* old setuid16 syscall*/
-SYSCALL(sys_getuid16,sys_ni_syscall,sys32_getuid16)            /* old getuid16 syscall*/
-SYSCALL(sys_stime,sys_ni_syscall,sys32_stime_wrapper)          /* 25 old stime syscall */
-SYSCALL(sys_ptrace,sys_ptrace,sys32_ptrace_wrapper)
-SYSCALL(sys_alarm,sys_alarm,sys32_alarm_wrapper)
+SYSCALL(sys_mount,sys_mount,compat_sys_mount)
+SYSCALL(sys_oldumount,sys_oldumount,compat_sys_oldumount)
+SYSCALL(sys_setuid16,sys_ni_syscall,compat_sys_s390_setuid16)  /* old setuid16 syscall*/
+SYSCALL(sys_getuid16,sys_ni_syscall,compat_sys_s390_getuid16)  /* old getuid16 syscall*/
+SYSCALL(sys_stime,sys_ni_syscall,compat_sys_stime)             /* 25 old stime syscall */
+SYSCALL(sys_ptrace,sys_ptrace,compat_sys_ptrace)
+SYSCALL(sys_alarm,sys_alarm,compat_sys_alarm)
 NI_SYSCALL                                                     /* old fstat syscall */
 SYSCALL(sys_pause,sys_pause,sys_pause)
-SYSCALL(sys_utime,sys_utime,compat_sys_utime_wrapper)          /* 30 */
+SYSCALL(sys_utime,sys_utime,compat_sys_utime)          /* 30 */
 NI_SYSCALL                                                     /* old stty syscall */
 NI_SYSCALL                                                     /* old gtty syscall */
-SYSCALL(sys_access,sys_access,sys32_access_wrapper)
-SYSCALL(sys_nice,sys_nice,sys32_nice_wrapper)
+SYSCALL(sys_access,sys_access,compat_sys_access)
+SYSCALL(sys_nice,sys_nice,compat_sys_nice)
 NI_SYSCALL                                                     /* 35 old ftime syscall */
 SYSCALL(sys_sync,sys_sync,sys_sync)
-SYSCALL(sys_kill,sys_kill,sys32_kill_wrapper)
-SYSCALL(sys_rename,sys_rename,sys32_rename_wrapper)
-SYSCALL(sys_mkdir,sys_mkdir,sys32_mkdir_wrapper)
-SYSCALL(sys_rmdir,sys_rmdir,sys32_rmdir_wrapper)               /* 40 */
-SYSCALL(sys_dup,sys_dup,sys32_dup_wrapper)
-SYSCALL(sys_pipe,sys_pipe,sys32_pipe_wrapper)
-SYSCALL(sys_times,sys_times,compat_sys_times_wrapper)
+SYSCALL(sys_kill,sys_kill,compat_sys_kill)
+SYSCALL(sys_rename,sys_rename,compat_sys_rename)
+SYSCALL(sys_mkdir,sys_mkdir,compat_sys_mkdir)
+SYSCALL(sys_rmdir,sys_rmdir,compat_sys_rmdir)          /* 40 */
+SYSCALL(sys_dup,sys_dup,compat_sys_dup)
+SYSCALL(sys_pipe,sys_pipe,compat_sys_pipe)
+SYSCALL(sys_times,sys_times,compat_sys_times)
 NI_SYSCALL                                                     /* old prof syscall */
-SYSCALL(sys_brk,sys_brk,sys32_brk_wrapper)                     /* 45 */
-SYSCALL(sys_setgid16,sys_ni_syscall,sys32_setgid16_wrapper)    /* old setgid16 syscall*/
-SYSCALL(sys_getgid16,sys_ni_syscall,sys32_getgid16)            /* old getgid16 syscall*/
-SYSCALL(sys_signal,sys_signal,sys32_signal_wrapper)
-SYSCALL(sys_geteuid16,sys_ni_syscall,sys32_geteuid16)          /* old geteuid16 syscall */
-SYSCALL(sys_getegid16,sys_ni_syscall,sys32_getegid16)          /* 50 old getegid16 syscall */
-SYSCALL(sys_acct,sys_acct,sys32_acct_wrapper)
-SYSCALL(sys_umount,sys_umount,sys32_umount_wrapper)
+SYSCALL(sys_brk,sys_brk,compat_sys_brk)                                /* 45 */
+SYSCALL(sys_setgid16,sys_ni_syscall,compat_sys_s390_setgid16)  /* old setgid16 syscall*/
+SYSCALL(sys_getgid16,sys_ni_syscall,compat_sys_s390_getgid16)  /* old getgid16 syscall*/
+SYSCALL(sys_signal,sys_signal,compat_sys_signal)
+SYSCALL(sys_geteuid16,sys_ni_syscall,compat_sys_s390_geteuid16)        /* old geteuid16 syscall */
+SYSCALL(sys_getegid16,sys_ni_syscall,compat_sys_s390_getegid16)        /* 50 old getegid16 syscall */
+SYSCALL(sys_acct,sys_acct,compat_sys_acct)
+SYSCALL(sys_umount,sys_umount,compat_sys_umount)
 NI_SYSCALL                                                     /* old lock syscall */
-SYSCALL(sys_ioctl,sys_ioctl,compat_sys_ioctl_wrapper)
-SYSCALL(sys_fcntl,sys_fcntl,compat_sys_fcntl_wrapper)          /* 55 */
+SYSCALL(sys_ioctl,sys_ioctl,compat_sys_ioctl)
+SYSCALL(sys_fcntl,sys_fcntl,compat_sys_fcntl)          /* 55 */
 NI_SYSCALL                                                     /* intel mpx syscall */
-SYSCALL(sys_setpgid,sys_setpgid,sys32_setpgid_wrapper)
+SYSCALL(sys_setpgid,sys_setpgid,compat_sys_setpgid)
 NI_SYSCALL                                                     /* old ulimit syscall */
 NI_SYSCALL                                                     /* old uname syscall */
-SYSCALL(sys_umask,sys_umask,sys32_umask_wrapper)               /* 60 */
-SYSCALL(sys_chroot,sys_chroot,sys32_chroot_wrapper)
-SYSCALL(sys_ustat,sys_ustat,sys32_ustat_wrapper)
-SYSCALL(sys_dup2,sys_dup2,sys32_dup2_wrapper)
+SYSCALL(sys_umask,sys_umask,compat_sys_umask)                  /* 60 */
+SYSCALL(sys_chroot,sys_chroot,compat_sys_chroot)
+SYSCALL(sys_ustat,sys_ustat,compat_sys_ustat)
+SYSCALL(sys_dup2,sys_dup2,compat_sys_dup2)
 SYSCALL(sys_getppid,sys_getppid,sys_getppid)
 SYSCALL(sys_getpgrp,sys_getpgrp,sys_getpgrp)                   /* 65 */
 SYSCALL(sys_setsid,sys_setsid,sys_setsid)
 SYSCALL(sys_sigaction,sys_sigaction,compat_sys_sigaction)
 NI_SYSCALL                                                     /* old sgetmask syscall*/
 NI_SYSCALL                                                     /* old ssetmask syscall*/
-SYSCALL(sys_setreuid16,sys_ni_syscall,sys32_setreuid16_wrapper)        /* old setreuid16 syscall */
-SYSCALL(sys_setregid16,sys_ni_syscall,sys32_setregid16_wrapper)        /* old setregid16 syscall */
-SYSCALL(sys_sigsuspend,sys_sigsuspend,sys_sigsuspend_wrapper)
-SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper)
-SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
-SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)      /* 75 */
-SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
+SYSCALL(sys_setreuid16,sys_ni_syscall,compat_sys_s390_setreuid16) /* old setreuid16 syscall */
+SYSCALL(sys_setregid16,sys_ni_syscall,compat_sys_s390_setregid16) /* old setregid16 syscall */
+SYSCALL(sys_sigsuspend,sys_sigsuspend,compat_sys_sigsuspend)
+SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending)
+SYSCALL(sys_sethostname,sys_sethostname,compat_sys_sethostname)
+SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit)      /* 75 */
+SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit)
 SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage)
-SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
-SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
-SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper)      /* 80 old getgroups16 syscall */
-SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper)      /* old setgroups16 syscall */
+SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday)
+SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday)
+SYSCALL(sys_getgroups16,sys_ni_syscall,compat_sys_s390_getgroups16)    /* 80 old getgroups16 syscall */
+SYSCALL(sys_setgroups16,sys_ni_syscall,compat_sys_s390_setgroups16)    /* old setgroups16 syscall */
 NI_SYSCALL                                                     /* old select syscall */
-SYSCALL(sys_symlink,sys_symlink,sys32_symlink_wrapper)
+SYSCALL(sys_symlink,sys_symlink,compat_sys_symlink)
 NI_SYSCALL                                                     /* old lstat syscall */
-SYSCALL(sys_readlink,sys_readlink,sys32_readlink_wrapper)      /* 85 */
-SYSCALL(sys_uselib,sys_uselib,sys32_uselib_wrapper)
-SYSCALL(sys_swapon,sys_swapon,sys32_swapon_wrapper)
-SYSCALL(sys_reboot,sys_reboot,sys32_reboot_wrapper)
-SYSCALL(sys_ni_syscall,sys_ni_syscall,old32_readdir_wrapper)   /* old readdir syscall */
-SYSCALL(sys_old_mmap,sys_old_mmap,old32_mmap_wrapper)          /* 90 */
-SYSCALL(sys_munmap,sys_munmap,sys32_munmap_wrapper)
+SYSCALL(sys_readlink,sys_readlink,compat_sys_readlink)         /* 85 */
+SYSCALL(sys_uselib,sys_uselib,compat_sys_uselib)
+SYSCALL(sys_swapon,sys_swapon,compat_sys_swapon)
+SYSCALL(sys_reboot,sys_reboot,compat_sys_reboot)
+SYSCALL(sys_ni_syscall,sys_ni_syscall,compat_sys_old_readdir)  /* old readdir syscall */
+SYSCALL(sys_old_mmap,sys_old_mmap,compat_sys_s390_old_mmap)    /* 90 */
+SYSCALL(sys_munmap,sys_munmap,compat_sys_munmap)
 SYSCALL(sys_truncate,sys_truncate,compat_sys_truncate)
 SYSCALL(sys_ftruncate,sys_ftruncate,compat_sys_ftruncate)
-SYSCALL(sys_fchmod,sys_fchmod,sys32_fchmod_wrapper)
-SYSCALL(sys_fchown16,sys_ni_syscall,sys32_fchown16_wrapper)    /* 95 old fchown16 syscall*/
-SYSCALL(sys_getpriority,sys_getpriority,sys32_getpriority_wrapper)
-SYSCALL(sys_setpriority,sys_setpriority,sys32_setpriority_wrapper)
+SYSCALL(sys_fchmod,sys_fchmod,compat_sys_fchmod)
+SYSCALL(sys_fchown16,sys_ni_syscall,compat_sys_s390_fchown16)  /* 95 old fchown16 syscall*/
+SYSCALL(sys_getpriority,sys_getpriority,compat_sys_getpriority)
+SYSCALL(sys_setpriority,sys_setpriority,compat_sys_setpriority)
 NI_SYSCALL                                                     /* old profil syscall */
-SYSCALL(sys_statfs,sys_statfs,compat_sys_statfs_wrapper)
-SYSCALL(sys_fstatfs,sys_fstatfs,compat_sys_fstatfs_wrapper)    /* 100 */
+SYSCALL(sys_statfs,sys_statfs,compat_sys_statfs)
+SYSCALL(sys_fstatfs,sys_fstatfs,compat_sys_fstatfs)    /* 100 */
 NI_SYSCALL                                                     /* ioperm for i386 */
-SYSCALL(sys_socketcall,sys_socketcall,compat_sys_socketcall_wrapper)
-SYSCALL(sys_syslog,sys_syslog,sys32_syslog_wrapper)
+SYSCALL(sys_socketcall,sys_socketcall,compat_sys_socketcall)
+SYSCALL(sys_syslog,sys_syslog,compat_sys_syslog)
 SYSCALL(sys_setitimer,sys_setitimer,compat_sys_setitimer)
 SYSCALL(sys_getitimer,sys_getitimer,compat_sys_getitimer)      /* 105 */
-SYSCALL(sys_newstat,sys_newstat,compat_sys_newstat_wrapper)
-SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat_wrapper)
-SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat_wrapper)
+SYSCALL(sys_newstat,sys_newstat,compat_sys_newstat)
+SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat)
+SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat)
 NI_SYSCALL                                                     /* old uname syscall */
 SYSCALL(sys_lookup_dcookie,sys_lookup_dcookie,compat_sys_lookup_dcookie)       /* 110 */
 SYSCALL(sys_vhangup,sys_vhangup,sys_vhangup)
 NI_SYSCALL                                                     /* old "idle" system call */
 NI_SYSCALL                                                     /* vm86old for i386 */
 SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4)
-SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper)         /* 115 */
-SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper)
+SYSCALL(sys_swapoff,sys_swapoff,compat_sys_swapoff)            /* 115 */
+SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo)
 SYSCALL(sys_s390_ipc,sys_s390_ipc,compat_sys_s390_ipc)
-SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
-SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn)
-SYSCALL(sys_clone,sys_clone,sys_clone_wrapper)                 /* 120 */
-SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper)
-SYSCALL(sys_newuname,sys_newuname,sys32_newuname_wrapper)
+SYSCALL(sys_fsync,sys_fsync,compat_sys_fsync)
+SYSCALL(sys_sigreturn,sys_sigreturn,compat_sys_sigreturn)
+SYSCALL(sys_clone,sys_clone,compat_sys_clone)                  /* 120 */
+SYSCALL(sys_setdomainname,sys_setdomainname,compat_sys_setdomainname)
+SYSCALL(sys_newuname,sys_newuname,compat_sys_newuname)
 NI_SYSCALL                                                     /* modify_ldt for i386 */
-SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper)
-SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper)      /* 125 */
+SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex)
+SYSCALL(sys_mprotect,sys_mprotect,compat_sys_mprotect)         /* 125 */
 SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask)
 NI_SYSCALL                                                     /* old "create module" */
-SYSCALL(sys_init_module,sys_init_module,sys_init_module_wrapper)
-SYSCALL(sys_delete_module,sys_delete_module,sys_delete_module_wrapper)
+SYSCALL(sys_init_module,sys_init_module,compat_sys_init_module)
+SYSCALL(sys_delete_module,sys_delete_module,compat_sys_delete_module)
 NI_SYSCALL                                                     /* 130: old get_kernel_syms */
-SYSCALL(sys_quotactl,sys_quotactl,sys32_quotactl_wrapper)
-SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper)
-SYSCALL(sys_fchdir,sys_fchdir,sys32_fchdir_wrapper)
-SYSCALL(sys_bdflush,sys_bdflush,sys32_bdflush_wrapper)
-SYSCALL(sys_sysfs,sys_sysfs,sys32_sysfs_wrapper)               /* 135 */
-SYSCALL(sys_personality,sys_s390_personality,sys32_personality_wrapper)
+SYSCALL(sys_quotactl,sys_quotactl,compat_sys_quotactl)
+SYSCALL(sys_getpgid,sys_getpgid,compat_sys_getpgid)
+SYSCALL(sys_fchdir,sys_fchdir,compat_sys_fchdir)
+SYSCALL(sys_bdflush,sys_bdflush,compat_sys_bdflush)
+SYSCALL(sys_sysfs,sys_sysfs,compat_sys_sysfs)          /* 135 */
+SYSCALL(sys_personality,sys_s390_personality,compat_sys_s390_personality)
 NI_SYSCALL                                                     /* for afs_syscall */
-SYSCALL(sys_setfsuid16,sys_ni_syscall,sys32_setfsuid16_wrapper)        /* old setfsuid16 syscall */
-SYSCALL(sys_setfsgid16,sys_ni_syscall,sys32_setfsgid16_wrapper)        /* old setfsgid16 syscall */
-SYSCALL(sys_llseek,sys_llseek,sys32_llseek_wrapper)            /* 140 */
-SYSCALL(sys_getdents,sys_getdents,sys32_getdents_wrapper)
-SYSCALL(sys_select,sys_select,compat_sys_select_wrapper)
-SYSCALL(sys_flock,sys_flock,sys32_flock_wrapper)
-SYSCALL(sys_msync,sys_msync,sys32_msync_wrapper)
-SYSCALL(sys_readv,sys_readv,compat_sys_readv_wrapper)          /* 145 */
-SYSCALL(sys_writev,sys_writev,compat_sys_writev_wrapper)
-SYSCALL(sys_getsid,sys_getsid,sys32_getsid_wrapper)
-SYSCALL(sys_fdatasync,sys_fdatasync,sys32_fdatasync_wrapper)
+SYSCALL(sys_setfsuid16,sys_ni_syscall,compat_sys_s390_setfsuid16)      /* old setfsuid16 syscall */
+SYSCALL(sys_setfsgid16,sys_ni_syscall,compat_sys_s390_setfsgid16)      /* old setfsgid16 syscall */
+SYSCALL(sys_llseek,sys_llseek,compat_sys_llseek)               /* 140 */
+SYSCALL(sys_getdents,sys_getdents,compat_sys_getdents)
+SYSCALL(sys_select,sys_select,compat_sys_select)
+SYSCALL(sys_flock,sys_flock,compat_sys_flock)
+SYSCALL(sys_msync,sys_msync,compat_sys_msync)
+SYSCALL(sys_readv,sys_readv,compat_sys_readv)          /* 145 */
+SYSCALL(sys_writev,sys_writev,compat_sys_writev)
+SYSCALL(sys_getsid,sys_getsid,compat_sys_getsid)
+SYSCALL(sys_fdatasync,sys_fdatasync,compat_sys_fdatasync)
 SYSCALL(sys_sysctl,sys_sysctl,compat_sys_sysctl)
-SYSCALL(sys_mlock,sys_mlock,sys32_mlock_wrapper)               /* 150 */
-SYSCALL(sys_munlock,sys_munlock,sys32_munlock_wrapper)
-SYSCALL(sys_mlockall,sys_mlockall,sys32_mlockall_wrapper)
+SYSCALL(sys_mlock,sys_mlock,compat_sys_mlock)                  /* 150 */
+SYSCALL(sys_munlock,sys_munlock,compat_sys_munlock)
+SYSCALL(sys_mlockall,sys_mlockall,compat_sys_mlockall)
 SYSCALL(sys_munlockall,sys_munlockall,sys_munlockall)
-SYSCALL(sys_sched_setparam,sys_sched_setparam,sys32_sched_setparam_wrapper)
-SYSCALL(sys_sched_getparam,sys_sched_getparam,sys32_sched_getparam_wrapper)    /* 155 */
-SYSCALL(sys_sched_setscheduler,sys_sched_setscheduler,sys32_sched_setscheduler_wrapper)
-SYSCALL(sys_sched_getscheduler,sys_sched_getscheduler,sys32_sched_getscheduler_wrapper)
+SYSCALL(sys_sched_setparam,sys_sched_setparam,compat_sys_sched_setparam)
+SYSCALL(sys_sched_getparam,sys_sched_getparam,compat_sys_sched_getparam)       /* 155 */
+SYSCALL(sys_sched_setscheduler,sys_sched_setscheduler,compat_sys_sched_setscheduler)
+SYSCALL(sys_sched_getscheduler,sys_sched_getscheduler,compat_sys_sched_getscheduler)
 SYSCALL(sys_sched_yield,sys_sched_yield,sys_sched_yield)
-SYSCALL(sys_sched_get_priority_max,sys_sched_get_priority_max,sys32_sched_get_priority_max_wrapper)
-SYSCALL(sys_sched_get_priority_min,sys_sched_get_priority_min,sys32_sched_get_priority_min_wrapper)    /* 160 */
+SYSCALL(sys_sched_get_priority_max,sys_sched_get_priority_max,compat_sys_sched_get_priority_max)
+SYSCALL(sys_sched_get_priority_min,sys_sched_get_priority_min,compat_sys_sched_get_priority_min)       /* 160 */
 SYSCALL(sys_sched_rr_get_interval,sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval)
-SYSCALL(sys_nanosleep,sys_nanosleep,compat_sys_nanosleep_wrapper)
-SYSCALL(sys_mremap,sys_mremap,sys32_mremap_wrapper)
-SYSCALL(sys_setresuid16,sys_ni_syscall,sys32_setresuid16_wrapper)      /* old setresuid16 syscall */
-SYSCALL(sys_getresuid16,sys_ni_syscall,sys32_getresuid16_wrapper)      /* 165 old getresuid16 syscall */
+SYSCALL(sys_nanosleep,sys_nanosleep,compat_sys_nanosleep)
+SYSCALL(sys_mremap,sys_mremap,compat_sys_mremap)
+SYSCALL(sys_setresuid16,sys_ni_syscall,compat_sys_s390_setresuid16)    /* old setresuid16 syscall */
+SYSCALL(sys_getresuid16,sys_ni_syscall,compat_sys_s390_getresuid16)    /* 165 old getresuid16 syscall */
 NI_SYSCALL                                                     /* for vm86 */
 NI_SYSCALL                                                     /* old sys_query_module */
-SYSCALL(sys_poll,sys_poll,sys32_poll_wrapper)
+SYSCALL(sys_poll,sys_poll,compat_sys_poll)
 NI_SYSCALL                                                     /* old nfsservctl */
-SYSCALL(sys_setresgid16,sys_ni_syscall,sys32_setresgid16_wrapper)      /* 170 old setresgid16 syscall */
-SYSCALL(sys_getresgid16,sys_ni_syscall,sys32_getresgid16_wrapper)      /* old getresgid16 syscall */
-SYSCALL(sys_prctl,sys_prctl,sys32_prctl_wrapper)
-SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,sys32_rt_sigreturn)
+SYSCALL(sys_setresgid16,sys_ni_syscall,compat_sys_s390_setresgid16)    /* 170 old setresgid16 syscall */
+SYSCALL(sys_getresgid16,sys_ni_syscall,compat_sys_s390_getresgid16)    /* old getresgid16 syscall */
+SYSCALL(sys_prctl,sys_prctl,compat_sys_prctl)
+SYSCALL(sys_rt_sigreturn,sys_rt_sigreturn,compat_sys_rt_sigreturn)
 SYSCALL(sys_rt_sigaction,sys_rt_sigaction,compat_sys_rt_sigaction)
 SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,compat_sys_rt_sigprocmask) /* 175 */
 SYSCALL(sys_rt_sigpending,sys_rt_sigpending,compat_sys_rt_sigpending)
 SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_sys_rt_sigtimedwait)
 SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,compat_sys_rt_sigqueueinfo)
 SYSCALL(sys_rt_sigsuspend,sys_rt_sigsuspend,compat_sys_rt_sigsuspend)
-SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper)         /* 180 */
-SYSCALL(sys_pwrite64,sys_pwrite64,sys32_pwrite64_wrapper)
-SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper)      /* old chown16 syscall */
-SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper)
-SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper)
-SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper)            /* 185 */
+SYSCALL(sys_pread64,sys_pread64,compat_sys_s390_pread64)               /* 180 */
+SYSCALL(sys_pwrite64,sys_pwrite64,compat_sys_s390_pwrite64)
+SYSCALL(sys_chown16,sys_ni_syscall,compat_sys_s390_chown16)    /* old chown16 syscall */
+SYSCALL(sys_getcwd,sys_getcwd,compat_sys_getcwd)
+SYSCALL(sys_capget,sys_capget,compat_sys_capget)
+SYSCALL(sys_capset,sys_capset,compat_sys_capset)               /* 185 */
 SYSCALL(sys_sigaltstack,sys_sigaltstack,compat_sys_sigaltstack)
 SYSCALL(sys_sendfile,sys_sendfile64,compat_sys_sendfile)
 NI_SYSCALL                                                     /* streams1 */
 NI_SYSCALL                                                     /* streams2 */
 SYSCALL(sys_vfork,sys_vfork,sys_vfork)                         /* 190 */
-SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit_wrapper)
-SYSCALL(sys_mmap2,sys_mmap2,sys32_mmap2_wrapper)
-SYSCALL(sys_truncate64,sys_ni_syscall,sys32_truncate64_wrapper)
-SYSCALL(sys_ftruncate64,sys_ni_syscall,sys32_ftruncate64_wrapper)
-SYSCALL(sys_stat64,sys_ni_syscall,sys32_stat64_wrapper)                /* 195 */
-SYSCALL(sys_lstat64,sys_ni_syscall,sys32_lstat64_wrapper)
-SYSCALL(sys_fstat64,sys_ni_syscall,sys32_fstat64_wrapper)
-SYSCALL(sys_lchown,sys_lchown,sys32_lchown_wrapper)
+SYSCALL(sys_getrlimit,sys_getrlimit,compat_sys_getrlimit)
+SYSCALL(sys_mmap2,sys_mmap2,compat_sys_s390_mmap2)
+SYSCALL(sys_truncate64,sys_ni_syscall,compat_sys_s390_truncate64)
+SYSCALL(sys_ftruncate64,sys_ni_syscall,compat_sys_s390_ftruncate64)
+SYSCALL(sys_stat64,sys_ni_syscall,compat_sys_s390_stat64)              /* 195 */
+SYSCALL(sys_lstat64,sys_ni_syscall,compat_sys_s390_lstat64)
+SYSCALL(sys_fstat64,sys_ni_syscall,compat_sys_s390_fstat64)
+SYSCALL(sys_lchown,sys_lchown,compat_sys_lchown)
 SYSCALL(sys_getuid,sys_getuid,sys_getuid)
 SYSCALL(sys_getgid,sys_getgid,sys_getgid)                      /* 200 */
 SYSCALL(sys_geteuid,sys_geteuid,sys_geteuid)
 SYSCALL(sys_getegid,sys_getegid,sys_getegid)
-SYSCALL(sys_setreuid,sys_setreuid,sys32_setreuid_wrapper)
-SYSCALL(sys_setregid,sys_setregid,sys32_setregid_wrapper)
-SYSCALL(sys_getgroups,sys_getgroups,sys32_getgroups_wrapper)   /* 205 */
-SYSCALL(sys_setgroups,sys_setgroups,sys32_setgroups_wrapper)
-SYSCALL(sys_fchown,sys_fchown,sys32_fchown_wrapper)
-SYSCALL(sys_setresuid,sys_setresuid,sys32_setresuid_wrapper)
-SYSCALL(sys_getresuid,sys_getresuid,sys32_getresuid_wrapper)
-SYSCALL(sys_setresgid,sys_setresgid,sys32_setresgid_wrapper)   /* 210 */
-SYSCALL(sys_getresgid,sys_getresgid,sys32_getresgid_wrapper)
-SYSCALL(sys_chown,sys_chown,sys32_chown_wrapper)
-SYSCALL(sys_setuid,sys_setuid,sys32_setuid_wrapper)
-SYSCALL(sys_setgid,sys_setgid,sys32_setgid_wrapper)
-SYSCALL(sys_setfsuid,sys_setfsuid,sys32_setfsuid_wrapper)      /* 215 */
-SYSCALL(sys_setfsgid,sys_setfsgid,sys32_setfsgid_wrapper)
-SYSCALL(sys_pivot_root,sys_pivot_root,sys32_pivot_root_wrapper)
-SYSCALL(sys_mincore,sys_mincore,sys32_mincore_wrapper)
-SYSCALL(sys_madvise,sys_madvise,sys32_madvise_wrapper)
-SYSCALL(sys_getdents64,sys_getdents64,sys32_getdents64_wrapper)        /* 220 */
-SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64_wrapper)
-SYSCALL(sys_readahead,sys_readahead,sys32_readahead_wrapper)
+SYSCALL(sys_setreuid,sys_setreuid,compat_sys_setreuid)
+SYSCALL(sys_setregid,sys_setregid,compat_sys_setregid)
+SYSCALL(sys_getgroups,sys_getgroups,compat_sys_getgroups)      /* 205 */
+SYSCALL(sys_setgroups,sys_setgroups,compat_sys_setgroups)
+SYSCALL(sys_fchown,sys_fchown,compat_sys_fchown)
+SYSCALL(sys_setresuid,sys_setresuid,compat_sys_setresuid)
+SYSCALL(sys_getresuid,sys_getresuid,compat_sys_getresuid)
+SYSCALL(sys_setresgid,sys_setresgid,compat_sys_setresgid)      /* 210 */
+SYSCALL(sys_getresgid,sys_getresgid,compat_sys_getresgid)
+SYSCALL(sys_chown,sys_chown,compat_sys_chown)
+SYSCALL(sys_setuid,sys_setuid,compat_sys_setuid)
+SYSCALL(sys_setgid,sys_setgid,compat_sys_setgid)
+SYSCALL(sys_setfsuid,sys_setfsuid,compat_sys_setfsuid) /* 215 */
+SYSCALL(sys_setfsgid,sys_setfsgid,compat_sys_setfsgid)
+SYSCALL(sys_pivot_root,sys_pivot_root,compat_sys_pivot_root)
+SYSCALL(sys_mincore,sys_mincore,compat_sys_mincore)
+SYSCALL(sys_madvise,sys_madvise,compat_sys_madvise)
+SYSCALL(sys_getdents64,sys_getdents64,compat_sys_getdents64)   /* 220 */
+SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64)
+SYSCALL(sys_readahead,sys_readahead,compat_sys_s390_readahead)
 SYSCALL(sys_sendfile64,sys_ni_syscall,compat_sys_sendfile64)
-SYSCALL(sys_setxattr,sys_setxattr,sys32_setxattr_wrapper)
-SYSCALL(sys_lsetxattr,sys_lsetxattr,sys32_lsetxattr_wrapper)   /* 225 */
-SYSCALL(sys_fsetxattr,sys_fsetxattr,sys32_fsetxattr_wrapper)
-SYSCALL(sys_getxattr,sys_getxattr,sys32_getxattr_wrapper)
-SYSCALL(sys_lgetxattr,sys_lgetxattr,sys32_lgetxattr_wrapper)
-SYSCALL(sys_fgetxattr,sys_fgetxattr,sys32_fgetxattr_wrapper)
-SYSCALL(sys_listxattr,sys_listxattr,sys32_listxattr_wrapper)   /* 230 */
-SYSCALL(sys_llistxattr,sys_llistxattr,sys32_llistxattr_wrapper)
-SYSCALL(sys_flistxattr,sys_flistxattr,sys32_flistxattr_wrapper)
-SYSCALL(sys_removexattr,sys_removexattr,sys32_removexattr_wrapper)
-SYSCALL(sys_lremovexattr,sys_lremovexattr,sys32_lremovexattr_wrapper)
-SYSCALL(sys_fremovexattr,sys_fremovexattr,sys32_fremovexattr_wrapper)  /* 235 */
+SYSCALL(sys_setxattr,sys_setxattr,compat_sys_setxattr)
+SYSCALL(sys_lsetxattr,sys_lsetxattr,compat_sys_lsetxattr)      /* 225 */
+SYSCALL(sys_fsetxattr,sys_fsetxattr,compat_sys_fsetxattr)
+SYSCALL(sys_getxattr,sys_getxattr,compat_sys_getxattr)
+SYSCALL(sys_lgetxattr,sys_lgetxattr,compat_sys_lgetxattr)
+SYSCALL(sys_fgetxattr,sys_fgetxattr,compat_sys_fgetxattr)
+SYSCALL(sys_listxattr,sys_listxattr,compat_sys_listxattr)      /* 230 */
+SYSCALL(sys_llistxattr,sys_llistxattr,compat_sys_llistxattr)
+SYSCALL(sys_flistxattr,sys_flistxattr,compat_sys_flistxattr)
+SYSCALL(sys_removexattr,sys_removexattr,compat_sys_removexattr)
+SYSCALL(sys_lremovexattr,sys_lremovexattr,compat_sys_lremovexattr)
+SYSCALL(sys_fremovexattr,sys_fremovexattr,compat_sys_fremovexattr)     /* 235 */
 SYSCALL(sys_gettid,sys_gettid,sys_gettid)
-SYSCALL(sys_tkill,sys_tkill,sys_tkill_wrapper)
+SYSCALL(sys_tkill,sys_tkill,compat_sys_tkill)
 SYSCALL(sys_futex,sys_futex,compat_sys_futex)
-SYSCALL(sys_sched_setaffinity,sys_sched_setaffinity,sys32_sched_setaffinity_wrapper)
-SYSCALL(sys_sched_getaffinity,sys_sched_getaffinity,sys32_sched_getaffinity_wrapper)   /* 240 */
-SYSCALL(sys_tgkill,sys_tgkill,sys_tgkill_wrapper)
+SYSCALL(sys_sched_setaffinity,sys_sched_setaffinity,compat_sys_sched_setaffinity)
+SYSCALL(sys_sched_getaffinity,sys_sched_getaffinity,compat_sys_sched_getaffinity)      /* 240 */
+SYSCALL(sys_tgkill,sys_tgkill,compat_sys_tgkill)
 NI_SYSCALL                                                     /* reserved for TUX */
-SYSCALL(sys_io_setup,sys_io_setup,sys32_io_setup_wrapper)
-SYSCALL(sys_io_destroy,sys_io_destroy,sys32_io_destroy_wrapper)
-SYSCALL(sys_io_getevents,sys_io_getevents,sys32_io_getevents_wrapper)  /* 245 */
-SYSCALL(sys_io_submit,sys_io_submit,sys32_io_submit_wrapper)
-SYSCALL(sys_io_cancel,sys_io_cancel,sys32_io_cancel_wrapper)
-SYSCALL(sys_exit_group,sys_exit_group,sys32_exit_group_wrapper)
-SYSCALL(sys_epoll_create,sys_epoll_create,sys_epoll_create_wrapper)
-SYSCALL(sys_epoll_ctl,sys_epoll_ctl,sys_epoll_ctl_wrapper)     /* 250 */
-SYSCALL(sys_epoll_wait,sys_epoll_wait,sys_epoll_wait_wrapper)
-SYSCALL(sys_set_tid_address,sys_set_tid_address,sys32_set_tid_address_wrapper)
-SYSCALL(sys_s390_fadvise64,sys_fadvise64_64,sys32_fadvise64_wrapper)
-SYSCALL(sys_timer_create,sys_timer_create,sys32_timer_create_wrapper)
-SYSCALL(sys_timer_settime,sys_timer_settime,sys32_timer_settime_wrapper)       /* 255 */
-SYSCALL(sys_timer_gettime,sys_timer_gettime,sys32_timer_gettime_wrapper)
-SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,sys32_timer_getoverrun_wrapper)
-SYSCALL(sys_timer_delete,sys_timer_delete,sys32_timer_delete_wrapper)
-SYSCALL(sys_clock_settime,sys_clock_settime,sys32_clock_settime_wrapper)
-SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper)       /* 260 */
-SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper)
-SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper)
+SYSCALL(sys_io_setup,sys_io_setup,compat_sys_io_setup)
+SYSCALL(sys_io_destroy,sys_io_destroy,compat_sys_io_destroy)
+SYSCALL(sys_io_getevents,sys_io_getevents,compat_sys_io_getevents)     /* 245 */
+SYSCALL(sys_io_submit,sys_io_submit,compat_sys_io_submit)
+SYSCALL(sys_io_cancel,sys_io_cancel,compat_sys_io_cancel)
+SYSCALL(sys_exit_group,sys_exit_group,compat_sys_exit_group)
+SYSCALL(sys_epoll_create,sys_epoll_create,compat_sys_epoll_create)
+SYSCALL(sys_epoll_ctl,sys_epoll_ctl,compat_sys_epoll_ctl)      /* 250 */
+SYSCALL(sys_epoll_wait,sys_epoll_wait,compat_sys_epoll_wait)
+SYSCALL(sys_set_tid_address,sys_set_tid_address,compat_sys_set_tid_address)
+SYSCALL(sys_s390_fadvise64,sys_fadvise64_64,compat_sys_s390_fadvise64)
+SYSCALL(sys_timer_create,sys_timer_create,compat_sys_timer_create)
+SYSCALL(sys_timer_settime,sys_timer_settime,compat_sys_timer_settime)  /* 255 */
+SYSCALL(sys_timer_gettime,sys_timer_gettime,compat_sys_timer_gettime)
+SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,compat_sys_timer_getoverrun)
+SYSCALL(sys_timer_delete,sys_timer_delete,compat_sys_timer_delete)
+SYSCALL(sys_clock_settime,sys_clock_settime,compat_sys_clock_settime)
+SYSCALL(sys_clock_gettime,sys_clock_gettime,compat_sys_clock_gettime)  /* 260 */
+SYSCALL(sys_clock_getres,sys_clock_getres,compat_sys_clock_getres)
+SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,compat_sys_clock_nanosleep)
 NI_SYSCALL                                                     /* reserved for vserver */
-SYSCALL(sys_s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper)
-SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper)
-SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper)
-SYSCALL(sys_remap_file_pages,sys_remap_file_pages,sys32_remap_file_pages_wrapper)
+SYSCALL(sys_s390_fadvise64_64,sys_ni_syscall,compat_sys_s390_fadvise64_64)
+SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64)
+SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64)
+SYSCALL(sys_remap_file_pages,sys_remap_file_pages,compat_sys_remap_file_pages)
 NI_SYSCALL                                                     /* 268 sys_mbind */
 NI_SYSCALL                                                     /* 269 sys_get_mempolicy */
 NI_SYSCALL                                                     /* 270 sys_set_mempolicy */
-SYSCALL(sys_mq_open,sys_mq_open,compat_sys_mq_open_wrapper)
-SYSCALL(sys_mq_unlink,sys_mq_unlink,sys32_mq_unlink_wrapper)
-SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend_wrapper)
-SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper)
-SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */
-SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
-SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load_wrapper)
-SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
-SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
-SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl_wrapper)               /* 280 */
+SYSCALL(sys_mq_open,sys_mq_open,compat_sys_mq_open)
+SYSCALL(sys_mq_unlink,sys_mq_unlink,compat_sys_mq_unlink)
+SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend)
+SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive)
+SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify) /* 275 */
+SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr)
+SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load)
+SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key)
+SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key)
+SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl)               /* 280 */
 SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid)
-SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper)
-SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper)
+SYSCALL(sys_ioprio_set,sys_ioprio_set,compat_sys_ioprio_set)
+SYSCALL(sys_ioprio_get,sys_ioprio_get,compat_sys_ioprio_get)
 SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init)
-SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)     /* 285 */
-SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper)
+SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,compat_sys_inotify_add_watch)      /* 285 */
+SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,compat_sys_inotify_rm_watch)
 NI_SYSCALL                                                     /* 287 sys_migrate_pages */
 SYSCALL(sys_openat,sys_openat,compat_sys_openat)
-SYSCALL(sys_mkdirat,sys_mkdirat,sys_mkdirat_wrapper)
-SYSCALL(sys_mknodat,sys_mknodat,sys_mknodat_wrapper)   /* 290 */
-SYSCALL(sys_fchownat,sys_fchownat,sys_fchownat_wrapper)
-SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat_wrapper)
-SYSCALL(sys_fstatat64,sys_newfstatat,sys32_fstatat64_wrapper)
-SYSCALL(sys_unlinkat,sys_unlinkat,sys_unlinkat_wrapper)
-SYSCALL(sys_renameat,sys_renameat,sys_renameat_wrapper)        /* 295 */
-SYSCALL(sys_linkat,sys_linkat,sys_linkat_wrapper)
-SYSCALL(sys_symlinkat,sys_symlinkat,sys_symlinkat_wrapper)
-SYSCALL(sys_readlinkat,sys_readlinkat,sys_readlinkat_wrapper)
-SYSCALL(sys_fchmodat,sys_fchmodat,sys_fchmodat_wrapper)
-SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper)     /* 300 */
-SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
-SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
-SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper)
+SYSCALL(sys_mkdirat,sys_mkdirat,compat_sys_mkdirat)
+SYSCALL(sys_mknodat,sys_mknodat,compat_sys_mknodat)    /* 290 */
+SYSCALL(sys_fchownat,sys_fchownat,compat_sys_fchownat)
+SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat)
+SYSCALL(sys_fstatat64,sys_newfstatat,compat_sys_s390_fstatat64)
+SYSCALL(sys_unlinkat,sys_unlinkat,compat_sys_unlinkat)
+SYSCALL(sys_renameat,sys_renameat,compat_sys_renameat) /* 295 */
+SYSCALL(sys_linkat,sys_linkat,compat_sys_linkat)
+SYSCALL(sys_symlinkat,sys_symlinkat,compat_sys_symlinkat)
+SYSCALL(sys_readlinkat,sys_readlinkat,compat_sys_readlinkat)
+SYSCALL(sys_fchmodat,sys_fchmodat,compat_sys_fchmodat)
+SYSCALL(sys_faccessat,sys_faccessat,compat_sys_faccessat)      /* 300 */
+SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6)
+SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll)
+SYSCALL(sys_unshare,sys_unshare,compat_sys_unshare)
 SYSCALL(sys_set_robust_list,sys_set_robust_list,compat_sys_set_robust_list)
 SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list)
-SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
-SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
-SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
+SYSCALL(sys_splice,sys_splice,compat_sys_splice)
+SYSCALL(sys_sync_file_range,sys_sync_file_range,compat_sys_s390_sync_file_range)
+SYSCALL(sys_tee,sys_tee,compat_sys_tee)
 SYSCALL(sys_vmsplice,sys_vmsplice,compat_sys_vmsplice)
 NI_SYSCALL                                                     /* 310 sys_move_pages */
-SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
+SYSCALL(sys_getcpu,sys_getcpu,compat_sys_getcpu)
 SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait)
-SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
-SYSCALL(sys_s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
-SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)      /* 315 */
+SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes)
+SYSCALL(sys_s390_fallocate,sys_fallocate,compat_sys_s390_fallocate)
+SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat)      /* 315 */
 SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd)
 NI_SYSCALL                                             /* 317 old sys_timer_fd */
-SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
-SYSCALL(sys_timerfd_create,sys_timerfd_create,sys_timerfd_create_wrapper)
+SYSCALL(sys_eventfd,sys_eventfd,compat_sys_eventfd)
+SYSCALL(sys_timerfd_create,sys_timerfd_create,compat_sys_timerfd_create)
 SYSCALL(sys_timerfd_settime,sys_timerfd_settime,compat_sys_timerfd_settime) /* 320 */
 SYSCALL(sys_timerfd_gettime,sys_timerfd_gettime,compat_sys_timerfd_gettime)
 SYSCALL(sys_signalfd4,sys_signalfd4,compat_sys_signalfd4)
-SYSCALL(sys_eventfd2,sys_eventfd2,sys_eventfd2_wrapper)
-SYSCALL(sys_inotify_init1,sys_inotify_init1,sys_inotify_init1_wrapper)
-SYSCALL(sys_pipe2,sys_pipe2,sys_pipe2_wrapper) /* 325 */
-SYSCALL(sys_dup3,sys_dup3,sys_dup3_wrapper)
-SYSCALL(sys_epoll_create1,sys_epoll_create1,sys_epoll_create1_wrapper)
+SYSCALL(sys_eventfd2,sys_eventfd2,compat_sys_eventfd2)
+SYSCALL(sys_inotify_init1,sys_inotify_init1,compat_sys_inotify_init1)
+SYSCALL(sys_pipe2,sys_pipe2,compat_sys_pipe2) /* 325 */
+SYSCALL(sys_dup3,sys_dup3,compat_sys_dup3)
+SYSCALL(sys_epoll_create1,sys_epoll_create1,compat_sys_epoll_create1)
 SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv)
 SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev)
 SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
-SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
-SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
+SYSCALL(sys_perf_event_open,sys_perf_event_open,compat_sys_perf_event_open)
+SYSCALL(sys_fanotify_init,sys_fanotify_init,compat_sys_fanotify_init)
 SYSCALL(sys_fanotify_mark,sys_fanotify_mark,compat_sys_fanotify_mark)
-SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper)
-SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */
+SYSCALL(sys_prlimit64,sys_prlimit64,compat_sys_prlimit64)
+SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,compat_sys_name_to_handle_at) /* 335 */
 SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at)
-SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
-SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
-SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
-SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
-SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
-SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
-SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
-SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper)
-SYSCALL(sys_sched_setattr,sys_sched_setattr,sys_sched_setattr_wrapper) /* 345 */
-SYSCALL(sys_sched_getattr,sys_sched_getattr,sys_sched_getattr_wrapper)
+SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime)
+SYSCALL(sys_syncfs,sys_syncfs,compat_sys_syncfs)
+SYSCALL(sys_setns,sys_setns,compat_sys_setns)
+SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv) /* 340 */
+SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev)
+SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,compat_sys_s390_runtime_instr)
+SYSCALL(sys_kcmp,sys_kcmp,compat_sys_kcmp)
+SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module)
+SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
+SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
index 4b2e3e317004a3cf5d725887c1136c9cbcdd4045..6298fed11cedf8bcfcb536474d33552a115f2fe2 100644 (file)
@@ -451,7 +451,6 @@ static int __init topology_init(void)
        }
        set_topology_timer();
 out:
-       update_cpu_masks();
        return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
 }
 device_initcall(topology_init);
index 8216c0e0b2e299494ee297540ed0d7015e006858..6f9cfa50037246d8d37bb5dd81a21d643ff3f544 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <asm/pgalloc.h>
 #include <asm/virtio-ccw.h>
 #include "kvm-s390.h"
 #include "trace.h"
@@ -86,9 +87,11 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
        switch (subcode) {
        case 3:
                vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
+               page_table_reset_pgste(current->mm, 0, TASK_SIZE);
                break;
        case 4:
                vcpu->run->s390_reset_flags = 0;
+               page_table_reset_pgste(current->mm, 0, TASK_SIZE);
                break;
        default:
                return -EOPNOTSUPP;
index e0676f390d57d22aeaf991a95c0a7d0e3458d369..10b5db3c9bc4a71d179ed02b994d7fdea6109311 100644 (file)
@@ -68,6 +68,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
        { "instruction_stsch", VCPU_STAT(instruction_stsch) },
        { "instruction_chsc", VCPU_STAT(instruction_chsc) },
+       { "instruction_essa", VCPU_STAT(instruction_essa) },
        { "instruction_stsi", VCPU_STAT(instruction_stsi) },
        { "instruction_stfl", VCPU_STAT(instruction_stfl) },
        { "instruction_tprot", VCPU_STAT(instruction_tprot) },
@@ -283,7 +284,11 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
        if (kvm_is_ucontrol(vcpu->kvm))
                gmap_free(vcpu->arch.gmap);
 
+       if (vcpu->arch.sie_block->cbrlo)
+               __free_page(__pfn_to_page(
+                               vcpu->arch.sie_block->cbrlo >> PAGE_SHIFT));
        free_page((unsigned long)(vcpu->arch.sie_block));
+
        kvm_vcpu_uninit(vcpu);
        kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
@@ -390,6 +395,8 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
+       struct page *cbrl;
+
        atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
                                                    CPUSTAT_SM |
                                                    CPUSTAT_STOPPED |
@@ -401,6 +408,14 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.sie_block->ecb2  = 8;
        vcpu->arch.sie_block->eca   = 0xC1002001U;
        vcpu->arch.sie_block->fac   = (int) (long) vfacilities;
+       if (kvm_enabled_cmma()) {
+               cbrl = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               if (cbrl) {
+                       vcpu->arch.sie_block->ecb2 |= 0x80;
+                       vcpu->arch.sie_block->ecb2 &= ~0x08;
+                       vcpu->arch.sie_block->cbrlo = page_to_phys(cbrl);
+               }
+       }
        hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
        tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
                     (unsigned long) vcpu);
@@ -761,6 +776,16 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
        return rc;
 }
 
+bool kvm_enabled_cmma(void)
+{
+       if (!MACHINE_IS_LPAR)
+               return false;
+       /* only enable for z10 and later */
+       if (!MACHINE_HAS_EDAT1)
+               return false;
+       return true;
+}
+
 static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
        int rc, exit_reason;
index f9559b0bd620962d095851fc5c884a759b49996c..564514f410f45682272bdc5a3e5064306a9e9960 100644 (file)
@@ -156,6 +156,8 @@ void s390_vcpu_block(struct kvm_vcpu *vcpu);
 void s390_vcpu_unblock(struct kvm_vcpu *vcpu);
 void exit_sie(struct kvm_vcpu *vcpu);
 void exit_sie_sync(struct kvm_vcpu *vcpu);
+/* are we going to support cmma? */
+bool kvm_enabled_cmma(void);
 /* implemented in diag.c */
 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu);
 
index 75beea632a10ee7c1bba185d344831e11ec684c5..aacb6b129914bc1c7d207d0587fc4fb2efe66ccf 100644 (file)
@@ -636,8 +636,49 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static int handle_essa(struct kvm_vcpu *vcpu)
+{
+       /* entries expected to be 1FF */
+       int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
+       unsigned long *cbrlo, cbrle;
+       struct gmap *gmap;
+       int i;
+
+       VCPU_EVENT(vcpu, 5, "cmma release %d pages", entries);
+       gmap = vcpu->arch.gmap;
+       vcpu->stat.instruction_essa++;
+       if (!kvm_enabled_cmma() || !vcpu->arch.sie_block->cbrlo)
+               return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
+
+       if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+               return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
+
+       if (((vcpu->arch.sie_block->ipb & 0xf0000000) >> 28) > 6)
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+
+       /* Rewind PSW to repeat the ESSA instruction */
+       vcpu->arch.sie_block->gpsw.addr =
+               __rewind_psw(vcpu->arch.sie_block->gpsw, 4);
+       vcpu->arch.sie_block->cbrlo &= PAGE_MASK;       /* reset nceo */
+       cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
+       down_read(&gmap->mm->mmap_sem);
+       for (i = 0; i < entries; ++i) {
+               cbrle = cbrlo[i];
+               if (unlikely(cbrle & ~PAGE_MASK || cbrle < 2 * PAGE_SIZE))
+                       /* invalid entry */
+                       break;
+               /* try to free backing */
+               __gmap_zap(cbrle, gmap);
+       }
+       up_read(&gmap->mm->mmap_sem);
+       if (i < entries)
+               return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+       return 0;
+}
+
 static const intercept_handler_t b9_handlers[256] = {
        [0x8d] = handle_epsw,
+       [0xab] = handle_essa,
        [0xaf] = handle_pfmf,
 };
 
index b068729e50ace9711774adab984f03a8a41e9338..e3fffe1dff513a05ec2839114b1952c65801721c 100644 (file)
@@ -2,8 +2,7 @@
 # Makefile for s390-specific library files..
 #
 
-lib-y += delay.o string.o uaccess_pt.o find.o
+lib-y += delay.o string.o uaccess_pt.o uaccess_mvcos.o find.o
 obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
 obj-$(CONFIG_64BIT) += mem64.o
-lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
index 620d34d6487e5217ce485ab7a6a00e8a19a9171c..922003c1b90d388c96b26c33a19947dc1c8d95d0 100644 (file)
@@ -4,7 +4,7 @@
  * On s390x the bits are numbered:
  *   |0..............63|64............127|128...........191|192...........255|
  * and on s390:
- *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|
  *
  * The reason for this bit numbering is the fact that the hardware sets bits
  * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
index b1a22173d027b9bde6774194631d635932bc42ff..c7e0e81f4b4ebf73cf15664f048301faaffccabb 100644 (file)
@@ -6,7 +6,11 @@
 #ifndef __ARCH_S390_LIB_UACCESS_H
 #define __ARCH_S390_LIB_UACCESS_H
 
-extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
+unsigned long copy_from_user_pt(void *to, const void __user *from, unsigned long n);
+unsigned long copy_to_user_pt(void __user *to, const void *from, unsigned long n);
+unsigned long copy_in_user_pt(void __user *to, const void __user *from, unsigned long n);
+unsigned long clear_user_pt(void __user *to, unsigned long n);
+unsigned long strnlen_user_pt(const char __user *src, unsigned long count);
+long strncpy_from_user_pt(char *dst, const char __user *src, long count);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
index 4b7993bf69b96bd42f503e8772f29caedf5dd4b0..ae97b8df11aa12e154e3403fc080a603395d5346 100644 (file)
@@ -6,8 +6,11 @@
  *              Gerald Schaefer (gerald.schaefer@de.ibm.com)
  */
 
+#include <linux/jump_label.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/mm.h>
+#include <asm/facility.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
 #include "uaccess.h"
 #define SLR    "slgr"
 #endif
 
-static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
+static struct static_key have_mvcos = STATIC_KEY_INIT_TRUE;
+
+static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr,
+                                                unsigned long size)
 {
        register unsigned long reg0 asm("0") = 0x81UL;
        unsigned long tmp1, tmp2;
@@ -65,7 +71,16 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
        return size;
 }
 
-static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
+unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+       if (static_key_true(&have_mvcos))
+               return copy_from_user_mvcos(to, from, n);
+       return copy_from_user_pt(to, from, n);
+}
+EXPORT_SYMBOL(__copy_from_user);
+
+static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x,
+                                              unsigned long size)
 {
        register unsigned long reg0 asm("0") = 0x810000UL;
        unsigned long tmp1, tmp2;
@@ -94,8 +109,16 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
        return size;
 }
 
-static size_t copy_in_user_mvcos(size_t size, void __user *to,
-                                const void __user *from)
+unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       if (static_key_true(&have_mvcos))
+               return copy_to_user_mvcos(to, from, n);
+       return copy_to_user_pt(to, from, n);
+}
+EXPORT_SYMBOL(__copy_to_user);
+
+static inline unsigned long copy_in_user_mvcos(void __user *to, const void __user *from,
+                                              unsigned long size)
 {
        register unsigned long reg0 asm("0") = 0x810081UL;
        unsigned long tmp1, tmp2;
@@ -117,7 +140,15 @@ static size_t copy_in_user_mvcos(size_t size, void __user *to,
        return size;
 }
 
-static size_t clear_user_mvcos(size_t size, void __user *to)
+unsigned long __copy_in_user(void __user *to, const void __user *from, unsigned long n)
+{
+       if (static_key_true(&have_mvcos))
+               return copy_in_user_mvcos(to, from, n);
+       return copy_in_user_pt(to, from, n);
+}
+EXPORT_SYMBOL(__copy_in_user);
+
+static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size)
 {
        register unsigned long reg0 asm("0") = 0x810000UL;
        unsigned long tmp1, tmp2;
@@ -145,17 +176,26 @@ static size_t clear_user_mvcos(size_t size, void __user *to)
        return size;
 }
 
-static size_t strnlen_user_mvcos(size_t count, const char __user *src)
+unsigned long __clear_user(void __user *to, unsigned long size)
 {
-       size_t done, len, offset, len_str;
+       if (static_key_true(&have_mvcos))
+               return clear_user_mvcos(to, size);
+       return clear_user_pt(to, size);
+}
+EXPORT_SYMBOL(__clear_user);
+
+static inline unsigned long strnlen_user_mvcos(const char __user *src,
+                                              unsigned long count)
+{
+       unsigned long done, len, offset, len_str;
        char buf[256];
 
        done = 0;
        do {
-               offset = (size_t)src & ~PAGE_MASK;
+               offset = (unsigned long)src & ~PAGE_MASK;
                len = min(256UL, PAGE_SIZE - offset);
                len = min(count - done, len);
-               if (copy_from_user_mvcos(len, src, buf))
+               if (copy_from_user_mvcos(buf, src, len))
                        return 0;
                len_str = strnlen(buf, len);
                done += len_str;
@@ -164,18 +204,26 @@ static size_t strnlen_user_mvcos(size_t count, const char __user *src)
        return done + 1;
 }
 
-static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
-                                     char *dst)
+unsigned long __strnlen_user(const char __user *src, unsigned long count)
 {
-       size_t done, len, offset, len_str;
+       if (static_key_true(&have_mvcos))
+               return strnlen_user_mvcos(src, count);
+       return strnlen_user_pt(src, count);
+}
+EXPORT_SYMBOL(__strnlen_user);
 
-       if (unlikely(!count))
+static inline long strncpy_from_user_mvcos(char *dst, const char __user *src,
+                                          long count)
+{
+       unsigned long done, len, offset, len_str;
+
+       if (unlikely(count <= 0))
                return 0;
        done = 0;
        do {
-               offset = (size_t)src & ~PAGE_MASK;
+               offset = (unsigned long)src & ~PAGE_MASK;
                len = min(count - done, PAGE_SIZE - offset);
-               if (copy_from_user_mvcos(len, src, dst))
+               if (copy_from_user_mvcos(dst, src, len))
                        return -EFAULT;
                len_str = strnlen(dst, len);
                done += len_str;
@@ -185,13 +233,31 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
        return done;
 }
 
-struct uaccess_ops uaccess_mvcos = {
-       .copy_from_user = copy_from_user_mvcos,
-       .copy_to_user = copy_to_user_mvcos,
-       .copy_in_user = copy_in_user_mvcos,
-       .clear_user = clear_user_mvcos,
-       .strnlen_user = strnlen_user_mvcos,
-       .strncpy_from_user = strncpy_from_user_mvcos,
-       .futex_atomic_op = futex_atomic_op_pt,
-       .futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt,
-};
+long __strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       if (static_key_true(&have_mvcos))
+               return strncpy_from_user_mvcos(dst, src, count);
+       return strncpy_from_user_pt(dst, src, count);
+}
+EXPORT_SYMBOL(__strncpy_from_user);
+
+/*
+ * The uaccess page tabe walk variant can be enforced with the "uaccesspt"
+ * kernel parameter. This is mainly for debugging purposes.
+ */
+static int force_uaccess_pt __initdata;
+
+static int __init parse_uaccess_pt(char *__unused)
+{
+       force_uaccess_pt = 1;
+       return 0;
+}
+early_param("uaccesspt", parse_uaccess_pt);
+
+static int __init uaccess_init(void)
+{
+       if (IS_ENABLED(CONFIG_32BIT) || force_uaccess_pt || !test_facility(27))
+               static_key_slow_dec(&have_mvcos);
+       return 0;
+}
+early_initcall(uaccess_init);
index 61ebcc9ccb3472abe320fd8ed4939b4cc5074ebe..8d39760bae68f9f4e65bbbf4d42d5db25ef4958c 100644 (file)
@@ -22,7 +22,7 @@
 #define SLR    "slgr"
 #endif
 
-static size_t strnlen_kernel(size_t count, const char __user *src)
+static unsigned long strnlen_kernel(const char __user *src, unsigned long count)
 {
        register unsigned long reg0 asm("0") = 0UL;
        unsigned long tmp1, tmp2;
@@ -42,8 +42,8 @@ static size_t strnlen_kernel(size_t count, const char __user *src)
        return count;
 }
 
-static size_t copy_in_kernel(size_t count, void __user *to,
-                            const void __user *from)
+static unsigned long copy_in_kernel(void __user *to, const void __user *from,
+                                   unsigned long count)
 {
        unsigned long tmp1;
 
@@ -146,8 +146,8 @@ static unsigned long follow_table(struct mm_struct *mm,
 
 #endif /* CONFIG_64BIT */
 
-static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
-                                            size_t n, int write_user)
+static inline unsigned long __user_copy_pt(unsigned long uaddr, void *kptr,
+                                          unsigned long n, int write_user)
 {
        struct mm_struct *mm = current->mm;
        unsigned long offset, done, size, kaddr;
@@ -189,8 +189,7 @@ fault:
  * Do DAT for user address by page table walk, return kernel address.
  * This function needs to be called with current->mm->page_table_lock held.
  */
-static __always_inline unsigned long __dat_user_addr(unsigned long uaddr,
-                                                    int write)
+static inline unsigned long __dat_user_addr(unsigned long uaddr, int write)
 {
        struct mm_struct *mm = current->mm;
        unsigned long kaddr;
@@ -211,29 +210,29 @@ fault:
        return 0;
 }
 
-static size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
+unsigned long copy_from_user_pt(void *to, const void __user *from, unsigned long n)
 {
-       size_t rc;
+       unsigned long rc;
 
        if (segment_eq(get_fs(), KERNEL_DS))
-               return copy_in_kernel(n, (void __user *) to, from);
+               return copy_in_kernel((void __user *) to, from, n);
        rc = __user_copy_pt((unsigned long) from, to, n, 0);
        if (unlikely(rc))
                memset(to + n - rc, 0, rc);
        return rc;
 }
 
-static size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
+unsigned long copy_to_user_pt(void __user *to, const void *from, unsigned long n)
 {
        if (segment_eq(get_fs(), KERNEL_DS))
-               return copy_in_kernel(n, to, (void __user *) from);
+               return copy_in_kernel(to, (void __user *) from, n);
        return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
 }
 
-static size_t clear_user_pt(size_t n, void __user *to)
+unsigned long clear_user_pt(void __user *to, unsigned long n)
 {
        void *zpage = (void *) empty_zero_page;
-       long done, size, ret;
+       unsigned long done, size, ret;
 
        done = 0;
        do {
@@ -242,7 +241,7 @@ static size_t clear_user_pt(size_t n, void __user *to)
                else
                        size = n - done;
                if (segment_eq(get_fs(), KERNEL_DS))
-                       ret = copy_in_kernel(n, to, (void __user *) zpage);
+                       ret = copy_in_kernel(to, (void __user *) zpage, n);
                else
                        ret = __user_copy_pt((unsigned long) to, zpage, size, 1);
                done += size;
@@ -253,17 +252,17 @@ static size_t clear_user_pt(size_t n, void __user *to)
        return 0;
 }
 
-static size_t strnlen_user_pt(size_t count, const char __user *src)
+unsigned long strnlen_user_pt(const char __user *src, unsigned long count)
 {
        unsigned long uaddr = (unsigned long) src;
        struct mm_struct *mm = current->mm;
        unsigned long offset, done, len, kaddr;
-       size_t len_str;
+       unsigned long len_str;
 
        if (unlikely(!count))
                return 0;
        if (segment_eq(get_fs(), KERNEL_DS))
-               return strnlen_kernel(count, src);
+               return strnlen_kernel(src, count);
        if (!mm)
                return 0;
        done = 0;
@@ -289,19 +288,18 @@ fault:
        goto retry;
 }
 
-static size_t strncpy_from_user_pt(size_t count, const char __user *src,
-                                  char *dst)
+long strncpy_from_user_pt(char *dst, const char __user *src, long count)
 {
-       size_t done, len, offset, len_str;
+       unsigned long done, len, offset, len_str;
 
-       if (unlikely(!count))
+       if (unlikely(count <= 0))
                return 0;
        done = 0;
        do {
-               offset = (size_t)src & ~PAGE_MASK;
+               offset = (unsigned long)src & ~PAGE_MASK;
                len = min(count - done, PAGE_SIZE - offset);
                if (segment_eq(get_fs(), KERNEL_DS)) {
-                       if (copy_in_kernel(len, (void __user *) dst, src))
+                       if (copy_in_kernel((void __user *) dst, src, len))
                                return -EFAULT;
                } else {
                        if (__user_copy_pt((unsigned long) src, dst, len, 0))
@@ -315,8 +313,8 @@ static size_t strncpy_from_user_pt(size_t count, const char __user *src,
        return done;
 }
 
-static size_t copy_in_user_pt(size_t n, void __user *to,
-                             const void __user *from)
+unsigned long copy_in_user_pt(void __user *to, const void __user *from,
+                             unsigned long n)
 {
        struct mm_struct *mm = current->mm;
        unsigned long offset_max, uaddr, done, size, error_code;
@@ -326,7 +324,7 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
        int write_user;
 
        if (segment_eq(get_fs(), KERNEL_DS))
-               return copy_in_kernel(n, to, from);
+               return copy_in_kernel(to, from, n);
        if (!mm)
                return n;
        done = 0;
@@ -411,7 +409,7 @@ static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
        return ret;
 }
 
-int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
+int __futex_atomic_op_inuser(int op, u32 __user *uaddr, int oparg, int *old)
 {
        int ret;
 
@@ -449,8 +447,8 @@ static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
        return ret;
 }
 
-int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
-                           u32 oldval, u32 newval)
+int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+                                 u32 oldval, u32 newval)
 {
        int ret;
 
@@ -471,14 +469,3 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
        put_page(virt_to_page(uaddr));
        return ret;
 }
-
-struct uaccess_ops uaccess_pt = {
-       .copy_from_user         = copy_from_user_pt,
-       .copy_to_user           = copy_to_user_pt,
-       .copy_in_user           = copy_in_user_pt,
-       .clear_user             = clear_user_pt,
-       .strnlen_user           = strnlen_user_pt,
-       .strncpy_from_user      = strncpy_from_user_pt,
-       .futex_atomic_op        = futex_atomic_op_pt,
-       .futex_atomic_cmpxchg   = futex_atomic_cmpxchg_pt,
-};
index d1e0e0c7a7e22e44f7f136a0bcef51bf412f1099..2a2e35416d2fe7fc4a835795f5c64bca444f1de4 100644 (file)
@@ -128,7 +128,7 @@ void memcpy_absolute(void *dest, void *src, size_t count)
 /*
  * Copy memory from kernel (real) to user (virtual)
  */
-int copy_to_user_real(void __user *dest, void *src, size_t count)
+int copy_to_user_real(void __user *dest, void *src, unsigned long count)
 {
        int offs = 0, size, rc;
        char *buf;
@@ -151,32 +151,6 @@ out:
        return rc;
 }
 
-/*
- * Copy memory from user (virtual) to kernel (real)
- */
-int copy_from_user_real(void *dest, void __user *src, size_t count)
-{
-       int offs = 0, size, rc;
-       char *buf;
-
-       buf = (char *) __get_free_page(GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-       rc = -EFAULT;
-       while (offs < count) {
-               size = min(PAGE_SIZE, count - offs);
-               if (copy_from_user(buf, src + offs, size))
-                       goto out;
-               if (memcpy_real(dest + offs, buf, size))
-                       goto out;
-               offs += size;
-       }
-       rc = 0;
-out:
-       free_page((unsigned long) buf);
-       return rc;
-}
-
 /*
  * Check if physical address is within prefix or zero page
  */
index a90d45e9dfb0cbb7b1dce5fb8441a249dc0556c3..27c50f4d90cb32ce97db6004ce450096b807655c 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 #include <linux/init.h>
+#include <asm/setup.h>
+#include <asm/ipl.h>
 
 #define ESSA_SET_STABLE                1
 #define ESSA_SET_UNUSED                2
@@ -41,6 +43,14 @@ void __init cmma_init(void)
 
        if (!cmma_flag)
                return;
+       /*
+        * Disable CMM for dump, otherwise  the tprot based memory
+        * detection can fail because of unstable pages.
+        */
+       if (OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP) {
+               cmma_flag = 0;
+               return;
+       }
        asm volatile(
                "       .insn rrf,0xb9ab0000,%1,%1,0,0\n"
                "0:     la      %0,0\n"
index 3584ed9b20a183de8c58cb4521c99517c2532c9a..796c9320c709f5850bb0679778a28bc488773be2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/quicklist.h>
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
+#include <linux/swapops.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -594,6 +595,82 @@ unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
 }
 EXPORT_SYMBOL_GPL(gmap_fault);
 
+static void gmap_zap_swap_entry(swp_entry_t entry, struct mm_struct *mm)
+{
+       if (!non_swap_entry(entry))
+               dec_mm_counter(mm, MM_SWAPENTS);
+       else if (is_migration_entry(entry)) {
+               struct page *page = migration_entry_to_page(entry);
+
+               if (PageAnon(page))
+                       dec_mm_counter(mm, MM_ANONPAGES);
+               else
+                       dec_mm_counter(mm, MM_FILEPAGES);
+       }
+       free_swap_and_cache(entry);
+}
+
+/**
+ * The mm->mmap_sem lock must be held
+ */
+static void gmap_zap_unused(struct mm_struct *mm, unsigned long address)
+{
+       unsigned long ptev, pgstev;
+       spinlock_t *ptl;
+       pgste_t pgste;
+       pte_t *ptep, pte;
+
+       ptep = get_locked_pte(mm, address, &ptl);
+       if (unlikely(!ptep))
+               return;
+       pte = *ptep;
+       if (!pte_swap(pte))
+               goto out_pte;
+       /* Zap unused and logically-zero pages */
+       pgste = pgste_get_lock(ptep);
+       pgstev = pgste_val(pgste);
+       ptev = pte_val(pte);
+       if (((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED) ||
+           ((pgstev & _PGSTE_GPS_ZERO) && (ptev & _PAGE_INVALID))) {
+               gmap_zap_swap_entry(pte_to_swp_entry(pte), mm);
+               pte_clear(mm, address, ptep);
+       }
+       pgste_set_unlock(ptep, pgste);
+out_pte:
+       pte_unmap_unlock(*ptep, ptl);
+}
+
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+void __gmap_zap(unsigned long address, struct gmap *gmap)
+{
+       unsigned long *table, *segment_ptr;
+       unsigned long segment, pgstev, ptev;
+       struct gmap_pgtable *mp;
+       struct page *page;
+
+       segment_ptr = gmap_table_walk(address, gmap);
+       if (IS_ERR(segment_ptr))
+               return;
+       segment = *segment_ptr;
+       if (segment & _SEGMENT_ENTRY_INVALID)
+               return;
+       page = pfn_to_page(segment >> PAGE_SHIFT);
+       mp = (struct gmap_pgtable *) page->index;
+       address = mp->vmaddr | (address & ~PMD_MASK);
+       /* Page table is present */
+       table = (unsigned long *)(segment & _SEGMENT_ENTRY_ORIGIN);
+       table = table + ((address >> 12) & 0xff);
+       pgstev = table[PTRS_PER_PTE];
+       ptev = table[0];
+       /* quick check, checked again with locks held */
+       if (((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED) ||
+           ((pgstev & _PGSTE_GPS_ZERO) && (ptev & _PAGE_INVALID)))
+               gmap_zap_unused(gmap->mm, address);
+}
+EXPORT_SYMBOL_GPL(__gmap_zap);
+
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
 {
 
@@ -671,7 +748,7 @@ EXPORT_SYMBOL_GPL(gmap_unregister_ipte_notifier);
 /**
  * gmap_ipte_notify - mark a range of ptes for invalidation notification
  * @gmap: pointer to guest mapping meta data structure
- * @address: virtual address in the guest address space
+ * @start: virtual address in the guest address space
  * @len: size of area
  *
  * Returns 0 if for each page in the given range a gmap mapping exists and
@@ -725,13 +802,12 @@ EXPORT_SYMBOL_GPL(gmap_ipte_notify);
 /**
  * gmap_do_ipte_notify - call all invalidation callbacks for a specific pte.
  * @mm: pointer to the process mm_struct
- * @addr: virtual address in the process address space
  * @pte: pointer to the page table entry
  *
  * This function is assumed to be called with the page table lock held
  * for the pte to notify.
  */
-void gmap_do_ipte_notify(struct mm_struct *mm, unsigned long addr, pte_t *pte)
+void gmap_do_ipte_notify(struct mm_struct *mm, pte_t *pte)
 {
        unsigned long segment_offset;
        struct gmap_notifier *nb;
@@ -802,6 +878,78 @@ static inline void page_table_free_pgste(unsigned long *table)
        __free_page(page);
 }
 
+static inline unsigned long page_table_reset_pte(struct mm_struct *mm,
+                       pmd_t *pmd, unsigned long addr, unsigned long end)
+{
+       pte_t *start_pte, *pte;
+       spinlock_t *ptl;
+       pgste_t pgste;
+
+       start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       pte = start_pte;
+       do {
+               pgste = pgste_get_lock(pte);
+               pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
+               pgste_set_unlock(pte, pgste);
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+       pte_unmap_unlock(start_pte, ptl);
+
+       return addr;
+}
+
+static inline unsigned long page_table_reset_pmd(struct mm_struct *mm,
+                       pud_t *pud, unsigned long addr, unsigned long end)
+{
+       unsigned long next;
+       pmd_t *pmd;
+
+       pmd = pmd_offset(pud, addr);
+       do {
+               next = pmd_addr_end(addr, end);
+               if (pmd_none_or_clear_bad(pmd))
+                       continue;
+               next = page_table_reset_pte(mm, pmd, addr, next);
+       } while (pmd++, addr = next, addr != end);
+
+       return addr;
+}
+
+static inline unsigned long page_table_reset_pud(struct mm_struct *mm,
+                       pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+       unsigned long next;
+       pud_t *pud;
+
+       pud = pud_offset(pgd, addr);
+       do {
+               next = pud_addr_end(addr, end);
+               if (pud_none_or_clear_bad(pud))
+                       continue;
+               next = page_table_reset_pmd(mm, pud, addr, next);
+       } while (pud++, addr = next, addr != end);
+
+       return addr;
+}
+
+void page_table_reset_pgste(struct mm_struct *mm,
+                       unsigned long start, unsigned long end)
+{
+       unsigned long addr, next;
+       pgd_t *pgd;
+
+       addr = start;
+       down_read(&mm->mmap_sem);
+       pgd = pgd_offset(mm, addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               if (pgd_none_or_clear_bad(pgd))
+                       continue;
+               next = page_table_reset_pud(mm, pgd, addr, next);
+       } while (pgd++, addr = next, addr != end);
+       up_read(&mm->mmap_sem);
+}
+EXPORT_SYMBOL(page_table_reset_pgste);
+
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
                          unsigned long key, bool nq)
 {
@@ -1248,7 +1396,7 @@ void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
 {
        struct list_head *lh = (struct list_head *) pgtable;
 
-       assert_spin_locked(&mm->page_table_lock);
+       assert_spin_locked(pmd_lockptr(mm, pmdp));
 
        /* FIFO */
        if (!pmd_huge_pte(mm, pmdp))
@@ -1264,7 +1412,7 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
        pgtable_t pgtable;
        pte_t *ptep;
 
-       assert_spin_locked(&mm->page_table_lock);
+       assert_spin_locked(pmd_lockptr(mm, pmdp));
 
        /* FIFO */
        pgtable = pmd_huge_pte(mm, pmdp);
index 75c69b402e05aa3ca12f3b7ee8ca78864886c1b4..c5c66840ac00a8fd8382584a6dabc5b699596b17 100644 (file)
@@ -139,7 +139,7 @@ void zpci_debug_exit_device(struct zpci_dev *zdev)
 int __init zpci_debug_init(void)
 {
        /* event trace buffer */
-       pci_debug_msg_id = debug_register("pci_msg", 16, 1, 16 * sizeof(long));
+       pci_debug_msg_id = debug_register("pci_msg", 8, 1, 8 * sizeof(long));
        if (!pci_debug_msg_id)
                return -EINVAL;
        debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
index 60c11a629d96d0220d6b01cf1e1425d41c0ffaab..f91c03119804751894c39433eb52da1844dbcf3b 100644 (file)
@@ -206,11 +206,13 @@ static void dma_cleanup_tables(struct zpci_dev *zdev)
        zdev->dma_table = NULL;
 }
 
-static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, unsigned long start,
-                                  int size)
+static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev,
+                                      unsigned long start, int size)
 {
-       unsigned long boundary_size = 0x1000000;
+       unsigned long boundary_size;
 
+       boundary_size = ALIGN(dma_get_seg_boundary(&zdev->pdev->dev) + 1,
+                             PAGE_SIZE) >> PAGE_SHIFT;
        return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
                                start, size, 0, boundary_size, 0);
 }
index 146b9d5e89f83ba0b41506aa369254d5869dbe88..2f947aba4bd4d248984c1c865248e71fd3a0445c 100644 (file)
@@ -1,10 +1,12 @@
 
 header-y +=
 
+
 generic-y += barrier.h
 generic-y += clkdev.h
+generic-y += cputime.h
 generic-y += hash.h
+generic-y += mcs_spinlock.h
+generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += xor.h
-generic-y += preempt.h
-
diff --git a/arch/score/include/asm/cputime.h b/arch/score/include/asm/cputime.h
deleted file mode 100644 (file)
index 1fced99..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCORE_CPUTIME_H
-#define _ASM_SCORE_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* _ASM_SCORE_CPUTIME_H */
index 0cd7198a452425dbc96d7dbc72c7c61223527bb2..c19e47dacb31bceec56abeac4c96ca32ad3a2977 100644 (file)
@@ -8,18 +8,21 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
 generic-y += fcntl.h
+generic-y += hash.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kvm_para.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
+generic-y += mman.h
+generic-y += msgbuf.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += percpu.h
 generic-y += poll.h
-generic-y += mman.h
-generic-y += msgbuf.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -34,5 +37,3 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 673515bc413559a24600f988baeb91e8a6b9b1d4..aa1b2b9088a77b061758f48f4a434185e760d6ca 100644 (file)
@@ -18,7 +18,7 @@
 #define SH_CACHE_ASSOC         8
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7619)
-#define CCR            0xffffffec
+#define SH_CCR         0xffffffec
 
 #define CCR_CACHE_CE   0x01    /* Cache enable */
 #define CCR_CACHE_WT   0x02    /* CCR[bit1=1,bit2=1] */
index defb0baa5a0682b95222bccc60440ee760bd6680..b27ce92cb600bc17c47dacda12d0e3dc9f8d06a1 100644 (file)
@@ -17,8 +17,8 @@
 #define SH_CACHE_COMBINED      4
 #define SH_CACHE_ASSOC         8
 
-#define CCR            0xfffc1000 /* CCR1 */
-#define CCR2           0xfffc1004
+#define SH_CCR         0xfffc1000 /* CCR1 */
+#define SH_CCR2                0xfffc1004
 
 /*
  * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not
index bee2d81c56bfbde6392866f1d4bb05b58d1aa4b8..29700fd88c75d30be16340966c3013f1c880f076 100644 (file)
@@ -17,7 +17,7 @@
 #define SH_CACHE_COMBINED      4
 #define SH_CACHE_ASSOC         8
 
-#define CCR            0xffffffec      /* Address of Cache Control Register */
+#define SH_CCR         0xffffffec      /* Address of Cache Control Register */
 
 #define CCR_CACHE_CE   0x01    /* Cache Enable */
 #define CCR_CACHE_WT   0x02    /* Write-Through (for P0,U0,P3) (else writeback) */
index 7bfb9e8b069c22d789318085e866440502f0c755..92c4cd119b662f99dc4ed9d0f5d1b54dea3001a9 100644 (file)
@@ -17,7 +17,7 @@
 #define SH_CACHE_COMBINED      4
 #define SH_CACHE_ASSOC         8
 
-#define CCR            0xff00001c      /* Address of Cache Control Register */
+#define SH_CCR         0xff00001c      /* Address of Cache Control Register */
 #define CCR_CACHE_OCE  0x0001  /* Operand Cache Enable */
 #define CCR_CACHE_WT   0x0002  /* Write-Through (for P0,U0,P3) (else writeback)*/
 #define CCR_CACHE_CB   0x0004  /* Copy-Back (for P1) (else writethrough) */
index ecf83cd158dc38fefb91f2fa83cdb452cfa5c6bf..0d7360d549c17858c59f93b6dc0d279f4222a640 100644 (file)
@@ -112,7 +112,7 @@ static void cache_init(void)
        unsigned long ccr, flags;
 
        jump_to_uncached();
-       ccr = __raw_readl(CCR);
+       ccr = __raw_readl(SH_CCR);
 
        /*
         * At this point we don't know whether the cache is enabled or not - a
@@ -189,7 +189,7 @@ static void cache_init(void)
 
        l2_cache_init();
 
-       __raw_writel(flags, CCR);
+       __raw_writel(flags, SH_CCR);
        back_to_cached();
 }
 #else
index 2ea4483fd7227c669796644bc47bd3e80b252222..be616ee0cf8799a6c7deeb058a7a92da6a8f213c 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/thread_info.h>
 #include <linux/irqflags.h>
 #include <linux/smp.h>
-#include <linux/cpuidle.h>
 #include <linux/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/smp.h>
@@ -40,8 +39,7 @@ void arch_cpu_idle_dead(void)
 
 void arch_cpu_idle(void)
 {
-       if (cpuidle_idle_call())
-               sh_idle();
+       sh_idle();
 }
 
 void __init select_idle_routine(void)
index 115725198038da862a19ef634a0ec38adf23b76f..777e50f33c00f3f96fe4b34f7723132507b13935 100644 (file)
@@ -36,7 +36,7 @@ static int cache_seq_show(struct seq_file *file, void *iter)
         */
        jump_to_uncached();
 
-       ccr = __raw_readl(CCR);
+       ccr = __raw_readl(SH_CCR);
        if ((ccr & CCR_CACHE_ENABLE) == 0) {
                back_to_cached();
 
index defcf719f2e84eb5cae2b6be57fed58227eeb6ec..a74259f2f9815e93d499634b67d9756472662e76 100644 (file)
@@ -63,9 +63,9 @@ static void sh2__flush_invalidate_region(void *start, int size)
        local_irq_save(flags);
        jump_to_uncached();
 
-       ccr = __raw_readl(CCR);
+       ccr = __raw_readl(SH_CCR);
        ccr |= CCR_CACHE_INVALIDATE;
-       __raw_writel(ccr, CCR);
+       __raw_writel(ccr, SH_CCR);
 
        back_to_cached();
        local_irq_restore(flags);
index 949e2d3138a0ca24ffe07e6228a68eeeb72321e9..ee87d081259b86950d527151618a3e52814ade5a 100644 (file)
@@ -134,7 +134,8 @@ static void sh2a__flush_invalidate_region(void *start, int size)
 
        /* If there are too many pages then just blow the cache */
        if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
-               __raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
+               __raw_writel(__raw_readl(SH_CCR) | CCR_OCACHE_INVALIDATE,
+                            SH_CCR);
        } else {
                for (v = begin; v < end; v += L1_CACHE_BYTES)
                        sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v);
@@ -167,7 +168,8 @@ static void sh2a_flush_icache_range(void *args)
        /* I-Cache invalidate */
        /* If there are too many pages then just blow the cache */
        if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
-               __raw_writel(__raw_readl(CCR) | CCR_ICACHE_INVALIDATE, CCR);
+               __raw_writel(__raw_readl(SH_CCR) | CCR_ICACHE_INVALIDATE,
+                            SH_CCR);
        } else {
                for (v = start; v < end; v += L1_CACHE_BYTES)
                        sh2a_invalidate_line(CACHE_IC_ADDRESS_ARRAY, v);
index 0e529285b28d42c688fb0901349ba70218385d51..51d8f7f31d1d797392ab2813f4fb3d4d33480598 100644 (file)
@@ -133,9 +133,9 @@ static void flush_icache_all(void)
        jump_to_uncached();
 
        /* Flush I-cache */
-       ccr = __raw_readl(CCR);
+       ccr = __raw_readl(SH_CCR);
        ccr |= CCR_CACHE_ICI;
-       __raw_writel(ccr, CCR);
+       __raw_writel(ccr, SH_CCR);
 
        /*
         * back_to_cached() will take care of the barrier for us, don't add
index c0adbee97b5f29a2cdb33f6124c1d62ee821ebec..24c58b7dc02265c795000fa997ac96da59207175 100644 (file)
@@ -19,7 +19,7 @@ void __init shx3_cache_init(void)
 {
        unsigned int ccr;
 
-       ccr = __raw_readl(CCR);
+       ccr = __raw_readl(SH_CCR);
 
        /*
         * If we've got cache aliases, resolve them in hardware.
@@ -40,5 +40,5 @@ void __init shx3_cache_init(void)
        ccr |= CCR_CACHE_IBE;
 #endif
 
-       writel_uncached(ccr, CCR);
+       writel_uncached(ccr, SH_CCR);
 }
index 616966a96cba61d6a680d4bc57cf71150a04fb3e..097c2cdd117f53c543fb919ba6740210b1471a4a 100644 (file)
@@ -285,8 +285,8 @@ void __init cpu_cache_init(void)
 {
        unsigned int cache_disabled = 0;
 
-#ifdef CCR
-       cache_disabled = !(__raw_readl(CCR) & CCR_CACHE_ENABLE);
+#ifdef SH_CCR
+       cache_disabled = !(__raw_readl(SH_CCR) & CCR_CACHE_ENABLE);
 #endif
 
        compute_alias(&boot_cpu_data.icache);
index c51efdcd07a2d09e76c06e31671efcd19a6db4ed..7d8b7e94b93b6fb8e9795f49368c056053597bec 100644 (file)
@@ -27,7 +27,7 @@ config SPARC
        select RTC_DRV_M48T59
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
-       select HAVE_ARCH_JUMP_LABEL
+       select HAVE_ARCH_JUMP_LABEL if SPARC64
        select GENERIC_IRQ_SHOW
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_PCI_IOMAP
index 4b60a0c325ecaa1820b7b6619cfc4ea89ec7e8bf..a45821818003fce80d501b59653ac35eedcc6875 100644 (file)
@@ -6,15 +6,16 @@ generic-y += cputime.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += exec.h
-generic-y += linkage.h
-generic-y += local64.h
-generic-y += mutex.h
+generic-y += hash.h
 generic-y += irq_regs.h
+generic-y += linkage.h
 generic-y += local.h
+generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += module.h
+generic-y += mutex.h
+generic-y += preempt.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
-generic-y += preempt.h
-generic-y += hash.h
index dd3bef4b9896c8921f2257cf5fab24399722495d..05710393959f174bc0bf9a8596ef5fbf9bafa391 100644 (file)
@@ -32,7 +32,6 @@
 
 DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
 extern cpumask_t cpu_core_map[NR_CPUS];
-extern int sparc64_multi_core;
 
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
index 1754390a426fb1e3c8eef4f1b947b04271bc794c..a2d10fc64fafd34ace3614383ba0500612da706f 100644 (file)
@@ -42,8 +42,6 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
 #define topology_core_id(cpu)                  (cpu_data(cpu).core_id)
 #define topology_core_cpumask(cpu)             (&cpu_core_map[cpu])
 #define topology_thread_cpumask(cpu)           (&per_cpu(cpu_sibling_map, cpu))
-#define mc_capable()                           (sparc64_multi_core)
-#define smt_capable()                          (sparc64_multi_core)
 #endif /* CONFIG_SMP */
 
 extern cpumask_t cpu_core_map[NR_CPUS];
index b90bf23e3aabf36950c03383afe215a8af6006ee..a1a4400d40258acbfa00b08b9672604e8cc22935 100644 (file)
@@ -896,10 +896,6 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
 
        mdesc_iterate_over_cpus(fill_in_one_cpu, NULL, mask);
 
-#ifdef CONFIG_SMP
-       sparc64_multi_core = 1;
-#endif
-
        hp = mdesc_grab();
 
        set_core_ids(hp);
index 32a280ec38c1d6edef71b5576ce474221726ec1e..d7b4967f8fa6209307854c367347f88d14103839 100644 (file)
@@ -58,9 +58,12 @@ void arch_cpu_idle(void)
 {
        if (tlb_type != hypervisor) {
                touch_nmi_watchdog();
+               local_irq_enable();
        } else {
                unsigned long pstate;
 
+               local_irq_enable();
+
                 /* The sun4v sleeping code requires that we have PSTATE.IE cleared over
                  * the cpu sleep hypervisor call.
                  */
@@ -82,7 +85,6 @@ void arch_cpu_idle(void)
                        : "=&r" (pstate)
                        : "i" (PSTATE_IE));
        }
-       local_irq_enable();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index 6b39125eb9271d986b32896fcd35015cbd752ef8..9a690d39c01b50f2465263063246565479a0c126 100644 (file)
@@ -555,9 +555,6 @@ static void *fill_in_one_cpu(struct device_node *dp, int cpuid, int arg)
 
                cpu_data(cpuid).core_id = portid + 1;
                cpu_data(cpuid).proc_id = portid;
-#ifdef CONFIG_SMP
-               sparc64_multi_core = 1;
-#endif
        } else {
                cpu_data(cpuid).dcache_size =
                        of_getintprop_default(dp, "dcache-size", 16 * 1024);
index b085311dcd0ea9f81840e1fc2550c4f870e984eb..9781048161ab8865a3ce203074d4067312989b95 100644 (file)
@@ -53,8 +53,6 @@
 
 #include "cpumap.h"
 
-int sparc64_multi_core __read_mostly;
-
 DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
 cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
        { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
index 87729fff13b96729cd6cadcc3825dba172ab1d7c..33a17e7b3ccd0fad8477d4c5b051cca1b24f248a 100644 (file)
@@ -189,7 +189,8 @@ linux_sparc_syscall32:
         mov    %i0, %l5                                ! IEU1
 5:     call    %l7                                     ! CTI   Group brk forced
         srl    %i5, 0, %o5                             ! IEU1
-       ba,a,pt %xcc, 3f
+       ba,pt   %xcc, 3f
+        sra    %o0, 0, %o0
 
        /* Linux native system calls enter here... */
        .align  32
@@ -217,7 +218,6 @@ linux_sparc_syscall:
 3:     stx     %o0, [%sp + PTREGS_OFF + PT_V9_I0]
 ret_sys_call:
        ldx     [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
-       sra     %o0, 0, %o0
        mov     %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
        sllx    %g2, 32, %g2
 
index 869023abe5a4440c3ec08777e987c7abcc9777b8..cfbe53c17b0dbb61b25f8ae48c0f3017f307cc6f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
 #include <linux/kdebug.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/log2.h>
@@ -62,6 +63,7 @@ extern unsigned long last_valid_pfn;
 static pgd_t *srmmu_swapper_pg_dir;
 
 const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+EXPORT_SYMBOL(sparc32_cachetlb_ops);
 
 #ifdef CONFIG_SMP
 const struct sparc32_cachetlb_ops *local_ops;
index 3b3a360b429a8ac78b5089a98c09027aa40634a3..f5d506fdddad3dea459aa97308e9a8872f34ffe8 100644 (file)
@@ -273,7 +273,7 @@ void __init pgtable_cache_init(void)
                prom_halt();
        }
 
-       for (i = 0; i < 8; i++) {
+       for (i = 0; i < ARRAY_SIZE(tsb_cache_names); i++) {
                unsigned long size = 8192 << i;
                const char *name = tsb_cache_names[i];
 
index 3793c75e45d982fb4ae72fb7a17c0f2478e98fea..0aa5675e7025e1f791da57ed9bc52133dd4121da 100644 (file)
@@ -11,6 +11,7 @@ generic-y += errno.h
 generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -18,12 +19,14 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += msgbuf.h
 generic-y += mutex.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sembuf.h
@@ -38,5 +41,3 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 88a330dcdede1b06b85b1d7eba2da5580a97e99b..a5e4b6068213f4f147639a9ba428b120d8e9c886 100644 (file)
@@ -1,8 +1,28 @@
-generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
-generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
-generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
-generic-y += switch_to.h clkdev.h
-generic-y += trace_clock.h
-generic-y += preempt.h
-generic-y += hash.h
 generic-y += barrier.h
+generic-y += bug.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += emergency-restart.h
+generic-y += exec.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += hash.h
+generic-y += hw_irq.h
+generic-y += io.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += mcs_spinlock.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += preempt.h
+generic-y += sections.h
+generic-y += switch_to.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += xor.h
index 3ef4f9d9bf5deaf74f06d254f8d6b6c3fae75ba6..1e5fb872a4aa60d3292705b8bc34a69a9038d85a 100644 (file)
@@ -16,6 +16,7 @@ generic-y += fcntl.h
 generic-y += ftrace.h
 generic-y += futex.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
@@ -24,6 +25,7 @@ generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
 generic-y += local.h
+generic-y += mcs_spinlock.h
 generic-y += mman.h
 generic-y += module.h
 generic-y += msgbuf.h
@@ -32,6 +34,7 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -60,5 +63,3 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 940e50ebfafa66c76b9f0ed00d8928ed4e145fcb..8453fe1342eaf137bcf2c707bc93ac4717ee27db 100644 (file)
@@ -444,6 +444,7 @@ config X86_INTEL_MID
        bool "Intel MID platform support"
        depends on X86_32
        depends on X86_EXTENDED_PLATFORM
+       depends on X86_PLATFORM_DEVICES
        depends on PCI
        depends on PCI_GOANY
        depends on X86_IO_APIC
@@ -1051,9 +1052,9 @@ config MICROCODE_INTEL
          This options enables microcode patch loading support for Intel
          processors.
 
-         For latest news and information on obtaining all the required
-         Intel ingredients for this driver, check:
-         <http://www.urbanmyth.org/microcode/>.
+         For the current Intel microcode data package go to
+         <https://downloadcenter.intel.com> and search for
+         'Linux Processor Microcode Data File'.
 
 config MICROCODE_AMD
        bool "AMD microcode loading support"
@@ -1584,6 +1585,20 @@ config EFI_STUB
 
          See Documentation/efi-stub.txt for more information.
 
+config EFI_MIXED
+       bool "EFI mixed-mode support"
+       depends on EFI_STUB && X86_64
+       ---help---
+          Enabling this feature allows a 64-bit kernel to be booted
+          on a 32-bit firmware, provided that your CPU supports 64-bit
+          mode.
+
+          Note that it is not possible to boot a mixed-mode enabled
+          kernel via the EFI boot stub - a bootloader that supports
+          the EFI handover protocol must be used.
+
+          If unsure, say N.
+
 config SECCOMP
        def_bool y
        prompt "Enable seccomp to safely compute untrusted bytecode"
index c026cca5602c6fe5c84619f0b43b2fe7c3bb2382..f3aaf231b4e590fad07b58b51583eb6693a924cd 100644 (file)
@@ -341,10 +341,6 @@ config X86_USE_3DNOW
        def_bool y
        depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML
 
-config X86_OOSTORE
-       def_bool y
-       depends on (MWINCHIP3D || MWINCHIPC6) && MTRR
-
 #
 # P6_NOPs are a relatively minor optimization that require a family >=
 # 6 processor, except that it is broken on certain VIA chips.
index 0f3621ed1db6f9d613211a1209374e69ab6cfb0e..61bd2ad94281884f13b70f3bb9e397fdcef9338a 100644 (file)
@@ -81,6 +81,15 @@ config X86_PTDUMP
          kernel.
          If in doubt, say "N"
 
+config EFI_PGT_DUMP
+       bool "Dump the EFI pagetable"
+       depends on EFI && X86_PTDUMP
+       ---help---
+         Enable this if you want to dump the EFI page table before
+         enabling virtual mode. This can be used to debug miscellaneous
+         issues with the mapping of the EFI runtime regions into that
+         table.
+
 config DEBUG_RODATA
        bool "Write protect kernel read-only data structures"
        default y
@@ -184,6 +193,7 @@ config HAVE_MMIOTRACE_SUPPORT
 config X86_DECODER_SELFTEST
        bool "x86 instruction decoder selftest"
        depends on DEBUG_KERNEL && KPROBES
+       depends on !COMPILE_TEST
        ---help---
         Perform x86 instruction decoder selftests at build time.
         This option is useful for checking the sanity of x86 instruction
index eeda43abed6ec8d48837abaa5f6c18a40c38785a..3b9348a0c1a496244575dced7f89303ae78b168d 100644 (file)
@@ -82,8 +82,8 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
-        # Don't autogenerate MMX or SSE instructions
-        KBUILD_CFLAGS += -mno-mmx -mno-sse
+        # Don't autogenerate traditional x87, MMX or SSE instructions
+        KBUILD_CFLAGS += -mno-mmx -mno-sse -mno-80387 -mno-fp-ret-in-387
 
        # Use -mpreferred-stack-boundary=3 if supported.
        KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
@@ -152,6 +152,7 @@ cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTI
 
 # does binutils support specific instructions?
 asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
+asinstr += $(call as-instr,crc32l %eax$(comma)%eax,-DCONFIG_AS_CRC32=1)
 avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
 avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
 
index 878df7e88cd4d9c4293d9540432fdd3d7c78fc6e..abb9eba61b500192cd816dd9283fe8c8fb70b858 100644 (file)
@@ -80,7 +80,7 @@ targets += voffset.h
 $(obj)/voffset.h: vmlinux FORCE
        $(call if_changed,voffset)
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
index 90a21f430117d1690f847c8b198e80d6afb3c825..4dbf967da50daab8c7ed9f3952fa08b18b5b6271 100644 (file)
@@ -111,7 +111,7 @@ struct mem_vector {
 };
 
 #define MEM_AVOID_MAX 5
-struct mem_vector mem_avoid[MEM_AVOID_MAX];
+static struct mem_vector mem_avoid[MEM_AVOID_MAX];
 
 static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
 {
@@ -180,7 +180,7 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
 }
 
 /* Does this memory vector overlap a known avoided area? */
-bool mem_avoid_overlap(struct mem_vector *img)
+static bool mem_avoid_overlap(struct mem_vector *img)
 {
        int i;
 
@@ -192,8 +192,9 @@ bool mem_avoid_overlap(struct mem_vector *img)
        return false;
 }
 
-unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN];
-unsigned long slot_max = 0;
+static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
+                          CONFIG_PHYSICAL_ALIGN];
+static unsigned long slot_max;
 
 static void slots_append(unsigned long addr)
 {
index a7677babf946dc406735d94512eca4765b31569d..1e6146137f8e56753aab7d68b0e0b45af3c5fed9 100644 (file)
 
 static efi_system_table_t *sys_table;
 
+static struct efi_config *efi_early;
+
+#define efi_call_early(f, ...)                                         \
+       efi_early->call(efi_early->f, __VA_ARGS__);
+
+#define BOOT_SERVICES(bits)                                            \
+static void setup_boot_services##bits(struct efi_config *c)            \
+{                                                                      \
+       efi_system_table_##bits##_t *table;                             \
+       efi_boot_services_##bits##_t *bt;                               \
+                                                                       \
+       table = (typeof(table))sys_table;                               \
+                                                                       \
+       c->text_output = table->con_out;                                \
+                                                                       \
+       bt = (typeof(bt))(unsigned long)(table->boottime);              \
+                                                                       \
+       c->allocate_pool = bt->allocate_pool;                           \
+       c->allocate_pages = bt->allocate_pages;                         \
+       c->get_memory_map = bt->get_memory_map;                         \
+       c->free_pool = bt->free_pool;                                   \
+       c->free_pages = bt->free_pages;                                 \
+       c->locate_handle = bt->locate_handle;                           \
+       c->handle_protocol = bt->handle_protocol;                       \
+       c->exit_boot_services = bt->exit_boot_services;                 \
+}
+BOOT_SERVICES(32);
+BOOT_SERVICES(64);
 
-#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
+static void efi_printk(efi_system_table_t *, char *);
+static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+
+static efi_status_t
+__file_size32(void *__fh, efi_char16_t *filename_16,
+             void **handle, u64 *file_sz)
+{
+       efi_file_handle_32_t *h, *fh = __fh;
+       efi_file_info_t *info;
+       efi_status_t status;
+       efi_guid_t info_guid = EFI_FILE_INFO_ID;
+       u32 info_sz;
+
+       status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
+                                EFI_FILE_MODE_READ, (u64)0);
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to open file: ");
+               efi_char16_printk(sys_table, filename_16);
+               efi_printk(sys_table, "\n");
+               return status;
+       }
+
+       *handle = h;
+
+       info_sz = 0;
+       status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
+                                &info_sz, NULL);
+       if (status != EFI_BUFFER_TOO_SMALL) {
+               efi_printk(sys_table, "Failed to get file info size\n");
+               return status;
+       }
+
+grow:
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               info_sz, (void **)&info);
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to alloc mem for file info\n");
+               return status;
+       }
+
+       status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
+                                &info_sz, info);
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               efi_call_early(free_pool, info);
+               goto grow;
+       }
+
+       *file_sz = info->file_size;
+       efi_call_early(free_pool, info);
+
+       if (status != EFI_SUCCESS)
+               efi_printk(sys_table, "Failed to get initrd info\n");
+
+       return status;
+}
+
+static efi_status_t
+__file_size64(void *__fh, efi_char16_t *filename_16,
+             void **handle, u64 *file_sz)
+{
+       efi_file_handle_64_t *h, *fh = __fh;
+       efi_file_info_t *info;
+       efi_status_t status;
+       efi_guid_t info_guid = EFI_FILE_INFO_ID;
+       u32 info_sz;
 
+       status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
+                                EFI_FILE_MODE_READ, (u64)0);
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to open file: ");
+               efi_char16_printk(sys_table, filename_16);
+               efi_printk(sys_table, "\n");
+               return status;
+       }
 
+       *handle = h;
+
+       info_sz = 0;
+       status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
+                                &info_sz, NULL);
+       if (status != EFI_BUFFER_TOO_SMALL) {
+               efi_printk(sys_table, "Failed to get file info size\n");
+               return status;
+       }
+
+grow:
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               info_sz, (void **)&info);
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to alloc mem for file info\n");
+               return status;
+       }
+
+       status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
+                                &info_sz, info);
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               efi_call_early(free_pool, info);
+               goto grow;
+       }
+
+       *file_sz = info->file_size;
+       efi_call_early(free_pool, info);
+
+       if (status != EFI_SUCCESS)
+               efi_printk(sys_table, "Failed to get initrd info\n");
+
+       return status;
+}
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table, void *__fh,
+             efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+       if (efi_early->is64)
+               return __file_size64(__fh, filename_16, handle, file_sz);
+
+       return __file_size32(__fh, filename_16, handle, file_sz);
+}
+
+static inline efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
+{
+       unsigned long func;
+
+       if (efi_early->is64) {
+               efi_file_handle_64_t *fh = __fh;
+
+               func = (unsigned long)fh->read;
+               return efi_early->call(func, handle, size, addr);
+       } else {
+               efi_file_handle_32_t *fh = __fh;
+
+               func = (unsigned long)fh->read;
+               return efi_early->call(func, handle, size, addr);
+       }
+}
+
+static inline efi_status_t efi_file_close(void *__fh, void *handle)
+{
+       if (efi_early->is64) {
+               efi_file_handle_64_t *fh = __fh;
+
+               return efi_early->call((unsigned long)fh->close, handle);
+       } else {
+               efi_file_handle_32_t *fh = __fh;
+
+               return efi_early->call((unsigned long)fh->close, handle);
+       }
+}
+
+static inline efi_status_t __open_volume32(void *__image, void **__fh)
+{
+       efi_file_io_interface_t *io;
+       efi_loaded_image_32_t *image = __image;
+       efi_file_handle_32_t *fh;
+       efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+       efi_status_t status;
+       void *handle = (void *)(unsigned long)image->device_handle;
+       unsigned long func;
+
+       status = efi_call_early(handle_protocol, handle,
+                               &fs_proto, (void **)&io);
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to handle fs_proto\n");
+               return status;
+       }
+
+       func = (unsigned long)io->open_volume;
+       status = efi_early->call(func, io, &fh);
+       if (status != EFI_SUCCESS)
+               efi_printk(sys_table, "Failed to open volume\n");
+
+       *__fh = fh;
+       return status;
+}
+
+static inline efi_status_t __open_volume64(void *__image, void **__fh)
+{
+       efi_file_io_interface_t *io;
+       efi_loaded_image_64_t *image = __image;
+       efi_file_handle_64_t *fh;
+       efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+       efi_status_t status;
+       void *handle = (void *)(unsigned long)image->device_handle;
+       unsigned long func;
+
+       status = efi_call_early(handle_protocol, handle,
+                               &fs_proto, (void **)&io);
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to handle fs_proto\n");
+               return status;
+       }
+
+       func = (unsigned long)io->open_volume;
+       status = efi_early->call(func, io, &fh);
+       if (status != EFI_SUCCESS)
+               efi_printk(sys_table, "Failed to open volume\n");
+
+       *__fh = fh;
+       return status;
+}
+
+static inline efi_status_t
+efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
+{
+       if (efi_early->is64)
+               return __open_volume64(__image, __fh);
+
+       return __open_volume32(__image, __fh);
+}
+
+static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
+{
+       unsigned long output_string;
+       size_t offset;
+
+       if (efi_early->is64) {
+               struct efi_simple_text_output_protocol_64 *out;
+               u64 *func;
+
+               offset = offsetof(typeof(*out), output_string);
+               output_string = efi_early->text_output + offset;
+               func = (u64 *)output_string;
+
+               efi_early->call(*func, efi_early->text_output, str);
+       } else {
+               struct efi_simple_text_output_protocol_32 *out;
+               u32 *func;
+
+               offset = offsetof(typeof(*out), output_string);
+               output_string = efi_early->text_output + offset;
+               func = (u32 *)output_string;
+
+               efi_early->call(*func, efi_early->text_output, str);
+       }
+}
+
+#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
 
 static void find_bits(unsigned long mask, u8 *pos, u8 *size)
 {
@@ -47,105 +309,97 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
        *size = len;
 }
 
-static efi_status_t setup_efi_pci(struct boot_params *params)
+static efi_status_t
+__setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
 {
-       efi_pci_io_protocol *pci;
+       struct pci_setup_rom *rom = NULL;
        efi_status_t status;
-       void **pci_handle;
-       efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
-       unsigned long nr_pci, size = 0;
-       int i;
-       struct setup_data *data;
+       unsigned long size;
+       uint64_t attributes;
 
-       data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
+       status = efi_early->call(pci->attributes, pci,
+                                EfiPciIoAttributeOperationGet, 0, 0,
+                                &attributes);
+       if (status != EFI_SUCCESS)
+               return status;
 
-       while (data && data->next)
-               data = (struct setup_data *)(unsigned long)data->next;
+       if (!pci->romimage || !pci->romsize)
+               return EFI_INVALID_PARAMETER;
 
-       status = efi_call_phys5(sys_table->boottime->locate_handle,
-                               EFI_LOCATE_BY_PROTOCOL, &pci_proto,
-                               NULL, &size, pci_handle);
+       size = pci->romsize + sizeof(*rom);
 
-       if (status == EFI_BUFFER_TOO_SMALL) {
-               status = efi_call_phys3(sys_table->boottime->allocate_pool,
-                                       EFI_LOADER_DATA, size, &pci_handle);
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
+       if (status != EFI_SUCCESS)
+               return status;
 
-               if (status != EFI_SUCCESS)
-                       return status;
+       memset(rom, 0, sizeof(*rom));
 
-               status = efi_call_phys5(sys_table->boottime->locate_handle,
-                                       EFI_LOCATE_BY_PROTOCOL, &pci_proto,
-                                       NULL, &size, pci_handle);
-       }
+       rom->data.type = SETUP_PCI;
+       rom->data.len = size - sizeof(struct setup_data);
+       rom->data.next = 0;
+       rom->pcilen = pci->romsize;
+       *__rom = rom;
 
-       if (status != EFI_SUCCESS)
-               goto free_handle;
-
-       nr_pci = size / sizeof(void *);
-       for (i = 0; i < nr_pci; i++) {
-               void *h = pci_handle[i];
-               uint64_t attributes;
-               struct pci_setup_rom *rom;
+       status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+                                PCI_VENDOR_ID, 1, &(rom->vendor));
 
-               status = efi_call_phys3(sys_table->boottime->handle_protocol,
-                                       h, &pci_proto, &pci);
+       if (status != EFI_SUCCESS)
+               goto free_struct;
 
-               if (status != EFI_SUCCESS)
-                       continue;
+       status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+                                PCI_DEVICE_ID, 1, &(rom->devid));
 
-               if (!pci)
-                       continue;
+       if (status != EFI_SUCCESS)
+               goto free_struct;
 
-#ifdef CONFIG_X86_64
-               status = efi_call_phys4(pci->attributes, pci,
-                                       EfiPciIoAttributeOperationGet, 0,
-                                       &attributes);
-#else
-               status = efi_call_phys5(pci->attributes, pci,
-                                       EfiPciIoAttributeOperationGet, 0, 0,
-                                       &attributes);
-#endif
-               if (status != EFI_SUCCESS)
-                       continue;
+       status = efi_early->call(pci->get_location, pci, &(rom->segment),
+                                &(rom->bus), &(rom->device), &(rom->function));
 
-               if (!pci->romimage || !pci->romsize)
-                       continue;
+       if (status != EFI_SUCCESS)
+               goto free_struct;
 
-               size = pci->romsize + sizeof(*rom);
+       memcpy(rom->romdata, pci->romimage, pci->romsize);
+       return status;
 
-               status = efi_call_phys3(sys_table->boottime->allocate_pool,
-                               EFI_LOADER_DATA, size, &rom);
+free_struct:
+       efi_call_early(free_pool, rom);
+       return status;
+}
 
-               if (status != EFI_SUCCESS)
-                       continue;
+static efi_status_t
+setup_efi_pci32(struct boot_params *params, void **pci_handle,
+               unsigned long size)
+{
+       efi_pci_io_protocol_32 *pci = NULL;
+       efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+       u32 *handles = (u32 *)(unsigned long)pci_handle;
+       efi_status_t status;
+       unsigned long nr_pci;
+       struct setup_data *data;
+       int i;
 
-               rom->data.type = SETUP_PCI;
-               rom->data.len = size - sizeof(struct setup_data);
-               rom->data.next = 0;
-               rom->pcilen = pci->romsize;
+       data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
 
-               status = efi_call_phys5(pci->pci.read, pci,
-                                       EfiPciIoWidthUint16, PCI_VENDOR_ID,
-                                       1, &(rom->vendor));
+       while (data && data->next)
+               data = (struct setup_data *)(unsigned long)data->next;
 
-               if (status != EFI_SUCCESS)
-                       goto free_struct;
+       nr_pci = size / sizeof(u32);
+       for (i = 0; i < nr_pci; i++) {
+               struct pci_setup_rom *rom = NULL;
+               u32 h = handles[i];
 
-               status = efi_call_phys5(pci->pci.read, pci,
-                                       EfiPciIoWidthUint16, PCI_DEVICE_ID,
-                                       1, &(rom->devid));
+               status = efi_call_early(handle_protocol, h,
+                                       &pci_proto, (void **)&pci);
 
                if (status != EFI_SUCCESS)
-                       goto free_struct;
+                       continue;
 
-               status = efi_call_phys5(pci->get_location, pci,
-                                       &(rom->segment), &(rom->bus),
-                                       &(rom->device), &(rom->function));
+               if (!pci)
+                       continue;
 
+               status = __setup_efi_pci32(pci, &rom);
                if (status != EFI_SUCCESS)
-                       goto free_struct;
-
-               memcpy(rom->romdata, pci->romimage, pci->romsize);
+                       continue;
 
                if (data)
                        data->next = (unsigned long)rom;
@@ -154,105 +408,155 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
 
                data = (struct setup_data *)rom;
 
-               continue;
-       free_struct:
-               efi_call_phys1(sys_table->boottime->free_pool, rom);
        }
 
-free_handle:
-       efi_call_phys1(sys_table->boottime->free_pool, pci_handle);
        return status;
 }
 
-/*
- * See if we have Graphics Output Protocol
- */
-static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
-                             unsigned long size)
+static efi_status_t
+__setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
 {
-       struct efi_graphics_output_protocol *gop, *first_gop;
-       struct efi_pixel_bitmask pixel_info;
-       unsigned long nr_gops;
+       struct pci_setup_rom *rom;
        efi_status_t status;
-       void **gop_handle;
-       u16 width, height;
-       u32 fb_base, fb_size;
-       u32 pixels_per_scan_line;
-       int pixel_format;
-       int i;
+       unsigned long size;
+       uint64_t attributes;
 
-       status = efi_call_phys3(sys_table->boottime->allocate_pool,
-                               EFI_LOADER_DATA, size, &gop_handle);
+       status = efi_early->call(pci->attributes, pci,
+                                EfiPciIoAttributeOperationGet, 0,
+                                &attributes);
        if (status != EFI_SUCCESS)
                return status;
 
-       status = efi_call_phys5(sys_table->boottime->locate_handle,
-                               EFI_LOCATE_BY_PROTOCOL, proto,
-                               NULL, &size, gop_handle);
+       if (!pci->romimage || !pci->romsize)
+               return EFI_INVALID_PARAMETER;
+
+       size = pci->romsize + sizeof(*rom);
+
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
        if (status != EFI_SUCCESS)
-               goto free_handle;
+               return status;
 
-       first_gop = NULL;
+       rom->data.type = SETUP_PCI;
+       rom->data.len = size - sizeof(struct setup_data);
+       rom->data.next = 0;
+       rom->pcilen = pci->romsize;
+       *__rom = rom;
 
-       nr_gops = size / sizeof(void *);
-       for (i = 0; i < nr_gops; i++) {
-               struct efi_graphics_output_mode_info *info;
-               efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
-               bool conout_found = false;
-               void *dummy;
-               void *h = gop_handle[i];
+       status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+                                PCI_VENDOR_ID, 1, &(rom->vendor));
+
+       if (status != EFI_SUCCESS)
+               goto free_struct;
+
+       status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
+                                PCI_DEVICE_ID, 1, &(rom->devid));
+
+       if (status != EFI_SUCCESS)
+               goto free_struct;
+
+       status = efi_early->call(pci->get_location, pci, &(rom->segment),
+                                &(rom->bus), &(rom->device), &(rom->function));
+
+       if (status != EFI_SUCCESS)
+               goto free_struct;
+
+       memcpy(rom->romdata, pci->romimage, pci->romsize);
+       return status;
+
+free_struct:
+       efi_call_early(free_pool, rom);
+       return status;
+
+}
+
+static efi_status_t
+setup_efi_pci64(struct boot_params *params, void **pci_handle,
+               unsigned long size)
+{
+       efi_pci_io_protocol_64 *pci = NULL;
+       efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+       u64 *handles = (u64 *)(unsigned long)pci_handle;
+       efi_status_t status;
+       unsigned long nr_pci;
+       struct setup_data *data;
+       int i;
+
+       data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
+
+       while (data && data->next)
+               data = (struct setup_data *)(unsigned long)data->next;
+
+       nr_pci = size / sizeof(u64);
+       for (i = 0; i < nr_pci; i++) {
+               struct pci_setup_rom *rom = NULL;
+               u64 h = handles[i];
+
+               status = efi_call_early(handle_protocol, h,
+                                       &pci_proto, (void **)&pci);
 
-               status = efi_call_phys3(sys_table->boottime->handle_protocol,
-                                       h, proto, &gop);
                if (status != EFI_SUCCESS)
                        continue;
 
-               status = efi_call_phys3(sys_table->boottime->handle_protocol,
-                                       h, &conout_proto, &dummy);
+               if (!pci)
+                       continue;
 
-               if (status == EFI_SUCCESS)
-                       conout_found = true;
+               status = __setup_efi_pci64(pci, &rom);
+               if (status != EFI_SUCCESS)
+                       continue;
 
-               status = efi_call_phys4(gop->query_mode, gop,
-                                       gop->mode->mode, &size, &info);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
-                       /*
-                        * Systems that use the UEFI Console Splitter may
-                        * provide multiple GOP devices, not all of which are
-                        * backed by real hardware. The workaround is to search
-                        * for a GOP implementing the ConOut protocol, and if
-                        * one isn't found, to just fall back to the first GOP.
-                        */
-                       width = info->horizontal_resolution;
-                       height = info->vertical_resolution;
-                       fb_base = gop->mode->frame_buffer_base;
-                       fb_size = gop->mode->frame_buffer_size;
-                       pixel_format = info->pixel_format;
-                       pixel_info = info->pixel_information;
-                       pixels_per_scan_line = info->pixels_per_scan_line;
+               if (data)
+                       data->next = (unsigned long)rom;
+               else
+                       params->hdr.setup_data = (unsigned long)rom;
+
+               data = (struct setup_data *)rom;
 
-                       /*
-                        * Once we've found a GOP supporting ConOut,
-                        * don't bother looking any further.
-                        */
-                       first_gop = gop;
-                       if (conout_found)
-                               break;
-               }
        }
 
-       /* Did we find any GOPs? */
-       if (!first_gop)
+       return status;
+}
+
+static efi_status_t setup_efi_pci(struct boot_params *params)
+{
+       efi_status_t status;
+       void **pci_handle = NULL;
+       efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
+       unsigned long size = 0;
+
+       status = efi_call_early(locate_handle,
+                               EFI_LOCATE_BY_PROTOCOL,
+                               &pci_proto, NULL, &size, pci_handle);
+
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               status = efi_call_early(allocate_pool,
+                                       EFI_LOADER_DATA,
+                                       size, (void **)&pci_handle);
+
+               if (status != EFI_SUCCESS)
+                       return status;
+
+               status = efi_call_early(locate_handle,
+                                       EFI_LOCATE_BY_PROTOCOL, &pci_proto,
+                                       NULL, &size, pci_handle);
+       }
+
+       if (status != EFI_SUCCESS)
                goto free_handle;
 
-       /* EFI framebuffer */
-       si->orig_video_isVGA = VIDEO_TYPE_EFI;
+       if (efi_early->is64)
+               status = setup_efi_pci64(params, pci_handle, size);
+       else
+               status = setup_efi_pci32(params, pci_handle, size);
 
-       si->lfb_width = width;
-       si->lfb_height = height;
-       si->lfb_base = fb_base;
-       si->pages = 1;
+free_handle:
+       efi_call_early(free_pool, pci_handle);
+       return status;
+}
 
+static void
+setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+                struct efi_pixel_bitmask pixel_info, int pixel_format)
+{
        if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
                si->lfb_depth = 32;
                si->lfb_linelength = pixels_per_scan_line * 4;
@@ -297,62 +601,319 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
                si->rsvd_size = 0;
                si->rsvd_pos = 0;
        }
+}
+
+static efi_status_t
+__gop_query32(struct efi_graphics_output_protocol_32 *gop32,
+             struct efi_graphics_output_mode_info **info,
+             unsigned long *size, u32 *fb_base)
+{
+       struct efi_graphics_output_protocol_mode_32 *mode;
+       efi_status_t status;
+       unsigned long m;
+
+       m = gop32->mode;
+       mode = (struct efi_graphics_output_protocol_mode_32 *)m;
+
+       status = efi_early->call(gop32->query_mode, gop32,
+                                mode->mode, size, info);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       *fb_base = mode->frame_buffer_base;
+       return status;
+}
+
+static efi_status_t
+setup_gop32(struct screen_info *si, efi_guid_t *proto,
+           unsigned long size, void **gop_handle)
+{
+       struct efi_graphics_output_protocol_32 *gop32, *first_gop;
+       unsigned long nr_gops;
+       u16 width, height;
+       u32 pixels_per_scan_line;
+       u32 fb_base;
+       struct efi_pixel_bitmask pixel_info;
+       int pixel_format;
+       efi_status_t status;
+       u32 *handles = (u32 *)(unsigned long)gop_handle;
+       int i;
+
+       first_gop = NULL;
+       gop32 = NULL;
+
+       nr_gops = size / sizeof(u32);
+       for (i = 0; i < nr_gops; i++) {
+               struct efi_graphics_output_mode_info *info = NULL;
+               efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+               bool conout_found = false;
+               void *dummy = NULL;
+               u32 h = handles[i];
+
+               status = efi_call_early(handle_protocol, h,
+                                       proto, (void **)&gop32);
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               status = efi_call_early(handle_protocol, h,
+                                       &conout_proto, &dummy);
+               if (status == EFI_SUCCESS)
+                       conout_found = true;
+
+               status = __gop_query32(gop32, &info, &size, &fb_base);
+               if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+                       /*
+                        * Systems that use the UEFI Console Splitter may
+                        * provide multiple GOP devices, not all of which are
+                        * backed by real hardware. The workaround is to search
+                        * for a GOP implementing the ConOut protocol, and if
+                        * one isn't found, to just fall back to the first GOP.
+                        */
+                       width = info->horizontal_resolution;
+                       height = info->vertical_resolution;
+                       pixel_format = info->pixel_format;
+                       pixel_info = info->pixel_information;
+                       pixels_per_scan_line = info->pixels_per_scan_line;
+
+                       /*
+                        * Once we've found a GOP supporting ConOut,
+                        * don't bother looking any further.
+                        */
+                       first_gop = gop32;
+                       if (conout_found)
+                               break;
+               }
+       }
+
+       /* Did we find any GOPs? */
+       if (!first_gop)
+               goto out;
+
+       /* EFI framebuffer */
+       si->orig_video_isVGA = VIDEO_TYPE_EFI;
+
+       si->lfb_width = width;
+       si->lfb_height = height;
+       si->lfb_base = fb_base;
+       si->pages = 1;
+
+       setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
 
        si->lfb_size = si->lfb_linelength * si->lfb_height;
 
        si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+out:
+       return status;
+}
 
-free_handle:
-       efi_call_phys1(sys_table->boottime->free_pool, gop_handle);
+static efi_status_t
+__gop_query64(struct efi_graphics_output_protocol_64 *gop64,
+             struct efi_graphics_output_mode_info **info,
+             unsigned long *size, u32 *fb_base)
+{
+       struct efi_graphics_output_protocol_mode_64 *mode;
+       efi_status_t status;
+       unsigned long m;
+
+       m = gop64->mode;
+       mode = (struct efi_graphics_output_protocol_mode_64 *)m;
+
+       status = efi_early->call(gop64->query_mode, gop64,
+                                mode->mode, size, info);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       *fb_base = mode->frame_buffer_base;
+       return status;
+}
+
+static efi_status_t
+setup_gop64(struct screen_info *si, efi_guid_t *proto,
+           unsigned long size, void **gop_handle)
+{
+       struct efi_graphics_output_protocol_64 *gop64, *first_gop;
+       unsigned long nr_gops;
+       u16 width, height;
+       u32 pixels_per_scan_line;
+       u32 fb_base;
+       struct efi_pixel_bitmask pixel_info;
+       int pixel_format;
+       efi_status_t status;
+       u64 *handles = (u64 *)(unsigned long)gop_handle;
+       int i;
+
+       first_gop = NULL;
+       gop64 = NULL;
+
+       nr_gops = size / sizeof(u64);
+       for (i = 0; i < nr_gops; i++) {
+               struct efi_graphics_output_mode_info *info = NULL;
+               efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+               bool conout_found = false;
+               void *dummy = NULL;
+               u64 h = handles[i];
+
+               status = efi_call_early(handle_protocol, h,
+                                       proto, (void **)&gop64);
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               status = efi_call_early(handle_protocol, h,
+                                       &conout_proto, &dummy);
+               if (status == EFI_SUCCESS)
+                       conout_found = true;
+
+               status = __gop_query64(gop64, &info, &size, &fb_base);
+               if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+                       /*
+                        * Systems that use the UEFI Console Splitter may
+                        * provide multiple GOP devices, not all of which are
+                        * backed by real hardware. The workaround is to search
+                        * for a GOP implementing the ConOut protocol, and if
+                        * one isn't found, to just fall back to the first GOP.
+                        */
+                       width = info->horizontal_resolution;
+                       height = info->vertical_resolution;
+                       pixel_format = info->pixel_format;
+                       pixel_info = info->pixel_information;
+                       pixels_per_scan_line = info->pixels_per_scan_line;
+
+                       /*
+                        * Once we've found a GOP supporting ConOut,
+                        * don't bother looking any further.
+                        */
+                       first_gop = gop64;
+                       if (conout_found)
+                               break;
+               }
+       }
+
+       /* Did we find any GOPs? */
+       if (!first_gop)
+               goto out;
+
+       /* EFI framebuffer */
+       si->orig_video_isVGA = VIDEO_TYPE_EFI;
+
+       si->lfb_width = width;
+       si->lfb_height = height;
+       si->lfb_base = fb_base;
+       si->pages = 1;
+
+       setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+
+       si->lfb_size = si->lfb_linelength * si->lfb_height;
+
+       si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+out:
        return status;
 }
 
 /*
- * See if we have Universal Graphics Adapter (UGA) protocol
+ * See if we have Graphics Output Protocol
  */
-static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
+static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
                              unsigned long size)
 {
-       struct efi_uga_draw_protocol *uga, *first_uga;
-       unsigned long nr_ugas;
        efi_status_t status;
-       u32 width, height;
-       void **uga_handle = NULL;
-       int i;
+       void **gop_handle = NULL;
 
-       status = efi_call_phys3(sys_table->boottime->allocate_pool,
-                               EFI_LOADER_DATA, size, &uga_handle);
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               size, (void **)&gop_handle);
        if (status != EFI_SUCCESS)
                return status;
 
-       status = efi_call_phys5(sys_table->boottime->locate_handle,
-                               EFI_LOCATE_BY_PROTOCOL, uga_proto,
-                               NULL, &size, uga_handle);
+       status = efi_call_early(locate_handle,
+                               EFI_LOCATE_BY_PROTOCOL,
+                               proto, NULL, &size, gop_handle);
        if (status != EFI_SUCCESS)
                goto free_handle;
 
+       if (efi_early->is64)
+               status = setup_gop64(si, proto, size, gop_handle);
+       else
+               status = setup_gop32(si, proto, size, gop_handle);
+
+free_handle:
+       efi_call_early(free_pool, gop_handle);
+       return status;
+}
+
+static efi_status_t
+setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
+{
+       struct efi_uga_draw_protocol *uga = NULL, *first_uga;
+       efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
+       unsigned long nr_ugas;
+       u32 *handles = (u32 *)uga_handle;;
+       efi_status_t status;
+       int i;
+
        first_uga = NULL;
+       nr_ugas = size / sizeof(u32);
+       for (i = 0; i < nr_ugas; i++) {
+               efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
+               u32 w, h, depth, refresh;
+               void *pciio;
+               u32 handle = handles[i];
+
+               status = efi_call_early(handle_protocol, handle,
+                                       &uga_proto, (void **)&uga);
+               if (status != EFI_SUCCESS)
+                       continue;
+
+               efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
+
+               status = efi_early->call((unsigned long)uga->get_mode, uga,
+                                        &w, &h, &depth, &refresh);
+               if (status == EFI_SUCCESS && (!first_uga || pciio)) {
+                       *width = w;
+                       *height = h;
+
+                       /*
+                        * Once we've found a UGA supporting PCIIO,
+                        * don't bother looking any further.
+                        */
+                       if (pciio)
+                               break;
 
-       nr_ugas = size / sizeof(void *);
+                       first_uga = uga;
+               }
+       }
+
+       return status;
+}
+
+static efi_status_t
+setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
+{
+       struct efi_uga_draw_protocol *uga = NULL, *first_uga;
+       efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
+       unsigned long nr_ugas;
+       u64 *handles = (u64 *)uga_handle;;
+       efi_status_t status;
+       int i;
+
+       first_uga = NULL;
+       nr_ugas = size / sizeof(u64);
        for (i = 0; i < nr_ugas; i++) {
                efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
-               void *handle = uga_handle[i];
                u32 w, h, depth, refresh;
                void *pciio;
+               u64 handle = handles[i];
 
-               status = efi_call_phys3(sys_table->boottime->handle_protocol,
-                                       handle, uga_proto, &uga);
+               status = efi_call_early(handle_protocol, handle,
+                                       &uga_proto, (void **)&uga);
                if (status != EFI_SUCCESS)
                        continue;
 
-               efi_call_phys3(sys_table->boottime->handle_protocol,
-                              handle, &pciio_proto, &pciio);
+               efi_call_early(handle_protocol, handle, &pciio_proto, &pciio);
 
-               status = efi_call_phys5(uga->get_mode, uga, &w, &h,
-                                       &depth, &refresh);
+               status = efi_early->call((unsigned long)uga->get_mode, uga,
+                                        &w, &h, &depth, &refresh);
                if (status == EFI_SUCCESS && (!first_uga || pciio)) {
-                       width = w;
-                       height = h;
+                       *width = w;
+                       *height = h;
 
                        /*
                         * Once we've found a UGA supporting PCIIO,
@@ -365,7 +926,39 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
                }
        }
 
-       if (!first_uga)
+       return status;
+}
+
+/*
+ * See if we have Universal Graphics Adapter (UGA) protocol
+ */
+static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
+                             unsigned long size)
+{
+       efi_status_t status;
+       u32 width, height;
+       void **uga_handle = NULL;
+
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               size, (void **)&uga_handle);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       status = efi_call_early(locate_handle,
+                               EFI_LOCATE_BY_PROTOCOL,
+                               uga_proto, NULL, &size, uga_handle);
+       if (status != EFI_SUCCESS)
+               goto free_handle;
+
+       height = 0;
+       width = 0;
+
+       if (efi_early->is64)
+               status = setup_uga64(uga_handle, size, &width, &height);
+       else
+               status = setup_uga32(uga_handle, size, &width, &height);
+
+       if (!width && !height)
                goto free_handle;
 
        /* EFI framebuffer */
@@ -384,9 +977,8 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
        si->rsvd_size = 8;
        si->rsvd_pos = 24;
 
-
 free_handle:
-       efi_call_phys1(sys_table->boottime->free_pool, uga_handle);
+       efi_call_early(free_pool, uga_handle);
        return status;
 }
 
@@ -404,29 +996,28 @@ void setup_graphics(struct boot_params *boot_params)
        memset(si, 0, sizeof(*si));
 
        size = 0;
-       status = efi_call_phys5(sys_table->boottime->locate_handle,
-                               EFI_LOCATE_BY_PROTOCOL, &graphics_proto,
-                               NULL, &size, gop_handle);
+       status = efi_call_early(locate_handle,
+                               EFI_LOCATE_BY_PROTOCOL,
+                               &graphics_proto, NULL, &size, gop_handle);
        if (status == EFI_BUFFER_TOO_SMALL)
                status = setup_gop(si, &graphics_proto, size);
 
        if (status != EFI_SUCCESS) {
                size = 0;
-               status = efi_call_phys5(sys_table->boottime->locate_handle,
-                                       EFI_LOCATE_BY_PROTOCOL, &uga_proto,
-                                       NULL, &size, uga_handle);
+               status = efi_call_early(locate_handle,
+                                       EFI_LOCATE_BY_PROTOCOL,
+                                       &uga_proto, NULL, &size, uga_handle);
                if (status == EFI_BUFFER_TOO_SMALL)
                        setup_uga(si, &uga_proto, size);
        }
 }
 
-
 /*
  * Because the x86 boot code expects to be passed a boot_params we
  * need to create one ourselves (usually the bootloader would create
  * one for us).
  */
-struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
+struct boot_params *make_boot_params(struct efi_config *c)
 {
        struct boot_params *boot_params;
        struct sys_desc_table *sdt;
@@ -434,7 +1025,7 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
        struct setup_header *hdr;
        struct efi_info *efi;
        efi_loaded_image_t *image;
-       void *options;
+       void *options, *handle;
        efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
        int options_size = 0;
        efi_status_t status;
@@ -445,14 +1036,21 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
        unsigned long ramdisk_addr;
        unsigned long ramdisk_size;
 
-       sys_table = _table;
+       efi_early = c;
+       sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
+       handle = (void *)(unsigned long)efi_early->image_handle;
 
        /* Check if we were booted by the EFI firmware */
        if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
                return NULL;
 
-       status = efi_call_phys3(sys_table->boottime->handle_protocol,
-                               handle, &proto, (void *)&image);
+       if (efi_early->is64)
+               setup_boot_services64(efi_early);
+       else
+               setup_boot_services32(efi_early);
+
+       status = efi_call_early(handle_protocol, handle,
+                               &proto, (void *)&image);
        if (status != EFI_SUCCESS) {
                efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
                return NULL;
@@ -641,14 +1239,13 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
                sizeof(struct e820entry) * nr_desc;
 
        if (*e820ext) {
-               efi_call_phys1(sys_table->boottime->free_pool, *e820ext);
+               efi_call_early(free_pool, *e820ext);
                *e820ext = NULL;
                *e820ext_size = 0;
        }
 
-       status = efi_call_phys3(sys_table->boottime->allocate_pool,
-                               EFI_LOADER_DATA, size, e820ext);
-
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               size, (void **)e820ext);
        if (status == EFI_SUCCESS)
                *e820ext_size = size;
 
@@ -656,12 +1253,13 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
 }
 
 static efi_status_t exit_boot(struct boot_params *boot_params,
-                             void *handle)
+                             void *handle, bool is64)
 {
        struct efi_info *efi = &boot_params->efi_info;
        unsigned long map_sz, key, desc_size;
        efi_memory_desc_t *mem_map;
        struct setup_data *e820ext;
+       const char *signature;
        __u32 e820ext_size;
        __u32 nr_desc, prev_nr_desc;
        efi_status_t status;
@@ -691,11 +1289,13 @@ get_map:
                if (status != EFI_SUCCESS)
                        goto free_mem_map;
 
-               efi_call_phys1(sys_table->boottime->free_pool, mem_map);
+               efi_call_early(free_pool, mem_map);
                goto get_map; /* Allocated memory, get map again */
        }
 
-       memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32));
+       signature = is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE;
+       memcpy(&efi->efi_loader_signature, signature, sizeof(__u32));
+
        efi->efi_systab = (unsigned long)sys_table;
        efi->efi_memdesc_size = desc_size;
        efi->efi_memdesc_version = desc_version;
@@ -708,8 +1308,7 @@ get_map:
 #endif
 
        /* Might as well exit boot services now */
-       status = efi_call_phys2(sys_table->boottime->exit_boot_services,
-                               handle, key);
+       status = efi_call_early(exit_boot_services, handle, key);
        if (status != EFI_SUCCESS) {
                /*
                 * ExitBootServices() will fail if any of the event
@@ -722,7 +1321,7 @@ get_map:
                        goto free_mem_map;
 
                called_exit = true;
-               efi_call_phys1(sys_table->boottime->free_pool, mem_map);
+               efi_call_early(free_pool, mem_map);
                goto get_map;
        }
 
@@ -736,23 +1335,31 @@ get_map:
        return EFI_SUCCESS;
 
 free_mem_map:
-       efi_call_phys1(sys_table->boottime->free_pool, mem_map);
+       efi_call_early(free_pool, mem_map);
        return status;
 }
 
-
 /*
  * On success we return a pointer to a boot_params structure, and NULL
  * on failure.
  */
-struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
+struct boot_params *efi_main(struct efi_config *c,
                             struct boot_params *boot_params)
 {
-       struct desc_ptr *gdt;
+       struct desc_ptr *gdt = NULL;
        efi_loaded_image_t *image;
        struct setup_header *hdr = &boot_params->hdr;
        efi_status_t status;
        struct desc_struct *desc;
+       void *handle;
+       efi_system_table_t *_table;
+       bool is64;
+
+       efi_early = c;
+
+       _table = (efi_system_table_t *)(unsigned long)efi_early->table;
+       handle = (void *)(unsigned long)efi_early->image_handle;
+       is64 = efi_early->is64;
 
        sys_table = _table;
 
@@ -760,13 +1367,17 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
        if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
                goto fail;
 
+       if (is64)
+               setup_boot_services64(efi_early);
+       else
+               setup_boot_services32(efi_early);
+
        setup_graphics(boot_params);
 
        setup_efi_pci(boot_params);
 
-       status = efi_call_phys3(sys_table->boottime->allocate_pool,
-                               EFI_LOADER_DATA, sizeof(*gdt),
-                               (void **)&gdt);
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               sizeof(*gdt), (void **)&gdt);
        if (status != EFI_SUCCESS) {
                efi_printk(sys_table, "Failed to alloc mem for gdt structure\n");
                goto fail;
@@ -797,7 +1408,7 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
                hdr->code32_start = bzimage_addr;
        }
 
-       status = exit_boot(boot_params, handle);
+       status = exit_boot(boot_params, handle, is64);
        if (status != EFI_SUCCESS)
                goto fail;
 
index 81b6b652b46a948440601964e4e0f114563f4f5d..c88c31ecad1231bb2fc45257a8d98bafe7bc519b 100644 (file)
@@ -37,6 +37,24 @@ struct efi_graphics_output_mode_info {
        u32 pixels_per_scan_line;
 } __packed;
 
+struct efi_graphics_output_protocol_mode_32 {
+       u32 max_mode;
+       u32 mode;
+       u32 info;
+       u32 size_of_info;
+       u64 frame_buffer_base;
+       u32 frame_buffer_size;
+} __packed;
+
+struct efi_graphics_output_protocol_mode_64 {
+       u32 max_mode;
+       u32 mode;
+       u64 info;
+       u64 size_of_info;
+       u64 frame_buffer_base;
+       u64 frame_buffer_size;
+} __packed;
+
 struct efi_graphics_output_protocol_mode {
        u32 max_mode;
        u32 mode;
@@ -46,6 +64,20 @@ struct efi_graphics_output_protocol_mode {
        unsigned long frame_buffer_size;
 } __packed;
 
+struct efi_graphics_output_protocol_32 {
+       u32 query_mode;
+       u32 set_mode;
+       u32 blt;
+       u32 mode;
+};
+
+struct efi_graphics_output_protocol_64 {
+       u64 query_mode;
+       u64 set_mode;
+       u64 blt;
+       u64 mode;
+};
+
 struct efi_graphics_output_protocol {
        void *query_mode;
        unsigned long set_mode;
@@ -53,10 +85,38 @@ struct efi_graphics_output_protocol {
        struct efi_graphics_output_protocol_mode *mode;
 };
 
+struct efi_uga_draw_protocol_32 {
+       u32 get_mode;
+       u32 set_mode;
+       u32 blt;
+};
+
+struct efi_uga_draw_protocol_64 {
+       u64 get_mode;
+       u64 set_mode;
+       u64 blt;
+};
+
 struct efi_uga_draw_protocol {
        void *get_mode;
        void *set_mode;
        void *blt;
 };
 
+struct efi_config {
+       u64 image_handle;
+       u64 table;
+       u64 allocate_pool;
+       u64 allocate_pages;
+       u64 get_memory_map;
+       u64 free_pool;
+       u64 free_pages;
+       u64 locate_handle;
+       u64 handle_protocol;
+       u64 exit_boot_services;
+       u64 text_output;
+       efi_status_t (*call)(unsigned long, ...);
+       bool is64;
+} __packed;
+
 #endif /* BOOT_COMPRESSED_EBOOT_H */
index cedc60de86eb71eb8d51f495f1f9d9b799efedf1..7ff3632806b18ec9a48bd0ae88bdc7a9e9dbe091 100644 (file)
@@ -1 +1,30 @@
+#include <asm/segment.h>
+#include <asm/msr.h>
+#include <asm/processor-flags.h>
+
 #include "../../platform/efi/efi_stub_64.S"
+
+#ifdef CONFIG_EFI_MIXED
+       .code64
+       .text
+ENTRY(efi64_thunk)
+       push    %rbp
+       push    %rbx
+
+       subq    $16, %rsp
+       leaq    efi_exit32(%rip), %rax
+       movl    %eax, 8(%rsp)
+       leaq    efi_gdt64(%rip), %rax
+       movl    %eax, 4(%rsp)
+       movl    %eax, 2(%rax)           /* Fixup the gdt base address */
+       leaq    efi32_boot_gdt(%rip), %rax
+       movl    %eax, (%rsp)
+
+       call    __efi64_thunk
+
+       addq    $16, %rsp
+       pop     %rbx
+       pop     %rbp
+       ret
+ENDPROC(efi64_thunk)
+#endif /* CONFIG_EFI_MIXED */
index 9116aac232c746ae4f5262508fba437db9fbb431..de9d4200d305ba86eb48bb60f3a852b210fb2649 100644 (file)
@@ -42,26 +42,53 @@ ENTRY(startup_32)
 ENTRY(efi_pe_entry)
        add     $0x4, %esp
 
+       call    1f
+1:     popl    %esi
+       subl    $1b, %esi
+
+       popl    %ecx
+       movl    %ecx, efi32_config(%esi)        /* Handle */
+       popl    %ecx
+       movl    %ecx, efi32_config+8(%esi)      /* EFI System table pointer */
+
+       /* Relocate efi_config->call() */
+       leal    efi32_config(%esi), %eax
+       add     %esi, 88(%eax)
+       pushl   %eax
+
        call    make_boot_params
        cmpl    $0, %eax
-       je      1f
-       movl    0x4(%esp), %esi
-       movl    (%esp), %ecx
+       je      fail
+       popl    %ecx
        pushl   %eax
-       pushl   %esi
        pushl   %ecx
-       sub     $0x4, %esp
+       jmp     2f              /* Skip efi_config initialization */
 
-ENTRY(efi_stub_entry)
+ENTRY(efi32_stub_entry)
        add     $0x4, %esp
+       popl    %ecx
+       popl    %edx
+
+       call    1f
+1:     popl    %esi
+       subl    $1b, %esi
+
+       movl    %ecx, efi32_config(%esi)        /* Handle */
+       movl    %edx, efi32_config+8(%esi)      /* EFI System table pointer */
+
+       /* Relocate efi_config->call() */
+       leal    efi32_config(%esi), %eax
+       add     %esi, 88(%eax)
+       pushl   %eax
+2:
        call    efi_main
        cmpl    $0, %eax
        movl    %eax, %esi
        jne     2f
-1:
+fail:
        /* EFI init failed, so hang. */
        hlt
-       jmp     1b
+       jmp     fail
 2:
        call    3f
 3:
@@ -202,6 +229,15 @@ relocated:
        xorl    %ebx, %ebx
        jmp     *%eax
 
+#ifdef CONFIG_EFI_STUB
+       .data
+efi32_config:
+       .fill 11,8,0
+       .long efi_call_phys
+       .long 0
+       .byte 0
+#endif
+
 /*
  * Stack and heap for uncompression
  */
index c5c1ae0997e7b223128b009a220b899e22ffeb25..57e58a5fa21073de1c86f4ceee6b76e674d87399 100644 (file)
@@ -113,7 +113,8 @@ ENTRY(startup_32)
        lgdt    gdt(%ebp)
 
        /* Enable PAE mode */
-       movl    $(X86_CR4_PAE), %eax
+       movl    %cr4, %eax
+       orl     $X86_CR4_PAE, %eax
        movl    %eax, %cr4
 
  /*
@@ -178,6 +179,13 @@ ENTRY(startup_32)
         */
        pushl   $__KERNEL_CS
        leal    startup_64(%ebp), %eax
+#ifdef CONFIG_EFI_MIXED
+       movl    efi32_config(%ebp), %ebx
+       cmp     $0, %ebx
+       jz      1f
+       leal    handover_entry(%ebp), %eax
+1:
+#endif
        pushl   %eax
 
        /* Enter paged protected Mode, activating Long Mode */
@@ -188,6 +196,30 @@ ENTRY(startup_32)
        lret
 ENDPROC(startup_32)
 
+#ifdef CONFIG_EFI_MIXED
+       .org 0x190
+ENTRY(efi32_stub_entry)
+       add     $0x4, %esp              /* Discard return address */
+       popl    %ecx
+       popl    %edx
+       popl    %esi
+
+       leal    (BP_scratch+4)(%esi), %esp
+       call    1f
+1:     pop     %ebp
+       subl    $1b, %ebp
+
+       movl    %ecx, efi32_config(%ebp)
+       movl    %edx, efi32_config+8(%ebp)
+       sgdtl   efi32_boot_gdt(%ebp)
+
+       leal    efi32_config(%ebp), %eax
+       movl    %eax, efi_config(%ebp)
+
+       jmp     startup_32
+ENDPROC(efi32_stub_entry)
+#endif
+
        .code64
        .org 0x200
 ENTRY(startup_64)
@@ -209,26 +241,48 @@ ENTRY(startup_64)
        jmp     preferred_addr
 
 ENTRY(efi_pe_entry)
-       mov     %rcx, %rdi
-       mov     %rdx, %rsi
-       pushq   %rdi
-       pushq   %rsi
+       movq    %rcx, efi64_config(%rip)        /* Handle */
+       movq    %rdx, efi64_config+8(%rip) /* EFI System table pointer */
+
+       leaq    efi64_config(%rip), %rax
+       movq    %rax, efi_config(%rip)
+
+       call    1f
+1:     popq    %rbp
+       subq    $1b, %rbp
+
+       /*
+        * Relocate efi_config->call().
+        */
+       addq    %rbp, efi64_config+88(%rip)
+
+       movq    %rax, %rdi
        call    make_boot_params
        cmpq    $0,%rax
-       je      1f
-       mov     %rax, %rdx
-       popq    %rsi
-       popq    %rdi
+       je      fail
+       mov     %rax, %rsi
+       jmp     2f              /* Skip the relocation */
 
-ENTRY(efi_stub_entry)
+handover_entry:
+       call    1f
+1:     popq    %rbp
+       subq    $1b, %rbp
+
+       /*
+        * Relocate efi_config->call().
+        */
+       movq    efi_config(%rip), %rax
+       addq    %rbp, 88(%rax)
+2:
+       movq    efi_config(%rip), %rdi
        call    efi_main
        movq    %rax,%rsi
        cmpq    $0,%rax
        jne     2f
-1:
+fail:
        /* EFI init failed, so hang. */
        hlt
-       jmp     1b
+       jmp     fail
 2:
        call    3f
 3:
@@ -307,6 +361,20 @@ preferred_addr:
        leaq    relocated(%rbx), %rax
        jmp     *%rax
 
+#ifdef CONFIG_EFI_STUB
+       .org 0x390
+ENTRY(efi64_stub_entry)
+       movq    %rdi, efi64_config(%rip)        /* Handle */
+       movq    %rsi, efi64_config+8(%rip) /* EFI System table pointer */
+
+       leaq    efi64_config(%rip), %rax
+       movq    %rax, efi_config(%rip)
+
+       movq    %rdx, %rsi
+       jmp     handover_entry
+ENDPROC(efi64_stub_entry)
+#endif
+
        .text
 relocated:
 
@@ -372,6 +440,25 @@ gdt:
        .quad   0x0000000000000000      /* TS continued */
 gdt_end:
 
+#ifdef CONFIG_EFI_STUB
+efi_config:
+       .quad   0
+
+#ifdef CONFIG_EFI_MIXED
+       .global efi32_config
+efi32_config:
+       .fill   11,8,0
+       .quad   efi64_thunk
+       .byte   0
+#endif
+
+       .global efi64_config
+efi64_config:
+       .fill   11,8,0
+       .quad   efi_call6
+       .byte   1
+#endif /* CONFIG_EFI_STUB */
+
 /*
  * Stack and heap for uncompression
  */
index 100a9a10076a649e7e7008a3579867391ca16fa4..f0d0b20fe14982529a10d4cec1e8aff6ebf4d96d 100644 (file)
@@ -67,6 +67,13 @@ static int is_transmeta(void)
               cpu_vendor[2] == A32('M', 'x', '8', '6');
 }
 
+static int is_intel(void)
+{
+       return cpu_vendor[0] == A32('G', 'e', 'n', 'u') &&
+              cpu_vendor[1] == A32('i', 'n', 'e', 'I') &&
+              cpu_vendor[2] == A32('n', 't', 'e', 'l');
+}
+
 /* Returns a bitmask of which words we have error bits in */
 static int check_cpuflags(void)
 {
@@ -153,6 +160,19 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
                err = check_cpuflags();
+       } else if (err == 0x01 &&
+                  !(err_flags[0] & ~(1 << X86_FEATURE_PAE)) &&
+                  is_intel() && cpu.level == 6 &&
+                  (cpu.model == 9 || cpu.model == 13)) {
+               /* PAE is disabled on this Pentium M but can be forced */
+               if (cmdline_find_option_bool("forcepae")) {
+                       puts("WARNING: Forcing PAE in CPU flags\n");
+                       set_bit(X86_FEATURE_PAE, cpu.flags);
+                       err = check_cpuflags();
+               }
+               else {
+                       puts("WARNING: PAE disabled. Use parameter 'forcepae' to enable at your own risk!\n");
+               }
        }
 
        if (err_flags_ptr)
index ec3b8ba68096c5434d523c1182196f6ab42f8239..0ca9a5c362bc9681de69956f9c31ee9965d7bb10 100644 (file)
@@ -283,7 +283,7 @@ _start:
        # Part 2 of the header, from the old setup.S
 
                .ascii  "HdrS"          # header signature
-               .word   0x020c          # header version number (>= 0x0105)
+               .word   0x020d          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
                .globl realmode_swtch
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
@@ -350,7 +350,7 @@ cmd_line_ptr:       .long   0               # (Header version 0x0202 or later)
                                        # can be located anywhere in
                                        # low memory 0x10000 or higher.
 
-ramdisk_max:   .long 0x7fffffff
+initrd_addr_max: .long 0x7fffffff
                                        # (Header version 0x0203 or later)
                                        # The highest safe address for
                                        # the contents of an initrd
@@ -375,7 +375,8 @@ xloadflags:
 # define XLF0 0
 #endif
 
-#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64)
+#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) && \
+       !defined(CONFIG_EFI_MIXED)
    /* kernel/boot_param/ramdisk could be loaded above 4g */
 # define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
 #else
@@ -383,10 +384,14 @@ xloadflags:
 #endif
 
 #ifdef CONFIG_EFI_STUB
-# ifdef CONFIG_X86_64
-#  define XLF23 XLF_EFI_HANDOVER_64            /* 64-bit EFI handover ok */
+# ifdef CONFIG_EFI_MIXED
+#  define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)
 # else
-#  define XLF23 XLF_EFI_HANDOVER_32            /* 32-bit EFI handover ok */
+#  ifdef CONFIG_X86_64
+#   define XLF23 XLF_EFI_HANDOVER_64           /* 64-bit EFI handover ok */
+#  else
+#   define XLF23 XLF_EFI_HANDOVER_32           /* 32-bit EFI handover ok */
+#  endif
 # endif
 #else
 # define XLF23 0
@@ -426,13 +431,7 @@ pref_address:              .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 #define INIT_SIZE VO_INIT_SIZE
 #endif
 init_size:             .long INIT_SIZE         # kernel initialization size
-handover_offset:
-#ifdef CONFIG_EFI_STUB
-                       .long 0x30              # offset to the handover
-                                               # protocol entry point
-#else
-                       .long 0
-#endif
+handover_offset:       .long 0                 # Filled in by build.c
 
 # End of setup header #####################################################
 
index 8e15b22391fc40ad9e0a981ef3176d76643e7c45..1a2f2121cada2a11a1b273bdc518b1dcce34ea99 100644 (file)
@@ -53,7 +53,8 @@ int is_big_kernel;
 
 #define PECOFF_RELOC_RESERVE 0x20
 
-unsigned long efi_stub_entry;
+unsigned long efi32_stub_entry;
+unsigned long efi64_stub_entry;
 unsigned long efi_pe_entry;
 unsigned long startup_64;
 
@@ -219,6 +220,52 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
        update_pecoff_section_header(".text", text_start, text_sz);
 }
 
+static int reserve_pecoff_reloc_section(int c)
+{
+       /* Reserve 0x20 bytes for .reloc section */
+       memset(buf+c, 0, PECOFF_RELOC_RESERVE);
+       return PECOFF_RELOC_RESERVE;
+}
+
+static void efi_stub_defaults(void)
+{
+       /* Defaults for old kernel */
+#ifdef CONFIG_X86_32
+       efi_pe_entry = 0x10;
+#else
+       efi_pe_entry = 0x210;
+       startup_64 = 0x200;
+#endif
+}
+
+static void efi_stub_entry_update(void)
+{
+       unsigned long addr = efi32_stub_entry;
+
+#ifdef CONFIG_X86_64
+       /* Yes, this is really how we defined it :( */
+       addr = efi64_stub_entry - 0x200;
+#endif
+
+#ifdef CONFIG_EFI_MIXED
+       if (efi32_stub_entry != addr)
+               die("32-bit and 64-bit EFI entry points do not match\n");
+#endif
+       put_unaligned_le32(addr, &buf[0x264]);
+}
+
+#else
+
+static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
+static inline void update_pecoff_text(unsigned int text_start,
+                                     unsigned int file_sz) {}
+static inline void efi_stub_defaults(void) {}
+static inline void efi_stub_entry_update(void) {}
+
+static inline int reserve_pecoff_reloc_section(int c)
+{
+       return 0;
+}
 #endif /* CONFIG_EFI_STUB */
 
 
@@ -250,7 +297,8 @@ static void parse_zoffset(char *fname)
        p = (char *)buf;
 
        while (p && *p) {
-               PARSE_ZOFS(p, efi_stub_entry);
+               PARSE_ZOFS(p, efi32_stub_entry);
+               PARSE_ZOFS(p, efi64_stub_entry);
                PARSE_ZOFS(p, efi_pe_entry);
                PARSE_ZOFS(p, startup_64);
 
@@ -271,15 +319,7 @@ int main(int argc, char ** argv)
        void *kernel;
        u32 crc = 0xffffffffUL;
 
-       /* Defaults for old kernel */
-#ifdef CONFIG_X86_32
-       efi_pe_entry = 0x10;
-       efi_stub_entry = 0x30;
-#else
-       efi_pe_entry = 0x210;
-       efi_stub_entry = 0x230;
-       startup_64 = 0x200;
-#endif
+       efi_stub_defaults();
 
        if (argc != 5)
                usage();
@@ -302,11 +342,7 @@ int main(int argc, char ** argv)
                die("Boot block hasn't got boot flag (0xAA55)");
        fclose(file);
 
-#ifdef CONFIG_EFI_STUB
-       /* Reserve 0x20 bytes for .reloc section */
-       memset(buf+c, 0, PECOFF_RELOC_RESERVE);
-       c += PECOFF_RELOC_RESERVE;
-#endif
+       c += reserve_pecoff_reloc_section(c);
 
        /* Pad unused space with zeros */
        setup_sectors = (c + 511) / 512;
@@ -315,9 +351,7 @@ int main(int argc, char ** argv)
        i = setup_sectors*512;
        memset(buf+c, 0, i-c);
 
-#ifdef CONFIG_EFI_STUB
        update_pecoff_setup_and_reloc(i);
-#endif
 
        /* Set the default root device */
        put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
@@ -342,14 +376,9 @@ int main(int argc, char ** argv)
        buf[0x1f1] = setup_sectors-1;
        put_unaligned_le32(sys_size, &buf[0x1f4]);
 
-#ifdef CONFIG_EFI_STUB
        update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
 
-#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */
-       efi_stub_entry -= 0x200;
-#endif
-       put_unaligned_le32(efi_stub_entry, &buf[0x264]);
-#endif
+       efi_stub_entry_update();
 
        crc = partial_crc32(buf, i, crc);
        if (fwrite(buf, 1, i, dest) != i)
index 7f669853317a3e940647319c21705ca951fb18ac..4acddc43ee0cc60ae92e1506caf1915409fd94cc 100644 (file)
@@ -5,3 +5,5 @@ genhdr-y += unistd_64.h
 genhdr-y += unistd_x32.h
 
 generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += mcs_spinlock.h
index a54ee1d054d92e66a382dbed20bdc203cfe3f30b..aaac3b2fb746d3e61019f9e0804d7bf2913f8de2 100644 (file)
@@ -19,7 +19,7 @@ extern int amd_cache_northbridges(void);
 extern void amd_flush_garts(void);
 extern int amd_numa_init(void);
 extern int amd_get_subcaches(int);
-extern int amd_set_subcaches(int, int);
+extern int amd_set_subcaches(int, unsigned long);
 
 struct amd_l3_cache {
        unsigned indices;
index 1d2091a226bcac5b55b05225816bf1f374860c3c..19b0ebafcd3e3f9d5a7aa5d5d9900de66d03a374 100644 (file)
@@ -93,9 +93,6 @@ static inline int is_vsmp_box(void)
        return 0;
 }
 #endif
-extern void xapic_wait_icr_idle(void);
-extern u32 safe_xapic_wait_icr_idle(void);
-extern void xapic_icr_write(u32, u32);
 extern int setup_profiling_timer(unsigned int);
 
 static inline void native_apic_mem_write(u32 reg, u32 v)
@@ -184,7 +181,6 @@ extern int x2apic_phys;
 extern int x2apic_preenabled;
 extern void check_x2apic(void);
 extern void enable_x2apic(void);
-extern void x2apic_icr_write(u32 low, u32 id);
 static inline int x2apic_enabled(void)
 {
        u64 msr;
@@ -221,7 +217,6 @@ static inline void x2apic_force_phys(void)
 {
 }
 
-#define        nox2apic        0
 #define        x2apic_preenabled 0
 #define        x2apic_supported()      0
 #endif
@@ -351,7 +346,7 @@ struct apic {
        int trampoline_phys_low;
        int trampoline_phys_high;
 
-       void (*wait_for_init_deassert)(atomic_t *deassert);
+       bool wait_for_init_deassert;
        void (*smp_callin_clear_local_apic)(void);
        void (*inquire_remote_apic)(int apicid);
 
@@ -517,13 +512,6 @@ extern int default_cpu_present_to_apicid(int mps_cpu);
 extern int default_check_phys_apicid_present(int phys_apicid);
 #endif
 
-static inline void default_wait_for_init_deassert(atomic_t *deassert)
-{
-       while (!atomic_read(deassert))
-               cpu_relax();
-       return;
-}
-
 extern void generic_bigsmp_probe(void);
 
 
index 04a48903b2eb31973080d60d36cfd93b3fc68a5f..69bbb484502089b6a01d93d58e4c16a3f90e14f9 100644 (file)
 #else
 # define smp_rmb()     barrier()
 #endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb()     wmb()
-#else
-# define smp_wmb()     barrier()
-#endif
+#define smp_wmb()      barrier()
 #define smp_read_barrier_depends()     read_barrier_depends()
 #define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
 #else /* !SMP */
 #define set_mb(var, value) do { var = value; barrier(); } while (0)
 #endif /* SMP */
 
-#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
+#if defined(CONFIG_X86_PPRO_FENCE)
 
 /*
  * For either of these options x86 doesn't have a strong TSO memory
index e099f9502acec86cb5ec1412745d90384820e625..63211ef5046aef83ed4efd3ff163f5578202d119 100644 (file)
@@ -37,7 +37,7 @@
 #define X86_FEATURE_PAT                (0*32+16) /* Page Attribute Table */
 #define X86_FEATURE_PSE36      (0*32+17) /* 36-bit PSEs */
 #define X86_FEATURE_PN         (0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLSH     (0*32+19) /* "clflush" CLFLUSH instruction */
+#define X86_FEATURE_CLFLUSH    (0*32+19) /* CLFLUSH instruction */
 #define X86_FEATURE_DS         (0*32+21) /* "dts" Debug Store */
 #define X86_FEATURE_ACPI       (0*32+22) /* ACPI via MSR */
 #define X86_FEATURE_MMX                (0*32+23) /* Multimedia Extensions */
 #define X86_FEATURE_INVPCID    (9*32+10) /* Invalidate Processor Context ID */
 #define X86_FEATURE_RTM                (9*32+11) /* Restricted Transactional Memory */
 #define X86_FEATURE_MPX                (9*32+14) /* Memory Protection Extension */
+#define X86_FEATURE_AVX512F    (9*32+16) /* AVX-512 Foundation */
 #define X86_FEATURE_RDSEED     (9*32+18) /* The RDSEED instruction */
 #define X86_FEATURE_ADX                (9*32+19) /* The ADCX and ADOX instructions */
 #define X86_FEATURE_SMAP       (9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_CLFLUSHOPT (9*32+23) /* CLFLUSHOPT instruction */
+#define X86_FEATURE_AVX512PF   (9*32+26) /* AVX-512 Prefetch */
+#define X86_FEATURE_AVX512ER   (9*32+27) /* AVX-512 Exponential and Reciprocal */
+#define X86_FEATURE_AVX512CD   (9*32+28) /* AVX-512 Conflict Detection */
 
 /*
  * BUG word(s)
@@ -313,7 +318,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_pmm_enabled    boot_cpu_has(X86_FEATURE_PMM_EN)
 #define cpu_has_ds             boot_cpu_has(X86_FEATURE_DS)
 #define cpu_has_pebs           boot_cpu_has(X86_FEATURE_PEBS)
-#define cpu_has_clflush                boot_cpu_has(X86_FEATURE_CLFLSH)
+#define cpu_has_clflush                boot_cpu_has(X86_FEATURE_CLFLUSH)
 #define cpu_has_bts            boot_cpu_has(X86_FEATURE_BTS)
 #define cpu_has_gbpages                boot_cpu_has(X86_FEATURE_GBPAGES)
 #define cpu_has_arch_perfmon   boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
diff --git a/arch/x86/include/asm/cputime.h b/arch/x86/include/asm/cputime.h
deleted file mode 100644 (file)
index 6d68ad7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/cputime.h>
index 3b978c472d08b51aa8ff33d7fab589a3205fc87a..0869434eaf725e7a5aa5efb6f5ce8a62ed8176d3 100644 (file)
  */
 #define EFI_OLD_MEMMAP         EFI_ARCH_1
 
+#define EFI32_LOADER_SIGNATURE "EL32"
+#define EFI64_LOADER_SIGNATURE "EL64"
+
 #ifdef CONFIG_X86_32
 
-#define EFI_LOADER_SIGNATURE   "EL32"
 
 extern unsigned long asmlinkage efi_call_phys(void *, ...);
 
@@ -57,8 +59,6 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
 
 #else /* !CONFIG_X86_32 */
 
-#define EFI_LOADER_SIGNATURE   "EL64"
-
 extern u64 efi_call0(void *fp);
 extern u64 efi_call1(void *fp, u64 arg1);
 extern u64 efi_call2(void *fp, u64 arg1, u64 arg2);
@@ -119,7 +119,6 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
 #endif /* CONFIG_X86_32 */
 
 extern int add_efi_memmap;
-extern unsigned long x86_efi_facility;
 extern struct efi_scratch efi_scratch;
 extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
@@ -130,8 +129,13 @@ extern void efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
 extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
 extern void efi_sync_low_kernel_mappings(void);
-extern void efi_setup_page_tables(void);
+extern int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
 extern void __init old_map_region(efi_memory_desc_t *md);
+extern void __init runtime_code_page_mkexec(void);
+extern void __init efi_runtime_mkexec(void);
+extern void __init efi_dump_pagetable(void);
+extern void __init efi_apply_memmap_quirks(void);
 
 struct efi_setup_data {
        u64 fw_vendor;
@@ -150,8 +154,40 @@ static inline bool efi_is_native(void)
        return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
 }
 
+static inline bool efi_runtime_supported(void)
+{
+       if (efi_is_native())
+               return true;
+
+       if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_enabled(EFI_OLD_MEMMAP))
+               return true;
+
+       return false;
+}
+
 extern struct console early_efi_console;
 extern void parse_efi_setup(u64 phys_addr, u32 data_len);
+
+#ifdef CONFIG_EFI_MIXED
+extern void efi_thunk_runtime_setup(void);
+extern efi_status_t efi_thunk_set_virtual_address_map(
+       void *phys_set_virtual_address_map,
+       unsigned long memory_map_size,
+       unsigned long descriptor_size,
+       u32 descriptor_version,
+       efi_memory_desc_t *virtual_map);
+#else
+static inline void efi_thunk_runtime_setup(void) {}
+static inline efi_status_t efi_thunk_set_virtual_address_map(
+       void *phys_set_virtual_address_map,
+       unsigned long memory_map_size,
+       unsigned long descriptor_size,
+       u32 descriptor_version,
+       efi_memory_desc_t *virtual_map)
+{
+       return EFI_SUCCESS;
+}
+#endif /* CONFIG_EFI_MIXED */
 #else
 /*
  * IF EFI is not configured, have the EFI calls return -ENOSYS.
index 34f69cb9350ae3ecf36e4b8cd8d410a6a7b67a0b..91d9c69a629e2731f25aa152de91dd17663ec619 100644 (file)
@@ -237,7 +237,7 @@ memcpy_toio(volatile void __iomem *dst, const void *src, size_t count)
 
 static inline void flush_write_buffers(void)
 {
-#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
+#if defined(CONFIG_X86_PPRO_FENCE)
        asm volatile("lock; addl $0,0(%%esp)": : :"memory");
 #endif
 }
index e139b13f2a33a3572d91e4f7297952e1bf8a1ffc..de36f22eb0b9e79db05711cd46196c0c072bb023 100644 (file)
@@ -214,6 +214,8 @@ do {                                                            \
 
 struct msr *msrs_alloc(void);
 void msrs_free(struct msr *msrs);
+int msr_set_bit(u32 msr, u8 bit);
+int msr_clear_bit(u32 msr, u8 bit);
 
 #ifdef CONFIG_SMP
 int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
index 86f9301903c818c632b227537b44142b71883c8d..5f2fc4441b11016608f476848e3a60bd1e08d7a5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_X86_NMI_H
 #define _ASM_X86_NMI_H
 
+#include <linux/irq_work.h>
 #include <linux/pm.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -38,6 +39,8 @@ typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
 struct nmiaction {
        struct list_head        list;
        nmi_handler_t           handler;
+       u64                     max_duration;
+       struct irq_work         irq_work;
        unsigned long           flags;
        const char              *name;
 };
index bbc8b12fa443d47ee9a8faa59b36767e7aec866c..b459ddf27d64149915fb2e2938f2392a8322d957 100644 (file)
         : (prot))
 
 #ifndef __ASSEMBLY__
-
 #include <asm/x86_init.h>
 
+void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd);
+
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
index 1aa9ccd432236af7d5667657e4267c3a8ba218f6..708f19fb4fc788ea0a51838e43ea8ea50c9699d0 100644 (file)
@@ -382,9 +382,13 @@ static inline void update_page_count(int level, unsigned long pages) { }
  * as a pte too.
  */
 extern pte_t *lookup_address(unsigned long address, unsigned int *level);
+extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+                                   unsigned int *level);
 extern phys_addr_t slow_virt_to_phys(void *__address);
 extern int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
                                   unsigned numpages, unsigned long page_flags);
+void kernel_unmap_pages_in_pgd(pgd_t *root, unsigned long address,
+                              unsigned numpages);
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_X86_PGTABLE_DEFS_H */
index fdedd38fd0fc7feeabc26f8b366b525b65685904..a4ea02351f4d02bee5a43e78a9013b77ec94ea48 100644 (file)
@@ -449,6 +449,15 @@ struct stack_canary {
 };
 DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
 #endif
+/*
+ * per-CPU IRQ handling stacks
+ */
+struct irq_stack {
+       u32                     stack[THREAD_SIZE/sizeof(u32)];
+} __aligned(THREAD_SIZE);
+
+DECLARE_PER_CPU(struct irq_stack *, hardirq_stack);
+DECLARE_PER_CPU(struct irq_stack *, softirq_stack);
 #endif /* X86_64 */
 
 extern unsigned int xstate_size;
index 645cad2c95ff9c87ebd0592c95e891b7a53290fe..e820c080a4e99e45354fc7b6e5720d9f1933b241 100644 (file)
@@ -191,6 +191,14 @@ static inline void clflush(volatile void *__p)
        asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
 }
 
+static inline void clflushopt(volatile void *__p)
+{
+       alternative_io(".byte " __stringify(NOP_DS_PREFIX) "; clflush %P0",
+                      ".byte 0x66; clflush %P0",
+                      X86_FEATURE_CLFLUSHOPT,
+                      "+m" (*(volatile char __force *)__p));
+}
+
 #define nop() asm volatile ("nop")
 
 
index bf156ded74b56006a76cc02b8917984117af8afd..0f62f5482d91ec8fca86e884b6822fc467239dbc 100644 (file)
 # define LOCK_PTR_REG "D"
 #endif
 
-#if defined(CONFIG_X86_32) && \
-       (defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE))
+#if defined(CONFIG_X86_32) && (defined(CONFIG_X86_PPRO_FENCE))
 /*
- * On PPro SMP or if we are using OOSTORE, we use a locked operation to unlock
+ * On PPro SMP, we use a locked operation to unlock
  * (PPro errata 66, 92)
  */
 # define UNLOCK_LOCK_PREFIX LOCK_PREFIX
index e1940c06ed022d8b9ad7988aaf76970afc92c4b5..47e5de25ba799f787d7f9344c28daa797fde47b7 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/compiler.h>
 #include <asm/page.h>
+#include <asm/percpu.h>
 #include <asm/types.h>
 
 /*
@@ -32,12 +33,6 @@ struct thread_info {
        mm_segment_t            addr_limit;
        struct restart_block    restart_block;
        void __user             *sysenter_return;
-#ifdef CONFIG_X86_32
-       unsigned long           previous_esp;   /* ESP of the previous stack in
-                                                  case of nested (IRQ) stacks
-                                               */
-       __u8                    supervisor_stack[0];
-#endif
        unsigned int            sig_on_uaccess_error:1;
        unsigned int            uaccess_err:1;  /* uaccess failed */
 };
@@ -153,9 +148,9 @@ struct thread_info {
 #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
 
-#ifdef CONFIG_X86_32
+#define STACK_WARN             (THREAD_SIZE/8)
+#define KERNEL_STACK_OFFSET    (5*(BITS_PER_LONG/8))
 
-#define STACK_WARN     (THREAD_SIZE/8)
 /*
  * macros/functions for gaining access to the thread information structure
  *
@@ -163,42 +158,6 @@ struct thread_info {
  */
 #ifndef __ASSEMBLY__
 
-#define current_stack_pointer ({               \
-       unsigned long sp;                       \
-       asm("mov %%esp,%0" : "=g" (sp));        \
-       sp;                                     \
-})
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
-       return (struct thread_info *)
-               (current_stack_pointer & ~(THREAD_SIZE - 1));
-}
-
-#else /* !__ASSEMBLY__ */
-
-/* how to get the thread information struct from ASM */
-#define GET_THREAD_INFO(reg)    \
-       movl $-THREAD_SIZE, reg; \
-       andl %esp, reg
-
-/* use this one if reg already contains %esp */
-#define GET_THREAD_INFO_WITH_ESP(reg) \
-       andl $-THREAD_SIZE, reg
-
-#endif
-
-#else /* X86_32 */
-
-#include <asm/percpu.h>
-#define KERNEL_STACK_OFFSET (5*8)
-
-/*
- * macros/functions for gaining access to the thread information structure
- * preempt_count needs to be 1 initially, until the scheduler is functional.
- */
-#ifndef __ASSEMBLY__
 DECLARE_PER_CPU(unsigned long, kernel_stack);
 
 static inline struct thread_info *current_thread_info(void)
@@ -213,8 +172,8 @@ static inline struct thread_info *current_thread_info(void)
 
 /* how to get the thread information struct from ASM */
 #define GET_THREAD_INFO(reg) \
-       movq PER_CPU_VAR(kernel_stack),reg ; \
-       subq $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg
+       _ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \
+       _ASM_SUB $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg ;
 
 /*
  * Same if PER_CPU_VAR(kernel_stack) is, perhaps with some offset, already in
@@ -224,8 +183,6 @@ static inline struct thread_info *current_thread_info(void)
 
 #endif
 
-#endif /* !X86_32 */
-
 /*
  * Thread-synchronous status.
  *
index e6d90babc245c1c2713bea64d436fb2a736b83e6..04905bfc508b9925c697687b7c1d5754827ba417 100644 (file)
@@ -62,7 +62,7 @@ static inline void __flush_tlb_all(void)
 
 static inline void __flush_tlb_one(unsigned long addr)
 {
-       count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
+       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
        __flush_tlb_single(addr);
 }
 
@@ -93,13 +93,13 @@ static inline void __flush_tlb_one(unsigned long addr)
  */
 static inline void __flush_tlb_up(void)
 {
-       count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
        __flush_tlb();
 }
 
 static inline void flush_tlb_all(void)
 {
-       count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
        __flush_tlb_all();
 }
 
index d35f24e231cd2429c8d17c0d5b3d722951d3e04b..b28097e4c8c3e1e941df963f49cd2db32d89589a 100644 (file)
@@ -119,9 +119,10 @@ static inline void setup_node_to_cpumask_map(void) { }
 
 extern const struct cpumask *cpu_coregroup_mask(int cpu);
 
-#ifdef ENABLE_TOPO_DEFINES
 #define topology_physical_package_id(cpu)      (cpu_data(cpu).phys_proc_id)
 #define topology_core_id(cpu)                  (cpu_data(cpu).cpu_core_id)
+
+#ifdef ENABLE_TOPO_DEFINES
 #define topology_core_cpumask(cpu)             (per_cpu(cpu_core_map, cpu))
 #define topology_thread_cpumask(cpu)           (per_cpu(cpu_sibling_map, cpu))
 #endif
@@ -133,12 +134,6 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
 struct pci_bus;
 void x86_pci_root_bus_resources(int bus, struct list_head *resources);
 
-#ifdef CONFIG_SMP
-#define mc_capable()   ((boot_cpu_data.x86_max_cores > 1) && \
-                       (cpumask_weight(cpu_core_mask(0)) != nr_cpu_ids))
-#define smt_capable()                  (smp_num_siblings > 1)
-#endif
-
 #ifdef CONFIG_NUMA
 extern int get_mp_bus_to_node(int busnum);
 extern void set_mp_bus_to_node(int busnum, int node);
index 57ae63cd6ee2ec8aba5135a33e363267b65e4075..94605c0e9ceebc0058b18b995a5ac4f73a0d2aa6 100644 (file)
@@ -66,6 +66,6 @@ extern void tsc_save_sched_clock_state(void);
 extern void tsc_restore_sched_clock_state(void);
 
 /* MSR based TSC calibration for Intel Atom SoC platforms */
-int try_msr_calibrate_tsc(unsigned long *fast_calibrate);
+unsigned long try_msr_calibrate_tsc(void);
 
 #endif /* _ASM_X86_TSC_H */
index c2a48139c3401b5d0202a83c676242119106b1f2..3f556c6a015769a1a53a2615e3a0cf26da1725a3 100644 (file)
@@ -23,6 +23,9 @@
 #  include <asm/unistd_64.h>
 #  include <asm/unistd_64_x32.h>
 #  define __ARCH_WANT_COMPAT_SYS_TIME
+#  define __ARCH_WANT_COMPAT_SYS_GETDENTS64
+#  define __ARCH_WANT_COMPAT_SYS_PREADV64
+#  define __ARCH_WANT_COMPAT_SYS_PWRITEV64
 
 # endif
 
index 787e1bb5aafcfb27b6579eeb56ba62cd2c3f1abe..3e276eb23d1bd7c315f055ecfcb551b0cd5ed1b8 100644 (file)
@@ -52,8 +52,7 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s,
 extern int m2p_add_override(unsigned long mfn, struct page *page,
                            struct gnttab_map_grant_ref *kmap_op);
 extern int m2p_remove_override(struct page *page,
-                              struct gnttab_map_grant_ref *kmap_op,
-                              unsigned long mfn);
+                               struct gnttab_map_grant_ref *kmap_op);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
@@ -122,7 +121,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
                pfn = m2p_find_override_pfn(mfn, ~0);
        }
 
-       /*
+       /* 
         * pfn is ~0 if there are no entries in the m2p for mfn or if the
         * entry doesn't map back to the mfn and m2p_override doesn't have a
         * valid entry for it.
index 554738963b28cf47dd76fa9947338bb1eae5a0d0..6c1d7411eb009a5a96ef55004fdedf60aa1ef822 100644 (file)
@@ -6,11 +6,14 @@
 
 #define XSTATE_CPUID           0x0000000d
 
-#define XSTATE_FP      0x1
-#define XSTATE_SSE     0x2
-#define XSTATE_YMM     0x4
-#define XSTATE_BNDREGS 0x8
-#define XSTATE_BNDCSR  0x10
+#define XSTATE_FP              0x1
+#define XSTATE_SSE             0x2
+#define XSTATE_YMM             0x4
+#define XSTATE_BNDREGS         0x8
+#define XSTATE_BNDCSR          0x10
+#define XSTATE_OPMASK          0x20
+#define XSTATE_ZMM_Hi256       0x40
+#define XSTATE_Hi16_ZMM                0x80
 
 #define XSTATE_FPSSE   (XSTATE_FP | XSTATE_SSE)
 
@@ -23,7 +26,8 @@
 #define XSAVE_YMM_OFFSET    (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
 
 /* Supported features which support lazy state saving */
-#define XSTATE_LAZY    (XSTATE_FP | XSTATE_SSE | XSTATE_YMM)
+#define XSTATE_LAZY    (XSTATE_FP | XSTATE_SSE | XSTATE_YMM                  \
+                       | XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM)
 
 /* Supported features which require eager state saving */
 #define XSTATE_EAGER   (XSTATE_BNDREGS | XSTATE_BNDCSR)
index c19fc60ff06272f733df17a03f8cbf577d69073f..4924f4be2b992198995a3bf328f011de65dc2230 100644 (file)
 #define THERM_LOG_THRESHOLD1           (1 << 9)
 
 /* MISC_ENABLE bits: architectural */
-#define MSR_IA32_MISC_ENABLE_FAST_STRING       (1ULL << 0)
-#define MSR_IA32_MISC_ENABLE_TCC               (1ULL << 1)
-#define MSR_IA32_MISC_ENABLE_EMON              (1ULL << 7)
-#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL       (1ULL << 11)
-#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL      (1ULL << 12)
-#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP        (1ULL << 16)
-#define MSR_IA32_MISC_ENABLE_MWAIT             (1ULL << 18)
-#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID       (1ULL << 22)
-#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE      (1ULL << 23)
-#define MSR_IA32_MISC_ENABLE_XD_DISABLE                (1ULL << 34)
+#define MSR_IA32_MISC_ENABLE_FAST_STRING_BIT           0
+#define MSR_IA32_MISC_ENABLE_FAST_STRING               (1ULL << MSR_IA32_MISC_ENABLE_FAST_STRING_BIT)
+#define MSR_IA32_MISC_ENABLE_TCC_BIT                   1
+#define MSR_IA32_MISC_ENABLE_TCC                       (1ULL << MSR_IA32_MISC_ENABLE_TCC_BIT)
+#define MSR_IA32_MISC_ENABLE_EMON_BIT                  7
+#define MSR_IA32_MISC_ENABLE_EMON                      (1ULL << MSR_IA32_MISC_ENABLE_EMON_BIT)
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT           11
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL               (1ULL << MSR_IA32_MISC_ENABLE_BTS_UNAVAIL_BIT)
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT          12
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL              (1ULL << MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL_BIT)
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT    16
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP                (1ULL << MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP_BIT)
+#define MSR_IA32_MISC_ENABLE_MWAIT_BIT                 18
+#define MSR_IA32_MISC_ENABLE_MWAIT                     (1ULL << MSR_IA32_MISC_ENABLE_MWAIT_BIT)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT           22
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID               (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT);
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT          23
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE              (1ULL << MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT            34
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE                        (1ULL << MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT)
 
 /* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
-#define MSR_IA32_MISC_ENABLE_X87_COMPAT                (1ULL << 2)
-#define MSR_IA32_MISC_ENABLE_TM1               (1ULL << 3)
-#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE        (1ULL << 4)
-#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE   (1ULL << 6)
-#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK     (1ULL << 8)
-#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE  (1ULL << 9)
-#define MSR_IA32_MISC_ENABLE_FERR              (1ULL << 10)
-#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX    (1ULL << 10)
-#define MSR_IA32_MISC_ENABLE_TM2               (1ULL << 13)
-#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE  (1ULL << 19)
-#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK    (1ULL << 20)
-#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT       (1ULL << 24)
-#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE  (1ULL << 37)
-#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE     (1ULL << 38)
-#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE   (1ULL << 39)
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT            2
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT                        (1ULL << MSR_IA32_MISC_ENABLE_X87_COMPAT_BIT)
+#define MSR_IA32_MISC_ENABLE_TM1_BIT                   3
+#define MSR_IA32_MISC_ENABLE_TM1                       (1ULL << MSR_IA32_MISC_ENABLE_TM1_BIT)
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT    4
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE                (1ULL << MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT       6
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT         8
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK             (1ULL << MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK_BIT)
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT      9
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_FERR_BIT                  10
+#define MSR_IA32_MISC_ENABLE_FERR                      (1ULL << MSR_IA32_MISC_ENABLE_FERR_BIT)
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT                10
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX            (1ULL << MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT)
+#define MSR_IA32_MISC_ENABLE_TM2_BIT                   13
+#define MSR_IA32_MISC_ENABLE_TM2                       (1ULL << MSR_IA32_MISC_ENABLE_TM2_BIT)
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT      19
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT                20
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK            (1ULL << MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK_BIT)
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT           24
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT               (1ULL << MSR_IA32_MISC_ENABLE_L1D_CONTEXT_BIT)
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT      37
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE          (1ULL << MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT         38
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE             (1ULL << MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT)
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT       39
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT)
 
 #define MSR_IA32_TSC_DEADLINE          0x000006E0
 
index 1dac94265b5978282262b77d4f496ae512701eb8..9f46f2b1cfc2d528507dbb2986a30aacf44e2c8e 100644 (file)
@@ -613,10 +613,10 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
        int nid;
 
        nid = acpi_get_node(handle);
-       if (nid == -1 || !node_online(nid))
-               return;
-       set_apicid_to_node(physid, nid);
-       numa_set_node(cpu, nid);
+       if (nid != -1) {
+               set_apicid_to_node(physid, nid);
+               numa_set_node(cpu, nid);
+       }
 #endif
 }
 
index 59554dca96ec8945c1d7f514a1281e06c6e7e771..dec8de4e1663fd6c99c2cfcbf18cd75d9551a9a0 100644 (file)
@@ -179,7 +179,7 @@ int amd_get_subcaches(int cpu)
        return (mask >> (4 * cuid)) & 0xf;
 }
 
-int amd_set_subcaches(int cpu, int mask)
+int amd_set_subcaches(int cpu, unsigned long mask)
 {
        static unsigned int reset, ban;
        struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu));
index fd972a3e4cbb0919221f6f69299a857972ef44e6..9fa8aa051f54b235ed516d32e2eca2c3c9d62b5e 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
-#include <linux/ioport.h>
 #include <linux/suspend.h>
 #include <asm/e820.h>
 #include <asm/io.h>
@@ -54,18 +53,6 @@ int fallback_aper_force __initdata;
 
 int fix_aperture __initdata = 1;
 
-static struct resource gart_resource = {
-       .name   = "GART",
-       .flags  = IORESOURCE_MEM,
-};
-
-static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
-{
-       gart_resource.start = aper_base;
-       gart_resource.end = aper_base + aper_size - 1;
-       insert_resource(&iomem_resource, &gart_resource);
-}
-
 /* This code runs before the PCI subsystem is initialized, so just
    access the northbridge directly. */
 
@@ -96,7 +83,6 @@ static u32 __init allocate_aperture(void)
        memblock_reserve(addr, aper_size);
        printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n",
                        aper_size >> 10, addr);
-       insert_aperture_resource((u32)addr, aper_size);
        register_nosave_region(addr >> PAGE_SHIFT,
                               (addr+aper_size) >> PAGE_SHIFT);
 
@@ -444,12 +430,8 @@ int __init gart_iommu_hole_init(void)
 
 out:
        if (!fix && !fallback_aper_force) {
-               if (last_aper_base) {
-                       unsigned long n = (32 * 1024 * 1024) << last_aper_order;
-
-                       insert_aperture_resource((u32)last_aper_base, n);
+               if (last_aper_base)
                        return 1;
-               }
                return 0;
        }
 
index 7f26c9a70a9e0ada12f46382d7ee2cd73b2d5f29..53e20531470ee1ee125c510bf0c26308f74820d3 100644 (file)
@@ -133,6 +133,10 @@ static inline void imcr_apic_to_pic(void)
  * +1=force-enable
  */
 static int force_enable_local_apic __initdata;
+
+/* Control whether x2APIC mode is enabled or not */
+static bool nox2apic __initdata;
+
 /*
  * APIC command line parameters
  */
@@ -162,8 +166,7 @@ int x2apic_mode;
 /* x2apic enabled before OS handover */
 int x2apic_preenabled;
 static int x2apic_disabled;
-static int nox2apic;
-static __init int setup_nox2apic(char *str)
+static int __init setup_nox2apic(char *str)
 {
        if (x2apic_enabled()) {
                int apicid = native_apic_msr_read(APIC_ID);
@@ -178,7 +181,7 @@ static __init int setup_nox2apic(char *str)
        } else
                setup_clear_cpu_cap(X86_FEATURE_X2APIC);
 
-       nox2apic = 1;
+       nox2apic = true;
 
        return 0;
 }
@@ -283,8 +286,12 @@ u32 native_safe_apic_wait_icr_idle(void)
 
 void native_apic_icr_write(u32 low, u32 id)
 {
+       unsigned long flags;
+
+       local_irq_save(flags);
        apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id));
        apic_write(APIC_ICR, low);
+       local_irq_restore(flags);
 }
 
 u64 native_apic_icr_read(void)
index 2c621a6b901a7642838c5a74a54be4bf3fcbe58a..7c1b29479513a1d78f79410915a4ee30e5d1c53e 100644 (file)
@@ -198,7 +198,7 @@ static struct apic apic_flat =  {
 
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-       .wait_for_init_deassert         = NULL,
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
 
@@ -314,7 +314,7 @@ static struct apic apic_physflat =  {
 
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-       .wait_for_init_deassert         = NULL,
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
 
index 191ce75c0e54b8f2808cce5f730f5d62c18dfa09..8c7c98249c205f0f596e7c0866e89444dc3d4bc8 100644 (file)
@@ -172,8 +172,7 @@ struct apic apic_noop = {
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-       .wait_for_init_deassert         = NULL,
-
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = NULL,
 
index 3e67f9e3d7ef1e8eb093d9e8398b21aaf1a7b93e..a5b45df8bc881cafbc2560f3b7ea72ef02aa7c73 100644 (file)
@@ -248,7 +248,7 @@ static const struct apic apic_numachip __refconst = {
        .wakeup_secondary_cpu           = numachip_wakeup_secondary,
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-       .wait_for_init_deassert         = NULL,
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = NULL, /* REMRD not supported */
 
index d50e3640d5aed53daf4110ef68193cf0cbdac826..e4840aa7a255b63db235ab5cecd07ecabf5c5013 100644 (file)
@@ -199,8 +199,7 @@ static struct apic apic_bigsmp = {
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-       .wait_for_init_deassert         = default_wait_for_init_deassert,
-
+       .wait_for_init_deassert         = true,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
 
index c55224731b2d7f0de89d6a37a00e71bd4d8792ec..6f8f8b348a39fbf378953936cc796d5e1842849f 100644 (file)
@@ -394,12 +394,6 @@ static void es7000_enable_apic_mode(void)
                WARN(1, "Command failed, status = %x\n", mip_status);
 }
 
-static void es7000_wait_for_init_deassert(atomic_t *deassert)
-{
-       while (!atomic_read(deassert))
-               cpu_relax();
-}
-
 static unsigned int es7000_get_apic_id(unsigned long x)
 {
        return (x >> 24) & 0xFF;
@@ -658,8 +652,7 @@ static struct apic __refdata apic_es7000_cluster = {
        .trampoline_phys_low            = 0x467,
        .trampoline_phys_high           = 0x469,
 
-       .wait_for_init_deassert         = NULL,
-
+       .wait_for_init_deassert         = false,
        /* Nothing to do for most platforms, since cleared by the INIT cycle: */
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
@@ -722,8 +715,7 @@ static struct apic __refdata apic_es7000 = {
        .trampoline_phys_low            = 0x467,
        .trampoline_phys_high           = 0x469,
 
-       .wait_for_init_deassert         = es7000_wait_for_init_deassert,
-
+       .wait_for_init_deassert         = true,
        /* Nothing to do for most platforms, since cleared by the INIT cycle: */
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
index 1e42e8f305ee2096ed52c20f6c569fe8a8339b7b..030ea1c04f72b3184e339ed840f7d13382641ba6 100644 (file)
@@ -505,8 +505,7 @@ static struct apic __refdata apic_numaq = {
        .trampoline_phys_high           = NUMAQ_TRAMPOLINE_PHYS_HIGH,
 
        /* We don't do anything here because we use NMI's to boot instead */
-       .wait_for_init_deassert         = NULL,
-
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = numaq_smp_callin_clear_local_apic,
        .inquire_remote_apic            = NULL,
 
index eb35ef9ee63f779bde870822a01dcc98bd503b01..cceb352c968c62b13404d3ce78478f64e7a5d3c5 100644 (file)
@@ -119,8 +119,7 @@ static struct apic apic_default = {
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-       .wait_for_init_deassert         = default_wait_for_init_deassert,
-
+       .wait_for_init_deassert         = true,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
 
index 00146f9b0254315acfb191015314fedf35fa9ab0..b656128611cd3ebd71af4ba0f053e72471845e21 100644 (file)
@@ -532,8 +532,7 @@ static struct apic apic_summit = {
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
 
-       .wait_for_init_deassert         = default_wait_for_init_deassert,
-
+       .wait_for_init_deassert         = true,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = default_inquire_remote_apic,
 
index cac85ee6913f70ca64f3a8656dbff5d5cc603348..e66766bf164191de15d7ea9bf7b62c6506b2d6f2 100644 (file)
@@ -279,7 +279,7 @@ static struct apic apic_x2apic_cluster = {
 
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-       .wait_for_init_deassert         = NULL,
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = NULL,
 
index de231e328cae310bf4a39a1fb70ebc83993bb67c..6d600ebf6c127f94c4bb194a9e8bb25f0c607ffe 100644 (file)
@@ -133,7 +133,7 @@ static struct apic apic_x2apic_phys = {
 
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-       .wait_for_init_deassert         = NULL,
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = NULL,
 
index d263b1307de1e5b30a114cc0f37c017197d5728f..7834389ba5be0952b5e673ff11d6a6c64cee106d 100644 (file)
@@ -396,7 +396,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
        .wakeup_secondary_cpu           = uv_wakeup_secondary,
        .trampoline_phys_low            = DEFAULT_TRAMPOLINE_PHYS_LOW,
        .trampoline_phys_high           = DEFAULT_TRAMPOLINE_PHYS_HIGH,
-       .wait_for_init_deassert         = NULL,
+       .wait_for_init_deassert         = false,
        .smp_callin_clear_local_apic    = NULL,
        .inquire_remote_apic            = NULL,
 
index d3153e281d7291e78bb57d647d388171f4d006b2..ce8b8ff0e0ef4e1915272431c9b543e303101264 100644 (file)
@@ -218,7 +218,7 @@ static void amd_k7_smp_check(struct cpuinfo_x86 *c)
         */
        WARN_ONCE(1, "WARNING: This combination of AMD"
                " processors is not suitable for SMP.\n");
-       add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE);
+       add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
 }
 
 static void init_amd_k7(struct cpuinfo_x86 *c)
@@ -233,9 +233,7 @@ static void init_amd_k7(struct cpuinfo_x86 *c)
        if (c->x86_model >= 6 && c->x86_model <= 10) {
                if (!cpu_has(c, X86_FEATURE_XMM)) {
                        printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
-                       rdmsr(MSR_K7_HWCR, l, h);
-                       l &= ~0x00008000;
-                       wrmsr(MSR_K7_HWCR, l, h);
+                       msr_clear_bit(MSR_K7_HWCR, 15);
                        set_cpu_cap(c, X86_FEATURE_XMM);
                }
        }
@@ -509,14 +507,8 @@ static void early_init_amd(struct cpuinfo_x86 *c)
 #endif
 
        /* F16h erratum 793, CVE-2013-6885 */
-       if (c->x86 == 0x16 && c->x86_model <= 0xf) {
-               u64 val;
-
-               rdmsrl(MSR_AMD64_LS_CFG, val);
-               if (!(val & BIT(15)))
-                       wrmsrl(MSR_AMD64_LS_CFG, val | BIT(15));
-       }
-
+       if (c->x86 == 0x16 && c->x86_model <= 0xf)
+               msr_set_bit(MSR_AMD64_LS_CFG, 15);
 }
 
 static const int amd_erratum_383[];
@@ -536,11 +528,8 @@ static void init_amd(struct cpuinfo_x86 *c)
         * Errata 63 for SH-B3 steppings
         * Errata 122 for all steppings (F+ have it disabled by default)
         */
-       if (c->x86 == 0xf) {
-               rdmsrl(MSR_K7_HWCR, value);
-               value |= 1 << 6;
-               wrmsrl(MSR_K7_HWCR, value);
-       }
+       if (c->x86 == 0xf)
+               msr_set_bit(MSR_K7_HWCR, 6);
 #endif
 
        early_init_amd(c);
@@ -623,14 +612,11 @@ static void init_amd(struct cpuinfo_x86 *c)
            (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
            !cpu_has(c, X86_FEATURE_TOPOEXT)) {
 
-               if (!rdmsrl_safe(0xc0011005, &value)) {
-                       value |= 1ULL << 54;
-                       wrmsrl_safe(0xc0011005, value);
+               if (msr_set_bit(0xc0011005, 54) > 0) {
                        rdmsrl(0xc0011005, value);
-                       if (value & (1ULL << 54)) {
+                       if (value & BIT_64(54)) {
                                set_cpu_cap(c, X86_FEATURE_TOPOEXT);
-                               printk(KERN_INFO FW_INFO "CPU: Re-enabling "
-                                 "disabled Topology Extensions Support\n");
+                               pr_info(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
                        }
                }
        }
@@ -709,19 +695,12 @@ static void init_amd(struct cpuinfo_x86 *c)
                 * Disable GART TLB Walk Errors on Fam10h. We do this here
                 * because this is always needed when GART is enabled, even in a
                 * kernel which has no MCE support built in.
-                * BIOS should disable GartTlbWlk Errors themself. If
-                * it doesn't do it here as suggested by the BKDG.
+                * BIOS should disable GartTlbWlk Errors already. If
+                * it doesn't, do it here as suggested by the BKDG.
                 *
                 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
                 */
-               u64 mask;
-               int err;
-
-               err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask);
-               if (err == 0) {
-                       mask |= (1 << 10);
-                       wrmsrl_safe(MSR_AMD64_MCx_MASK(4), mask);
-               }
+               msr_set_bit(MSR_AMD64_MCx_MASK(4), 10);
 
                /*
                 * On family 10h BIOS may not have properly enabled WC+ support,
@@ -733,10 +712,7 @@ static void init_amd(struct cpuinfo_x86 *c)
                 * NOTE: we want to use the _safe accessors so as not to #GP kvm
                 * guests on older kvm hosts.
                 */
-
-               rdmsrl_safe(MSR_AMD64_BU_CFG2, &value);
-               value &= ~(1ULL << 24);
-               wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
+               msr_clear_bit(MSR_AMD64_BU_CFG2, 24);
 
                if (cpu_has_amd_erratum(c, amd_erratum_383))
                        set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
@@ -767,10 +743,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 
 static void cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c)
 {
-       tlb_flushall_shift = 5;
-
-       if (c->x86 <= 0x11)
-               tlb_flushall_shift = 4;
+       tlb_flushall_shift = 6;
 }
 
 static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
index 8779edab684efdcd04fd93d22d79d4633c6fd4f9..d8fba5c15fbd8882f317daa2779c39ff4429b0d4 100644 (file)
@@ -8,236 +8,6 @@
 
 #include "cpu.h"
 
-#ifdef CONFIG_X86_OOSTORE
-
-static u32 power2(u32 x)
-{
-       u32 s = 1;
-
-       while (s <= x)
-               s <<= 1;
-
-       return s >>= 1;
-}
-
-
-/*
- * Set up an actual MCR
- */
-static void centaur_mcr_insert(int reg, u32 base, u32 size, int key)
-{
-       u32 lo, hi;
-
-       hi = base & ~0xFFF;
-       lo = ~(size-1);         /* Size is a power of 2 so this makes a mask */
-       lo &= ~0xFFF;           /* Remove the ctrl value bits */
-       lo |= key;              /* Attribute we wish to set */
-       wrmsr(reg+MSR_IDT_MCR0, lo, hi);
-       mtrr_centaur_report_mcr(reg, lo, hi);   /* Tell the mtrr driver */
-}
-
-/*
- * Figure what we can cover with MCR's
- *
- * Shortcut: We know you can't put 4Gig of RAM on a winchip
- */
-static u32 ramtop(void)
-{
-       u32 clip = 0xFFFFFFFFUL;
-       u32 top = 0;
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long start, end;
-
-               if (e820.map[i].addr > 0xFFFFFFFFUL)
-                       continue;
-               /*
-                * Don't MCR over reserved space. Ignore the ISA hole
-                * we frob around that catastrophe already
-                */
-               if (e820.map[i].type == E820_RESERVED) {
-                       if (e820.map[i].addr >= 0x100000UL &&
-                           e820.map[i].addr < clip)
-                               clip = e820.map[i].addr;
-                       continue;
-               }
-               start = e820.map[i].addr;
-               end = e820.map[i].addr + e820.map[i].size;
-               if (start >= end)
-                       continue;
-               if (end > top)
-                       top = end;
-       }
-       /*
-        * Everything below 'top' should be RAM except for the ISA hole.
-        * Because of the limited MCR's we want to map NV/ACPI into our
-        * MCR range for gunk in RAM
-        *
-        * Clip might cause us to MCR insufficient RAM but that is an
-        * acceptable failure mode and should only bite obscure boxes with
-        * a VESA hole at 15Mb
-        *
-        * The second case Clip sometimes kicks in is when the EBDA is marked
-        * as reserved. Again we fail safe with reasonable results
-        */
-       if (top > clip)
-               top = clip;
-
-       return top;
-}
-
-/*
- * Compute a set of MCR's to give maximum coverage
- */
-static int centaur_mcr_compute(int nr, int key)
-{
-       u32 mem = ramtop();
-       u32 root = power2(mem);
-       u32 base = root;
-       u32 top = root;
-       u32 floor = 0;
-       int ct = 0;
-
-       while (ct < nr) {
-               u32 fspace = 0;
-               u32 high;
-               u32 low;
-
-               /*
-                * Find the largest block we will fill going upwards
-                */
-               high = power2(mem-top);
-
-               /*
-                * Find the largest block we will fill going downwards
-                */
-               low = base/2;
-
-               /*
-                * Don't fill below 1Mb going downwards as there
-                * is an ISA hole in the way.
-                */
-               if (base <= 1024*1024)
-                       low = 0;
-
-               /*
-                * See how much space we could cover by filling below
-                * the ISA hole
-                */
-
-               if (floor == 0)
-                       fspace = 512*1024;
-               else if (floor == 512*1024)
-                       fspace = 128*1024;
-
-               /* And forget ROM space */
-
-               /*
-                * Now install the largest coverage we get
-                */
-               if (fspace > high && fspace > low) {
-                       centaur_mcr_insert(ct, floor, fspace, key);
-                       floor += fspace;
-               } else if (high > low) {
-                       centaur_mcr_insert(ct, top, high, key);
-                       top += high;
-               } else if (low > 0) {
-                       base -= low;
-                       centaur_mcr_insert(ct, base, low, key);
-               } else
-                       break;
-               ct++;
-       }
-       /*
-        * We loaded ct values. We now need to set the mask. The caller
-        * must do this bit.
-        */
-       return ct;
-}
-
-static void centaur_create_optimal_mcr(void)
-{
-       int used;
-       int i;
-
-       /*
-        * Allocate up to 6 mcrs to mark as much of ram as possible
-        * as write combining and weak write ordered.
-        *
-        * To experiment with: Linux never uses stack operations for
-        * mmio spaces so we could globally enable stack operation wc
-        *
-        * Load the registers with type 31 - full write combining, all
-        * writes weakly ordered.
-        */
-       used = centaur_mcr_compute(6, 31);
-
-       /*
-        * Wipe unused MCRs
-        */
-       for (i = used; i < 8; i++)
-               wrmsr(MSR_IDT_MCR0+i, 0, 0);
-}
-
-static void winchip2_create_optimal_mcr(void)
-{
-       u32 lo, hi;
-       int used;
-       int i;
-
-       /*
-        * Allocate up to 6 mcrs to mark as much of ram as possible
-        * as write combining, weak store ordered.
-        *
-        * Load the registers with type 25
-        *      8       -       weak write ordering
-        *      16      -       weak read ordering
-        *      1       -       write combining
-        */
-       used = centaur_mcr_compute(6, 25);
-
-       /*
-        * Mark the registers we are using.
-        */
-       rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
-       for (i = 0; i < used; i++)
-               lo |= 1<<(9+i);
-       wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
-
-       /*
-        * Wipe unused MCRs
-        */
-
-       for (i = used; i < 8; i++)
-               wrmsr(MSR_IDT_MCR0+i, 0, 0);
-}
-
-/*
- * Handle the MCR key on the Winchip 2.
- */
-static void winchip2_unprotect_mcr(void)
-{
-       u32 lo, hi;
-       u32 key;
-
-       rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
-       lo &= ~0x1C0;   /* blank bits 8-6 */
-       key = (lo>>17) & 7;
-       lo |= key<<6;   /* replace with unlock key */
-       wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
-}
-
-static void winchip2_protect_mcr(void)
-{
-       u32 lo, hi;
-
-       rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
-       lo &= ~0x1C0;   /* blank bits 8-6 */
-       wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
-}
-#endif /* CONFIG_X86_OOSTORE */
-
 #define ACE_PRESENT    (1 << 6)
 #define ACE_ENABLED    (1 << 7)
 #define ACE_FCR                (1 << 28)       /* MSR_VIA_FCR */
@@ -362,20 +132,6 @@ static void init_centaur(struct cpuinfo_x86 *c)
                        fcr_clr = DPDC;
                        printk(KERN_NOTICE "Disabling bugged TSC.\n");
                        clear_cpu_cap(c, X86_FEATURE_TSC);
-#ifdef CONFIG_X86_OOSTORE
-                       centaur_create_optimal_mcr();
-                       /*
-                        * Enable:
-                        *      write combining on non-stack, non-string
-                        *      write combining on string, all types
-                        *      weak write ordering
-                        *
-                        * The C6 original lacks weak read order
-                        *
-                        * Note 0x120 is write only on Winchip 1
-                        */
-                       wrmsr(MSR_IDT_MCR_CTRL, 0x01F0001F, 0);
-#endif
                        break;
                case 8:
                        switch (c->x86_mask) {
@@ -392,40 +148,12 @@ static void init_centaur(struct cpuinfo_x86 *c)
                        fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
                                  E2MMX|EAMD3D;
                        fcr_clr = DPDC;
-#ifdef CONFIG_X86_OOSTORE
-                       winchip2_unprotect_mcr();
-                       winchip2_create_optimal_mcr();
-                       rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
-                       /*
-                        * Enable:
-                        *      write combining on non-stack, non-string
-                        *      write combining on string, all types
-                        *      weak write ordering
-                        */
-                       lo |= 31;
-                       wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
-                       winchip2_protect_mcr();
-#endif
                        break;
                case 9:
                        name = "3";
                        fcr_set = ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|
                                  E2MMX|EAMD3D;
                        fcr_clr = DPDC;
-#ifdef CONFIG_X86_OOSTORE
-                       winchip2_unprotect_mcr();
-                       winchip2_create_optimal_mcr();
-                       rdmsr(MSR_IDT_MCR_CTRL, lo, hi);
-                       /*
-                        * Enable:
-                        *      write combining on non-stack, non-string
-                        *      write combining on string, all types
-                        *      weak write ordering
-                        */
-                       lo |= 31;
-                       wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
-                       winchip2_protect_mcr();
-#endif
                        break;
                default:
                        name = "??";
index 24b6fd10625a5a95aeb0331da66cea8c148a08c9..a135239badb7fd4762ebf939ae755183660641b2 100644 (file)
@@ -284,8 +284,13 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c)
        raw_local_save_flags(eflags);
        BUG_ON(eflags & X86_EFLAGS_AC);
 
-       if (cpu_has(c, X86_FEATURE_SMAP))
+       if (cpu_has(c, X86_FEATURE_SMAP)) {
+#ifdef CONFIG_X86_SMAP
                set_in_cr4(X86_CR4_SMAP);
+#else
+               clear_in_cr4(X86_CR4_SMAP);
+#endif
+       }
 }
 
 /*
@@ -1020,7 +1025,8 @@ __setup("show_msr=", setup_show_msr);
 
 static __init int setup_noclflush(char *arg)
 {
-       setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+       setup_clear_cpu_cap(X86_FEATURE_CLFLUSH);
+       setup_clear_cpu_cap(X86_FEATURE_CLFLUSHOPT);
        return 1;
 }
 __setup("noclflush", setup_noclflush);
@@ -1073,6 +1079,10 @@ static __init int setup_disablecpuid(char *arg)
 }
 __setup("clearcpuid=", setup_disablecpuid);
 
+DEFINE_PER_CPU(unsigned long, kernel_stack) =
+       (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
+EXPORT_PER_CPU_SYMBOL(kernel_stack);
+
 #ifdef CONFIG_X86_64
 struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
 struct desc_ptr debug_idt_descr = { NR_VECTORS * 16 - 1,
@@ -1089,10 +1099,6 @@ DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned =
        &init_task;
 EXPORT_PER_CPU_SYMBOL(current_task);
 
-DEFINE_PER_CPU(unsigned long, kernel_stack) =
-       (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
-EXPORT_PER_CPU_SYMBOL(kernel_stack);
-
 DEFINE_PER_CPU(char *, irq_stack_ptr) =
        init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
 
index 3db61c644e440e8af7b978320b546a25336055f4..897d6201ef10b25ca98b3ea66ab4ff1706d5c81d 100644 (file)
@@ -31,11 +31,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)
 
        /* Unmask CPUID levels if masked: */
        if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
-               rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
-
-               if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) {
-                       misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
-                       wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+               if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
+                                 MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0) {
                        c->cpuid_level = cpuid_eax(0);
                        get_cpu_cap(c);
                }
@@ -129,16 +126,10 @@ static void early_init_intel(struct cpuinfo_x86 *c)
         * Ingo Molnar reported a Pentium D (model 6) and a Xeon
         * (model 2) with the same problem.
         */
-       if (c->x86 == 15) {
-               rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
-
-               if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING) {
-                       printk(KERN_INFO "kmemcheck: Disabling fast string operations\n");
-
-                       misc_enable &= ~MSR_IA32_MISC_ENABLE_FAST_STRING;
-                       wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
-               }
-       }
+       if (c->x86 == 15)
+               if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
+                                 MSR_IA32_MISC_ENABLE_FAST_STRING_BIT) > 0)
+                       pr_info("kmemcheck: Disabling fast string operations\n");
 #endif
 
        /*
@@ -195,10 +186,16 @@ static void intel_smp_check(struct cpuinfo_x86 *c)
        }
 }
 
-static void intel_workarounds(struct cpuinfo_x86 *c)
+static int forcepae;
+static int __init forcepae_setup(char *__unused)
 {
-       unsigned long lo, hi;
+       forcepae = 1;
+       return 1;
+}
+__setup("forcepae", forcepae_setup);
 
+static void intel_workarounds(struct cpuinfo_x86 *c)
+{
 #ifdef CONFIG_X86_F00F_BUG
        /*
         * All current models of Pentium and Pentium with MMX technology CPUs
@@ -224,17 +221,27 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
        if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
                clear_cpu_cap(c, X86_FEATURE_SEP);
 
+       /*
+        * PAE CPUID issue: many Pentium M report no PAE but may have a
+        * functionally usable PAE implementation.
+        * Forcefully enable PAE if kernel parameter "forcepae" is present.
+        */
+       if (forcepae) {
+               printk(KERN_WARNING "PAE forced!\n");
+               set_cpu_cap(c, X86_FEATURE_PAE);
+               add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
+       }
+
        /*
         * P4 Xeon errata 037 workaround.
         * Hardware prefetcher may cause stale data to be loaded into the cache.
         */
        if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
-               rdmsr(MSR_IA32_MISC_ENABLE, lo, hi);
-               if ((lo & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE) == 0) {
-                       printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n");
-                       printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n");
-                       lo |= MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE;
-                       wrmsr(MSR_IA32_MISC_ENABLE, lo, hi);
+               if (msr_set_bit(MSR_IA32_MISC_ENABLE,
+                               MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE_BIT)
+                   > 0) {
+                       pr_info("CPU: C0 stepping P4 Xeon detected.\n");
+                       pr_info("CPU: Disabling hardware prefetching (Errata 037)\n");
                }
        }
 
@@ -640,21 +647,17 @@ static void intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c)
        case 0x61d: /* six-core 45 nm xeon "Dunnington" */
                tlb_flushall_shift = -1;
                break;
+       case 0x63a: /* Ivybridge */
+               tlb_flushall_shift = 2;
+               break;
        case 0x61a: /* 45 nm nehalem, "Bloomfield" */
        case 0x61e: /* 45 nm nehalem, "Lynnfield" */
        case 0x625: /* 32 nm nehalem, "Clarkdale" */
        case 0x62c: /* 32 nm nehalem, "Gulftown" */
        case 0x62e: /* 45 nm nehalem-ex, "Beckton" */
        case 0x62f: /* 32 nm Xeon E7 */
-               tlb_flushall_shift = 6;
-               break;
        case 0x62a: /* SandyBridge */
        case 0x62d: /* SandyBridge, "Romely-EP" */
-               tlb_flushall_shift = 5;
-               break;
-       case 0x63a: /* Ivybridge */
-               tlb_flushall_shift = 1;
-               break;
        default:
                tlb_flushall_shift = 6;
        }
index 8384c0fa206f17d4ff3cffb55f427962c863fdc2..617a9e28424560d28e7594e2c8213985aaef3de2 100644 (file)
@@ -285,6 +285,15 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
 
        uci->cpu_sig.sig = cpuid_eax(0x00000001);
 }
+
+static void __init get_bsp_sig(void)
+{
+       unsigned int bsp = boot_cpu_data.cpu_index;
+       struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
+
+       if (!uci->cpu_sig.sig)
+               smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+}
 #else
 void load_ucode_amd_ap(void)
 {
@@ -337,31 +346,37 @@ void load_ucode_amd_ap(void)
 
 int __init save_microcode_in_initrd_amd(void)
 {
+       unsigned long cont;
        enum ucode_state ret;
        u32 eax;
 
-#ifdef CONFIG_X86_32
-       unsigned int bsp = boot_cpu_data.cpu_index;
-       struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
-
-       if (!uci->cpu_sig.sig)
-               smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+       if (!container)
+               return -EINVAL;
 
+#ifdef CONFIG_X86_32
+       get_bsp_sig();
+       cont = (unsigned long)container;
+#else
        /*
-        * Take into account the fact that the ramdisk might get relocated
-        * and therefore we need to recompute the container's position in
-        * virtual memory space.
+        * We need the physical address of the container for both bitness since
+        * boot_params.hdr.ramdisk_image is a physical address.
         */
-       container = (u8 *)(__va((u32)relocated_ramdisk) +
-                          ((u32)container - boot_params.hdr.ramdisk_image));
+       cont = __pa(container);
 #endif
+
+       /*
+        * Take into account the fact that the ramdisk might get relocated and
+        * therefore we need to recompute the container's position in virtual
+        * memory space.
+        */
+       if (relocated_ramdisk)
+               container = (u8 *)(__va(relocated_ramdisk) +
+                            (cont - boot_params.hdr.ramdisk_image));
+
        if (ucode_new_rev)
                pr_info("microcode: updated early to new patch_level=0x%08x\n",
                        ucode_new_rev);
 
-       if (!container)
-               return -EINVAL;
-
        eax   = cpuid_eax(0x00000001);
        eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
 
index 9f7ca266864a47cbb5484fead33a063d48f01f27..832d05a914ba9e3fe9f2e23fbcf26dd5f29462b5 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/irq_regs.h>
 #include <asm/i8259.h>
 #include <asm/apic.h>
+#include <asm/timer.h>
 
 struct ms_hyperv_info ms_hyperv;
 EXPORT_SYMBOL_GPL(ms_hyperv);
@@ -105,6 +106,11 @@ static void __init ms_hyperv_init_platform(void)
 
        if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
                clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
+
+#ifdef CONFIG_X86_IO_APIC
+       no_timer_check = 1;
+#endif
+
 }
 
 const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
index ce2d0a2c3e4ff56819152574eefded2e8d64ea69..0e25a1bc5ab5cfbbf21484ce268ad17ed48844ec 100644 (file)
@@ -683,7 +683,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
        }
 
        /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
-       count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
        __flush_tlb();
 
        /* Save MTRR state */
@@ -697,7 +697,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
 static void post_set(void) __releases(set_atomicity_lock)
 {
        /* Flush TLBs (no need to flush caches - they are disabled) */
-       count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
        __flush_tlb();
 
        /* Intel (P6) standard MTRRs */
index b88645191fe559b89b8d330c984865d07dbae21b..ae407f7226c89961fde14ddd6d932f174c64d8fc 100644 (file)
@@ -892,7 +892,6 @@ static void x86_pmu_enable(struct pmu *pmu)
                 * hw_perf_group_sched_in() or x86_pmu_enable()
                 *
                 * step1: save events moving to new counters
-                * step2: reprogram moved events into new counters
                 */
                for (i = 0; i < n_running; i++) {
                        event = cpuc->event_list[i];
@@ -918,6 +917,9 @@ static void x86_pmu_enable(struct pmu *pmu)
                        x86_pmu_stop(event, PERF_EF_UPDATE);
                }
 
+               /*
+                * step2: reprogram moved events into new counters
+                */
                for (i = 0; i < cpuc->n_events; i++) {
                        event = cpuc->event_list[i];
                        hwc = &event->hw;
@@ -1043,7 +1045,7 @@ static int x86_pmu_add(struct perf_event *event, int flags)
        /*
         * If group events scheduling transaction was started,
         * skip the schedulability test here, it will be performed
-        * at commit time (->commit_txn) as a whole
+        * at commit time (->commit_txn) as a whole.
         */
        if (cpuc->group_flag & PERF_EVENT_TXN)
                goto done_collect;
@@ -1058,6 +1060,10 @@ static int x86_pmu_add(struct perf_event *event, int flags)
        memcpy(cpuc->assign, assign, n*sizeof(int));
 
 done_collect:
+       /*
+        * Commit the collect_events() state. See x86_pmu_del() and
+        * x86_pmu_*_txn().
+        */
        cpuc->n_events = n;
        cpuc->n_added += n - n0;
        cpuc->n_txn += n - n0;
@@ -1183,25 +1189,38 @@ static void x86_pmu_del(struct perf_event *event, int flags)
         * If we're called during a txn, we don't need to do anything.
         * The events never got scheduled and ->cancel_txn will truncate
         * the event_list.
+        *
+        * XXX assumes any ->del() called during a TXN will only be on
+        * an event added during that same TXN.
         */
        if (cpuc->group_flag & PERF_EVENT_TXN)
                return;
 
+       /*
+        * Not a TXN, therefore cleanup properly.
+        */
        x86_pmu_stop(event, PERF_EF_UPDATE);
 
        for (i = 0; i < cpuc->n_events; i++) {
-               if (event == cpuc->event_list[i]) {
+               if (event == cpuc->event_list[i])
+                       break;
+       }
 
-                       if (x86_pmu.put_event_constraints)
-                               x86_pmu.put_event_constraints(cpuc, event);
+       if (WARN_ON_ONCE(i == cpuc->n_events)) /* called ->del() without ->add() ? */
+               return;
 
-                       while (++i < cpuc->n_events)
-                               cpuc->event_list[i-1] = cpuc->event_list[i];
+       /* If we have a newly added event; make sure to decrease n_added. */
+       if (i >= cpuc->n_events - cpuc->n_added)
+               --cpuc->n_added;
+
+       if (x86_pmu.put_event_constraints)
+               x86_pmu.put_event_constraints(cpuc, event);
+
+       /* Delete the array entry. */
+       while (++i < cpuc->n_events)
+               cpuc->event_list[i-1] = cpuc->event_list[i];
+       --cpuc->n_events;
 
-                       --cpuc->n_events;
-                       break;
-               }
-       }
        perf_event_update_userpage(event);
 }
 
@@ -1521,6 +1540,8 @@ static int __init init_hw_perf_events(void)
 
        pr_cont("%s PMU driver.\n", x86_pmu.name);
 
+       x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
+
        for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
                quirk->func();
 
@@ -1534,7 +1555,6 @@ static int __init init_hw_perf_events(void)
                __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
                                   0, x86_pmu.num_counters, 0, 0);
 
-       x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
        x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
        if (x86_pmu.event_attrs)
@@ -1594,7 +1614,8 @@ static void x86_pmu_cancel_txn(struct pmu *pmu)
 {
        __this_cpu_and(cpu_hw_events.group_flag, ~PERF_EVENT_TXN);
        /*
-        * Truncate the collected events.
+        * Truncate collected array by the number of events added in this
+        * transaction. See x86_pmu_add() and x86_pmu_*_txn().
         */
        __this_cpu_sub(cpu_hw_events.n_added, __this_cpu_read(cpu_hw_events.n_txn));
        __this_cpu_sub(cpu_hw_events.n_events, __this_cpu_read(cpu_hw_events.n_txn));
@@ -1605,6 +1626,8 @@ static void x86_pmu_cancel_txn(struct pmu *pmu)
  * Commit group events scheduling transaction
  * Perform the group schedulability test as a whole
  * Return 0 if success
+ *
+ * Does not cancel the transaction on failure; expects the caller to do this.
  */
 static int x86_pmu_commit_txn(struct pmu *pmu)
 {
@@ -1820,9 +1843,12 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
        if (ret)
                return ret;
 
+       if (x86_pmu.attr_rdpmc_broken)
+               return -ENOTSUPP;
+
        if (!!val != !!x86_pmu.attr_rdpmc) {
                x86_pmu.attr_rdpmc = !!val;
-               smp_call_function(change_rdpmc, (void *)val, 1);
+               on_each_cpu(change_rdpmc, (void *)val, 1);
        }
 
        return count;
index c1a861829d817a2749372060df21c6d689294fff..3b2f9bdd974be198d0622e306ddbba427add2d25 100644 (file)
@@ -130,9 +130,11 @@ struct cpu_hw_events {
        unsigned long           running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
        int                     enabled;
 
-       int                     n_events;
-       int                     n_added;
-       int                     n_txn;
+       int                     n_events; /* the # of events in the below arrays */
+       int                     n_added;  /* the # last events in the below arrays;
+                                            they've never been enabled yet */
+       int                     n_txn;    /* the # last events in the below arrays;
+                                            added in the current transaction */
        int                     assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
        u64                     tags[X86_PMC_IDX_MAX];
        struct perf_event       *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
@@ -409,6 +411,7 @@ struct x86_pmu {
        /*
         * sysfs attrs
         */
+       int             attr_rdpmc_broken;
        int             attr_rdpmc;
        struct attribute **format_attrs;
        struct attribute **event_attrs;
index 0fa4f242f0504ad53297360966e957b84a0edab8..aa333d9668866f808955209f8cd71737d447eafc 100644 (file)
@@ -1361,10 +1361,8 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
        intel_pmu_disable_all();
        handled = intel_pmu_drain_bts_buffer();
        status = intel_pmu_get_status();
-       if (!status) {
-               intel_pmu_enable_all(0);
-               return handled;
-       }
+       if (!status)
+               goto done;
 
        loops = 0;
 again:
@@ -2310,10 +2308,7 @@ __init int intel_pmu_init(void)
        if (version > 1)
                x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
 
-       /*
-        * v2 and above have a perf capabilities MSR
-        */
-       if (version > 1) {
+       if (boot_cpu_has(X86_FEATURE_PDCM)) {
                u64 capabilities;
 
                rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities);
index 29c248799cede4432ac2d57ca8689a215c35d0cc..bd2253d40cffe16363569384084bdf6d6d73e7f5 100644 (file)
@@ -66,6 +66,47 @@ DEFINE_UNCORE_FORMAT_ATTR(mask_vnw, mask_vnw, "config2:3-4");
 DEFINE_UNCORE_FORMAT_ATTR(mask0, mask0, "config2:0-31");
 DEFINE_UNCORE_FORMAT_ATTR(mask1, mask1, "config2:32-63");
 
+static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box);
+static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box);
+static void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event);
+static void uncore_pmu_event_read(struct perf_event *event);
+
+static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
+{
+       return container_of(event->pmu, struct intel_uncore_pmu, pmu);
+}
+
+static struct intel_uncore_box *
+uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
+{
+       struct intel_uncore_box *box;
+
+       box = *per_cpu_ptr(pmu->box, cpu);
+       if (box)
+               return box;
+
+       raw_spin_lock(&uncore_box_lock);
+       list_for_each_entry(box, &pmu->box_list, list) {
+               if (box->phys_id == topology_physical_package_id(cpu)) {
+                       atomic_inc(&box->refcnt);
+                       *per_cpu_ptr(pmu->box, cpu) = box;
+                       break;
+               }
+       }
+       raw_spin_unlock(&uncore_box_lock);
+
+       return *per_cpu_ptr(pmu->box, cpu);
+}
+
+static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
+{
+       /*
+        * perf core schedules event on the basis of cpu, uncore events are
+        * collected by one of the cpus inside a physical package.
+        */
+       return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id());
+}
+
 static u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
 {
        u64 count;
@@ -501,8 +542,11 @@ static struct extra_reg snbep_uncore_cbox_extra_regs[] = {
        SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
                                  SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
@@ -1178,10 +1222,15 @@ static struct extra_reg ivt_uncore_cbox_extra_regs[] = {
        SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
                                  SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
        SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
        SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
        SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
@@ -1631,6 +1680,349 @@ static struct intel_uncore_type *snb_msr_uncores[] = {
        &snb_uncore_cbox,
        NULL,
 };
+
+enum {
+       SNB_PCI_UNCORE_IMC,
+};
+
+static struct uncore_event_desc snb_uncore_imc_events[] = {
+       INTEL_UNCORE_EVENT_DESC(data_reads,  "event=0x01"),
+       INTEL_UNCORE_EVENT_DESC(data_reads.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(data_reads.unit, "MiB"),
+
+       INTEL_UNCORE_EVENT_DESC(data_writes, "event=0x02"),
+       INTEL_UNCORE_EVENT_DESC(data_writes.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(data_writes.unit, "MiB"),
+
+       { /* end: all zeroes */ },
+};
+
+#define SNB_UNCORE_PCI_IMC_EVENT_MASK          0xff
+#define SNB_UNCORE_PCI_IMC_BAR_OFFSET          0x48
+
+/* page size multiple covering all config regs */
+#define SNB_UNCORE_PCI_IMC_MAP_SIZE            0x6000
+
+#define SNB_UNCORE_PCI_IMC_DATA_READS          0x1
+#define SNB_UNCORE_PCI_IMC_DATA_READS_BASE     0x5050
+#define SNB_UNCORE_PCI_IMC_DATA_WRITES         0x2
+#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE    0x5054
+#define SNB_UNCORE_PCI_IMC_CTR_BASE            SNB_UNCORE_PCI_IMC_DATA_READS_BASE
+
+static struct attribute *snb_uncore_imc_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group snb_uncore_imc_format_group = {
+       .name = "format",
+       .attrs = snb_uncore_imc_formats_attr,
+};
+
+static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int where = SNB_UNCORE_PCI_IMC_BAR_OFFSET;
+       resource_size_t addr;
+       u32 pci_dword;
+
+       pci_read_config_dword(pdev, where, &pci_dword);
+       addr = pci_dword;
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+       pci_read_config_dword(pdev, where + 4, &pci_dword);
+       addr |= ((resource_size_t)pci_dword << 32);
+#endif
+
+       addr &= ~(PAGE_SIZE - 1);
+
+       box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
+       box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
+}
+
+static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
+{}
+
+static void snb_uncore_imc_disable_box(struct intel_uncore_box *box)
+{}
+
+static void snb_uncore_imc_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{}
+
+static void snb_uncore_imc_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{}
+
+static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       return (u64)*(unsigned int *)(box->io_addr + hwc->event_base);
+}
+
+/*
+ * custom event_init() function because we define our own fixed, free
+ * running counters, so we do not want to conflict with generic uncore
+ * logic. Also simplifies processing
+ */
+static int snb_uncore_imc_event_init(struct perf_event *event)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 cfg = event->attr.config & SNB_UNCORE_PCI_IMC_EVENT_MASK;
+       int idx, base;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       pmu = uncore_event_to_pmu(event);
+       /* no device found for this pmu */
+       if (pmu->func_id < 0)
+               return -ENOENT;
+
+       /* Sampling not supported yet */
+       if (hwc->sample_period)
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       /*
+        * Place all uncore events for a particular physical package
+        * onto a single cpu
+        */
+       if (event->cpu < 0)
+               return -EINVAL;
+
+       /* check only supported bits are set */
+       if (event->attr.config & ~SNB_UNCORE_PCI_IMC_EVENT_MASK)
+               return -EINVAL;
+
+       box = uncore_pmu_to_box(pmu, event->cpu);
+       if (!box || box->cpu < 0)
+               return -EINVAL;
+
+       event->cpu = box->cpu;
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+       event->hw.extra_reg.idx = EXTRA_REG_NONE;
+       event->hw.branch_reg.idx = EXTRA_REG_NONE;
+       /*
+        * check event is known (whitelist, determines counter)
+        */
+       switch (cfg) {
+       case SNB_UNCORE_PCI_IMC_DATA_READS:
+               base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
+               idx = UNCORE_PMC_IDX_FIXED;
+               break;
+       case SNB_UNCORE_PCI_IMC_DATA_WRITES:
+               base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
+               idx = UNCORE_PMC_IDX_FIXED + 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* must be done before validate_group */
+       event->hw.event_base = base;
+       event->hw.config = cfg;
+       event->hw.idx = idx;
+
+       /* no group validation needed, we have free running counters */
+
+       return 0;
+}
+
+static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       return 0;
+}
+
+static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       u64 count;
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       event->hw.state = 0;
+       box->n_active++;
+
+       list_add_tail(&event->active_entry, &box->active_list);
+
+       count = snb_uncore_imc_read_counter(box, event);
+       local64_set(&event->hw.prev_count, count);
+
+       if (box->n_active == 1)
+               uncore_pmu_start_hrtimer(box);
+}
+
+static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               box->n_active--;
+
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+
+               list_del(&event->active_entry);
+
+               if (box->n_active == 0)
+                       uncore_pmu_cancel_hrtimer(box);
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               uncore_perf_event_update(box, event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (!box)
+               return -ENODEV;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
+
+       snb_uncore_imc_event_start(event, 0);
+
+       box->n_events++;
+
+       return 0;
+}
+
+static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int i;
+
+       snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < box->n_events; i++) {
+               if (event == box->event_list[i]) {
+                       --box->n_events;
+                       break;
+               }
+       }
+}
+
+static int snb_pci2phy_map_init(int devid)
+{
+       struct pci_dev *dev = NULL;
+       int bus;
+
+       dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, dev);
+       if (!dev)
+               return -ENOTTY;
+
+       bus = dev->bus->number;
+
+       pcibus_to_physid[bus] = 0;
+
+       pci_dev_put(dev);
+
+       return 0;
+}
+
+static struct pmu snb_uncore_imc_pmu = {
+       .task_ctx_nr    = perf_invalid_context,
+       .event_init     = snb_uncore_imc_event_init,
+       .add            = snb_uncore_imc_event_add,
+       .del            = snb_uncore_imc_event_del,
+       .start          = snb_uncore_imc_event_start,
+       .stop           = snb_uncore_imc_event_stop,
+       .read           = uncore_pmu_event_read,
+};
+
+static struct intel_uncore_ops snb_uncore_imc_ops = {
+       .init_box       = snb_uncore_imc_init_box,
+       .enable_box     = snb_uncore_imc_enable_box,
+       .disable_box    = snb_uncore_imc_disable_box,
+       .disable_event  = snb_uncore_imc_disable_event,
+       .enable_event   = snb_uncore_imc_enable_event,
+       .hw_config      = snb_uncore_imc_hw_config,
+       .read_counter   = snb_uncore_imc_read_counter,
+};
+
+static struct intel_uncore_type snb_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .fixed_ctr_bits = 32,
+       .fixed_ctr      = SNB_UNCORE_PCI_IMC_CTR_BASE,
+       .event_descs    = snb_uncore_imc_events,
+       .format_group   = &snb_uncore_imc_format_group,
+       .perf_ctr       = SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
+       .event_mask     = SNB_UNCORE_PCI_IMC_EVENT_MASK,
+       .ops            = &snb_uncore_imc_ops,
+       .pmu            = &snb_uncore_imc_pmu,
+};
+
+static struct intel_uncore_type *snb_pci_uncores[] = {
+       [SNB_PCI_UNCORE_IMC]    = &snb_uncore_imc,
+       NULL,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(snb_uncore_pci_ids) = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static DEFINE_PCI_DEVICE_TABLE(ivb_uncore_pci_ids) = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static DEFINE_PCI_DEVICE_TABLE(hsw_uncore_pci_ids) = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static struct pci_driver snb_uncore_pci_driver = {
+       .name           = "snb_uncore",
+       .id_table       = snb_uncore_pci_ids,
+};
+
+static struct pci_driver ivb_uncore_pci_driver = {
+       .name           = "ivb_uncore",
+       .id_table       = ivb_uncore_pci_ids,
+};
+
+static struct pci_driver hsw_uncore_pci_driver = {
+       .name           = "hsw_uncore",
+       .id_table       = hsw_uncore_pci_ids,
+};
+
 /* end of Sandy Bridge uncore support */
 
 /* Nehalem uncore support */
@@ -2781,6 +3173,7 @@ again:
 static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
 {
        struct intel_uncore_box *box;
+       struct perf_event *event;
        unsigned long flags;
        int bit;
 
@@ -2793,19 +3186,27 @@ static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
         */
        local_irq_save(flags);
 
+       /*
+        * handle boxes with an active event list as opposed to active
+        * counters
+        */
+       list_for_each_entry(event, &box->active_list, active_entry) {
+               uncore_perf_event_update(box, event);
+       }
+
        for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
                uncore_perf_event_update(box, box->events[bit]);
 
        local_irq_restore(flags);
 
-       hrtimer_forward_now(hrtimer, ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL));
+       hrtimer_forward_now(hrtimer, ns_to_ktime(box->hrtimer_duration));
        return HRTIMER_RESTART;
 }
 
 static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
 {
        __hrtimer_start_range_ns(&box->hrtimer,
-                       ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL), 0,
+                       ns_to_ktime(box->hrtimer_duration), 0,
                        HRTIMER_MODE_REL_PINNED, 0);
 }
 
@@ -2839,43 +3240,12 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
        box->cpu = -1;
        box->phys_id = -1;
 
-       return box;
-}
-
-static struct intel_uncore_box *
-uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
-{
-       struct intel_uncore_box *box;
-
-       box = *per_cpu_ptr(pmu->box, cpu);
-       if (box)
-               return box;
+       /* set default hrtimer timeout */
+       box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
 
-       raw_spin_lock(&uncore_box_lock);
-       list_for_each_entry(box, &pmu->box_list, list) {
-               if (box->phys_id == topology_physical_package_id(cpu)) {
-                       atomic_inc(&box->refcnt);
-                       *per_cpu_ptr(pmu->box, cpu) = box;
-                       break;
-               }
-       }
-       raw_spin_unlock(&uncore_box_lock);
+       INIT_LIST_HEAD(&box->active_list);
 
-       return *per_cpu_ptr(pmu->box, cpu);
-}
-
-static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
-{
-       return container_of(event->pmu, struct intel_uncore_pmu, pmu);
-}
-
-static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
-{
-       /*
-        * perf core schedules event on the basis of cpu, uncore events are
-        * collected by one of the cpus inside a physical package.
-        */
-       return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id());
+       return box;
 }
 
 static int
@@ -3271,16 +3641,21 @@ static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
 {
        int ret;
 
-       pmu->pmu = (struct pmu) {
-               .attr_groups    = pmu->type->attr_groups,
-               .task_ctx_nr    = perf_invalid_context,
-               .event_init     = uncore_pmu_event_init,
-               .add            = uncore_pmu_event_add,
-               .del            = uncore_pmu_event_del,
-               .start          = uncore_pmu_event_start,
-               .stop           = uncore_pmu_event_stop,
-               .read           = uncore_pmu_event_read,
-       };
+       if (!pmu->type->pmu) {
+               pmu->pmu = (struct pmu) {
+                       .attr_groups    = pmu->type->attr_groups,
+                       .task_ctx_nr    = perf_invalid_context,
+                       .event_init     = uncore_pmu_event_init,
+                       .add            = uncore_pmu_event_add,
+                       .del            = uncore_pmu_event_del,
+                       .start          = uncore_pmu_event_start,
+                       .stop           = uncore_pmu_event_stop,
+                       .read           = uncore_pmu_event_read,
+               };
+       } else {
+               pmu->pmu = *pmu->type->pmu;
+               pmu->pmu.attr_groups = pmu->type->attr_groups;
+       }
 
        if (pmu->type->num_boxes == 1) {
                if (strlen(pmu->type->name) > 0)
@@ -3326,6 +3701,8 @@ static int __init uncore_type_init(struct intel_uncore_type *type)
        if (!pmus)
                return -ENOMEM;
 
+       type->pmus = pmus;
+
        type->unconstrainted = (struct event_constraint)
                __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1,
                                0, type->num_counters, 0, 0);
@@ -3361,7 +3738,6 @@ static int __init uncore_type_init(struct intel_uncore_type *type)
        }
 
        type->pmu_group = &uncore_pmu_attr_group;
-       type->pmus = pmus;
        return 0;
 fail:
        uncore_type_exit(type);
@@ -3493,6 +3869,28 @@ static int __init uncore_pci_init(void)
                pci_uncores = ivt_pci_uncores;
                uncore_pci_driver = &ivt_uncore_pci_driver;
                break;
+       case 42: /* Sandy Bridge */
+               ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_SNB_IMC);
+               if (ret)
+                       return ret;
+               pci_uncores = snb_pci_uncores;
+               uncore_pci_driver = &snb_uncore_pci_driver;
+               break;
+       case 58: /* Ivy Bridge */
+               ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_IVB_IMC);
+               if (ret)
+                       return ret;
+               pci_uncores = snb_pci_uncores;
+               uncore_pci_driver = &ivb_uncore_pci_driver;
+               break;
+       case 60: /* Haswell */
+       case 69: /* Haswell Celeron */
+               ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_HSW_IMC);
+               if (ret)
+                       return ret;
+               pci_uncores = snb_pci_uncores;
+               uncore_pci_driver = &hsw_uncore_pci_driver;
+               break;
        default:
                return 0;
        }
@@ -3764,7 +4162,7 @@ static void __init uncore_cpu_setup(void *dummy)
 
 static int __init uncore_cpu_init(void)
 {
-       int ret, cpu, max_cores;
+       int ret, max_cores;
 
        max_cores = boot_cpu_data.x86_max_cores;
        switch (boot_cpu_data.x86_model) {
@@ -3808,29 +4206,6 @@ static int __init uncore_cpu_init(void)
        if (ret)
                return ret;
 
-       get_online_cpus();
-
-       for_each_online_cpu(cpu) {
-               int i, phys_id = topology_physical_package_id(cpu);
-
-               for_each_cpu(i, &uncore_cpu_mask) {
-                       if (phys_id == topology_physical_package_id(i)) {
-                               phys_id = -1;
-                               break;
-                       }
-               }
-               if (phys_id < 0)
-                       continue;
-
-               uncore_cpu_prepare(cpu, phys_id);
-               uncore_event_init_cpu(cpu);
-       }
-       on_each_cpu(uncore_cpu_setup, NULL, 1);
-
-       register_cpu_notifier(&uncore_cpu_nb);
-
-       put_online_cpus();
-
        return 0;
 }
 
@@ -3859,6 +4234,41 @@ static int __init uncore_pmus_register(void)
        return 0;
 }
 
+static void __init uncore_cpumask_init(void)
+{
+       int cpu;
+
+       /*
+        * ony invoke once from msr or pci init code
+        */
+       if (!cpumask_empty(&uncore_cpu_mask))
+               return;
+
+       get_online_cpus();
+
+       for_each_online_cpu(cpu) {
+               int i, phys_id = topology_physical_package_id(cpu);
+
+               for_each_cpu(i, &uncore_cpu_mask) {
+                       if (phys_id == topology_physical_package_id(i)) {
+                               phys_id = -1;
+                               break;
+                       }
+               }
+               if (phys_id < 0)
+                       continue;
+
+               uncore_cpu_prepare(cpu, phys_id);
+               uncore_event_init_cpu(cpu);
+       }
+       on_each_cpu(uncore_cpu_setup, NULL, 1);
+
+       register_cpu_notifier(&uncore_cpu_nb);
+
+       put_online_cpus();
+}
+
+
 static int __init intel_uncore_init(void)
 {
        int ret;
@@ -3877,6 +4287,7 @@ static int __init intel_uncore_init(void)
                uncore_pci_exit();
                goto fail;
        }
+       uncore_cpumask_init();
 
        uncore_pmus_register();
        return 0;
index a80ab71a883de06be3cbed3a8c0848aa1dfff69a..90236f0c94a90679506973efe6e56c51bfb9bb2f 100644 (file)
@@ -6,6 +6,7 @@
 
 #define UNCORE_PMU_NAME_LEN            32
 #define UNCORE_PMU_HRTIMER_INTERVAL    (60LL * NSEC_PER_SEC)
+#define UNCORE_SNB_IMC_HRTIMER_INTERVAL (5ULL * NSEC_PER_SEC)
 
 #define UNCORE_FIXED_EVENT             0xff
 #define UNCORE_PMC_IDX_MAX_GENERIC     8
@@ -440,6 +441,7 @@ struct intel_uncore_type {
        struct intel_uncore_ops *ops;
        struct uncore_event_desc *event_descs;
        const struct attribute_group *attr_groups[4];
+       struct pmu *pmu; /* for custom pmu ops */
 };
 
 #define pmu_group attr_groups[0]
@@ -488,8 +490,11 @@ struct intel_uncore_box {
        u64 tags[UNCORE_PMC_IDX_MAX];
        struct pci_dev *pci_dev;
        struct intel_uncore_pmu *pmu;
+       u64 hrtimer_duration; /* hrtimer timeout for this box */
        struct hrtimer hrtimer;
        struct list_head list;
+       struct list_head active_list;
+       void *io_addr;
        struct intel_uncore_extra_reg shared_regs[0];
 };
 
index 3486e6660357e7b365f59c279d748b188a6e72e4..5d466b7d8609814355c90e2cf09ced760debd458 100644 (file)
@@ -1257,7 +1257,24 @@ again:
                        pass++;
                        goto again;
                }
-
+               /*
+                * Perf does test runs to see if a whole group can be assigned
+                * together succesfully.  There can be multiple rounds of this.
+                * Unfortunately, p4_pmu_swap_config_ts touches the hwc->config
+                * bits, such that the next round of group assignments will
+                * cause the above p4_should_swap_ts to pass instead of fail.
+                * This leads to counters exclusive to thread0 being used by
+                * thread1.
+                *
+                * Solve this with a cheap hack, reset the idx back to -1 to
+                * force a new lookup (p4_next_cntr) to get the right counter
+                * for the right thread.
+                *
+                * This probably doesn't comply with the general spirit of how
+                * perf wants to work, but P4 is special. :-(
+                */
+               if (p4_should_swap_ts(hwc->config, cpu))
+                       hwc->idx = -1;
                p4_pmu_swap_config_ts(hwc, cpu);
                if (assign)
                        assign[i] = cntr_idx;
@@ -1322,6 +1339,7 @@ static __initconst const struct x86_pmu p4_pmu = {
 __init int p4_pmu_init(void)
 {
        unsigned int low, high;
+       int i, reg;
 
        /* If we get stripped -- indexing fails */
        BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC);
@@ -1340,5 +1358,19 @@ __init int p4_pmu_init(void)
 
        x86_pmu = p4_pmu;
 
+       /*
+        * Even though the counters are configured to interrupt a particular
+        * logical processor when an overflow happens, testing has shown that
+        * on kdump kernels (which uses a single cpu), thread1's counter
+        * continues to run and will report an NMI on thread0.  Due to the
+        * overflow bug, this leads to a stream of unknown NMIs.
+        *
+        * Solve this by zero'ing out the registers to mimic a reset.
+        */
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               reg = x86_pmu_config_addr(i);
+               wrmsrl_safe(reg, 0ULL);
+       }
+
        return 0;
 }
index b1e2fe11532329bb9828ac4407f6b10093073187..7c1a0c07b607f1d882781978e1d08a8a94a546d2 100644 (file)
@@ -231,31 +231,49 @@ static __initconst const struct x86_pmu p6_pmu = {
 
 };
 
+static __init void p6_pmu_rdpmc_quirk(void)
+{
+       if (boot_cpu_data.x86_mask < 9) {
+               /*
+                * PPro erratum 26; fixed in stepping 9 and above.
+                */
+               pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
+               x86_pmu.attr_rdpmc_broken = 1;
+               x86_pmu.attr_rdpmc = 0;
+       }
+}
+
 __init int p6_pmu_init(void)
 {
+       x86_pmu = p6_pmu;
+
        switch (boot_cpu_data.x86_model) {
-       case 1:
-       case 3:  /* Pentium Pro */
-       case 5:
-       case 6:  /* Pentium II */
-       case 7:
-       case 8:
-       case 11: /* Pentium III */
-       case 9:
-       case 13:
-               /* Pentium M */
+       case  1: /* Pentium Pro */
+               x86_add_quirk(p6_pmu_rdpmc_quirk);
+               break;
+
+       case  3: /* Pentium II - Klamath */
+       case  5: /* Pentium II - Deschutes */
+       case  6: /* Pentium II - Mendocino */
                break;
+
+       case  7: /* Pentium III - Katmai */
+       case  8: /* Pentium III - Coppermine */
+       case 10: /* Pentium III Xeon */
+       case 11: /* Pentium III - Tualatin */
+               break;
+
+       case  9: /* Pentium M - Banias */
+       case 13: /* Pentium M - Dothan */
+               break;
+
        default:
-               pr_cont("unsupported p6 CPU model %d ",
-                       boot_cpu_data.x86_model);
+               pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
                return -ENODEV;
        }
 
-       x86_pmu = p6_pmu;
-
        memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
                sizeof(hw_cache_event_ids));
 
-
        return 0;
 }
index a57902efe2d597be4af85c9d52d995360d54dadb..507de80665942b87a148e032fd8aeedfeb76c70b 100644 (file)
@@ -57,9 +57,7 @@ static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
 {
 #ifdef CONFIG_X86_32
        struct pt_regs fixed_regs;
-#endif
 
-#ifdef CONFIG_X86_32
        if (!user_mode_vm(regs)) {
                crash_fixup_ss_esp(&fixed_regs, regs);
                regs = &fixed_regs;
index f2a1770ca176381b843f9ab6f08327e55a9a3d6c..5abd4cd4230c69f3ff4730e97a1297be40013c44 100644 (file)
 
 #include <asm/stacktrace.h>
 
+static void *is_irq_stack(void *p, void *irq)
+{
+       if (p < irq || p >= (irq + THREAD_SIZE))
+               return NULL;
+       return irq + THREAD_SIZE;
+}
+
+
+static void *is_hardirq_stack(unsigned long *stack, int cpu)
+{
+       void *irq = per_cpu(hardirq_stack, cpu);
+
+       return is_irq_stack(stack, irq);
+}
+
+static void *is_softirq_stack(unsigned long *stack, int cpu)
+{
+       void *irq = per_cpu(softirq_stack, cpu);
+
+       return is_irq_stack(stack, irq);
+}
 
 void dump_trace(struct task_struct *task, struct pt_regs *regs,
                unsigned long *stack, unsigned long bp,
                const struct stacktrace_ops *ops, void *data)
 {
+       const unsigned cpu = get_cpu();
        int graph = 0;
+       u32 *prev_esp;
 
        if (!task)
                task = current;
@@ -30,7 +53,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                unsigned long dummy;
 
                stack = &dummy;
-               if (task && task != current)
+               if (task != current)
                        stack = (unsigned long *)task->thread.sp;
        }
 
@@ -39,18 +62,31 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
 
        for (;;) {
                struct thread_info *context;
+               void *end_stack;
+
+               end_stack = is_hardirq_stack(stack, cpu);
+               if (!end_stack)
+                       end_stack = is_softirq_stack(stack, cpu);
 
-               context = (struct thread_info *)
-                       ((unsigned long)stack & (~(THREAD_SIZE - 1)));
-               bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);
+               context = task_thread_info(task);
+               bp = ops->walk_stack(context, stack, bp, ops, data,
+                                    end_stack, &graph);
 
-               stack = (unsigned long *)context->previous_esp;
+               /* Stop if not on irq stack */
+               if (!end_stack)
+                       break;
+
+               /* The previous esp is saved on the bottom of the stack */
+               prev_esp = (u32 *)(end_stack - THREAD_SIZE);
+               stack = (unsigned long *)*prev_esp;
                if (!stack)
                        break;
+
                if (ops->stack(data, "IRQ") < 0)
                        break;
                touch_nmi_watchdog();
        }
+       put_cpu();
 }
 EXPORT_SYMBOL(dump_trace);
 
index addb207dab92d11ebe4d48650babe07db36a1539..346b1df2412e238a35a558f66ec2b210b4710bf7 100644 (file)
@@ -104,6 +104,45 @@ in_irq_stack(unsigned long *stack, unsigned long *irq_stack,
        return (stack >= irq_stack && stack < irq_stack_end);
 }
 
+static const unsigned long irq_stack_size =
+       (IRQ_STACK_SIZE - 64) / sizeof(unsigned long);
+
+enum stack_type {
+       STACK_IS_UNKNOWN,
+       STACK_IS_NORMAL,
+       STACK_IS_EXCEPTION,
+       STACK_IS_IRQ,
+};
+
+static enum stack_type
+analyze_stack(int cpu, struct task_struct *task,
+             unsigned long *stack, unsigned long **stack_end, char **id)
+{
+       unsigned long *irq_stack;
+       unsigned long addr;
+       unsigned used = 0;
+
+       addr = ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+       if ((unsigned long)task_stack_page(task) == addr)
+               return STACK_IS_NORMAL;
+
+       *stack_end = in_exception_stack(cpu, (unsigned long)stack,
+                                        &used, id);
+       if (*stack_end)
+               return STACK_IS_EXCEPTION;
+
+       *stack_end = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
+       if (!*stack_end)
+               return STACK_IS_UNKNOWN;
+
+       irq_stack = *stack_end - irq_stack_size;
+
+       if (in_irq_stack(stack, irq_stack, *stack_end))
+               return STACK_IS_IRQ;
+
+       return STACK_IS_UNKNOWN;
+}
+
 /*
  * x86-64 can have up to three kernel stacks:
  * process stack
@@ -116,12 +155,11 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                const struct stacktrace_ops *ops, void *data)
 {
        const unsigned cpu = get_cpu();
-       unsigned long *irq_stack_end =
-               (unsigned long *)per_cpu(irq_stack_ptr, cpu);
-       unsigned used = 0;
        struct thread_info *tinfo;
-       int graph = 0;
+       unsigned long *irq_stack;
        unsigned long dummy;
+       int graph = 0;
+       int done = 0;
 
        if (!task)
                task = current;
@@ -143,49 +181,60 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
         * exceptions
         */
        tinfo = task_thread_info(task);
-       for (;;) {
+       while (!done) {
+               unsigned long *stack_end;
+               enum stack_type stype;
                char *id;
-               unsigned long *estack_end;
-               estack_end = in_exception_stack(cpu, (unsigned long)stack,
-                                               &used, &id);
 
-               if (estack_end) {
+               stype = analyze_stack(cpu, task, stack, &stack_end, &id);
+
+               /* Default finish unless specified to continue */
+               done = 1;
+
+               switch (stype) {
+
+               /* Break out early if we are on the thread stack */
+               case STACK_IS_NORMAL:
+                       break;
+
+               case STACK_IS_EXCEPTION:
+
                        if (ops->stack(data, id) < 0)
                                break;
 
                        bp = ops->walk_stack(tinfo, stack, bp, ops,
-                                            data, estack_end, &graph);
+                                            data, stack_end, &graph);
                        ops->stack(data, "<EOE>");
                        /*
                         * We link to the next stack via the
                         * second-to-last pointer (index -2 to end) in the
                         * exception stack:
                         */
-                       stack = (unsigned long *) estack_end[-2];
-                       continue;
-               }
-               if (irq_stack_end) {
-                       unsigned long *irq_stack;
-                       irq_stack = irq_stack_end -
-                               (IRQ_STACK_SIZE - 64) / sizeof(*irq_stack);
-
-                       if (in_irq_stack(stack, irq_stack, irq_stack_end)) {
-                               if (ops->stack(data, "IRQ") < 0)
-                                       break;
-                               bp = ops->walk_stack(tinfo, stack, bp,
-                                       ops, data, irq_stack_end, &graph);
-                               /*
-                                * We link to the next stack (which would be
-                                * the process stack normally) the last
-                                * pointer (index -1 to end) in the IRQ stack:
-                                */
-                               stack = (unsigned long *) (irq_stack_end[-1]);
-                               irq_stack_end = NULL;
-                               ops->stack(data, "EOI");
-                               continue;
-                       }
+                       stack = (unsigned long *) stack_end[-2];
+                       done = 0;
+                       break;
+
+               case STACK_IS_IRQ:
+
+                       if (ops->stack(data, "IRQ") < 0)
+                               break;
+                       bp = ops->walk_stack(tinfo, stack, bp,
+                                    ops, data, stack_end, &graph);
+                       /*
+                        * We link to the next stack (which would be
+                        * the process stack normally) the last
+                        * pointer (index -1 to end) in the IRQ stack:
+                        */
+                       stack = (unsigned long *) (stack_end[-1]);
+                       irq_stack = stack_end - irq_stack_size;
+                       ops->stack(data, "EOI");
+                       done = 0;
+                       break;
+
+               case STACK_IS_UNKNOWN:
+                       ops->stack(data, "UNK");
+                       break;
                }
-               break;
        }
 
        /*
index bc4a088f902396721e08a2d7314a451b7597eb1c..6d7d5a1260a68aca347b2b3d056a6d24dbf94f42 100644 (file)
@@ -203,18 +203,15 @@ static void __init intel_remapping_check(int num, int slot, int func)
        revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID);
 
        /*
-        * Revision 13 of all triggering devices id in this quirk have
-        * a problem draining interrupts when irq remapping is enabled,
-        * and should be flagged as broken.  Additionally revisions 0x12
-        * and 0x22 of device id 0x3405 has this problem.
+        * Revision <= 13 of all triggering devices id in this quirk
+        * have a problem draining interrupts when irq remapping is
+        * enabled, and should be flagged as broken. Additionally
+        * revision 0x22 of device id 0x3405 has this problem.
         */
-       if (revision == 0x13)
+       if (revision <= 0x13)
                set_irq_remapping_broken();
-       else if ((device == 0x3405) &&
-           ((revision == 0x12) ||
-            (revision == 0x22)))
+       else if (device == 0x3405 && revision == 0x22)
                set_irq_remapping_broken();
-
 }
 
 /*
index d4bdd253fea71358ca080ba567a44935a9830396..e6253195a301ade244143d4d13a73c947602a0cb 100644 (file)
@@ -77,8 +77,7 @@ within(unsigned long addr, unsigned long start, unsigned long end)
        return addr >= start && addr < end;
 }
 
-static int
-do_ftrace_mod_code(unsigned long ip, const void *new_code)
+static unsigned long text_ip_addr(unsigned long ip)
 {
        /*
         * On x86_64, kernel text mappings are mapped read-only with
@@ -91,7 +90,7 @@ do_ftrace_mod_code(unsigned long ip, const void *new_code)
        if (within(ip, (unsigned long)_text, (unsigned long)_etext))
                ip = (unsigned long)__va(__pa_symbol(ip));
 
-       return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE);
+       return ip;
 }
 
 static const unsigned char *ftrace_nop_replace(void)
@@ -123,8 +122,10 @@ ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code,
        if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
                return -EINVAL;
 
+       ip = text_ip_addr(ip);
+
        /* replace the text with the new text */
-       if (do_ftrace_mod_code(ip, new_code))
+       if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
                return -EPERM;
 
        sync_core();
@@ -221,37 +222,51 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
        return -EINVAL;
 }
 
-int ftrace_update_ftrace_func(ftrace_func_t func)
+static unsigned long ftrace_update_func;
+
+static int update_ftrace_func(unsigned long ip, void *new)
 {
-       unsigned long ip = (unsigned long)(&ftrace_call);
-       unsigned char old[MCOUNT_INSN_SIZE], *new;
+       unsigned char old[MCOUNT_INSN_SIZE];
        int ret;
 
-       memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
-       new = ftrace_call_replace(ip, (unsigned long)func);
+       memcpy(old, (void *)ip, MCOUNT_INSN_SIZE);
+
+       ftrace_update_func = ip;
+       /* Make sure the breakpoints see the ftrace_update_func update */
+       smp_wmb();
 
        /* See comment above by declaration of modifying_ftrace_code */
        atomic_inc(&modifying_ftrace_code);
 
        ret = ftrace_modify_code(ip, old, new);
 
+       atomic_dec(&modifying_ftrace_code);
+
+       return ret;
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+       unsigned long ip = (unsigned long)(&ftrace_call);
+       unsigned char *new;
+       int ret;
+
+       new = ftrace_call_replace(ip, (unsigned long)func);
+       ret = update_ftrace_func(ip, new);
+
        /* Also update the regs callback function */
        if (!ret) {
                ip = (unsigned long)(&ftrace_regs_call);
-               memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE);
                new = ftrace_call_replace(ip, (unsigned long)func);
-               ret = ftrace_modify_code(ip, old, new);
+               ret = update_ftrace_func(ip, new);
        }
 
-       atomic_dec(&modifying_ftrace_code);
-
        return ret;
 }
 
 static int is_ftrace_caller(unsigned long ip)
 {
-       if (ip == (unsigned long)(&ftrace_call) ||
-               ip == (unsigned long)(&ftrace_regs_call))
+       if (ip == ftrace_update_func)
                return 1;
 
        return 0;
@@ -677,45 +692,41 @@ int __init ftrace_dyn_arch_init(void *data)
 #ifdef CONFIG_DYNAMIC_FTRACE
 extern void ftrace_graph_call(void);
 
-static int ftrace_mod_jmp(unsigned long ip,
-                         int old_offset, int new_offset)
+static unsigned char *ftrace_jmp_replace(unsigned long ip, unsigned long addr)
 {
-       unsigned char code[MCOUNT_INSN_SIZE];
+       static union ftrace_code_union calc;
 
-       if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
-               return -EFAULT;
+       /* Jmp not a call (ignore the .e8) */
+       calc.e8         = 0xe9;
+       calc.offset     = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr);
 
-       if (code[0] != 0xe9 || old_offset != *(int *)(&code[1]))
-               return -EINVAL;
+       /*
+        * ftrace external locks synchronize the access to the static variable.
+        */
+       return calc.code;
+}
 
-       *(int *)(&code[1]) = new_offset;
+static int ftrace_mod_jmp(unsigned long ip, void *func)
+{
+       unsigned char *new;
 
-       if (do_ftrace_mod_code(ip, &code))
-               return -EPERM;
+       new = ftrace_jmp_replace(ip, (unsigned long)func);
 
-       return 0;
+       return update_ftrace_func(ip, new);
 }
 
 int ftrace_enable_ftrace_graph_caller(void)
 {
        unsigned long ip = (unsigned long)(&ftrace_graph_call);
-       int old_offset, new_offset;
 
-       old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
-       new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
-
-       return ftrace_mod_jmp(ip, old_offset, new_offset);
+       return ftrace_mod_jmp(ip, &ftrace_graph_caller);
 }
 
 int ftrace_disable_ftrace_graph_caller(void)
 {
        unsigned long ip = (unsigned long)(&ftrace_graph_call);
-       int old_offset, new_offset;
-
-       old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
-       new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
 
-       return ftrace_mod_jmp(ip, old_offset, new_offset);
+       return ftrace_mod_jmp(ip, &ftrace_stub);
 }
 
 #endif /* !CONFIG_DYNAMIC_FTRACE */
index 81ba27679f18ec6100bd167c3739608631a7c475..f36bd42d6f0c8b5fc5cd75dcf133b35a1f6bfe3b 100644 (file)
@@ -544,6 +544,10 @@ ENDPROC(early_idt_handlers)
        /* This is global to keep gas from relaxing the jumps */
 ENTRY(early_idt_handler)
        cld
+
+       cmpl $2,(%esp)          # X86_TRAP_NMI
+       je is_nmi               # Ignore NMI
+
        cmpl $2,%ss:early_recursion_flag
        je hlt_loop
        incl %ss:early_recursion_flag
@@ -594,8 +598,9 @@ ex_entry:
        pop %edx
        pop %ecx
        pop %eax
-       addl $8,%esp            /* drop vector number and error code */
        decl %ss:early_recursion_flag
+is_nmi:
+       addl $8,%esp            /* drop vector number and error code */
        iret
 ENDPROC(early_idt_handler)
 
index e1aabdb314c83740dd686eb4c70a6f40c312e258..a468c0a65c42e00df4e10afd9921d81a53dbba3d 100644 (file)
@@ -343,6 +343,9 @@ early_idt_handlers:
 ENTRY(early_idt_handler)
        cld
 
+       cmpl $2,(%rsp)          # X86_TRAP_NMI
+       je is_nmi               # Ignore NMI
+
        cmpl $2,early_recursion_flag(%rip)
        jz  1f
        incl early_recursion_flag(%rip)
@@ -405,8 +408,9 @@ ENTRY(early_idt_handler)
        popq %rdx
        popq %rcx
        popq %rax
-       addq $16,%rsp           # drop vector number and error code
        decl early_recursion_flag(%rip)
+is_nmi:
+       addq $16,%rsp           # drop vector number and error code
        INTERRUPT_RETURN
 ENDPROC(early_idt_handler)
 
index e8368c6dd2a2988c2d9d68cacc7030554424ad70..d5dd808144190ffd1d443229b4dbbd56740fface 100644 (file)
@@ -86,10 +86,19 @@ EXPORT_SYMBOL(__kernel_fpu_begin);
 
 void __kernel_fpu_end(void)
 {
-       if (use_eager_fpu())
-               math_state_restore();
-       else
+       if (use_eager_fpu()) {
+               /*
+                * For eager fpu, most the time, tsk_used_math() is true.
+                * Restore the user math as we are done with the kernel usage.
+                * At few instances during thread exit, signal handling etc,
+                * tsk_used_math() is false. Those few places will take proper
+                * actions, so we don't need to restore the math here.
+                */
+               if (likely(tsk_used_math(current)))
+                       math_state_restore();
+       } else {
                stts();
+       }
 }
 EXPORT_SYMBOL(__kernel_fpu_end);
 
index dbb60878b744d9678fac331ef446894e13410de3..d99f31d9a750216204a0c61faef3e489818ef925 100644 (file)
@@ -266,6 +266,14 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs)
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
 
 #ifdef CONFIG_HOTPLUG_CPU
+
+/* These two declarations are only used in check_irq_vectors_for_cpu_disable()
+ * below, which is protected by stop_machine().  Putting them on the stack
+ * results in a stack frame overflow.  Dynamically allocating could result in a
+ * failure so declare these two cpumasks as global.
+ */
+static struct cpumask affinity_new, online_new;
+
 /*
  * This cpu is going to be removed and its vectors migrated to the remaining
  * online cpus.  Check to see if there are enough vectors in the remaining cpus.
@@ -277,7 +285,6 @@ int check_irq_vectors_for_cpu_disable(void)
        unsigned int this_cpu, vector, this_count, count;
        struct irq_desc *desc;
        struct irq_data *data;
-       struct cpumask affinity_new, online_new;
 
        this_cpu = smp_processor_id();
        cpumask_copy(&online_new, cpu_online_mask);
index d7fcbedc9c43fa9659b7f2f2c687b8402a826dd2..63ce838e5a5423ad3f425368f1c5adffb8c8356e 100644 (file)
@@ -55,16 +55,8 @@ static inline int check_stack_overflow(void) { return 0; }
 static inline void print_stack_overflow(void) { }
 #endif
 
-/*
- * per-CPU IRQ handling contexts (thread information and stack)
- */
-union irq_ctx {
-       struct thread_info      tinfo;
-       u32                     stack[THREAD_SIZE/sizeof(u32)];
-} __attribute__((aligned(THREAD_SIZE)));
-
-static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
-static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
+DEFINE_PER_CPU(struct irq_stack *, hardirq_stack);
+DEFINE_PER_CPU(struct irq_stack *, softirq_stack);
 
 static void call_on_stack(void *func, void *stack)
 {
@@ -77,14 +69,26 @@ static void call_on_stack(void *func, void *stack)
                     : "memory", "cc", "edx", "ecx", "eax");
 }
 
+/* how to get the current stack pointer from C */
+#define current_stack_pointer ({               \
+       unsigned long sp;                       \
+       asm("mov %%esp,%0" : "=g" (sp));        \
+       sp;                                     \
+})
+
+static inline void *current_stack(void)
+{
+       return (void *)(current_stack_pointer & ~(THREAD_SIZE - 1));
+}
+
 static inline int
 execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
 {
-       union irq_ctx *curctx, *irqctx;
-       u32 *isp, arg1, arg2;
+       struct irq_stack *curstk, *irqstk;
+       u32 *isp, *prev_esp, arg1, arg2;
 
-       curctx = (union irq_ctx *) current_thread_info();
-       irqctx = __this_cpu_read(hardirq_ctx);
+       curstk = (struct irq_stack *) current_stack();
+       irqstk = __this_cpu_read(hardirq_stack);
 
        /*
         * this is where we switch to the IRQ stack. However, if we are
@@ -92,13 +96,14 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
         * handler) we can't do that and just have to keep using the
         * current stack (which is the irq stack already after all)
         */
-       if (unlikely(curctx == irqctx))
+       if (unlikely(curstk == irqstk))
                return 0;
 
-       /* build the stack frame on the IRQ stack */
-       isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
-       irqctx->tinfo.task = curctx->tinfo.task;
-       irqctx->tinfo.previous_esp = current_stack_pointer;
+       isp = (u32 *) ((char *)irqstk + sizeof(*irqstk));
+
+       /* Save the next esp at the bottom of the stack */
+       prev_esp = (u32 *)irqstk;
+       *prev_esp = current_stack_pointer;
 
        if (unlikely(overflow))
                call_on_stack(print_stack_overflow, isp);
@@ -118,46 +123,40 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
  */
 void irq_ctx_init(int cpu)
 {
-       union irq_ctx *irqctx;
+       struct irq_stack *irqstk;
 
-       if (per_cpu(hardirq_ctx, cpu))
+       if (per_cpu(hardirq_stack, cpu))
                return;
 
-       irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
+       irqstk = page_address(alloc_pages_node(cpu_to_node(cpu),
                                               THREADINFO_GFP,
                                               THREAD_SIZE_ORDER));
-       memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
-       irqctx->tinfo.cpu               = cpu;
-       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
-
-       per_cpu(hardirq_ctx, cpu) = irqctx;
+       per_cpu(hardirq_stack, cpu) = irqstk;
 
-       irqctx = page_address(alloc_pages_node(cpu_to_node(cpu),
+       irqstk = page_address(alloc_pages_node(cpu_to_node(cpu),
                                               THREADINFO_GFP,
                                               THREAD_SIZE_ORDER));
-       memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
-       irqctx->tinfo.cpu               = cpu;
-       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
-
-       per_cpu(softirq_ctx, cpu) = irqctx;
+       per_cpu(softirq_stack, cpu) = irqstk;
 
        printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
-              cpu, per_cpu(hardirq_ctx, cpu),  per_cpu(softirq_ctx, cpu));
+              cpu, per_cpu(hardirq_stack, cpu),  per_cpu(softirq_stack, cpu));
 }
 
 void do_softirq_own_stack(void)
 {
-       struct thread_info *curctx;
-       union irq_ctx *irqctx;
-       u32 *isp;
+       struct thread_info *curstk;
+       struct irq_stack *irqstk;
+       u32 *isp, *prev_esp;
 
-       curctx = current_thread_info();
-       irqctx = __this_cpu_read(softirq_ctx);
-       irqctx->tinfo.task = curctx->task;
-       irqctx->tinfo.previous_esp = current_stack_pointer;
+       curstk = current_stack();
+       irqstk = __this_cpu_read(softirq_stack);
 
        /* build the stack frame on the softirq stack */
-       isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
+       isp = (u32 *) ((char *)irqstk + sizeof(*irqstk));
+
+       /* Push the previous esp onto the stack */
+       prev_esp = (u32 *)irqstk;
+       *prev_esp = current_stack_pointer;
 
        call_on_stack(__do_softirq, isp);
 }
index 4eabc160696f510ec5ffaddc7939dd71856463d5..679cef0791cd842448216f4a6158cd2ae24fe0e0 100644 (file)
@@ -279,5 +279,7 @@ void arch_crash_save_vmcoreinfo(void)
        VMCOREINFO_SYMBOL(node_data);
        VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
 #endif
+       vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
+                             (unsigned long)&_text - __START_KERNEL);
 }
 
index 18be189368bbfdbf55cc2e7492c0e7b3b2514403..e69f9882bf95a942ae1ce0f75efbf07301c9adc3 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mm.h>
 #include <linux/gfp.h>
 #include <linux/jump_label.h>
+#include <linux/random.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -43,13 +44,52 @@ do {                                                        \
 } while (0)
 #endif
 
+#ifdef CONFIG_RANDOMIZE_BASE
+static unsigned long module_load_offset;
+static int randomize_modules = 1;
+
+/* Mutex protects the module_load_offset. */
+static DEFINE_MUTEX(module_kaslr_mutex);
+
+static int __init parse_nokaslr(char *p)
+{
+       randomize_modules = 0;
+       return 0;
+}
+early_param("nokaslr", parse_nokaslr);
+
+static unsigned long int get_module_load_offset(void)
+{
+       if (randomize_modules) {
+               mutex_lock(&module_kaslr_mutex);
+               /*
+                * Calculate the module_load_offset the first time this
+                * code is called. Once calculated it stays the same until
+                * reboot.
+                */
+               if (module_load_offset == 0)
+                       module_load_offset =
+                               (get_random_int() % 1024 + 1) * PAGE_SIZE;
+               mutex_unlock(&module_kaslr_mutex);
+       }
+       return module_load_offset;
+}
+#else
+static unsigned long int get_module_load_offset(void)
+{
+       return 0;
+}
+#endif
+
 void *module_alloc(unsigned long size)
 {
        if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
-       return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
-                               NUMA_NO_NODE, __builtin_return_address(0));
+       return __vmalloc_node_range(size, 1,
+                                   MODULES_VADDR + get_module_load_offset(),
+                                   MODULES_END, GFP_KERNEL | __GFP_HIGHMEM,
+                                   PAGE_KERNEL_EXEC, NUMA_NO_NODE,
+                                   __builtin_return_address(0));
 }
 
 #ifdef CONFIG_X86_32
index 6fcb49ce50a1260d1f4bfdf0b5a065dd4f6d77c7..b4872b999a713d7fc08f7578b672d804a30dd13e 100644 (file)
@@ -87,6 +87,7 @@ __setup("unknown_nmi_panic", setup_unknown_nmi_panic);
 #define nmi_to_desc(type) (&nmi_desc[type])
 
 static u64 nmi_longest_ns = 1 * NSEC_PER_MSEC;
+
 static int __init nmi_warning_debugfs(void)
 {
        debugfs_create_u64("nmi_longest_ns", 0644,
@@ -95,6 +96,20 @@ static int __init nmi_warning_debugfs(void)
 }
 fs_initcall(nmi_warning_debugfs);
 
+static void nmi_max_handler(struct irq_work *w)
+{
+       struct nmiaction *a = container_of(w, struct nmiaction, irq_work);
+       int remainder_ns, decimal_msecs;
+       u64 whole_msecs = ACCESS_ONCE(a->max_duration);
+
+       remainder_ns = do_div(whole_msecs, (1000 * 1000));
+       decimal_msecs = remainder_ns / 1000;
+
+       printk_ratelimited(KERN_INFO
+               "INFO: NMI handler (%ps) took too long to run: %lld.%03d msecs\n",
+               a->handler, whole_msecs, decimal_msecs);
+}
+
 static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b)
 {
        struct nmi_desc *desc = nmi_to_desc(type);
@@ -110,26 +125,20 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2
         * to handle those situations.
         */
        list_for_each_entry_rcu(a, &desc->head, list) {
-               u64 before, delta, whole_msecs;
-               int remainder_ns, decimal_msecs, thishandled;
+               int thishandled;
+               u64 delta;
 
-               before = sched_clock();
+               delta = sched_clock();
                thishandled = a->handler(type, regs);
                handled += thishandled;
-               delta = sched_clock() - before;
+               delta = sched_clock() - delta;
                trace_nmi_handler(a->handler, (int)delta, thishandled);
 
-               if (delta < nmi_longest_ns)
+               if (delta < nmi_longest_ns || delta < a->max_duration)
                        continue;
 
-               nmi_longest_ns = delta;
-               whole_msecs = delta;
-               remainder_ns = do_div(whole_msecs, (1000 * 1000));
-               decimal_msecs = remainder_ns / 1000;
-               printk_ratelimited(KERN_INFO
-                       "INFO: NMI handler (%ps) took too long to run: "
-                       "%lld.%03d msecs\n", a->handler, whole_msecs,
-                       decimal_msecs);
+               a->max_duration = delta;
+               irq_work_queue(&a->irq_work);
        }
 
        rcu_read_unlock();
@@ -146,6 +155,8 @@ int __register_nmi_handler(unsigned int type, struct nmiaction *action)
        if (!action->handler)
                return -EINVAL;
 
+       init_irq_work(&action->irq_work, nmi_max_handler);
+
        spin_lock_irqsave(&desc->lock, flags);
 
        /*
index 872079a67e4d262151dfdbe74f537033be5ebcc0..f7d0672481fd7c328682d601467313acb586280a 100644 (file)
@@ -100,8 +100,10 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
        flag |= __GFP_ZERO;
 again:
        page = NULL;
-       if (!(flag & GFP_ATOMIC))
+       /* CMA can be used only in the context which permits sleeping */
+       if (flag & __GFP_WAIT)
                page = dma_alloc_from_contiguous(dev, count, get_order(size));
+       /* fallback */
        if (!page)
                page = alloc_pages_node(dev_to_node(dev), flag, get_order(size));
        if (!page)
index 3fb8d95ab8b5ea3635ddb1f0d9f9c12e3a348285..4505e2a950d81f479663df20ce787dbad5f293b0 100644 (file)
@@ -298,10 +298,7 @@ void arch_cpu_idle_dead(void)
  */
 void arch_cpu_idle(void)
 {
-       if (cpuidle_idle_call())
-               x86_idle();
-       else
-               local_irq_enable();
+       x86_idle();
 }
 
 /*
index 0de43e98ce08604afa886ceba8e17b7c66583e97..7bc86bbe748599b92c2b9b2b221f98b10224c5b2 100644 (file)
@@ -314,6 +314,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
         */
        arch_end_context_switch(next_p);
 
+       this_cpu_write(kernel_stack,
+                 (unsigned long)task_stack_page(next_p) +
+                 THREAD_SIZE - KERNEL_STACK_OFFSET);
+
        /*
         * Restore %gs if needed (which is common)
         */
index 7461f50d5bb1e15dbf39d7f43a758138b0fad019..678c0ada3b3ce5f94135c7076cf59800850ca474 100644 (file)
@@ -184,14 +184,14 @@ 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;
+       u32 *prev_esp;
 
        if (context == (sp & ~(THREAD_SIZE - 1)))
                return sp;
 
-       tinfo = (struct thread_info *)context;
-       if (tinfo->previous_esp)
-               return tinfo->previous_esp;
+       prev_esp = (u32 *)(context);
+       if (prev_esp)
+               return (unsigned long)prev_esp;
 
        return (unsigned long)regs;
 }
index 04ee1e2e4c0251439ef2095cd891be1754bf3899..ff898bbf579d7f34ce7b8c98a5482f72e4d338bf 100644 (file)
@@ -529,7 +529,7 @@ static void quirk_amd_nb_node(struct pci_dev *dev)
                return;
 
        pci_read_config_dword(nb_ht, 0x60, &val);
-       node = val & 7;
+       node = pcibus_to_node(dev->bus) | (val & 7);
        /*
         * Some hardware may return an invalid node ID,
         * so check it first:
@@ -571,3 +571,40 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5,
                        quirk_amd_nb_node);
 
 #endif
+
+#ifdef CONFIG_PCI
+/*
+ * Processor does not ensure DRAM scrub read/write sequence
+ * is atomic wrt accesses to CC6 save state area. Therefore
+ * if a concurrent scrub read/write access is to same address
+ * the entry may appear as if it is not written. This quirk
+ * applies to Fam16h models 00h-0Fh
+ *
+ * See "Revision Guide" for AMD F16h models 00h-0fh,
+ * document 51810 rev. 3.04, Nov 2013
+ */
+static void amd_disable_seq_and_redirect_scrub(struct pci_dev *dev)
+{
+       u32 val;
+
+       /*
+        * Suggested workaround:
+        * set D18F3x58[4:0] = 00h and set D18F3x5C[0] = 0b
+        */
+       pci_read_config_dword(dev, 0x58, &val);
+       if (val & 0x1F) {
+               val &= ~(0x1F);
+               pci_write_config_dword(dev, 0x58, val);
+       }
+
+       pci_read_config_dword(dev, 0x5C, &val);
+       if (val & BIT(0)) {
+               val &= ~BIT(0);
+               pci_write_config_dword(dev, 0x5c, val);
+       }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3,
+                       amd_disable_seq_and_redirect_scrub);
+
+#endif
index c752cb43e52f192f431a5f2ab91b9366e42ef5b0..654b46574b916c20ac4472aace3ffe4165f131fd 100644 (file)
@@ -464,9 +464,12 @@ void __attribute__((weak)) mach_reboot_fixups(void)
  * 2) If still alive, write to the keyboard controller
  * 3) If still alive, write to the ACPI reboot register again
  * 4) If still alive, write to the keyboard controller again
+ * 5) If still alive, call the EFI runtime service to reboot
+ * 6) If still alive, write to the PCI IO port 0xCF9 to reboot
+ * 7) If still alive, inform BIOS to do a proper reboot
  *
  * If the machine is still alive at this stage, it gives up. We default to
- * following the same pattern, except that if we're still alive after (4) we'll
+ * following the same pattern, except that if we're still alive after (7) we'll
  * try to force a triple fault and then cycle between hitting the keyboard
  * controller and doing that
  */
@@ -502,7 +505,7 @@ static void native_machine_emergency_restart(void)
                                attempt = 1;
                                reboot_type = BOOT_ACPI;
                        } else {
-                               reboot_type = BOOT_TRIPLE;
+                               reboot_type = BOOT_EFI;
                        }
                        break;
 
@@ -510,13 +513,15 @@ static void native_machine_emergency_restart(void)
                        load_idt(&no_idt);
                        __asm__ __volatile__("int3");
 
+                       /* We're probably dead after this, but... */
                        reboot_type = BOOT_KBD;
                        break;
 
                case BOOT_BIOS:
                        machine_real_restart(MRR_BIOS);
 
-                       reboot_type = BOOT_KBD;
+                       /* We're probably dead after this, but... */
+                       reboot_type = BOOT_TRIPLE;
                        break;
 
                case BOOT_ACPI:
@@ -530,7 +535,7 @@ static void native_machine_emergency_restart(void)
                                                 EFI_RESET_WARM :
                                                 EFI_RESET_COLD,
                                                 EFI_SUCCESS, 0, NULL);
-                       reboot_type = BOOT_KBD;
+                       reboot_type = BOOT_CF9_COND;
                        break;
 
                case BOOT_CF9:
@@ -548,7 +553,7 @@ static void native_machine_emergency_restart(void)
                                outb(cf9|reboot_code, 0xcf9);
                                udelay(50);
                        }
-                       reboot_type = BOOT_KBD;
+                       reboot_type = BOOT_BIOS;
                        break;
                }
        }
index 06853e6703541f8349106e17330f86621fa984db..fa511acff7e6c24bbb216de1615569e6bca31db9 100644 (file)
@@ -926,11 +926,11 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_EFI
        if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
                     "EL32", 4)) {
-               set_bit(EFI_BOOT, &x86_efi_facility);
+               set_bit(EFI_BOOT, &efi.flags);
        } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
                     "EL64", 4)) {
-               set_bit(EFI_BOOT, &x86_efi_facility);
-               set_bit(EFI_64BIT, &x86_efi_facility);
+               set_bit(EFI_BOOT, &efi.flags);
+               set_bit(EFI_64BIT, &efi.flags);
        }
 
        if (efi_enabled(EFI_BOOT))
@@ -1239,14 +1239,8 @@ void __init setup_arch(char **cmdline_p)
        register_refined_jiffies(CLOCK_TICK_RATE);
 
 #ifdef CONFIG_EFI
-       /* Once setup is done above, unmap the EFI memory map on
-        * mismatched firmware/kernel archtectures since there is no
-        * support for runtime services.
-        */
-       if (efi_enabled(EFI_BOOT) && !efi_is_native()) {
-               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
-               efi_unmap_memmap();
-       }
+       if (efi_enabled(EFI_BOOT))
+               efi_apply_memmap_quirks();
 #endif
 }
 
index a32da804252e374b5d266e6788653f24fc98705d..34826934d4a7b37da39ae7556d04be37cae55ee8 100644 (file)
@@ -122,8 +122,9 @@ static void smp_callin(void)
         * Since CPU0 is not wakened up by INIT, it doesn't wait for the IPI.
         */
        cpuid = smp_processor_id();
-       if (apic->wait_for_init_deassert && cpuid != 0)
-               apic->wait_for_init_deassert(&init_deasserted);
+       if (apic->wait_for_init_deassert && cpuid)
+               while (!atomic_read(&init_deasserted))
+                       cpu_relax();
 
        /*
         * (This works even if the APIC is not enabled.)
@@ -701,11 +702,15 @@ wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid,
        int id;
        int boot_error;
 
+       preempt_disable();
+
        /*
         * Wake up AP by INIT, INIT, STARTUP sequence.
         */
-       if (cpu)
-               return wakeup_secondary_cpu_via_init(apicid, start_ip);
+       if (cpu) {
+               boot_error = wakeup_secondary_cpu_via_init(apicid, start_ip);
+               goto out;
+       }
 
        /*
         * Wake up BSP by nmi.
@@ -725,6 +730,9 @@ wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid,
                boot_error = wakeup_secondary_cpu_via_nmi(id, start_ip);
        }
 
+out:
+       preempt_enable();
+
        return boot_error;
 }
 
@@ -758,10 +766,10 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
 #else
        clear_tsk_thread_flag(idle, TIF_FORK);
        initial_gs = per_cpu_offset(cpu);
+#endif
        per_cpu(kernel_stack, cpu) =
                (unsigned long)task_stack_page(idle) -
                KERNEL_STACK_OFFSET + THREAD_SIZE;
-#endif
        early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
        initial_code = (unsigned long)start_secondary;
        stack_start  = idle->thread.sp;
@@ -1379,7 +1387,7 @@ static inline void mwait_play_dead(void)
 
        if (!this_cpu_has(X86_FEATURE_MWAIT))
                return;
-       if (!this_cpu_has(X86_FEATURE_CLFLSH))
+       if (!this_cpu_has(X86_FEATURE_CLFLUSH))
                return;
        if (__this_cpu_read(cpu_info.cpuid_level) < CPUID_MWAIT_LEAF)
                return;
index 24d3c91e9812f6f37be6b138deb8e0b6b23a30dd..6ec91c00d84d621701df27396928e6e108f29bd0 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/time.h>
 
 #ifdef CONFIG_X86_64
-DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES;
+__visible DEFINE_VVAR(volatile unsigned long, jiffies) = INITIAL_JIFFIES;
 #endif
 
 unsigned long profile_pc(struct pt_regs *regs)
index 19e5adb49a27d8ae4f586ad88b30faeef0f8e727..cfbe99f888300d819b53552a7668ab9bd12c3708 100644 (file)
@@ -209,7 +209,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
         * dance when its actually needed.
         */
 
-       preempt_disable();
+       preempt_disable_notrace();
        data = this_cpu_read(cyc2ns.head);
        tail = this_cpu_read(cyc2ns.tail);
 
@@ -229,7 +229,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
                if (!--data->__count)
                        this_cpu_write(cyc2ns.tail, data);
        }
-       preempt_enable();
+       preempt_enable_notrace();
 
        return ns;
 }
@@ -653,13 +653,10 @@ unsigned long native_calibrate_tsc(void)
 
        /* Calibrate TSC using MSR for Intel Atom SoCs */
        local_irq_save(flags);
-       i = try_msr_calibrate_tsc(&fast_calibrate);
+       fast_calibrate = try_msr_calibrate_tsc();
        local_irq_restore(flags);
-       if (i >= 0) {
-               if (i == 0)
-                       pr_warn("Fast TSC calibration using MSR failed\n");
+       if (fast_calibrate)
                return fast_calibrate;
-       }
 
        local_irq_save(flags);
        fast_calibrate = quick_pit_calibrate();
index 8b5434f4389fc4afbbc7d297ab61ec403aedb9d8..92ae6acac8a7fbcb9b91cb386b3c23015c5377ea 100644 (file)
@@ -53,7 +53,7 @@ static struct freq_desc freq_desc_tables[] = {
        /* TNG */
        { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } },
        /* VLV2 */
-       { 6, 0x37, 1, { 0, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
+       { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
        /* ANN */
        { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } },
 };
@@ -77,21 +77,18 @@ static int match_cpu(u8 family, u8 model)
 
 /*
  * Do MSR calibration only for known/supported CPUs.
- * Return values:
- * -1: CPU is unknown/unsupported for MSR based calibration
- *  0: CPU is known/supported, but calibration failed
- *  1: CPU is known/supported, and calibration succeeded
+ *
+ * Returns the calibration value or 0 if MSR calibration failed.
  */
-int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
+unsigned long try_msr_calibrate_tsc(void)
 {
-       int cpu_index;
        u32 lo, hi, ratio, freq_id, freq;
+       unsigned long res;
+       int cpu_index;
 
        cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model);
        if (cpu_index < 0)
-               return -1;
-
-       *fast_calibrate = 0;
+               return 0;
 
        if (freq_desc_tables[cpu_index].msr_plat) {
                rdmsr(MSR_PLATFORM_INFO, lo, hi);
@@ -103,7 +100,7 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
        pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
 
        if (!ratio)
-               return 0;
+               goto fail;
 
        /* Get FSB FREQ ID */
        rdmsr(MSR_FSB_FREQ, lo, hi);
@@ -112,16 +109,19 @@ int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
        pr_info("Resolved frequency ID: %u, frequency: %u KHz\n",
                                freq_id, freq);
        if (!freq)
-               return 0;
+               goto fail;
 
        /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
-       *fast_calibrate = freq * ratio;
-       pr_info("TSC runs at %lu KHz\n", *fast_calibrate);
+       res = freq * ratio;
+       pr_info("TSC runs at %lu KHz\n", res);
 
 #ifdef CONFIG_X86_LOCAL_APIC
        lapic_timer_frequency = (freq * 1000) / HZ;
        pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency);
 #endif
+       return res;
 
-       return 1;
+fail:
+       pr_warn("Fast TSC calibration using MSR failed\n");
+       return 0;
 }
index c6976257eff51281e023c264b355f166ce56dd5c..e5503d8aec1dac41f6ff7f97eb77e43beee6f38b 100644 (file)
@@ -263,7 +263,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                F(TSC) | F(MSR) | F(PAE) | F(MCE) |
                F(CX8) | F(APIC) | 0 /* Reserved */ | F(SEP) |
                F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
-               F(PAT) | F(PSE36) | 0 /* PSN */ | F(CLFLSH) |
+               F(PAT) | F(PSE36) | 0 /* PSN */ | F(CLFLUSH) |
                0 /* Reserved, DS, ACPI */ | F(MMX) |
                F(FXSR) | F(XMM) | F(XMM2) | F(SELFSNOOP) |
                0 /* HTT, TM, Reserved, PBE */;
index e50425d0f5f792c1c940f85cd66e890e5fa3a6ac..9b531351a5876835e3dda6527571383a7fbae751 100644 (file)
@@ -2672,6 +2672,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
                        break;
                }
 
+               drop_large_spte(vcpu, iterator.sptep);
                if (!is_shadow_present_pte(*iterator.sptep)) {
                        u64 base_addr = iterator.addr;
 
index e81df8fce0275781a654f356fe77e38129d5210a..2de1bc09a8d40a0508e7e364bc1de301215cc7c5 100644 (file)
@@ -3002,10 +3002,8 @@ static int cr8_write_interception(struct vcpu_svm *svm)
        u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
        /* instruction emulation calls kvm_set_cr8() */
        r = cr_interception(svm);
-       if (irqchip_in_kernel(svm->vcpu.kvm)) {
-               clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
+       if (irqchip_in_kernel(svm->vcpu.kvm))
                return r;
-       }
        if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
                return r;
        kvm_run->exit_reason = KVM_EXIT_SET_TPR;
@@ -3567,6 +3565,8 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
        if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
                return;
 
+       clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
+
        if (irr == -1)
                return;
 
index a06f101ef64b4ae43e954319bbaa81a5c24c326b..3927528347510bb137e8420f4e26b07d09055483 100644 (file)
@@ -6688,7 +6688,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                else if (is_page_fault(intr_info))
                        return enable_ept;
                else if (is_no_device(intr_info) &&
-                        !(nested_read_cr0(vmcs12) & X86_CR0_TS))
+                        !(vmcs12->guest_cr0 & X86_CR0_TS))
                        return 0;
                return vmcs12->exception_bitmap &
                                (1u << (intr_info & INTR_INFO_VECTOR_MASK));
index 39c28f09dfd5f03ca064be4bb5cfa01eb0d673a4..2b8578432d5bccd296fa6d5859e3575c0fe4aa02 100644 (file)
@@ -6186,7 +6186,7 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
                frag->len -= len;
        }
 
-       if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
+       if (vcpu->mmio_cur_fragment >= vcpu->mmio_nr_fragments) {
                vcpu->mmio_needed = 0;
 
                /* FIXME: return into emulator if single-stepping.  */
index 3056702e81fbc553d3d7986889bc31ef4bb4bd3f..ff4fa51a5b1f5c0ddffcfa64ce72556b012b084b 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/hash.h>
+#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
 
 static inline u32 crc32_u32(u32 crc, u32 val)
 {
+#ifdef CONFIG_AS_CRC32
        asm ("crc32l %1,%0\n" : "+r" (crc) : "rm" (val));
+#else
+       asm (".byte 0xf2, 0x0f, 0x38, 0xf1, 0xc1" : "+a" (crc) : "c" (val));
+#endif
        return crc;
 }
 
@@ -49,19 +54,18 @@ static u32 intel_crc4_2_hash(const void *data, u32 len, u32 seed)
        u32 i, tmp = 0;
 
        for (i = 0; i < len / 4; i++)
-               seed = crc32_u32(*p32++, seed);
+               seed = crc32_u32(seed, *p32++);
 
-       switch (3 - (len & 0x03)) {
-       case 0:
+       switch (len & 3) {
+       case 3:
                tmp |= *((const u8 *) p32 + 2) << 16;
                /* fallthrough */
-       case 1:
+       case 2:
                tmp |= *((const u8 *) p32 + 1) << 8;
                /* fallthrough */
-       case 2:
+       case 1:
                tmp |= *((const u8 *) p32);
-               seed = crc32_u32(tmp, seed);
-       default:
+               seed = crc32_u32(seed, tmp);
                break;
        }
 
@@ -74,12 +78,12 @@ static u32 intel_crc4_2_hash2(const u32 *data, u32 len, u32 seed)
        u32 i;
 
        for (i = 0; i < len; i++)
-               seed = crc32_u32(*p32++, seed);
+               seed = crc32_u32(seed, *p32++);
 
        return seed;
 }
 
-void setup_arch_fast_hash(struct fast_hash_ops *ops)
+void __init setup_arch_fast_hash(struct fast_hash_ops *ops)
 {
        if (cpu_has_xmm4_2) {
                ops->hash  = intel_crc4_2_hash;
index e78761d6b7f87811ea7f20feab53a72656547e1b..a404b4b7553319cd7d517355bf340784de344562 100644 (file)
@@ -4,7 +4,7 @@
 #undef memcpy
 #undef memset
 
-void *memcpy(void *to, const void *from, size_t n)
+__visible void *memcpy(void *to, const void *from, size_t n)
 {
 #ifdef CONFIG_X86_USE_3DNOW
        return __memcpy3d(to, from, n);
@@ -14,13 +14,13 @@ void *memcpy(void *to, const void *from, size_t n)
 }
 EXPORT_SYMBOL(memcpy);
 
-void *memset(void *s, int c, size_t count)
+__visible void *memset(void *s, int c, size_t count)
 {
        return __memset(s, c, count);
 }
 EXPORT_SYMBOL(memset);
 
-void *memmove(void *dest, const void *src, size_t n)
+__visible void *memmove(void *dest, const void *src, size_t n)
 {
        int d0,d1,d2,d3,d4,d5;
        char *ret = dest;
index 8f8eebdca7d4cadc249405e8a0c50108e34edc3b..db9db446b71a66fe5bd59de47232e8fa69e8c96e 100644 (file)
@@ -8,7 +8,7 @@ struct msr *msrs_alloc(void)
 
        msrs = alloc_percpu(struct msr);
        if (!msrs) {
-               pr_warning("%s: error allocating msrs\n", __func__);
+               pr_warn("%s: error allocating msrs\n", __func__);
                return NULL;
        }
 
@@ -21,3 +21,90 @@ void msrs_free(struct msr *msrs)
        free_percpu(msrs);
 }
 EXPORT_SYMBOL(msrs_free);
+
+/**
+ * Read an MSR with error handling
+ *
+ * @msr: MSR to read
+ * @m: value to read into
+ *
+ * It returns read data only on success, otherwise it doesn't change the output
+ * argument @m.
+ *
+ */
+int msr_read(u32 msr, struct msr *m)
+{
+       int err;
+       u64 val;
+
+       err = rdmsrl_safe(msr, &val);
+       if (!err)
+               m->q = val;
+
+       return err;
+}
+
+/**
+ * Write an MSR with error handling
+ *
+ * @msr: MSR to write
+ * @m: value to write
+ */
+int msr_write(u32 msr, struct msr *m)
+{
+       return wrmsrl_safe(msr, m->q);
+}
+
+static inline int __flip_bit(u32 msr, u8 bit, bool set)
+{
+       struct msr m, m1;
+       int err = -EINVAL;
+
+       if (bit > 63)
+               return err;
+
+       err = msr_read(msr, &m);
+       if (err)
+               return err;
+
+       m1 = m;
+       if (set)
+               m1.q |=  BIT_64(bit);
+       else
+               m1.q &= ~BIT_64(bit);
+
+       if (m1.q == m.q)
+               return 0;
+
+       err = msr_write(msr, &m);
+       if (err)
+               return err;
+
+       return 1;
+}
+
+/**
+ * Set @bit in a MSR @msr.
+ *
+ * Retval:
+ * < 0: An error was encountered.
+ * = 0: Bit was already set.
+ * > 0: Hardware accepted the MSR write.
+ */
+int msr_set_bit(u32 msr, u8 bit)
+{
+       return __flip_bit(msr, bit, true);
+}
+
+/**
+ * Clear @bit in a MSR @msr.
+ *
+ * Retval:
+ * < 0: An error was encountered.
+ * = 0: Bit was already cleared.
+ * > 0: Hardware accepted the MSR write.
+ */
+int msr_clear_bit(u32 msr, u8 bit)
+{
+       return __flip_bit(msr, bit, false);
+}
index 0002a3a33081c77134569c1872e5a70684dbd646..20621d753d5fb4564dddbf960999158a82bc0707 100644 (file)
@@ -30,6 +30,7 @@ struct pg_state {
        unsigned long start_address;
        unsigned long current_address;
        const struct addr_marker *marker;
+       bool to_dmesg;
 };
 
 struct addr_marker {
@@ -88,10 +89,28 @@ static struct addr_marker address_markers[] = {
 #define PUD_LEVEL_MULT (PTRS_PER_PMD * PMD_LEVEL_MULT)
 #define PGD_LEVEL_MULT (PTRS_PER_PUD * PUD_LEVEL_MULT)
 
+#define pt_dump_seq_printf(m, to_dmesg, fmt, args...)          \
+({                                                             \
+       if (to_dmesg)                                   \
+               printk(KERN_INFO fmt, ##args);                  \
+       else                                                    \
+               if (m)                                          \
+                       seq_printf(m, fmt, ##args);             \
+})
+
+#define pt_dump_cont_printf(m, to_dmesg, fmt, args...)         \
+({                                                             \
+       if (to_dmesg)                                   \
+               printk(KERN_CONT fmt, ##args);                  \
+       else                                                    \
+               if (m)                                          \
+                       seq_printf(m, fmt, ##args);             \
+})
+
 /*
  * Print a readable form of a pgprot_t to the seq_file
  */
-static void printk_prot(struct seq_file *m, pgprot_t prot, int level)
+static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
 {
        pgprotval_t pr = pgprot_val(prot);
        static const char * const level_name[] =
@@ -99,47 +118,47 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level)
 
        if (!pgprot_val(prot)) {
                /* Not present */
-               seq_printf(m, "                          ");
+               pt_dump_cont_printf(m, dmsg, "                          ");
        } else {
                if (pr & _PAGE_USER)
-                       seq_printf(m, "USR ");
+                       pt_dump_cont_printf(m, dmsg, "USR ");
                else
-                       seq_printf(m, "    ");
+                       pt_dump_cont_printf(m, dmsg, "    ");
                if (pr & _PAGE_RW)
-                       seq_printf(m, "RW ");
+                       pt_dump_cont_printf(m, dmsg, "RW ");
                else
-                       seq_printf(m, "ro ");
+                       pt_dump_cont_printf(m, dmsg, "ro ");
                if (pr & _PAGE_PWT)
-                       seq_printf(m, "PWT ");
+                       pt_dump_cont_printf(m, dmsg, "PWT ");
                else
-                       seq_printf(m, "    ");
+                       pt_dump_cont_printf(m, dmsg, "    ");
                if (pr & _PAGE_PCD)
-                       seq_printf(m, "PCD ");
+                       pt_dump_cont_printf(m, dmsg, "PCD ");
                else
-                       seq_printf(m, "    ");
+                       pt_dump_cont_printf(m, dmsg, "    ");
 
                /* Bit 9 has a different meaning on level 3 vs 4 */
                if (level <= 3) {
                        if (pr & _PAGE_PSE)
-                               seq_printf(m, "PSE ");
+                               pt_dump_cont_printf(m, dmsg, "PSE ");
                        else
-                               seq_printf(m, "    ");
+                               pt_dump_cont_printf(m, dmsg, "    ");
                } else {
                        if (pr & _PAGE_PAT)
-                               seq_printf(m, "pat ");
+                               pt_dump_cont_printf(m, dmsg, "pat ");
                        else
-                               seq_printf(m, "    ");
+                               pt_dump_cont_printf(m, dmsg, "    ");
                }
                if (pr & _PAGE_GLOBAL)
-                       seq_printf(m, "GLB ");
+                       pt_dump_cont_printf(m, dmsg, "GLB ");
                else
-                       seq_printf(m, "    ");
+                       pt_dump_cont_printf(m, dmsg, "    ");
                if (pr & _PAGE_NX)
-                       seq_printf(m, "NX ");
+                       pt_dump_cont_printf(m, dmsg, "NX ");
                else
-                       seq_printf(m, "x  ");
+                       pt_dump_cont_printf(m, dmsg, "x  ");
        }
-       seq_printf(m, "%s\n", level_name[level]);
+       pt_dump_cont_printf(m, dmsg, "%s\n", level_name[level]);
 }
 
 /*
@@ -178,7 +197,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                st->current_prot = new_prot;
                st->level = level;
                st->marker = address_markers;
-               seq_printf(m, "---[ %s ]---\n", st->marker->name);
+               pt_dump_seq_printf(m, st->to_dmesg, "---[ %s ]---\n",
+                                  st->marker->name);
        } else if (prot != cur || level != st->level ||
                   st->current_address >= st->marker[1].start_address) {
                const char *unit = units;
@@ -188,17 +208,17 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                /*
                 * Now print the actual finished series
                 */
-               seq_printf(m, "0x%0*lx-0x%0*lx   ",
-                          width, st->start_address,
-                          width, st->current_address);
+               pt_dump_seq_printf(m, st->to_dmesg,  "0x%0*lx-0x%0*lx   ",
+                                  width, st->start_address,
+                                  width, st->current_address);
 
                delta = (st->current_address - st->start_address) >> 10;
                while (!(delta & 1023) && unit[1]) {
                        delta >>= 10;
                        unit++;
                }
-               seq_printf(m, "%9lu%c ", delta, *unit);
-               printk_prot(m, st->current_prot, st->level);
+               pt_dump_cont_printf(m, st->to_dmesg, "%9lu%c ", delta, *unit);
+               printk_prot(m, st->current_prot, st->level, st->to_dmesg);
 
                /*
                 * We print markers for special areas of address space,
@@ -207,7 +227,8 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                 */
                if (st->current_address >= st->marker[1].start_address) {
                        st->marker++;
-                       seq_printf(m, "---[ %s ]---\n", st->marker->name);
+                       pt_dump_seq_printf(m, st->to_dmesg, "---[ %s ]---\n",
+                                          st->marker->name);
                }
 
                st->start_address = st->current_address;
@@ -296,7 +317,7 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
 #define pgd_none(a)  pud_none(__pud(pgd_val(a)))
 #endif
 
-static void walk_pgd_level(struct seq_file *m)
+void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
 {
 #ifdef CONFIG_X86_64
        pgd_t *start = (pgd_t *) &init_level4_pgt;
@@ -304,9 +325,12 @@ static void walk_pgd_level(struct seq_file *m)
        pgd_t *start = swapper_pg_dir;
 #endif
        int i;
-       struct pg_state st;
+       struct pg_state st = {};
 
-       memset(&st, 0, sizeof(st));
+       if (pgd) {
+               start = pgd;
+               st.to_dmesg = true;
+       }
 
        for (i = 0; i < PTRS_PER_PGD; i++) {
                st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
@@ -331,7 +355,7 @@ static void walk_pgd_level(struct seq_file *m)
 
 static int ptdump_show(struct seq_file *m, void *v)
 {
-       walk_pgd_level(m);
+       ptdump_walk_pgd_level(m, NULL);
        return 0;
 }
 
index 9d591c895803101e2decbc85a0ce9f23a0b4eaeb..8e57229926779eb9db2afad3e5b277def75d4e0a 100644 (file)
@@ -584,8 +584,13 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
 
        if (error_code & PF_INSTR) {
                unsigned int level;
+               pgd_t *pgd;
+               pte_t *pte;
 
-               pte_t *pte = lookup_address(address, &level);
+               pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+               pgd += pgd_index(address);
+
+               pte = lookup_address_in_pgd(pgd, address, &level);
 
                if (pte && pte_present(*pte) && !pte_exec(*pte))
                        printk(nx_warning, from_kuid(&init_user_ns, current_uid()));
@@ -1001,6 +1006,12 @@ static int fault_in_kernel_space(unsigned long address)
 
 static inline bool smap_violation(int error_code, struct pt_regs *regs)
 {
+       if (!IS_ENABLED(CONFIG_X86_SMAP))
+               return false;
+
+       if (!static_cpu_has(X86_FEATURE_SMAP))
+               return false;
+
        if (error_code & PF_USER)
                return false;
 
@@ -1014,13 +1025,17 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
  * routines.
+ *
+ * This function must have noinline because both callers
+ * {,trace_}do_page_fault() have notrace on. Having this an actual function
+ * guarantees there's a function trace entry.
  */
-static void __kprobes
-__do_page_fault(struct pt_regs *regs, unsigned long error_code)
+static void __kprobes noinline
+__do_page_fault(struct pt_regs *regs, unsigned long error_code,
+               unsigned long address)
 {
        struct vm_area_struct *vma;
        struct task_struct *tsk;
-       unsigned long address;
        struct mm_struct *mm;
        int fault;
        unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
@@ -1028,9 +1043,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
        tsk = current;
        mm = tsk->mm;
 
-       /* Get the faulting address: */
-       address = read_cr2();
-
        /*
         * Detect and handle instructions that would cause a page fault for
         * both a tracked kernel page and a userspace page.
@@ -1087,11 +1099,9 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
        if (unlikely(error_code & PF_RSVD))
                pgtable_bad(regs, error_code, address);
 
-       if (static_cpu_has(X86_FEATURE_SMAP)) {
-               if (unlikely(smap_violation(error_code, regs))) {
-                       bad_area_nosemaphore(regs, error_code, address);
-                       return;
-               }
+       if (unlikely(smap_violation(error_code, regs))) {
+               bad_area_nosemaphore(regs, error_code, address);
+               return;
        }
 
        /*
@@ -1244,32 +1254,50 @@ good_area:
        up_read(&mm->mmap_sem);
 }
 
-dotraplinkage void __kprobes
+dotraplinkage void __kprobes notrace
 do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
+       unsigned long address = read_cr2(); /* Get the faulting address */
        enum ctx_state prev_state;
 
+       /*
+        * We must have this function tagged with __kprobes, notrace and call
+        * read_cr2() before calling anything else. To avoid calling any kind
+        * of tracing machinery before we've observed the CR2 value.
+        *
+        * exception_{enter,exit}() contain all sorts of tracepoints.
+        */
+
        prev_state = exception_enter();
-       __do_page_fault(regs, error_code);
+       __do_page_fault(regs, error_code, address);
        exception_exit(prev_state);
 }
 
-static void trace_page_fault_entries(struct pt_regs *regs,
+#ifdef CONFIG_TRACING
+static void trace_page_fault_entries(unsigned long address, struct pt_regs *regs,
                                     unsigned long error_code)
 {
        if (user_mode(regs))
-               trace_page_fault_user(read_cr2(), regs, error_code);
+               trace_page_fault_user(address, regs, error_code);
        else
-               trace_page_fault_kernel(read_cr2(), regs, error_code);
+               trace_page_fault_kernel(address, regs, error_code);
 }
 
-dotraplinkage void __kprobes
+dotraplinkage void __kprobes notrace
 trace_do_page_fault(struct pt_regs *regs, unsigned long error_code)
 {
+       /*
+        * The exception_enter and tracepoint processing could
+        * trigger another page faults (user space callchain
+        * reading) and destroy the original cr2 value, so read
+        * the faulting address now.
+        */
+       unsigned long address = read_cr2();
        enum ctx_state prev_state;
 
        prev_state = exception_enter();
-       trace_page_fault_entries(regs, error_code);
-       __do_page_fault(regs, error_code);
+       trace_page_fault_entries(address, regs, error_code);
+       __do_page_fault(regs, error_code, address);
        exception_exit(prev_state);
 }
+#endif /* CONFIG_TRACING */
index 81b2750f3666f16d7a42e0699d8dc458530fd7b8..27aa0455fab31b930e12c6792ade37234814f4a4 100644 (file)
@@ -493,14 +493,6 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
                struct numa_memblk *mb = &mi->blk[i];
                memblock_set_node(mb->start, mb->end - mb->start,
                                  &memblock.memory, mb->nid);
-
-               /*
-                * At this time, all memory regions reserved by memblock are
-                * used by the kernel. Set the nid in memblock.reserved will
-                * mark out all the nodes the kernel resides in.
-                */
-               memblock_set_node(mb->start, mb->end - mb->start,
-                                 &memblock.reserved, mb->nid);
        }
 
        /*
@@ -565,10 +557,21 @@ static void __init numa_init_array(void)
 static void __init numa_clear_kernel_node_hotplug(void)
 {
        int i, nid;
-       nodemask_t numa_kernel_nodes;
+       nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
        unsigned long start, end;
        struct memblock_type *type = &memblock.reserved;
 
+       /*
+        * At this time, all memory regions reserved by memblock are
+        * used by the kernel. Set the nid in memblock.reserved will
+        * mark out all the nodes the kernel resides in.
+        */
+       for (i = 0; i < numa_meminfo.nr_blks; i++) {
+               struct numa_memblk *mb = &numa_meminfo.blk[i];
+               memblock_set_node(mb->start, mb->end - mb->start,
+                                 &memblock.reserved, mb->nid);
+       }
+
        /* Mark all kernel nodes. */
        for (i = 0; i < type->cnt; i++)
                node_set(type->regions[i].nid, numa_kernel_nodes);
index 0342d27ca7986924d9ed8c68f21a88bec982ed89..47b6436e41c24a10e6fea6051d57873beaf1c67a 100644 (file)
@@ -52,6 +52,8 @@ void memory_present(int nid, unsigned long start, unsigned long end)
                        nid, start, end);
        printk(KERN_DEBUG "  Setting physnode_map array to node %d for pfns:\n", nid);
        printk(KERN_DEBUG "  ");
+       start = round_down(start, PAGES_PER_SECTION);
+       end = round_up(end, PAGES_PER_SECTION);
        for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
                physnode_map[pfn / PAGES_PER_SECTION] = nid;
                printk(KERN_CONT "%lx ", pfn);
index b3b19f46c0164c7169c9259a68836afbaeae1943..ae242a7c11c7473cfeb163b78d54fa62005b8e44 100644 (file)
@@ -126,8 +126,8 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  * @vaddr:     virtual start address
  * @size:      number of bytes to flush
  *
- * clflush is an unordered instruction which needs fencing with mfence
- * to avoid ordering issues.
+ * clflushopt is an unordered instruction which needs fencing with mfence or
+ * sfence to avoid ordering issues.
  */
 void clflush_cache_range(void *vaddr, unsigned int size)
 {
@@ -136,11 +136,11 @@ void clflush_cache_range(void *vaddr, unsigned int size)
        mb();
 
        for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
-               clflush(vaddr);
+               clflushopt(vaddr);
        /*
         * Flush any possible final partial cacheline:
         */
-       clflush(vend);
+       clflushopt(vend);
 
        mb();
 }
@@ -323,8 +323,12 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
        return prot;
 }
 
-static pte_t *__lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
-                                     unsigned int *level)
+/*
+ * Lookup the page table entry for a virtual address in a specific pgd.
+ * Return a pointer to the entry and the level of the mapping.
+ */
+pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+                            unsigned int *level)
 {
        pud_t *pud;
        pmd_t *pmd;
@@ -365,7 +369,7 @@ static pte_t *__lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
  */
 pte_t *lookup_address(unsigned long address, unsigned int *level)
 {
-        return __lookup_address_in_pgd(pgd_offset_k(address), address, level);
+        return lookup_address_in_pgd(pgd_offset_k(address), address, level);
 }
 EXPORT_SYMBOL_GPL(lookup_address);
 
@@ -373,7 +377,7 @@ static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address,
                                  unsigned int *level)
 {
         if (cpa->pgd)
-               return __lookup_address_in_pgd(cpa->pgd + pgd_index(address),
+               return lookup_address_in_pgd(cpa->pgd + pgd_index(address),
                                               address, level);
 
         return lookup_address(address, level);
@@ -692,6 +696,18 @@ static bool try_to_free_pmd_page(pmd_t *pmd)
        return true;
 }
 
+static bool try_to_free_pud_page(pud_t *pud)
+{
+       int i;
+
+       for (i = 0; i < PTRS_PER_PUD; i++)
+               if (!pud_none(pud[i]))
+                       return false;
+
+       free_page((unsigned long)pud);
+       return true;
+}
+
 static bool unmap_pte_range(pmd_t *pmd, unsigned long start, unsigned long end)
 {
        pte_t *pte = pte_offset_kernel(pmd, start);
@@ -805,6 +821,16 @@ static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end)
         */
 }
 
+static void unmap_pgd_range(pgd_t *root, unsigned long addr, unsigned long end)
+{
+       pgd_t *pgd_entry = root + pgd_index(addr);
+
+       unmap_pud_range(pgd_entry, addr, end);
+
+       if (try_to_free_pud_page((pud_t *)pgd_page_vaddr(*pgd_entry)))
+               pgd_clear(pgd_entry);
+}
+
 static int alloc_pte_page(pmd_t *pmd)
 {
        pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
@@ -999,9 +1025,8 @@ static int populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
 static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 {
        pgprot_t pgprot = __pgprot(_KERNPG_TABLE);
-       bool allocd_pgd = false;
-       pgd_t *pgd_entry;
        pud_t *pud = NULL;      /* shut up gcc */
+       pgd_t *pgd_entry;
        int ret;
 
        pgd_entry = cpa->pgd + pgd_index(addr);
@@ -1015,7 +1040,6 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
                        return -1;
 
                set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
-               allocd_pgd = true;
        }
 
        pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
@@ -1023,19 +1047,11 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 
        ret = populate_pud(cpa, addr, pgd_entry, pgprot);
        if (ret < 0) {
-               unmap_pud_range(pgd_entry, addr,
+               unmap_pgd_range(cpa->pgd, addr,
                                addr + (cpa->numpages << PAGE_SHIFT));
-
-               if (allocd_pgd) {
-                       /*
-                        * If I allocated this PUD page, I can just as well
-                        * free it in this error path.
-                        */
-                       pgd_clear(pgd_entry);
-                       free_page((unsigned long)pud);
-               }
                return ret;
        }
+
        cpa->numpages = ret;
        return 0;
 }
@@ -1377,10 +1393,10 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
        cache = cache_attr(mask_set);
 
        /*
-        * On success we use clflush, when the CPU supports it to
-        * avoid the wbindv. If the CPU does not support it and in the
+        * On success we use CLFLUSH, when the CPU supports it to
+        * avoid the WBINVD. If the CPU does not support it and in the
         * error case we fall back to cpa_flush_all (which uses
-        * wbindv):
+        * WBINVD):
         */
        if (!ret && cpu_has_clflush) {
                if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
@@ -1861,6 +1877,12 @@ out:
        return retval;
 }
 
+void kernel_unmap_pages_in_pgd(pgd_t *root, unsigned long address,
+                              unsigned numpages)
+{
+       unmap_pgd_range(root, address, address + (numpages << PAGE_SHIFT));
+}
+
 /*
  * The testcases use internal knowledge of the implementation that shouldn't
  * be exposed to the rest of the kernel. Include these directly here.
index 1a25187e151e9086cde7110e266126907716d514..66338a60aa6ef961c6017731b6fd6d9d169736e1 100644 (file)
@@ -42,15 +42,31 @@ static __init inline int srat_disabled(void)
        return acpi_numa < 0;
 }
 
-/* Callback for SLIT parsing */
+/*
+ * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
+ * I/O localities since SRAT does not list them.  I/O localities are
+ * not supported at this point.
+ */
 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 {
        int i, j;
 
-       for (i = 0; i < slit->locality_count; i++)
-               for (j = 0; j < slit->locality_count; j++)
-                       numa_set_distance(pxm_to_node(i), pxm_to_node(j),
+       for (i = 0; i < slit->locality_count; i++) {
+               const int from_node = pxm_to_node(i);
+
+               if (from_node == NUMA_NO_NODE)
+                       continue;
+
+               for (j = 0; j < slit->locality_count; j++) {
+                       const int to_node = pxm_to_node(j);
+
+                       if (to_node == NUMA_NO_NODE)
+                               continue;
+
+                       numa_set_distance(from_node, to_node,
                                slit->entry[slit->locality_count * i + j]);
+               }
+       }
 }
 
 /* Callback for Proximity Domain -> x2APIC mapping */
index ae699b3bbac84a920042349c1fc8605a8f93aba0..dd8dda167a242621515c901a3a5d62b4fcadf37b 100644 (file)
@@ -103,7 +103,7 @@ static void flush_tlb_func(void *info)
        if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
                return;
 
-       count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
+       count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
        if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
                if (f->flush_end == TLB_FLUSH_ALL)
                        local_flush_tlb();
@@ -131,7 +131,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
        info.flush_start = start;
        info.flush_end = end;
 
-       count_vm_event(NR_TLB_REMOTE_FLUSH);
+       count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
        if (is_uv_system()) {
                unsigned int cpu;
 
@@ -151,44 +151,19 @@ void flush_tlb_current_task(void)
 
        preempt_disable();
 
-       count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
        local_flush_tlb();
        if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
                flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
        preempt_enable();
 }
 
-/*
- * It can find out the THP large page, or
- * HUGETLB page in tlb_flush when THP disabled
- */
-static inline unsigned long has_large_page(struct mm_struct *mm,
-                                unsigned long start, unsigned long end)
-{
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       unsigned long addr = ALIGN(start, HPAGE_SIZE);
-       for (; addr < end; addr += HPAGE_SIZE) {
-               pgd = pgd_offset(mm, addr);
-               if (likely(!pgd_none(*pgd))) {
-                       pud = pud_offset(pgd, addr);
-                       if (likely(!pud_none(*pud))) {
-                               pmd = pmd_offset(pud, addr);
-                               if (likely(!pmd_none(*pmd)))
-                                       if (pmd_large(*pmd))
-                                               return addr;
-                       }
-               }
-       }
-       return 0;
-}
-
 void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
                                unsigned long end, unsigned long vmflag)
 {
        unsigned long addr;
        unsigned act_entries, tlb_entries = 0;
+       unsigned long nr_base_pages;
 
        preempt_disable();
        if (current->active_mm != mm)
@@ -210,21 +185,20 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
                tlb_entries = tlb_lli_4k[ENTRIES];
        else
                tlb_entries = tlb_lld_4k[ENTRIES];
+
        /* Assume all of TLB entries was occupied by this task */
-       act_entries = mm->total_vm > tlb_entries ? tlb_entries : mm->total_vm;
+       act_entries = tlb_entries >> tlb_flushall_shift;
+       act_entries = mm->total_vm > act_entries ? act_entries : mm->total_vm;
+       nr_base_pages = (end - start) >> PAGE_SHIFT;
 
        /* tlb_flushall_shift is on balance point, details in commit log */
-       if ((end - start) >> PAGE_SHIFT > act_entries >> tlb_flushall_shift) {
-               count_vm_event(NR_TLB_LOCAL_FLUSH_ALL);
+       if (nr_base_pages > act_entries) {
+               count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
                local_flush_tlb();
        } else {
-               if (has_large_page(mm, start, end)) {
-                       local_flush_tlb();
-                       goto flush_all;
-               }
                /* flush range by one by one 'invlpg' */
                for (addr = start; addr < end;  addr += PAGE_SIZE) {
-                       count_vm_event(NR_TLB_LOCAL_FLUSH_ONE);
+                       count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ONE);
                        __flush_tlb_single(addr);
                }
 
@@ -262,7 +236,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)
 
 static void do_flush_tlb_all(void *info)
 {
-       count_vm_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
+       count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
        __flush_tlb_all();
        if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
                leave_mm(smp_processor_id());
@@ -270,7 +244,7 @@ static void do_flush_tlb_all(void *info)
 
 void flush_tlb_all(void)
 {
-       count_vm_event(NR_TLB_REMOTE_FLUSH);
+       count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
        on_each_cpu(do_flush_tlb_all, NULL, 1);
 }
 
index 877b9a1b21523183d06973b60a9beb2459fff895..01495755701bd3d068db95df291ef71096d9cf33 100644 (file)
@@ -140,7 +140,7 @@ bpf_slow_path_byte_msh:
        push    %r9;                                            \
        push    SKBDATA;                                        \
 /* rsi already has offset */                                   \
-       mov     $SIZE,%ecx;     /* size */                      \
+       mov     $SIZE,%edx;     /* size */                      \
        call    bpf_internal_load_pointer_neg_helper;           \
        test    %rax,%rax;                                      \
        pop     SKBDATA;                                        \
index b7b0b35c198127dfed4c73dae046665a42ba5561..d51045afcaaf5e386ca101d889d4462f197afa93 100644 (file)
@@ -1,3 +1,4 @@
 obj-$(CONFIG_EFI)              += efi.o efi_$(BITS).o efi_stub_$(BITS).o
 obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
 obj-$(CONFIG_EARLY_PRINTK_EFI) += early_printk.o
+obj-$(CONFIG_EFI_MIXED)                += efi_thunk_$(BITS).o
index 7145ec63c5205f710a9f28bc676008e899878d76..f15103dff4b43f04e16ff8bbd59354435aec4cb7 100644 (file)
@@ -42,14 +42,15 @@ void __init efi_bgrt_init(void)
 
        if (bgrt_tab->header.length < sizeof(*bgrt_tab))
                return;
-       if (bgrt_tab->version != 1)
+       if (bgrt_tab->version != 1 || bgrt_tab->status != 1)
                return;
        if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
                return;
 
        image = efi_lookup_mapped_addr(bgrt_tab->image_address);
        if (!image) {
-               image = ioremap(bgrt_tab->image_address, sizeof(bmp_header));
+               image = early_memremap(bgrt_tab->image_address,
+                                      sizeof(bmp_header));
                ioremapped = true;
                if (!image)
                        return;
@@ -57,7 +58,7 @@ void __init efi_bgrt_init(void)
 
        memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
        if (ioremapped)
-               iounmap(image);
+               early_iounmap(image, sizeof(bmp_header));
        bgrt_image_size = bmp_header.size;
 
        bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL);
@@ -65,7 +66,8 @@ void __init efi_bgrt_init(void)
                return;
 
        if (ioremapped) {
-               image = ioremap(bgrt_tab->image_address, bmp_header.size);
+               image = early_memremap(bgrt_tab->image_address,
+                                      bmp_header.size);
                if (!image) {
                        kfree(bgrt_image);
                        bgrt_image = NULL;
@@ -75,5 +77,5 @@ void __init efi_bgrt_init(void)
 
        memcpy_fromio(bgrt_image, image, bgrt_image_size);
        if (ioremapped)
-               iounmap(image);
+               early_iounmap(image, bmp_header.size);
 }
index d62ec87a2b26d5d51bf2228ac7c2155cf9e8b06e..3781dd39e8bd55a03b8acd779113f40c151442b4 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/tlbflush.h>
 #include <asm/x86_init.h>
 #include <asm/rtc.h>
+#include <asm/uv/uv.h>
 
 #define EFI_DEBUG
 
@@ -67,9 +68,7 @@ struct efi_memory_map memmap;
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
-unsigned long x86_efi_facility;
-
-static __initdata efi_config_table_type_t arch_tables[] = {
+static efi_config_table_type_t arch_tables[] __initdata = {
 #ifdef CONFIG_X86_UV
        {UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab},
 #endif
@@ -78,16 +77,7 @@ static __initdata efi_config_table_type_t arch_tables[] = {
 
 u64 efi_setup;         /* efi setup_data physical address */
 
-/*
- * Returns 1 if 'facility' is enabled, 0 otherwise.
- */
-int efi_enabled(int facility)
-{
-       return test_bit(facility, &x86_efi_facility) != 0;
-}
-EXPORT_SYMBOL(efi_enabled);
-
-static bool __initdata disable_runtime = false;
+static bool disable_runtime __initdata = false;
 static int __init setup_noefi(char *arg)
 {
        disable_runtime = true;
@@ -256,27 +246,12 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
        return status;
 }
 
-static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
-                                            efi_time_cap_t *tc)
-{
-       unsigned long flags;
-       efi_status_t status;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       efi_call_phys_prelog();
-       status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm),
-                               virt_to_phys(tc));
-       efi_call_phys_epilog();
-       spin_unlock_irqrestore(&rtc_lock, flags);
-       return status;
-}
-
 int efi_set_rtc_mmss(const struct timespec *now)
 {
        unsigned long nowtime = now->tv_sec;
-       efi_status_t    status;
-       efi_time_t      eft;
-       efi_time_cap_t  cap;
+       efi_status_t    status;
+       efi_time_t      eft;
+       efi_time_cap_t  cap;
        struct rtc_time tm;
 
        status = efi.get_time(&eft, &cap);
@@ -294,9 +269,8 @@ int efi_set_rtc_mmss(const struct timespec *now)
                eft.second = tm.tm_sec;
                eft.nanosecond = 0;
        } else {
-               printk(KERN_ERR
-                      "%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
-                      __FUNCTION__, nowtime);
+               pr_err("%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
+                      __func__, nowtime);
                return -1;
        }
 
@@ -412,8 +386,7 @@ static void __init print_efi_memmap(void)
             p < memmap.map_end;
             p += memmap.desc_size, i++) {
                md = p;
-               pr_info("mem%02u: type=%u, attr=0x%llx, "
-                       "range=[0x%016llx-0x%016llx) (%lluMB)\n",
+               pr_info("mem%02u: type=%u, attr=0x%llx, range=[0x%016llx-0x%016llx) (%lluMB)\n",
                        i, md->type, md->attribute, md->phys_addr,
                        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
                        (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
@@ -445,9 +418,8 @@ void __init efi_reserve_boot_services(void)
                        memblock_is_region_reserved(start, size)) {
                        /* Could not reserve, skip it */
                        md->num_pages = 0;
-                       memblock_dbg("Could not reserve boot range "
-                                       "[0x%010llx-0x%010llx]\n",
-                                               start, start+size-1);
+                       memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
+                                    start, start+size-1);
                } else
                        memblock_reserve(start, size);
        }
@@ -455,7 +427,7 @@ void __init efi_reserve_boot_services(void)
 
 void __init efi_unmap_memmap(void)
 {
-       clear_bit(EFI_MEMMAP, &x86_efi_facility);
+       clear_bit(EFI_MEMMAP, &efi.flags);
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
                memmap.map = NULL;
@@ -466,9 +438,6 @@ void __init efi_free_boot_services(void)
 {
        void *p;
 
-       if (!efi_is_native())
-               return;
-
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                efi_memory_desc_t *md = p;
                unsigned long long start = md->phys_addr;
@@ -583,45 +552,82 @@ static int __init efi_systab_init(void *phys)
                return -EINVAL;
        }
        if ((efi.systab->hdr.revision >> 16) == 0)
-               pr_err("Warning: System table version "
-                      "%d.%02d, expected 1.00 or greater!\n",
+               pr_err("Warning: System table version %d.%02d, expected 1.00 or greater!\n",
                       efi.systab->hdr.revision >> 16,
                       efi.systab->hdr.revision & 0xffff);
 
+       set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
        return 0;
 }
 
-static int __init efi_runtime_init(void)
+static int __init efi_runtime_init32(void)
 {
-       efi_runtime_services_t *runtime;
+       efi_runtime_services_32_t *runtime;
+
+       runtime = early_ioremap((unsigned long)efi.systab->runtime,
+                       sizeof(efi_runtime_services_32_t));
+       if (!runtime) {
+               pr_err("Could not map the runtime service table!\n");
+               return -ENOMEM;
+       }
 
        /*
-        * Check out the runtime services table. We need to map
-        * the runtime services table so that we can grab the physical
-        * address of several of the EFI runtime functions, needed to
-        * set the firmware into virtual mode.
+        * We will only need *early* access to the following two
+        * EFI runtime services before set_virtual_address_map
+        * is invoked.
         */
+       efi_phys.set_virtual_address_map =
+                       (efi_set_virtual_address_map_t *)
+                       (unsigned long)runtime->set_virtual_address_map;
+       early_iounmap(runtime, sizeof(efi_runtime_services_32_t));
+
+       return 0;
+}
+
+static int __init efi_runtime_init64(void)
+{
+       efi_runtime_services_64_t *runtime;
+
        runtime = early_ioremap((unsigned long)efi.systab->runtime,
-                               sizeof(efi_runtime_services_t));
+                       sizeof(efi_runtime_services_64_t));
        if (!runtime) {
                pr_err("Could not map the runtime service table!\n");
                return -ENOMEM;
        }
+
        /*
-        * We will only need *early* access to the following
-        * two EFI runtime services before set_virtual_address_map
+        * We will only need *early* access to the following two
+        * EFI runtime services before set_virtual_address_map
         * is invoked.
         */
-       efi_phys.get_time = (efi_get_time_t *)runtime->get_time;
        efi_phys.set_virtual_address_map =
-               (efi_set_virtual_address_map_t *)
-               runtime->set_virtual_address_map;
+                       (efi_set_virtual_address_map_t *)
+                       (unsigned long)runtime->set_virtual_address_map;
+       early_iounmap(runtime, sizeof(efi_runtime_services_64_t));
+
+       return 0;
+}
+
+static int __init efi_runtime_init(void)
+{
+       int rv;
+
        /*
-        * Make efi_get_time can be called before entering
-        * virtual mode.
+        * Check out the runtime services table. We need to map
+        * the runtime services table so that we can grab the physical
+        * address of several of the EFI runtime functions, needed to
+        * set the firmware into virtual mode.
         */
-       efi.get_time = phys_efi_get_time;
-       early_iounmap(runtime, sizeof(efi_runtime_services_t));
+       if (efi_enabled(EFI_64BIT))
+               rv = efi_runtime_init64();
+       else
+               rv = efi_runtime_init32();
+
+       if (rv)
+               return rv;
+
+       set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 
        return 0;
 }
@@ -640,6 +646,8 @@ static int __init efi_memmap_init(void)
        if (add_efi_memmap)
                do_add_efi_memmap();
 
+       set_bit(EFI_MEMMAP, &efi.flags);
+
        return 0;
 }
 
@@ -722,7 +730,7 @@ void __init efi_init(void)
        if (efi_systab_init(efi_phys.systab))
                return;
 
-       set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
+       set_bit(EFI_SYSTEM_TABLES, &efi.flags);
 
        efi.config_table = (unsigned long)efi.systab->tables;
        efi.fw_vendor    = (unsigned long)efi.systab->fw_vendor;
@@ -750,24 +758,21 @@ void __init efi_init(void)
        if (efi_config_init(arch_tables))
                return;
 
-       set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
-
        /*
         * Note: We currently don't support runtime services on an EFI
         * that doesn't match the kernel 32/64-bit mode.
         */
 
-       if (!efi_is_native())
+       if (!efi_runtime_supported())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else {
                if (disable_runtime || efi_runtime_init())
                        return;
-               set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
        }
        if (efi_memmap_init())
                return;
 
-       set_bit(EFI_MEMMAP, &x86_efi_facility);
+       set_bit(EFI_MEMMAP, &efi.flags);
 
        print_efi_memmap();
 }
@@ -792,7 +797,7 @@ void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
                set_memory_nx(addr, npages);
 }
 
-static void __init runtime_code_page_mkexec(void)
+void __init runtime_code_page_mkexec(void)
 {
        efi_memory_desc_t *md;
        void *p;
@@ -844,6 +849,22 @@ void __init old_map_region(efi_memory_desc_t *md)
                       (unsigned long long)md->phys_addr);
 }
 
+static void native_runtime_setup(void)
+{
+       efi.get_time = virt_efi_get_time;
+       efi.set_time = virt_efi_set_time;
+       efi.get_wakeup_time = virt_efi_get_wakeup_time;
+       efi.set_wakeup_time = virt_efi_set_wakeup_time;
+       efi.get_variable = virt_efi_get_variable;
+       efi.get_next_variable = virt_efi_get_next_variable;
+       efi.set_variable = virt_efi_set_variable;
+       efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
+       efi.reset_system = virt_efi_reset_system;
+       efi.query_variable_info = virt_efi_query_variable_info;
+       efi.update_capsule = virt_efi_update_capsule;
+       efi.query_capsule_caps = virt_efi_query_capsule_caps;
+}
+
 /* Merge contiguous regions of the same type and attribute */
 static void __init efi_merge_regions(void)
 {
@@ -891,8 +912,9 @@ static void __init get_systab_virt_addr(efi_memory_desc_t *md)
        }
 }
 
-static int __init save_runtime_map(void)
+static void __init save_runtime_map(void)
 {
+#ifdef CONFIG_KEXEC
        efi_memory_desc_t *md;
        void *tmp, *p, *q = NULL;
        int count = 0;
@@ -914,38 +936,44 @@ static int __init save_runtime_map(void)
        }
 
        efi_runtime_map_setup(q, count, memmap.desc_size);
+       return;
 
-       return 0;
 out:
        kfree(q);
-       return -ENOMEM;
+       pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
+#endif
 }
 
-/*
- * Map efi regions which were passed via setup_data. The virt_addr is a fixed
- * addr which was used in first kernel of a kexec boot.
- */
-static void __init efi_map_regions_fixed(void)
+static void *realloc_pages(void *old_memmap, int old_shift)
 {
-       void *p;
-       efi_memory_desc_t *md;
+       void *ret;
 
-       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-               md = p;
-               efi_map_region_fixed(md); /* FIXME: add error handling */
-               get_systab_virt_addr(md);
-       }
+       ret = (void *)__get_free_pages(GFP_KERNEL, old_shift + 1);
+       if (!ret)
+               goto out;
+
+       /*
+        * A first-time allocation doesn't have anything to copy.
+        */
+       if (!old_memmap)
+               return ret;
 
+       memcpy(ret, old_memmap, PAGE_SIZE << old_shift);
+
+out:
+       free_pages((unsigned long)old_memmap, old_shift);
+       return ret;
 }
 
 /*
- * Map efi memory ranges for runtime serivce and update new_memmap with virtual
- * addresses.
+ * Map the efi memory ranges of the runtime services and update new_mmap with
+ * virtual addresses.
  */
-static void * __init efi_map_regions(int *count)
+static void * __init efi_map_regions(int *count, int *pg_shift)
 {
+       void *p, *new_memmap = NULL;
+       unsigned long left = 0;
        efi_memory_desc_t *md;
-       void *p, *tmp, *new_memmap = NULL;
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
@@ -960,20 +988,80 @@ static void * __init efi_map_regions(int *count)
                efi_map_region(md);
                get_systab_virt_addr(md);
 
-               tmp = krealloc(new_memmap, (*count + 1) * memmap.desc_size,
-                              GFP_KERNEL);
-               if (!tmp)
-                       goto out;
-               new_memmap = tmp;
+               if (left < memmap.desc_size) {
+                       new_memmap = realloc_pages(new_memmap, *pg_shift);
+                       if (!new_memmap)
+                               return NULL;
+
+                       left += PAGE_SIZE << *pg_shift;
+                       (*pg_shift)++;
+               }
+
                memcpy(new_memmap + (*count * memmap.desc_size), md,
                       memmap.desc_size);
+
+               left -= memmap.desc_size;
                (*count)++;
        }
 
        return new_memmap;
-out:
-       kfree(new_memmap);
-       return NULL;
+}
+
+static void __init kexec_enter_virtual_mode(void)
+{
+#ifdef CONFIG_KEXEC
+       efi_memory_desc_t *md;
+       void *p;
+
+       efi.systab = NULL;
+
+       /*
+        * We don't do virtual mode, since we don't do runtime services, on
+        * non-native EFI
+        */
+       if (!efi_is_native()) {
+               efi_unmap_memmap();
+               return;
+       }
+
+       /*
+       * Map efi regions which were passed via setup_data. The virt_addr is a
+       * fixed addr which was used in first kernel of a kexec boot.
+       */
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
+               efi_map_region_fixed(md); /* FIXME: add error handling */
+               get_systab_virt_addr(md);
+       }
+
+       save_runtime_map();
+
+       BUG_ON(!efi.systab);
+
+       efi_sync_low_kernel_mappings();
+
+       /*
+        * Now that EFI is in virtual mode, update the function
+        * pointers in the runtime service table to the new virtual addresses.
+        *
+        * Call EFI services through wrapper functions.
+        */
+       efi.runtime_version = efi_systab.hdr.revision;
+
+       native_runtime_setup();
+
+       efi.set_virtual_address_map = NULL;
+
+       if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
+               runtime_code_page_mkexec();
+
+       /* clean DUMMY object */
+       efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+                        EFI_VARIABLE_NON_VOLATILE |
+                        EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                        EFI_VARIABLE_RUNTIME_ACCESS,
+                        0, NULL);
+#endif
 }
 
 /*
@@ -995,57 +1083,53 @@ out:
  *
  * Specially for kexec boot, efi runtime maps in previous kernel should
  * be passed in via setup_data. In that case runtime ranges will be mapped
- * to the same virtual addresses as the first kernel.
+ * to the same virtual addresses as the first kernel, see
+ * kexec_enter_virtual_mode().
  */
-void __init efi_enter_virtual_mode(void)
+static void __init __efi_enter_virtual_mode(void)
 {
-       efi_status_t status;
+       int count = 0, pg_shift = 0;
        void *new_memmap = NULL;
-       int err, count = 0;
+       efi_status_t status;
 
        efi.systab = NULL;
 
-       /*
-        * We don't do virtual mode, since we don't do runtime services, on
-        * non-native EFI
-        */
-       if (!efi_is_native()) {
-               efi_unmap_memmap();
+       efi_merge_regions();
+       new_memmap = efi_map_regions(&count, &pg_shift);
+       if (!new_memmap) {
+               pr_err("Error reallocating memory, EFI runtime non-functional!\n");
                return;
        }
 
-       if (efi_setup) {
-               efi_map_regions_fixed();
-       } else {
-               efi_merge_regions();
-               new_memmap = efi_map_regions(&count);
-               if (!new_memmap) {
-                       pr_err("Error reallocating memory, EFI runtime non-functional!\n");
-                       return;
-               }
-       }
-
-       err = save_runtime_map();
-       if (err)
-               pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
+       save_runtime_map();
 
        BUG_ON(!efi.systab);
 
-       efi_setup_page_tables();
+       if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift))
+               return;
+
        efi_sync_low_kernel_mappings();
+       efi_dump_pagetable();
 
-       if (!efi_setup) {
+       if (efi_is_native()) {
                status = phys_efi_set_virtual_address_map(
-                       memmap.desc_size * count,
-                       memmap.desc_size,
-                       memmap.desc_version,
-                       (efi_memory_desc_t *)__pa(new_memmap));
-
-               if (status != EFI_SUCCESS) {
-                       pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
-                                status);
-                       panic("EFI call to SetVirtualAddressMap() failed!");
-               }
+                               memmap.desc_size * count,
+                               memmap.desc_size,
+                               memmap.desc_version,
+                               (efi_memory_desc_t *)__pa(new_memmap));
+       } else {
+               status = efi_thunk_set_virtual_address_map(
+                               efi_phys.set_virtual_address_map,
+                               memmap.desc_size * count,
+                               memmap.desc_size,
+                               memmap.desc_version,
+                               (efi_memory_desc_t *)__pa(new_memmap));
+       }
+
+       if (status != EFI_SUCCESS) {
+               pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
+                        status);
+               panic("EFI call to SetVirtualAddressMap() failed!");
        }
 
        /*
@@ -1055,24 +1139,43 @@ void __init efi_enter_virtual_mode(void)
         * Call EFI services through wrapper functions.
         */
        efi.runtime_version = efi_systab.hdr.revision;
-       efi.get_time = virt_efi_get_time;
-       efi.set_time = virt_efi_set_time;
-       efi.get_wakeup_time = virt_efi_get_wakeup_time;
-       efi.set_wakeup_time = virt_efi_set_wakeup_time;
-       efi.get_variable = virt_efi_get_variable;
-       efi.get_next_variable = virt_efi_get_next_variable;
-       efi.set_variable = virt_efi_set_variable;
-       efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
-       efi.reset_system = virt_efi_reset_system;
+
+       if (efi_is_native())
+               native_runtime_setup();
+       else
+               efi_thunk_runtime_setup();
+
        efi.set_virtual_address_map = NULL;
-       efi.query_variable_info = virt_efi_query_variable_info;
-       efi.update_capsule = virt_efi_update_capsule;
-       efi.query_capsule_caps = virt_efi_query_capsule_caps;
 
-       if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
-               runtime_code_page_mkexec();
+       efi_runtime_mkexec();
 
-       kfree(new_memmap);
+       /*
+        * We mapped the descriptor array into the EFI pagetable above but we're
+        * not unmapping it here. Here's why:
+        *
+        * We're copying select PGDs from the kernel page table to the EFI page
+        * table and when we do so and make changes to those PGDs like unmapping
+        * stuff from them, those changes appear in the kernel page table and we
+        * go boom.
+        *
+        * From setup_real_mode():
+        *
+        * ...
+        * trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd;
+        *
+        * In this particular case, our allocation is in PGD 0 of the EFI page
+        * table but we've copied that PGD from PGD[272] of the EFI page table:
+        *
+        *      pgd_index(__PAGE_OFFSET = 0xffff880000000000) = 272
+        *
+        * where the direct memory mapping in kernel space is.
+        *
+        * new_memmap's VA comes from that direct mapping and thus clearing it,
+        * it would get cleared in the kernel page table too.
+        *
+        * efi_cleanup_page_tables(__pa(new_memmap), 1 << pg_shift);
+        */
+       free_pages((unsigned long)new_memmap, pg_shift);
 
        /* clean DUMMY object */
        efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
@@ -1082,6 +1185,14 @@ void __init efi_enter_virtual_mode(void)
                         0, NULL);
 }
 
+void __init efi_enter_virtual_mode(void)
+{
+       if (efi_setup)
+               kexec_enter_virtual_mode();
+       else
+               __efi_enter_virtual_mode();
+}
+
 /*
  * Convenience functions to obtain memory types and attributes
  */
@@ -1119,9 +1230,8 @@ u64 efi_mem_attributes(unsigned long phys_addr)
 }
 
 /*
- * Some firmware has serious problems when using more than 50% of the EFI
- * variable store, i.e. it triggers bugs that can brick machines. Ensure that
- * we never use more than this safe limit.
+ * Some firmware implementations refuse to boot if there's insufficient space
+ * in the variable store. Ensure that we never use more than a safe limit.
  *
  * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
  * store.
@@ -1140,10 +1250,9 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
                return status;
 
        /*
-        * Some firmware implementations refuse to boot if there's insufficient
-        * space in the variable store. We account for that by refusing the
-        * write if permitting it would reduce the available space to under
-        * 5KB. This figure was provided by Samsung, so should be safe.
+        * We account for that by refusing the write if permitting it would
+        * reduce the available space to under 5KB. This figure was provided by
+        * Samsung, so should be safe.
         */
        if ((remaining_size - size < EFI_MIN_RESERVE) &&
                !efi_no_storage_paranoia) {
@@ -1206,8 +1315,27 @@ static int __init parse_efi_cmdline(char *str)
                str++;
 
        if (!strncmp(str, "old_map", 7))
-               set_bit(EFI_OLD_MEMMAP, &x86_efi_facility);
+               set_bit(EFI_OLD_MEMMAP, &efi.flags);
 
        return 0;
 }
 early_param("efi", parse_efi_cmdline);
+
+void __init efi_apply_memmap_quirks(void)
+{
+       /*
+        * Once setup is done earlier, unmap the EFI memory map on mismatched
+        * firmware/kernel architectures since there is no support for runtime
+        * services.
+        */
+       if (!efi_runtime_supported()) {
+               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               efi_unmap_memmap();
+       }
+
+       /*
+        * UV doesn't support the new EFI pagetable mapping yet.
+        */
+       if (is_uv_system())
+               set_bit(EFI_OLD_MEMMAP, &efi.flags);
+}
index 249b183cf41799d473012321435b2bdedf979903..9ee3491e31fbab7f6643462395d31c6f9f36f1b4 100644 (file)
 static unsigned long efi_rt_eflags;
 
 void efi_sync_low_kernel_mappings(void) {}
-void efi_setup_page_tables(void) {}
+void __init efi_dump_pagetable(void) {}
+int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+{
+       return 0;
+}
+void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages) {}
 
 void __init efi_map_region(efi_memory_desc_t *md)
 {
@@ -77,3 +82,9 @@ void efi_call_phys_epilog(void)
 
        local_irq_restore(efi_rt_eflags);
 }
+
+void __init efi_runtime_mkexec(void)
+{
+       if (__supported_pte_mask & _PAGE_NX)
+               runtime_code_page_mkexec();
+}
index 6284f158a47d851b1f4a0ca3f951e20ac5c3ffd7..290d397e1dd9125e408a1ee140fe4d3ced51a33d 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/realmode.h>
+#include <asm/time.h>
 
 static pgd_t *save_pgd __initdata;
 static unsigned long efi_flags __initdata;
@@ -58,7 +59,8 @@ struct efi_scratch {
        u64 prev_cr3;
        pgd_t *efi_pgt;
        bool use_pgd;
-};
+       u64 phys_stack;
+} __packed;
 
 static void __init early_code_mapping_set_exec(int executable)
 {
@@ -137,12 +139,64 @@ void efi_sync_low_kernel_mappings(void)
                sizeof(pgd_t) * num_pgds);
 }
 
-void efi_setup_page_tables(void)
+int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
+       unsigned long text;
+       struct page *page;
+       unsigned npages;
+       pgd_t *pgd;
+
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return 0;
+
        efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd;
+       pgd = __va(efi_scratch.efi_pgt);
 
-       if (!efi_enabled(EFI_OLD_MEMMAP))
-               efi_scratch.use_pgd = true;
+       /*
+        * It can happen that the physical address of new_memmap lands in memory
+        * which is not mapped in the EFI page table. Therefore we need to go
+        * and ident-map those pages containing the map before calling
+        * phys_efi_set_virtual_address_map().
+        */
+       if (kernel_map_pages_in_pgd(pgd, pa_memmap, pa_memmap, num_pages, _PAGE_NX)) {
+               pr_err("Error ident-mapping new memmap (0x%lx)!\n", pa_memmap);
+               return 1;
+       }
+
+       efi_scratch.use_pgd = true;
+
+       /*
+        * When making calls to the firmware everything needs to be 1:1
+        * mapped and addressable with 32-bit pointers. Map the kernel
+        * text and allocate a new stack because we can't rely on the
+        * stack pointer being < 4GB.
+        */
+       if (!IS_ENABLED(CONFIG_EFI_MIXED))
+               return 0;
+
+       page = alloc_page(GFP_KERNEL|__GFP_DMA32);
+       if (!page)
+               panic("Unable to allocate EFI runtime stack < 4GB\n");
+
+       efi_scratch.phys_stack = virt_to_phys(page_address(page));
+       efi_scratch.phys_stack += PAGE_SIZE; /* stack grows down */
+
+       npages = (_end - _text) >> PAGE_SHIFT;
+       text = __pa(_text);
+
+       if (kernel_map_pages_in_pgd(pgd, text >> PAGE_SHIFT, text, npages, 0)) {
+               pr_err("Failed to map kernel text 1:1\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+{
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+       kernel_unmap_pages_in_pgd(pgd, pa_memmap, num_pages);
 }
 
 static void __init __map_region(efi_memory_desc_t *md, u64 va)
@@ -173,6 +227,16 @@ void __init efi_map_region(efi_memory_desc_t *md)
         */
        __map_region(md, md->phys_addr);
 
+       /*
+        * Enforce the 1:1 mapping as the default virtual address when
+        * booting in EFI mixed mode, because even though we may be
+        * running a 64-bit kernel, the firmware may only be 32-bit.
+        */
+       if (!efi_is_native () && IS_ENABLED(CONFIG_EFI_MIXED)) {
+               md->virt_addr = md->phys_addr;
+               return;
+       }
+
        efi_va -= size;
 
        /* Is PA 2M-aligned? */
@@ -233,3 +297,308 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len)
 {
        efi_setup = phys_addr + sizeof(struct setup_data);
 }
+
+void __init efi_runtime_mkexec(void)
+{
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
+       if (__supported_pte_mask & _PAGE_NX)
+               runtime_code_page_mkexec();
+}
+
+void __init efi_dump_pagetable(void)
+{
+#ifdef CONFIG_EFI_PGT_DUMP
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+       ptdump_walk_pgd_level(NULL, pgd);
+#endif
+}
+
+#ifdef CONFIG_EFI_MIXED
+extern efi_status_t efi64_thunk(u32, ...);
+
+#define runtime_service32(func)                                                 \
+({                                                                      \
+       u32 table = (u32)(unsigned long)efi.systab;                      \
+       u32 *rt, *___f;                                                  \
+                                                                        \
+       rt = (u32 *)(table + offsetof(efi_system_table_32_t, runtime));  \
+       ___f = (u32 *)(*rt + offsetof(efi_runtime_services_32_t, func)); \
+       *___f;                                                           \
+})
+
+/*
+ * Switch to the EFI page tables early so that we can access the 1:1
+ * runtime services mappings which are not mapped in any other page
+ * tables. This function must be called before runtime_service32().
+ *
+ * Also, disable interrupts because the IDT points to 64-bit handlers,
+ * which aren't going to function correctly when we switch to 32-bit.
+ */
+#define efi_thunk(f, ...)                                              \
+({                                                                     \
+       efi_status_t __s;                                               \
+       unsigned long flags;                                            \
+       u32 func;                                                       \
+                                                                       \
+       efi_sync_low_kernel_mappings();                                 \
+       local_irq_save(flags);                                          \
+                                                                       \
+       efi_scratch.prev_cr3 = read_cr3();                              \
+       write_cr3((unsigned long)efi_scratch.efi_pgt);                  \
+       __flush_tlb_all();                                              \
+                                                                       \
+       func = runtime_service32(f);                                    \
+       __s = efi64_thunk(func, __VA_ARGS__);                   \
+                                                                       \
+       write_cr3(efi_scratch.prev_cr3);                                \
+       __flush_tlb_all();                                              \
+       local_irq_restore(flags);                                       \
+                                                                       \
+       __s;                                                            \
+})
+
+efi_status_t efi_thunk_set_virtual_address_map(
+       void *phys_set_virtual_address_map,
+       unsigned long memory_map_size,
+       unsigned long descriptor_size,
+       u32 descriptor_version,
+       efi_memory_desc_t *virtual_map)
+{
+       efi_status_t status;
+       unsigned long flags;
+       u32 func;
+
+       efi_sync_low_kernel_mappings();
+       local_irq_save(flags);
+
+       efi_scratch.prev_cr3 = read_cr3();
+       write_cr3((unsigned long)efi_scratch.efi_pgt);
+       __flush_tlb_all();
+
+       func = (u32)(unsigned long)phys_set_virtual_address_map;
+       status = efi64_thunk(func, memory_map_size, descriptor_size,
+                            descriptor_version, virtual_map);
+
+       write_cr3(efi_scratch.prev_cr3);
+       __flush_tlb_all();
+       local_irq_restore(flags);
+
+       return status;
+}
+
+static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+       efi_status_t status;
+       u32 phys_tm, phys_tc;
+
+       spin_lock(&rtc_lock);
+
+       phys_tm = virt_to_phys(tm);
+       phys_tc = virt_to_phys(tc);
+
+       status = efi_thunk(get_time, phys_tm, phys_tc);
+
+       spin_unlock(&rtc_lock);
+
+       return status;
+}
+
+static efi_status_t efi_thunk_set_time(efi_time_t *tm)
+{
+       efi_status_t status;
+       u32 phys_tm;
+
+       spin_lock(&rtc_lock);
+
+       phys_tm = virt_to_phys(tm);
+
+       status = efi_thunk(set_time, phys_tm);
+
+       spin_unlock(&rtc_lock);
+
+       return status;
+}
+
+static efi_status_t
+efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
+                         efi_time_t *tm)
+{
+       efi_status_t status;
+       u32 phys_enabled, phys_pending, phys_tm;
+
+       spin_lock(&rtc_lock);
+
+       phys_enabled = virt_to_phys(enabled);
+       phys_pending = virt_to_phys(pending);
+       phys_tm = virt_to_phys(tm);
+
+       status = efi_thunk(get_wakeup_time, phys_enabled,
+                            phys_pending, phys_tm);
+
+       spin_unlock(&rtc_lock);
+
+       return status;
+}
+
+static efi_status_t
+efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+{
+       efi_status_t status;
+       u32 phys_tm;
+
+       spin_lock(&rtc_lock);
+
+       phys_tm = virt_to_phys(tm);
+
+       status = efi_thunk(set_wakeup_time, enabled, phys_tm);
+
+       spin_unlock(&rtc_lock);
+
+       return status;
+}
+
+
+static efi_status_t
+efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
+                      u32 *attr, unsigned long *data_size, void *data)
+{
+       efi_status_t status;
+       u32 phys_name, phys_vendor, phys_attr;
+       u32 phys_data_size, phys_data;
+
+       phys_data_size = virt_to_phys(data_size);
+       phys_vendor = virt_to_phys(vendor);
+       phys_name = virt_to_phys(name);
+       phys_attr = virt_to_phys(attr);
+       phys_data = virt_to_phys(data);
+
+       status = efi_thunk(get_variable, phys_name, phys_vendor,
+                          phys_attr, phys_data_size, phys_data);
+
+       return status;
+}
+
+static efi_status_t
+efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
+                      u32 attr, unsigned long data_size, void *data)
+{
+       u32 phys_name, phys_vendor, phys_data;
+       efi_status_t status;
+
+       phys_name = virt_to_phys(name);
+       phys_vendor = virt_to_phys(vendor);
+       phys_data = virt_to_phys(data);
+
+       /* If data_size is > sizeof(u32) we've got problems */
+       status = efi_thunk(set_variable, phys_name, phys_vendor,
+                          attr, data_size, phys_data);
+
+       return status;
+}
+
+static efi_status_t
+efi_thunk_get_next_variable(unsigned long *name_size,
+                           efi_char16_t *name,
+                           efi_guid_t *vendor)
+{
+       efi_status_t status;
+       u32 phys_name_size, phys_name, phys_vendor;
+
+       phys_name_size = virt_to_phys(name_size);
+       phys_vendor = virt_to_phys(vendor);
+       phys_name = virt_to_phys(name);
+
+       status = efi_thunk(get_next_variable, phys_name_size,
+                          phys_name, phys_vendor);
+
+       return status;
+}
+
+static efi_status_t
+efi_thunk_get_next_high_mono_count(u32 *count)
+{
+       efi_status_t status;
+       u32 phys_count;
+
+       phys_count = virt_to_phys(count);
+       status = efi_thunk(get_next_high_mono_count, phys_count);
+
+       return status;
+}
+
+static void
+efi_thunk_reset_system(int reset_type, efi_status_t status,
+                      unsigned long data_size, efi_char16_t *data)
+{
+       u32 phys_data;
+
+       phys_data = virt_to_phys(data);
+
+       efi_thunk(reset_system, reset_type, status, data_size, phys_data);
+}
+
+static efi_status_t
+efi_thunk_update_capsule(efi_capsule_header_t **capsules,
+                        unsigned long count, unsigned long sg_list)
+{
+       /*
+        * To properly support this function we would need to repackage
+        * 'capsules' because the firmware doesn't understand 64-bit
+        * pointers.
+        */
+       return EFI_UNSUPPORTED;
+}
+
+static efi_status_t
+efi_thunk_query_variable_info(u32 attr, u64 *storage_space,
+                             u64 *remaining_space,
+                             u64 *max_variable_size)
+{
+       efi_status_t status;
+       u32 phys_storage, phys_remaining, phys_max;
+
+       if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+               return EFI_UNSUPPORTED;
+
+       phys_storage = virt_to_phys(storage_space);
+       phys_remaining = virt_to_phys(remaining_space);
+       phys_max = virt_to_phys(max_variable_size);
+
+       status = efi_thunk(query_variable_info, attr, phys_storage,
+                          phys_remaining, phys_max);
+
+       return status;
+}
+
+static efi_status_t
+efi_thunk_query_capsule_caps(efi_capsule_header_t **capsules,
+                            unsigned long count, u64 *max_size,
+                            int *reset_type)
+{
+       /*
+        * To properly support this function we would need to repackage
+        * 'capsules' because the firmware doesn't understand 64-bit
+        * pointers.
+        */
+       return EFI_UNSUPPORTED;
+}
+
+void efi_thunk_runtime_setup(void)
+{
+       efi.get_time = efi_thunk_get_time;
+       efi.set_time = efi_thunk_set_time;
+       efi.get_wakeup_time = efi_thunk_get_wakeup_time;
+       efi.set_wakeup_time = efi_thunk_set_wakeup_time;
+       efi.get_variable = efi_thunk_get_variable;
+       efi.get_next_variable = efi_thunk_get_next_variable;
+       efi.set_variable = efi_thunk_set_variable;
+       efi.get_next_high_mono_count = efi_thunk_get_next_high_mono_count;
+       efi.reset_system = efi_thunk_reset_system;
+       efi.query_variable_info = efi_thunk_query_variable_info;
+       efi.update_capsule = efi_thunk_update_capsule;
+       efi.query_capsule_caps = efi_thunk_query_capsule_caps;
+}
+#endif /* CONFIG_EFI_MIXED */
index 88073b1402988b49eb6c5e95f9f801a14d40f144..e0984ef0374b87a4dcf9d770b812feff2825285d 100644 (file)
@@ -7,6 +7,10 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/msr.h>
+#include <asm/processor-flags.h>
+#include <asm/page_types.h>
 
 #define SAVE_XMM                       \
        mov %rsp, %rax;                 \
@@ -164,7 +168,169 @@ ENTRY(efi_call6)
        ret
 ENDPROC(efi_call6)
 
+#ifdef CONFIG_EFI_MIXED
+
+/*
+ * We run this function from the 1:1 mapping.
+ *
+ * This function must be invoked with a 1:1 mapped stack.
+ */
+ENTRY(__efi64_thunk)
+       movl    %ds, %eax
+       push    %rax
+       movl    %es, %eax
+       push    %rax
+       movl    %ss, %eax
+       push    %rax
+
+       subq    $32, %rsp
+       movl    %esi, 0x0(%rsp)
+       movl    %edx, 0x4(%rsp)
+       movl    %ecx, 0x8(%rsp)
+       movq    %r8, %rsi
+       movl    %esi, 0xc(%rsp)
+       movq    %r9, %rsi
+       movl    %esi,  0x10(%rsp)
+
+       sgdt    save_gdt(%rip)
+
+       leaq    1f(%rip), %rbx
+       movq    %rbx, func_rt_ptr(%rip)
+
+       /* Switch to gdt with 32-bit segments */
+       movl    64(%rsp), %eax
+       lgdt    (%rax)
+
+       leaq    efi_enter32(%rip), %rax
+       pushq   $__KERNEL_CS
+       pushq   %rax
+       lretq
+
+1:     addq    $32, %rsp
+
+       lgdt    save_gdt(%rip)
+
+       pop     %rbx
+       movl    %ebx, %ss
+       pop     %rbx
+       movl    %ebx, %es
+       pop     %rbx
+       movl    %ebx, %ds
+
+       /*
+        * Convert 32-bit status code into 64-bit.
+        */
+       test    %rax, %rax
+       jz      1f
+       movl    %eax, %ecx
+       andl    $0x0fffffff, %ecx
+       andl    $0xf0000000, %eax
+       shl     $32, %rax
+       or      %rcx, %rax
+1:
+       ret
+ENDPROC(__efi64_thunk)
+
+ENTRY(efi_exit32)
+       movq    func_rt_ptr(%rip), %rax
+       push    %rax
+       mov     %rdi, %rax
+       ret
+ENDPROC(efi_exit32)
+
+       .code32
+/*
+ * EFI service pointer must be in %edi.
+ *
+ * The stack should represent the 32-bit calling convention.
+ */
+ENTRY(efi_enter32)
+       movl    $__KERNEL_DS, %eax
+       movl    %eax, %ds
+       movl    %eax, %es
+       movl    %eax, %ss
+
+       /* Reload pgtables */
+       movl    %cr3, %eax
+       movl    %eax, %cr3
+
+       /* Disable paging */
+       movl    %cr0, %eax
+       btrl    $X86_CR0_PG_BIT, %eax
+       movl    %eax, %cr0
+
+       /* Disable long mode via EFER */
+       movl    $MSR_EFER, %ecx
+       rdmsr
+       btrl    $_EFER_LME, %eax
+       wrmsr
+
+       call    *%edi
+
+       /* We must preserve return value */
+       movl    %eax, %edi
+
+       /*
+        * Some firmware will return with interrupts enabled. Be sure to
+        * disable them before we switch GDTs.
+        */
+       cli
+
+       movl    68(%esp), %eax
+       movl    %eax, 2(%eax)
+       lgdtl   (%eax)
+
+       movl    %cr4, %eax
+       btsl    $(X86_CR4_PAE_BIT), %eax
+       movl    %eax, %cr4
+
+       movl    %cr3, %eax
+       movl    %eax, %cr3
+
+       movl    $MSR_EFER, %ecx
+       rdmsr
+       btsl    $_EFER_LME, %eax
+       wrmsr
+
+       xorl    %eax, %eax
+       lldt    %ax
+
+       movl    72(%esp), %eax
+       pushl   $__KERNEL_CS
+       pushl   %eax
+
+       /* Enable paging */
+       movl    %cr0, %eax
+       btsl    $X86_CR0_PG_BIT, %eax
+       movl    %eax, %cr0
+       lret
+ENDPROC(efi_enter32)
+
+       .data
+       .balign 8
+       .global efi32_boot_gdt
+efi32_boot_gdt:        .word   0
+               .quad   0
+
+save_gdt:      .word   0
+               .quad   0
+func_rt_ptr:   .quad   0
+
+       .global efi_gdt64
+efi_gdt64:
+       .word   efi_gdt64_end - efi_gdt64
+       .long   0                       /* Filled out by user */
+       .word   0
+       .quad   0x0000000000000000      /* NULL descriptor */
+       .quad   0x00af9a000000ffff      /* __KERNEL_CS */
+       .quad   0x00cf92000000ffff      /* __KERNEL_DS */
+       .quad   0x0080890000000000      /* TS descriptor */
+       .quad   0x0000000000000000      /* TS continued */
+efi_gdt64_end:
+#endif /* CONFIG_EFI_MIXED */
+
        .data
 ENTRY(efi_scratch)
        .fill 3,8,0
        .byte 0
+       .quad 0
diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S
new file mode 100644 (file)
index 0000000..8806fa7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 Intel Corporation; author Matt Fleming
+ */
+
+#include <linux/linkage.h>
+#include <asm/page_types.h>
+
+       .text
+       .code64
+ENTRY(efi64_thunk)
+       push    %rbp
+       push    %rbx
+
+       /*
+        * Switch to 1:1 mapped 32-bit stack pointer.
+        */
+       movq    %rsp, efi_saved_sp(%rip)
+       movq    efi_scratch+25(%rip), %rsp
+
+       /*
+        * Calculate the physical address of the kernel text.
+        */
+       movq    $__START_KERNEL_map, %rax
+       subq    phys_base(%rip), %rax
+
+       /*
+        * Push some physical addresses onto the stack. This is easier
+        * to do now in a code64 section while the assembler can address
+        * 64-bit values. Note that all the addresses on the stack are
+        * 32-bit.
+        */
+       subq    $16, %rsp
+       leaq    efi_exit32(%rip), %rbx
+       subq    %rax, %rbx
+       movl    %ebx, 8(%rsp)
+       leaq    efi_gdt64(%rip), %rbx
+       subq    %rax, %rbx
+       movl    %ebx, 2(%ebx)
+       movl    %ebx, 4(%rsp)
+       leaq    efi_gdt32(%rip), %rbx
+       subq    %rax, %rbx
+       movl    %ebx, 2(%ebx)
+       movl    %ebx, (%rsp)
+
+       leaq    __efi64_thunk(%rip), %rbx
+       subq    %rax, %rbx
+       call    *%rbx
+
+       movq    efi_saved_sp(%rip), %rsp
+       pop     %rbx
+       pop     %rbp
+       retq
+ENDPROC(efi64_thunk)
+
+       .data
+efi_gdt32:
+       .word   efi_gdt32_end - efi_gdt32
+       .long   0                       /* Filled out above */
+       .word   0
+       .quad   0x0000000000000000      /* NULL descriptor */
+       .quad   0x00cf9a000000ffff      /* __KERNEL_CS */
+       .quad   0x00cf93000000ffff      /* __KERNEL_DS */
+efi_gdt32_end:
+
+efi_saved_sp:          .quad 0
index 39febb214e8c748ffd245c409c3b0cea31d3cebd..9471b9456f259762baf47c05a742d8401146b81e 100644 (file)
@@ -88,7 +88,7 @@ struct ts5500_sbc {
 static const struct {
        const char * const string;
        const ssize_t offset;
-} ts5500_signatures[] __initdata = {
+} ts5500_signatures[] __initconst = {
        { "TS-5x00 AMD Elan", 0xb14 },
 };
 
index 7d01b8c56c0029a59aa9b5b9e33036728ea7c77e..cc04e67bfd0589966e1c4b4b2fa29079c439ae24 100644 (file)
 #define smp_rmb()      barrier()
 #endif /* CONFIG_X86_PPRO_FENCE */
 
-#ifdef CONFIG_X86_OOSTORE
-#define smp_wmb()      wmb()
-#else /* CONFIG_X86_OOSTORE */
 #define smp_wmb()      barrier()
-#endif /* CONFIG_X86_OOSTORE */
 
 #define smp_read_barrier_depends()     read_barrier_depends()
 #define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
index fd14be1d1472204afc041a5bef320b2f7c7275af..9206ac7961a596798a1302b808bcf1fd6f119272 100644 (file)
@@ -2,6 +2,8 @@
 # Building vDSO images for x86.
 #
 
+KBUILD_CFLAGS += $(DISABLE_LTO)
+
 VDSO64-$(CONFIG_X86_64)                := y
 VDSOX32-$(CONFIG_X86_X32_ABI)  := y
 VDSO32-$(CONFIG_X86_32)                := y
@@ -35,7 +37,8 @@ export CPPFLAGS_vdso.lds += -P -C
 
 VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
                        -Wl,--no-undefined \
-                       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
+                       -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 \
+                       $(DISABLE_LTO)
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
 
@@ -127,7 +130,7 @@ vdso32.so-$(VDSO32-y)               += sysenter
 vdso32-images                  = $(vdso32.so-y:%=vdso32-%.so)
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-m,elf_i386 -Wl,-soname=linux-gate.so.1
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
@@ -181,7 +184,8 @@ quiet_cmd_vdso = VDSO    $@
                       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
                 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+               $(LTO_CFLAGS)
 GCOV_PROFILE := n
 
 #
index a4d7b647867f30783d9eab4f2091b3d991a314e1..201d09a7c46bbae56a21d15e56e222d67163f5ff 100644 (file)
@@ -1473,6 +1473,18 @@ static void xen_pvh_set_cr_flags(int cpu)
         * X86_CR0_TS, X86_CR0_PE, X86_CR0_ET are set by Xen for HVM guests
         * (which PVH shared codepaths), while X86_CR0_PG is for PVH. */
        write_cr0(read_cr0() | X86_CR0_MP | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM);
+
+       if (!cpu)
+               return;
+       /*
+        * For BSP, PSE PGE are set in probe_page_size_mask(), for APs
+        * set them here. For all, OSFXSR OSXMMEXCPT are set in fpu_init.
+       */
+       if (cpu_has_pse)
+               set_in_cr4(X86_CR4_PSE);
+
+       if (cpu_has_pge)
+               set_in_cr4(X86_CR4_PGE);
 }
 
 /*
index 8009acbe41e4ca954470796b3ad4e1befd679fe2..696c694986d0ab6aa967f3db7c6a345ef9c1ab59 100644 (file)
@@ -899,6 +899,13 @@ int m2p_add_override(unsigned long mfn, struct page *page,
                                        "m2p_add_override: pfn %lx not mapped", pfn))
                        return -EINVAL;
        }
+       WARN_ON(PagePrivate(page));
+       SetPagePrivate(page);
+       set_page_private(page, mfn);
+       page->index = pfn_to_mfn(pfn);
+
+       if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
+               return -ENOMEM;
 
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
@@ -937,16 +944,19 @@ int m2p_add_override(unsigned long mfn, struct page *page,
 }
 EXPORT_SYMBOL_GPL(m2p_add_override);
 int m2p_remove_override(struct page *page,
-                       struct gnttab_map_grant_ref *kmap_op,
-                       unsigned long mfn)
+               struct gnttab_map_grant_ref *kmap_op)
 {
        unsigned long flags;
+       unsigned long mfn;
        unsigned long pfn;
        unsigned long uninitialized_var(address);
        unsigned level;
        pte_t *ptep = NULL;
 
        pfn = page_to_pfn(page);
+       mfn = get_phys_to_machine(pfn);
+       if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
+               return -EINVAL;
 
        if (!PageHighMem(page)) {
                address = (unsigned long)__va(pfn << PAGE_SHIFT);
@@ -960,7 +970,10 @@ int m2p_remove_override(struct page *page,
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_del(&page->lru);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
+       WARN_ON(!PagePrivate(page));
+       ClearPagePrivate(page);
 
+       set_phys_to_machine(pfn, page->index);
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
                        struct multicall_space mcs;
index ba56e11cbf77697f4e972fadd7dd3281f07d4376..c87ae7c6e5f94636ab576a649ada006b4fb376dc 100644 (file)
@@ -20,6 +20,7 @@ config XTENSA
        select HAVE_FUNCTION_TRACER
        select HAVE_IRQ_TIME_ACCOUNTING
        select HAVE_PERF_EVENTS
+       select COMMON_CLK
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
          primarily for embedded systems.  These processors are both
@@ -80,7 +81,6 @@ choice
 config XTENSA_VARIANT_FSF
        bool "fsf - default (not generic) configuration"
        select MMU
-       select HAVE_XTENSA_GPIO32
 
 config XTENSA_VARIANT_DC232B
        bool "dc232b - Diamond 232L Standard Core Rev.B (LE)"
@@ -135,7 +135,6 @@ config HAVE_SMP
 config SMP
        bool "Enable Symmetric multi-processing support"
        depends on HAVE_SMP
-       select USE_GENERIC_SMP_HELPERS
        select GENERIC_SMP_IDLE_THREAD
        help
          Enabled SMP Software; allows more than one CPU/CORE
index 46b4f5eab421badbec1ae38cab4afac88fb7c731..e7370b11348e8d06c113d420704664740dbdec9b 100644 (file)
                interrupt-controller;
        };
 
+       clocks {
+               osc: main-oscillator {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+               };
+       };
+
        serial0: serial@fd050020 {
                device_type = "serial";
                compatible = "ns16550a";
@@ -42,9 +49,7 @@
                reg = <0xfd050020 0x20>;
                reg-shift = <2>;
                interrupts = <0 1>; /* external irq 0 */
-               /* Filled in by platform_setup from FPGA register
-                * clock-frequency = <100000000>;
-                */
+               clocks = <&osc>;
        };
 
        enet0: ethoc@fd030000 {
@@ -52,5 +57,6 @@
                reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
                interrupts = <1 1>; /* external irq 1 */
                local-mac-address = [00 50 c2 13 6f 00];
+               clocks = <&osc>;
        };
 };
index 0a337e4a8370aefce9d310c47bf75053316a1d5a..c3d20ba6eb86d6f7d42102f076f6085bcbe096c8 100644 (file)
@@ -9,6 +9,7 @@ generic-y += errno.h
 generic-y += exec.h
 generic-y += fcntl.h
 generic-y += hardirq.h
+generic-y += hash.h
 generic-y += ioctl.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
@@ -17,7 +18,9 @@ generic-y += kvm_para.h
 generic-y += linkage.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += mcs_spinlock.h
 generic-y += percpu.h
+generic-y += preempt.h
 generic-y += resource.h
 generic-y += scatterlist.h
 generic-y += sections.h
@@ -27,5 +30,3 @@ generic-y += termios.h
 generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += xor.h
-generic-y += preempt.h
-generic-y += hash.h
index 2a042d430c253b7dae704633727f0eabc0d5fc91..74944207167eccfb0f6e122ad7418d5728d4a2b7 100644 (file)
@@ -25,7 +25,7 @@
 
 #ifdef CONFIG_MMU
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 extern unsigned long xtensa_kio_paddr;
 
 static inline unsigned long xtensa_get_kio_paddr(void)
index 8c194f6af45e09932976b3f71d8d70a8f556488f..677bfcf4ee5ddab2207ed0e5f2885b4accd29f16 100644 (file)
@@ -23,25 +23,37 @@ void secondary_trap_init(void);
 
 static inline void spill_registers(void)
 {
-
+#if XCHAL_NUM_AREGS > 16
        __asm__ __volatile__ (
-               "movi   a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t"
-               "mov    a12, a0\n\t"
-               "rsr    a13, sar\n\t"
-               "xsr    a14, ps\n\t"
-               "movi   a0, _spill_registers\n\t"
-               "rsync\n\t"
-               "callx0 a0\n\t"
-               "mov    a0, a12\n\t"
-               "wsr    a13, sar\n\t"
-               "wsr    a14, ps\n\t"
-               : :
-#if defined(CONFIG_FRAME_POINTER)
-               : "a2", "a3", "a4",       "a11", "a12", "a13", "a14", "a15",
+               "       call12  1f\n"
+               "       _j      2f\n"
+               "       retw\n"
+               "       .align  4\n"
+               "1:\n"
+               "       _entry  a1, 48\n"
+               "       addi    a12, a0, 3\n"
+#if XCHAL_NUM_AREGS > 32
+               "       .rept   (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
+               "       _entry  a1, 48\n"
+               "       mov     a12, a0\n"
+               "       .endr\n"
+#endif
+               "       _entry  a1, 48\n"
+#if XCHAL_NUM_AREGS % 12 == 0
+               "       mov     a8, a8\n"
+#elif XCHAL_NUM_AREGS % 12 == 4
+               "       mov     a12, a12\n"
+#elif XCHAL_NUM_AREGS % 12 == 8
+               "       mov     a4, a4\n"
+#endif
+               "       retw\n"
+               "2:\n"
+               : : : "a12", "a13", "memory");
 #else
-               : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15",
+       __asm__ __volatile__ (
+               "       mov     a12, a12\n"
+               : : : "memory");
 #endif
-                 "memory");
 }
 
 #endif /* _XTENSA_TRAPS_H */
index 5791b45d5a5d5b25f97f9d7d5ee8e05b80ace6cb..f74ddfbb92ef56587b618db2a7e80a2c96593499 100644 (file)
@@ -25,7 +25,7 @@
 #define XCHAL_KIO_DEFAULT_PADDR                0xf0000000
 #define XCHAL_KIO_SIZE                 0x10000000
 
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
 #define XCHAL_KIO_PADDR                        xtensa_get_kio_paddr()
 #else
 #define XCHAL_KIO_PADDR                        XCHAL_KIO_DEFAULT_PADDR
index 51940fec6990f2b9a1c86fa5c43a199c3eade2f0..b9395529f02d465643091d71c4d6b6ca9650ff4b 100644 (file)
@@ -734,7 +734,12 @@ __SYSCALL(332, sys_finit_module, 3)
 #define __NR_accept4                           333
 __SYSCALL(333, sys_accept4, 4)
 
-#define __NR_syscall_count                     334
+#define __NR_sched_setattr                     334
+__SYSCALL(334, sys_sched_setattr, 2)
+#define __NR_sched_getattr                     335
+__SYSCALL(335, sys_sched_getattr, 3)
+
+#define __NR_syscall_count                     336
 
 /*
  * sysxtensa syscall handler
index 21dbe6bdb8edc661d729f656a02a5f1cf01a18c1..ef7f4990722b4fde3a175a0d524f82c3b2ce8b7b 100644 (file)
@@ -1081,196 +1081,53 @@ ENTRY(fast_syscall_spill_registers)
 
        rsr     a0, sar
        s32i    a3, a2, PT_AREG3
-       s32i    a4, a2, PT_AREG4
-       s32i    a0, a2, PT_AREG5        # store SAR to PT_AREG5
+       s32i    a0, a2, PT_SAR
 
-       /* The spill routine might clobber a7, a11, and a15. */
+       /* The spill routine might clobber a4, a7, a8, a11, a12, and a15. */
 
+       s32i    a4, a2, PT_AREG4
        s32i    a7, a2, PT_AREG7
+       s32i    a8, a2, PT_AREG8
        s32i    a11, a2, PT_AREG11
+       s32i    a12, a2, PT_AREG12
        s32i    a15, a2, PT_AREG15
 
-       call0   _spill_registers        # destroys a3, a4, and SAR
-
-       /* Advance PC, restore registers and SAR, and return from exception. */
-
-       l32i    a3, a2, PT_AREG5
-       l32i    a4, a2, PT_AREG4
-       l32i    a0, a2, PT_AREG0
-       wsr     a3, sar
-       l32i    a3, a2, PT_AREG3
-
-       /* Restore clobbered registers. */
-
-       l32i    a7, a2, PT_AREG7
-       l32i    a11, a2, PT_AREG11
-       l32i    a15, a2, PT_AREG15
-
-       movi    a2, 0
-       rfe
-
-ENDPROC(fast_syscall_spill_registers)
-
-/* Fixup handler.
- *
- * We get here if the spill routine causes an exception, e.g. tlb miss.
- * We basically restore WINDOWBASE and WINDOWSTART to the condition when
- * we entered the spill routine and jump to the user exception handler.
- *
- * a0: value of depc, original value in depc
- * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
- * a3: exctable, original value in excsave1
- */
-
-ENTRY(fast_syscall_spill_registers_fixup)
-
-       rsr     a2, windowbase  # get current windowbase (a2 is saved)
-       xsr     a0, depc        # restore depc and a0
-       ssl     a2              # set shift (32 - WB)
-
-       /* We need to make sure the current registers (a0-a3) are preserved.
-        * To do this, we simply set the bit for the current window frame
-        * in WS, so that the exception handlers save them to the task stack.
-        */
-
-       xsr     a3, excsave1    # get spill-mask
-       slli    a3, a3, 1       # shift left by one
-
-       slli    a2, a3, 32-WSBITS
-       src     a2, a3, a2      # a2 = xxwww1yyxxxwww1yy......
-       wsr     a2, windowstart # set corrected windowstart
-
-       srli    a3, a3, 1
-       rsr     a2, excsave1
-       l32i    a2, a2, EXC_TABLE_DOUBLE_SAVE   # restore a2
-       xsr     a2, excsave1
-       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE   # save a3
-       l32i    a3, a2, EXC_TABLE_PARAM # original WB (in user task)
-       xsr     a2, excsave1
-
-       /* Return to the original (user task) WINDOWBASE.
-        * We leave the following frame behind:
-        * a0, a1, a2   same
-        * a3:          trashed (saved in EXC_TABLE_DOUBLE_SAVE)
-        * depc:        depc (we have to return to that address)
-        * excsave_1:   exctable
-        */
-
-       wsr     a3, windowbase
-       rsync
-
-       /* We are now in the original frame when we entered _spill_registers:
-        *  a0: return address
-        *  a1: used, stack pointer
-        *  a2: kernel stack pointer
-        *  a3: available
-        *  depc: exception address
-        *  excsave: exctable
-        * Note: This frame might be the same as above.
-        */
-
-       /* Setup stack pointer. */
-
-       addi    a2, a2, -PT_USER_SIZE
-       s32i    a0, a2, PT_AREG0
-
-       /* Make sure we return to this fixup handler. */
-
-       movi    a3, fast_syscall_spill_registers_fixup_return
-       s32i    a3, a2, PT_DEPC         # setup depc
-
-       /* Jump to the exception handler. */
-
-       rsr     a3, excsave1
-       rsr     a0, exccause
-       addx4   a0, a0, a3                      # find entry in table
-       l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
-       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
-       jx      a0
-
-ENDPROC(fast_syscall_spill_registers_fixup)
-
-ENTRY(fast_syscall_spill_registers_fixup_return)
-
-       /* When we return here, all registers have been restored (a2: DEPC) */
-
-       wsr     a2, depc                # exception address
-
-       /* Restore fixup handler. */
-
-       rsr     a2, excsave1
-       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE
-       movi    a3, fast_syscall_spill_registers_fixup
-       s32i    a3, a2, EXC_TABLE_FIXUP
-       rsr     a3, windowbase
-       s32i    a3, a2, EXC_TABLE_PARAM
-       l32i    a2, a2, EXC_TABLE_KSTK
-
-       /* Load WB at the time the exception occurred. */
-
-       rsr     a3, sar                 # WB is still in SAR
-       neg     a3, a3
-       wsr     a3, windowbase
-       rsync
-
-       rsr     a3, excsave1
-       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
-
-       rfde
-
-ENDPROC(fast_syscall_spill_registers_fixup_return)
-
-/*
- * spill all registers.
- *
- * This is not a real function. The following conditions must be met:
- *
- *  - must be called with call0.
- *  - uses a3, a4 and SAR.
- *  - the last 'valid' register of each frame are clobbered.
- *  - the caller must have registered a fixup handler
- *    (or be inside a critical section)
- *  - PS_EXCM must be set (PS_WOE cleared?)
- */
-
-ENTRY(_spill_registers)
-
        /*
         * Rotate ws so that the current windowbase is at bit 0.
         * Assume ws = xxxwww1yy (www1 current window frame).
         * Rotate ws right so that a4 = yyxxxwww1.
         */
 
-       rsr     a4, windowbase
+       rsr     a0, windowbase
        rsr     a3, windowstart         # a3 = xxxwww1yy
-       ssr     a4                      # holds WB
-       slli    a4, a3, WSBITS
-       or      a3, a3, a4              # a3 = xxxwww1yyxxxwww1yy
+       ssr     a0                      # holds WB
+       slli    a0, a3, WSBITS
+       or      a3, a3, a0              # a3 = xxxwww1yyxxxwww1yy
        srl     a3, a3                  # a3 = 00xxxwww1yyxxxwww1
 
        /* We are done if there are no more than the current register frame. */
 
        extui   a3, a3, 1, WSBITS-1     # a3 = 0yyxxxwww
-       movi    a4, (1 << (WSBITS-1))
+       movi    a0, (1 << (WSBITS-1))
        _beqz   a3, .Lnospill           # only one active frame? jump
 
        /* We want 1 at the top, so that we return to the current windowbase */
 
-       or      a3, a3, a4              # 1yyxxxwww
+       or      a3, a3, a0              # 1yyxxxwww
 
        /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
 
        wsr     a3, windowstart         # save shifted windowstart
-       neg     a4, a3
-       and     a3, a4, a3              # first bit set from right: 000010000
+       neg     a0, a3
+       and     a3, a0, a3              # first bit set from right: 000010000
 
-       ffs_ws  a4, a3                  # a4: shifts to skip empty frames
+       ffs_ws  a0, a3                  # a0: shifts to skip empty frames
        movi    a3, WSBITS
-       sub     a4, a3, a4              # WSBITS-a4:number of 0-bits from right
-       ssr     a4                      # save in SAR for later.
+       sub     a0, a3, a0              # WSBITS-a0:number of 0-bits from right
+       ssr     a0                      # save in SAR for later.
 
        rsr     a3, windowbase
-       add     a3, a3, a4
+       add     a3, a3, a0
        wsr     a3, windowbase
        rsync
 
@@ -1285,22 +1142,6 @@ ENTRY(_spill_registers)
         * we have to save 4,8. or 12 registers.
         */
 
-       _bbsi.l a3, 1, .Lc4
-       _bbsi.l a3, 2, .Lc8
-
-       /* Special case: we have a call12-frame starting at a4. */
-
-       _bbci.l a3, 3, .Lc12    # bit 3 shouldn't be zero! (Jump to Lc12 first)
-
-       s32e    a4, a1, -16     # a1 is valid with an empty spill area
-       l32e    a4, a5, -12
-       s32e    a8, a4, -48
-       mov     a8, a4
-       l32e    a4, a1, -16
-       j       .Lc12c
-
-.Lnospill:
-       ret
 
 .Lloop: _bbsi.l        a3, 1, .Lc4
        _bbci.l a3, 2, .Lc12
@@ -1314,20 +1155,10 @@ ENTRY(_spill_registers)
        s32e    a9, a4, -28
        s32e    a10, a4, -24
        s32e    a11, a4, -20
-
        srli    a11, a3, 2              # shift windowbase by 2
        rotw    2
        _bnei   a3, 1, .Lloop
-
-.Lexit: /* Done. Do the final rotation, set WS, and return. */
-
-       rotw    1
-       rsr     a3, windowbase
-       ssl     a3
-       movi    a3, 1
-       sll     a3, a3
-       wsr     a3, windowstart
-       ret
+       j       .Lexit
 
 .Lc4:  s32e    a4, a9, -16
        s32e    a5, a9, -12
@@ -1343,11 +1174,11 @@ ENTRY(_spill_registers)
 
        /* 12-register frame (call12) */
 
-       l32e    a2, a5, -12
-       s32e    a8, a2, -48
-       mov     a8, a2
+       l32e    a0, a5, -12
+       s32e    a8, a0, -48
+       mov     a8, a0
 
-.Lc12c: s32e   a9, a8, -44
+       s32e    a9, a8, -44
        s32e    a10, a8, -40
        s32e    a11, a8, -36
        s32e    a12, a8, -32
@@ -1367,30 +1198,54 @@ ENTRY(_spill_registers)
         */
 
        rotw    1
-       mov     a5, a13
+       mov     a4, a13
        rotw    -1
 
-       s32e    a4, a9, -16
-       s32e    a5, a9, -12
-       s32e    a6, a9, -8
-       s32e    a7, a9, -4
+       s32e    a4, a8, -16
+       s32e    a5, a8, -12
+       s32e    a6, a8, -8
+       s32e    a7, a8, -4
 
        rotw    3
 
        _beqi   a3, 1, .Lexit
        j       .Lloop
 
-.Linvalid_mask:
+.Lexit:
 
-       /* We get here because of an unrecoverable error in the window
-        * registers. If we are in user space, we kill the application,
-        * however, this condition is unrecoverable in kernel space.
-        */
+       /* Done. Do the final rotation and set WS */
+
+       rotw    1
+       rsr     a3, windowbase
+       ssl     a3
+       movi    a3, 1
+       sll     a3, a3
+       wsr     a3, windowstart
+.Lnospill:
+
+       /* Advance PC, restore registers and SAR, and return from exception. */
+
+       l32i    a3, a2, PT_SAR
+       l32i    a0, a2, PT_AREG0
+       wsr     a3, sar
+       l32i    a3, a2, PT_AREG3
 
-       rsr     a0, ps
-       _bbci.l a0, PS_UM_BIT, 1f
+       /* Restore clobbered registers. */
 
-       /* User space: Setup a dummy frame and kill application.
+       l32i    a4, a2, PT_AREG4
+       l32i    a7, a2, PT_AREG7
+       l32i    a8, a2, PT_AREG8
+       l32i    a11, a2, PT_AREG11
+       l32i    a12, a2, PT_AREG12
+       l32i    a15, a2, PT_AREG15
+
+       movi    a2, 0
+       rfe
+
+.Linvalid_mask:
+
+       /* We get here because of an unrecoverable error in the window
+        * registers, so set up a dummy frame and kill the user application.
         * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
         */
 
@@ -1414,14 +1269,136 @@ ENTRY(_spill_registers)
        movi    a4, do_exit
        callx4  a4
 
-1:     /* Kernel space: PANIC! */
+       /* shouldn't return, so panic */
 
        wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0              # should not return
 1:     j       1b
 
-ENDPROC(_spill_registers)
+
+ENDPROC(fast_syscall_spill_registers)
+
+/* Fixup handler.
+ *
+ * We get here if the spill routine causes an exception, e.g. tlb miss.
+ * We basically restore WINDOWBASE and WINDOWSTART to the condition when
+ * we entered the spill routine and jump to the user exception handler.
+ *
+ * Note that we only need to restore the bits in windowstart that have not
+ * been spilled yet by the _spill_register routine. Luckily, a3 contains a
+ * rotated windowstart with only those bits set for frames that haven't been
+ * spilled yet. Because a3 is rotated such that bit 0 represents the register
+ * frame for the current windowbase - 1, we need to rotate a3 left by the
+ * value of the current windowbase + 1 and move it to windowstart.
+ *
+ * a0: value of depc, original value in depc
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
+ * a3: exctable, original value in excsave1
+ */
+
+ENTRY(fast_syscall_spill_registers_fixup)
+
+       rsr     a2, windowbase  # get current windowbase (a2 is saved)
+       xsr     a0, depc        # restore depc and a0
+       ssl     a2              # set shift (32 - WB)
+
+       /* We need to make sure the current registers (a0-a3) are preserved.
+        * To do this, we simply set the bit for the current window frame
+        * in WS, so that the exception handlers save them to the task stack.
+        *
+        * Note: we use a3 to set the windowbase, so we take a special care
+        * of it, saving it in the original _spill_registers frame across
+        * the exception handler call.
+        */
+
+       xsr     a3, excsave1    # get spill-mask
+       slli    a3, a3, 1       # shift left by one
+       addi    a3, a3, 1       # set the bit for the current window frame
+
+       slli    a2, a3, 32-WSBITS
+       src     a2, a3, a2      # a2 = xxwww1yyxxxwww1yy......
+       wsr     a2, windowstart # set corrected windowstart
+
+       srli    a3, a3, 1
+       rsr     a2, excsave1
+       l32i    a2, a2, EXC_TABLE_DOUBLE_SAVE   # restore a2
+       xsr     a2, excsave1
+       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE   # save a3
+       l32i    a3, a2, EXC_TABLE_PARAM # original WB (in user task)
+       xsr     a2, excsave1
+
+       /* Return to the original (user task) WINDOWBASE.
+        * We leave the following frame behind:
+        * a0, a1, a2   same
+        * a3:          trashed (saved in EXC_TABLE_DOUBLE_SAVE)
+        * depc:        depc (we have to return to that address)
+        * excsave_1:   exctable
+        */
+
+       wsr     a3, windowbase
+       rsync
+
+       /* We are now in the original frame when we entered _spill_registers:
+        *  a0: return address
+        *  a1: used, stack pointer
+        *  a2: kernel stack pointer
+        *  a3: available
+        *  depc: exception address
+        *  excsave: exctable
+        * Note: This frame might be the same as above.
+        */
+
+       /* Setup stack pointer. */
+
+       addi    a2, a2, -PT_USER_SIZE
+       s32i    a0, a2, PT_AREG0
+
+       /* Make sure we return to this fixup handler. */
+
+       movi    a3, fast_syscall_spill_registers_fixup_return
+       s32i    a3, a2, PT_DEPC         # setup depc
+
+       /* Jump to the exception handler. */
+
+       rsr     a3, excsave1
+       rsr     a0, exccause
+       addx4   a0, a0, a3                      # find entry in table
+       l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
+       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
+       jx      a0
+
+ENDPROC(fast_syscall_spill_registers_fixup)
+
+ENTRY(fast_syscall_spill_registers_fixup_return)
+
+       /* When we return here, all registers have been restored (a2: DEPC) */
+
+       wsr     a2, depc                # exception address
+
+       /* Restore fixup handler. */
+
+       rsr     a2, excsave1
+       s32i    a3, a2, EXC_TABLE_DOUBLE_SAVE
+       movi    a3, fast_syscall_spill_registers_fixup
+       s32i    a3, a2, EXC_TABLE_FIXUP
+       rsr     a3, windowbase
+       s32i    a3, a2, EXC_TABLE_PARAM
+       l32i    a2, a2, EXC_TABLE_KSTK
+
+       /* Load WB at the time the exception occurred. */
+
+       rsr     a3, sar                 # WB is still in SAR
+       neg     a3, a3
+       wsr     a3, windowbase
+       rsync
+
+       rsr     a3, excsave1
+       l32i    a3, a3, EXC_TABLE_DOUBLE_SAVE
+
+       rfde
+
+ENDPROC(fast_syscall_spill_registers_fixup_return)
 
 #ifdef CONFIG_MMU
 /*
@@ -1794,6 +1771,43 @@ ENTRY(system_call)
 
 ENDPROC(system_call)
 
+/*
+ * Spill live registers on the kernel stack macro.
+ *
+ * Entry condition: ps.woe is set, ps.excm is cleared
+ * Exit condition: windowstart has single bit set
+ * May clobber: a12, a13
+ */
+       .macro  spill_registers_kernel
+
+#if XCHAL_NUM_AREGS > 16
+       call12  1f
+       _j      2f
+       retw
+       .align  4
+1:
+       _entry  a1, 48
+       addi    a12, a0, 3
+#if XCHAL_NUM_AREGS > 32
+       .rept   (XCHAL_NUM_AREGS - 32) / 12
+       _entry  a1, 48
+       mov     a12, a0
+       .endr
+#endif
+       _entry  a1, 48
+#if XCHAL_NUM_AREGS % 12 == 0
+       mov     a8, a8
+#elif XCHAL_NUM_AREGS % 12 == 4
+       mov     a12, a12
+#elif XCHAL_NUM_AREGS % 12 == 8
+       mov     a4, a4
+#endif
+       retw
+2:
+#else
+       mov     a12, a12
+#endif
+       .endm
 
 /*
  * Task switch.
@@ -1806,21 +1820,20 @@ ENTRY(_switch_to)
 
        entry   a1, 16
 
-       mov     a12, a2                 # preserve 'prev' (a2)
-       mov     a13, a3                 # and 'next' (a3)
+       mov     a10, a2                 # preserve 'prev' (a2)
+       mov     a11, a3                 # and 'next' (a3)
 
        l32i    a4, a2, TASK_THREAD_INFO
        l32i    a5, a3, TASK_THREAD_INFO
 
-       save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+       save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
-       s32i    a0, a12, THREAD_RA      # save return address
-       s32i    a1, a12, THREAD_SP      # save stack pointer
+       s32i    a0, a10, THREAD_RA      # save return address
+       s32i    a1, a10, THREAD_SP      # save stack pointer
 
        /* Disable ints while we manipulate the stack pointer. */
 
-       movi    a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
-       xsr     a14, ps
+       rsil    a14, LOCKLEVEL
        rsr     a3, excsave1
        rsync
        s32i    a3, a3, EXC_TABLE_FIXUP /* enter critical section */
@@ -1835,7 +1848,7 @@ ENTRY(_switch_to)
 
        /* Flush register file. */
 
-       call0   _spill_registers        # destroys a3, a4, and SAR
+       spill_registers_kernel
 
        /* Set kernel stack (and leave critical section)
         * Note: It's save to set it here. The stack will not be overwritten
@@ -1851,13 +1864,13 @@ ENTRY(_switch_to)
 
        /* restore context of the task 'next' */
 
-       l32i    a0, a13, THREAD_RA      # restore return address
-       l32i    a1, a13, THREAD_SP      # restore stack pointer
+       l32i    a0, a11, THREAD_RA      # restore return address
+       l32i    a1, a11, THREAD_SP      # restore stack pointer
 
-       load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+       load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
        wsr     a14, ps
-       mov     a2, a12                 # return 'prev'
+       mov     a2, a10                 # return 'prev'
        rsync
 
        retw
index 7d12af1317f183d9af4b813ba4fd11bc94450924..84fe931bb60e1f012417d202d002813b12cf68aa 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
+#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
@@ -276,6 +277,7 @@ void __init early_init_devtree(void *params)
 
 static int __init xtensa_device_probe(void)
 {
+       of_clk_init(NULL);
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
        return 0;
 }
index 08b769d3b3a1c48482179eac8c68c562f61321c4..2a1823de69ccf621b6ea63e2ad815bbe118fa2f9 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/platform.h>
 
 unsigned long ccount_freq;             /* ccount Hz */
+EXPORT_SYMBOL(ccount_freq);
 
 static cycle_t ccount_read(struct clocksource *cs)
 {
index cb8fd44caabc6d246ce7975dfc0f370d87052fc2..f9e1ec346e359c7410482c5d8dfd5a9de88bfafc 100644 (file)
@@ -235,7 +235,7 @@ ENTRY(_DoubleExceptionVector)
 
        /* Check for overflow/underflow exception, jump if overflow. */
 
-       _bbci.l a0, 6, _DoubleExceptionVector_WindowOverflow
+       bbci.l  a0, 6, _DoubleExceptionVector_WindowOverflow
 
        /*
         * Restart window underflow exception.
index 74a60c7e085ea40349336089889de2d52f9d142c..80b33ed51f31174fd41a53bebd957c140517d8f9 100644 (file)
@@ -122,9 +122,7 @@ EXPORT_SYMBOL(insw);
 EXPORT_SYMBOL(insl);
 
 extern long common_exception_return;
-extern long _spill_registers;
 EXPORT_SYMBOL(common_exception_return);
-EXPORT_SYMBOL(_spill_registers);
 
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
index 479d7537a32a4f8039ae02581f8644d53eb80dda..aff108df92d3a301e8ba0ccaf7e13a5fb26c9038 100644 (file)
@@ -90,7 +90,7 @@ int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
 
 
 /*
- * Initialize the bootmem system and give it all the memory we have available.
+ * Initialize the bootmem system and give it all low memory we have available.
  */
 
 void __init bootmem_init(void)
@@ -142,9 +142,14 @@ void __init bootmem_init(void)
 
        /* Add all remaining memory pieces into the bootmem map */
 
-       for (i=0; i<sysmem.nr_banks; i++)
-               free_bootmem(sysmem.bank[i].start,
-                            sysmem.bank[i].end - sysmem.bank[i].start);
+       for (i = 0; i < sysmem.nr_banks; i++) {
+               if (sysmem.bank[i].start >> PAGE_SHIFT < max_low_pfn) {
+                       unsigned long end = min(max_low_pfn << PAGE_SHIFT,
+                                               sysmem.bank[i].end);
+                       free_bootmem(sysmem.bank[i].start,
+                                    end - sysmem.bank[i].start);
+               }
+       }
 
 }
 
index 36ec171698b833ddbebb6c9e51e9f18d4c53f278..861203e958da828deb140122752e95b47ddbf35f 100644 (file)
@@ -39,7 +39,7 @@ void init_mmu(void)
        set_itlbcfg_register(0);
        set_dtlbcfg_register(0);
 #endif
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && CONFIG_OF
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
        /*
         * Update the IO area mapping in case xtensa_kio_paddr has changed
         */
index 800227862fe8b91d561e8b318b757675a1e21f68..57fd08b36f51a151a389794bf4e8af7c9b64fd13 100644 (file)
@@ -135,11 +135,11 @@ static void __init update_local_mac(struct device_node *node)
 
 static int __init machine_setup(void)
 {
-       struct device_node *serial;
+       struct device_node *clock;
        struct device_node *eth = NULL;
 
-       for_each_compatible_node(serial, NULL, "ns16550a")
-               update_clock_frequency(serial);
+       for_each_node_by_name(clock, "main-oscillator")
+               update_clock_frequency(clock);
 
        if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc")))
                update_local_mac(eth);
@@ -290,6 +290,7 @@ static int __init xtavnet_init(void)
         * knows whether they set it correctly on the DIP switches.
         */
        pr_info("XTFPGA: Ethernet MAC %pM\n", ethoc_pdata.hwaddr);
+       ethoc_pdata.eth_clkfreq = *(long *)XTFPGA_CLKFRQ_VADDR;
 
        return 0;
 }
index bf4020116df521d18e1891d33a1815154b6046e9..244cdea4dee50252a06e41799badfb1c5c2e61a1 100644 (file)
 #define XCHAL_CP_MASK                  0x00    /* bitmask of all CPs by ID */
 #define XCHAL_CP_PORT_MASK             0x00    /* bitmask of only port CPs */
 
-/*  Basic parameters of each coprocessor:  */
-#define XCHAL_CP7_NAME                 "XTIOP"
-#define XCHAL_CP7_IDENT                        XTIOP
-#define XCHAL_CP7_SA_SIZE              0       /* size of state save area */
-#define XCHAL_CP7_SA_ALIGN             1       /* min alignment of save area */
-#define XCHAL_CP_ID_XTIOP              7       /* coprocessor ID (0..7) */
-
 /*  Filler info for unassigned coprocessors, to simplify arrays etc:  */
 #define XCHAL_NCP_SA_SIZE              0
 #define XCHAL_NCP_SA_ALIGN             1
@@ -42,6 +35,8 @@
 #define XCHAL_CP5_SA_ALIGN             1
 #define XCHAL_CP6_SA_SIZE              0
 #define XCHAL_CP6_SA_ALIGN             1
+#define XCHAL_CP7_SA_SIZE              0
+#define XCHAL_CP7_SA_ALIGN             1
 
 /*  Save area for non-coprocessor optional and custom (TIE) state:  */
 #define XCHAL_NCP_SA_SIZE              0
index c00e0bdeab4ab4724c42b379717200d405d9c584..bfe16d5af9f91a7eec049420e3f5b080476dc503 100644 (file)
@@ -708,9 +708,13 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
        if (!q)
                return NULL;
 
-       if (blk_init_rl(&q->root_rl, q, GFP_KERNEL))
+       q->flush_rq = kzalloc(sizeof(struct request), GFP_KERNEL);
+       if (!q->flush_rq)
                return NULL;
 
+       if (blk_init_rl(&q->root_rl, q, GFP_KERNEL))
+               goto fail;
+
        q->request_fn           = rfn;
        q->prep_rq_fn           = NULL;
        q->unprep_rq_fn         = NULL;
@@ -733,12 +737,16 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
        /* init elevator */
        if (elevator_init(q, NULL)) {
                mutex_unlock(&q->sysfs_lock);
-               return NULL;
+               goto fail;
        }
 
        mutex_unlock(&q->sysfs_lock);
 
        return q;
+
+fail:
+       kfree(q->flush_rq);
+       return NULL;
 }
 EXPORT_SYMBOL(blk_init_allocated_queue);
 
@@ -1127,7 +1135,7 @@ static struct request *blk_old_get_request(struct request_queue *q, int rw,
 struct request *blk_get_request(struct request_queue *q, int rw, gfp_t gfp_mask)
 {
        if (q->mq_ops)
-               return blk_mq_alloc_request(q, rw, gfp_mask, false);
+               return blk_mq_alloc_request(q, rw, gfp_mask);
        else
                return blk_old_get_request(q, rw, gfp_mask);
 }
@@ -1278,6 +1286,11 @@ void __blk_put_request(struct request_queue *q, struct request *req)
        if (unlikely(!q))
                return;
 
+       if (q->mq_ops) {
+               blk_mq_free_request(req);
+               return;
+       }
+
        blk_pm_put_request(req);
 
        elv_completed_request(q, req);
index bbfc072a79c2b5d0921ee84d322e4391d85c529b..dbf4502b1d6779eadd1573f28f75def4e26a031a 100644 (file)
@@ -65,7 +65,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
         * be resued after dying flag is set
         */
        if (q->mq_ops) {
-               blk_mq_insert_request(q, rq, true);
+               blk_mq_insert_request(rq, at_head, true, false);
                return;
        }
 
index 9288aaf35c21fc8c0f579fa001f316e697a4dfbb..43e6b4755e9a7e74e05479a83d42fbd88762e9f4 100644 (file)
@@ -130,20 +130,29 @@ static void blk_flush_restore_request(struct request *rq)
        blk_clear_rq_complete(rq);
 }
 
-static void mq_flush_data_run(struct work_struct *work)
+static void mq_flush_run(struct work_struct *work)
 {
        struct request *rq;
 
-       rq = container_of(work, struct request, mq_flush_data);
+       rq = container_of(work, struct request, mq_flush_work);
 
        memset(&rq->csd, 0, sizeof(rq->csd));
-       blk_mq_run_request(rq, true, false);
+       blk_mq_insert_request(rq, false, true, false);
 }
 
-static void blk_mq_flush_data_insert(struct request *rq)
+static bool blk_flush_queue_rq(struct request *rq, bool add_front)
 {
-       INIT_WORK(&rq->mq_flush_data, mq_flush_data_run);
-       kblockd_schedule_work(rq->q, &rq->mq_flush_data);
+       if (rq->q->mq_ops) {
+               INIT_WORK(&rq->mq_flush_work, mq_flush_run);
+               kblockd_schedule_work(rq->q, &rq->mq_flush_work);
+               return false;
+       } else {
+               if (add_front)
+                       list_add(&rq->queuelist, &rq->q->queue_head);
+               else
+                       list_add_tail(&rq->queuelist, &rq->q->queue_head);
+               return true;
+       }
 }
 
 /**
@@ -187,12 +196,7 @@ static bool blk_flush_complete_seq(struct request *rq, unsigned int seq,
 
        case REQ_FSEQ_DATA:
                list_move_tail(&rq->flush.list, &q->flush_data_in_flight);
-               if (q->mq_ops)
-                       blk_mq_flush_data_insert(rq);
-               else {
-                       list_add(&rq->queuelist, &q->queue_head);
-                       queued = true;
-               }
+               queued = blk_flush_queue_rq(rq, true);
                break;
 
        case REQ_FSEQ_DONE:
@@ -216,9 +220,6 @@ static bool blk_flush_complete_seq(struct request *rq, unsigned int seq,
        }
 
        kicked = blk_kick_flush(q);
-       /* blk_mq_run_flush will run queue */
-       if (q->mq_ops)
-               return queued;
        return kicked | queued;
 }
 
@@ -230,10 +231,9 @@ static void flush_end_io(struct request *flush_rq, int error)
        struct request *rq, *n;
        unsigned long flags = 0;
 
-       if (q->mq_ops) {
-               blk_mq_free_request(flush_rq);
+       if (q->mq_ops)
                spin_lock_irqsave(&q->mq_flush_lock, flags);
-       }
+
        running = &q->flush_queue[q->flush_running_idx];
        BUG_ON(q->flush_pending_idx == q->flush_running_idx);
 
@@ -263,49 +263,14 @@ static void flush_end_io(struct request *flush_rq, int error)
         * kblockd.
         */
        if (queued || q->flush_queue_delayed) {
-               if (!q->mq_ops)
-                       blk_run_queue_async(q);
-               else
-               /*
-                * This can be optimized to only run queues with requests
-                * queued if necessary.
-                */
-                       blk_mq_run_queues(q, true);
+               WARN_ON(q->mq_ops);
+               blk_run_queue_async(q);
        }
        q->flush_queue_delayed = 0;
        if (q->mq_ops)
                spin_unlock_irqrestore(&q->mq_flush_lock, flags);
 }
 
-static void mq_flush_work(struct work_struct *work)
-{
-       struct request_queue *q;
-       struct request *rq;
-
-       q = container_of(work, struct request_queue, mq_flush_work);
-
-       /* We don't need set REQ_FLUSH_SEQ, it's for consistency */
-       rq = blk_mq_alloc_request(q, WRITE_FLUSH|REQ_FLUSH_SEQ,
-               __GFP_WAIT|GFP_ATOMIC, true);
-       rq->cmd_type = REQ_TYPE_FS;
-       rq->end_io = flush_end_io;
-
-       blk_mq_run_request(rq, true, false);
-}
-
-/*
- * We can't directly use q->flush_rq, because it doesn't have tag and is not in
- * hctx->rqs[]. so we must allocate a new request, since we can't sleep here,
- * so offload the work to workqueue.
- *
- * Note: we assume a flush request finished in any hardware queue will flush
- * the whole disk cache.
- */
-static void mq_run_flush(struct request_queue *q)
-{
-       kblockd_schedule_work(q, &q->mq_flush_work);
-}
-
 /**
  * blk_kick_flush - consider issuing flush request
  * @q: request_queue being kicked
@@ -340,19 +305,31 @@ static bool blk_kick_flush(struct request_queue *q)
         * different from running_idx, which means flush is in flight.
         */
        q->flush_pending_idx ^= 1;
+
        if (q->mq_ops) {
-               mq_run_flush(q);
-               return true;
+               struct blk_mq_ctx *ctx = first_rq->mq_ctx;
+               struct blk_mq_hw_ctx *hctx = q->mq_ops->map_queue(q, ctx->cpu);
+
+               blk_mq_rq_init(hctx, q->flush_rq);
+               q->flush_rq->mq_ctx = ctx;
+
+               /*
+                * Reuse the tag value from the fist waiting request,
+                * with blk-mq the tag is generated during request
+                * allocation and drivers can rely on it being inside
+                * the range they asked for.
+                */
+               q->flush_rq->tag = first_rq->tag;
+       } else {
+               blk_rq_init(q, q->flush_rq);
        }
 
-       blk_rq_init(q, &q->flush_rq);
-       q->flush_rq.cmd_type = REQ_TYPE_FS;
-       q->flush_rq.cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ;
-       q->flush_rq.rq_disk = first_rq->rq_disk;
-       q->flush_rq.end_io = flush_end_io;
+       q->flush_rq->cmd_type = REQ_TYPE_FS;
+       q->flush_rq->cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ;
+       q->flush_rq->rq_disk = first_rq->rq_disk;
+       q->flush_rq->end_io = flush_end_io;
 
-       list_add_tail(&q->flush_rq.queuelist, &q->queue_head);
-       return true;
+       return blk_flush_queue_rq(q->flush_rq, false);
 }
 
 static void flush_data_end_io(struct request *rq, int error)
@@ -437,7 +414,7 @@ void blk_insert_flush(struct request *rq)
        if ((policy & REQ_FSEQ_DATA) &&
            !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
                if (q->mq_ops) {
-                       blk_mq_run_request(rq, false, true);
+                       blk_mq_insert_request(rq, false, false, true);
                } else
                        list_add_tail(&rq->queuelist, &q->queue_head);
                return;
@@ -558,5 +535,4 @@ EXPORT_SYMBOL(blkdev_issue_flush);
 void blk_mq_init_flush(struct request_queue *q)
 {
        spin_lock_init(&q->mq_flush_lock);
-       INIT_WORK(&q->mq_flush_work, mq_flush_work);
 }
index 2da76c999ef3f37bd965f9d91b48dac43196a208..97a733cf3d5f925d1eede00d0dbca63f3565fd38 100644 (file)
@@ -119,6 +119,14 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 
                atomic_inc(&bb.done);
                submit_bio(type, bio);
+
+               /*
+                * We can loop for a long time in here, if someone does
+                * full device discards (like mkfs). Be nice and allow
+                * us to schedule out to avoid softlocking if preempt
+                * is disabled.
+                */
+               cond_resched();
        }
        blk_finish_plug(&plug);
 
index 8f8adaa95466ccc8335cde7e313b551b375ed9b9..6c583f9c5b65d002a6ca357c53b19799f822f512 100644 (file)
@@ -21,6 +21,16 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
        if (!bio)
                return 0;
 
+       /*
+        * This should probably be returning 0, but blk_add_request_payload()
+        * (Christoph!!!!)
+        */
+       if (bio->bi_rw & REQ_DISCARD)
+               return 1;
+
+       if (bio->bi_rw & REQ_WRITE_SAME)
+               return 1;
+
        fbio = bio;
        cluster = blk_queue_cluster(q);
        seg_size = 0;
@@ -161,30 +171,60 @@ new_segment:
        *bvprv = *bvec;
 }
 
-/*
- * map a request to scatterlist, return number of sg entries setup. Caller
- * must make sure sg can hold rq->nr_phys_segments entries
- */
-int blk_rq_map_sg(struct request_queue *q, struct request *rq,
-                 struct scatterlist *sglist)
+static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio,
+                            struct scatterlist *sglist,
+                            struct scatterlist **sg)
 {
        struct bio_vec bvec, bvprv = { NULL };
-       struct req_iterator iter;
-       struct scatterlist *sg;
+       struct bvec_iter iter;
        int nsegs, cluster;
 
        nsegs = 0;
        cluster = blk_queue_cluster(q);
 
-       /*
-        * for each bio in rq
-        */
-       sg = NULL;
-       rq_for_each_segment(bvec, rq, iter) {
-               __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg,
-                                    &nsegs, &cluster);
-       } /* segments in rq */
+       if (bio->bi_rw & REQ_DISCARD) {
+               /*
+                * This is a hack - drivers should be neither modifying the
+                * biovec, nor relying on bi_vcnt - but because of
+                * blk_add_request_payload(), a discard bio may or may not have
+                * a payload we need to set up here (thank you Christoph) and
+                * bi_vcnt is really the only way of telling if we need to.
+                */
+
+               if (bio->bi_vcnt)
+                       goto single_segment;
+
+               return 0;
+       }
+
+       if (bio->bi_rw & REQ_WRITE_SAME) {
+single_segment:
+               *sg = sglist;
+               bvec = bio_iovec(bio);
+               sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
+               return 1;
+       }
+
+       for_each_bio(bio)
+               bio_for_each_segment(bvec, bio, iter)
+                       __blk_segment_map_sg(q, &bvec, sglist, &bvprv, sg,
+                                            &nsegs, &cluster);
 
+       return nsegs;
+}
+
+/*
+ * map a request to scatterlist, return number of sg entries setup. Caller
+ * must make sure sg can hold rq->nr_phys_segments entries
+ */
+int blk_rq_map_sg(struct request_queue *q, struct request *rq,
+                 struct scatterlist *sglist)
+{
+       struct scatterlist *sg = NULL;
+       int nsegs = 0;
+
+       if (rq->bio)
+               nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg);
 
        if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
            (blk_rq_bytes(rq) & q->dma_pad_mask)) {
@@ -230,20 +270,13 @@ EXPORT_SYMBOL(blk_rq_map_sg);
 int blk_bio_map_sg(struct request_queue *q, struct bio *bio,
                   struct scatterlist *sglist)
 {
-       struct bio_vec bvec, bvprv = { NULL };
-       struct scatterlist *sg;
-       int nsegs, cluster;
-       struct bvec_iter iter;
-
-       nsegs = 0;
-       cluster = blk_queue_cluster(q);
-
-       sg = NULL;
-       bio_for_each_segment(bvec, bio, iter) {
-               __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg,
-                                    &nsegs, &cluster);
-       } /* segments in bio */
+       struct scatterlist *sg = NULL;
+       int nsegs;
+       struct bio *next = bio->bi_next;
+       bio->bi_next = NULL;
 
+       nsegs = __blk_bios_map_sg(q, bio, sglist, &sg);
+       bio->bi_next = next;
        if (sg)
                sg_mark_end(sg);
 
index 3146befb56aaac7b925428d0afee89c9e083094a..136ef8643bbade3dd2d5d84e35183c749bc00399 100644 (file)
@@ -11,7 +11,7 @@
 #include "blk-mq.h"
 
 static LIST_HEAD(blk_mq_cpu_notify_list);
-static DEFINE_SPINLOCK(blk_mq_cpu_notify_lock);
+static DEFINE_RAW_SPINLOCK(blk_mq_cpu_notify_lock);
 
 static int blk_mq_main_cpu_notify(struct notifier_block *self,
                                  unsigned long action, void *hcpu)
@@ -19,12 +19,12 @@ static int blk_mq_main_cpu_notify(struct notifier_block *self,
        unsigned int cpu = (unsigned long) hcpu;
        struct blk_mq_cpu_notifier *notify;
 
-       spin_lock(&blk_mq_cpu_notify_lock);
+       raw_spin_lock(&blk_mq_cpu_notify_lock);
 
        list_for_each_entry(notify, &blk_mq_cpu_notify_list, list)
                notify->notify(notify->data, action, cpu);
 
-       spin_unlock(&blk_mq_cpu_notify_lock);
+       raw_spin_unlock(&blk_mq_cpu_notify_lock);
        return NOTIFY_OK;
 }
 
@@ -32,16 +32,16 @@ void blk_mq_register_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
 {
        BUG_ON(!notifier->notify);
 
-       spin_lock(&blk_mq_cpu_notify_lock);
+       raw_spin_lock(&blk_mq_cpu_notify_lock);
        list_add_tail(&notifier->list, &blk_mq_cpu_notify_list);
-       spin_unlock(&blk_mq_cpu_notify_lock);
+       raw_spin_unlock(&blk_mq_cpu_notify_lock);
 }
 
 void blk_mq_unregister_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
 {
-       spin_lock(&blk_mq_cpu_notify_lock);
+       raw_spin_lock(&blk_mq_cpu_notify_lock);
        list_del(&notifier->list);
-       spin_unlock(&blk_mq_cpu_notify_lock);
+       raw_spin_unlock(&blk_mq_cpu_notify_lock);
 }
 
 void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier,
index 5d70edc9855f7febabb4ebcb7f37ef23585d4b91..83ae96c51a2762cf7386f096e348eace58525e37 100644 (file)
@@ -184,7 +184,7 @@ void blk_mq_free_tags(struct blk_mq_tags *tags)
 ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page)
 {
        char *orig_page = page;
-       int cpu;
+       unsigned int cpu;
 
        if (!tags)
                return 0;
index 57039fcd9c93e7c3e014842fbbcaf2fc6550edd1..883f7208901585ab1ee02891a3ad5b67599a4243 100644 (file)
@@ -73,8 +73,8 @@ static void blk_mq_hctx_mark_pending(struct blk_mq_hw_ctx *hctx,
                set_bit(ctx->index_hw, hctx->ctx_map);
 }
 
-static struct request *blk_mq_alloc_rq(struct blk_mq_hw_ctx *hctx, gfp_t gfp,
-                                      bool reserved)
+static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx,
+                                             gfp_t gfp, bool reserved)
 {
        struct request *rq;
        unsigned int tag;
@@ -193,12 +193,6 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
        ctx->rq_dispatched[rw_is_sync(rw_flags)]++;
 }
 
-static struct request *__blk_mq_alloc_request(struct blk_mq_hw_ctx *hctx,
-                                             gfp_t gfp, bool reserved)
-{
-       return blk_mq_alloc_rq(hctx, gfp, reserved);
-}
-
 static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
                                                   int rw, gfp_t gfp,
                                                   bool reserved)
@@ -226,15 +220,14 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
        return rq;
 }
 
-struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
-               gfp_t gfp, bool reserved)
+struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp)
 {
        struct request *rq;
 
        if (blk_mq_queue_enter(q))
                return NULL;
 
-       rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved);
+       rq = blk_mq_alloc_request_pinned(q, rw, gfp, false);
        if (rq)
                blk_mq_put_ctx(rq->mq_ctx);
        return rq;
@@ -258,7 +251,7 @@ EXPORT_SYMBOL(blk_mq_alloc_reserved_request);
 /*
  * Re-init and set pdu, if we have it
  */
-static void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq)
+void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq)
 {
        blk_rq_init(hctx->queue, rq);
 
@@ -290,38 +283,10 @@ void blk_mq_free_request(struct request *rq)
        __blk_mq_free_request(hctx, ctx, rq);
 }
 
-static void blk_mq_bio_endio(struct request *rq, struct bio *bio, int error)
-{
-       if (error)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
-               error = -EIO;
-
-       if (unlikely(rq->cmd_flags & REQ_QUIET))
-               set_bit(BIO_QUIET, &bio->bi_flags);
-
-       /* don't actually finish bio if it's part of flush sequence */
-       if (!(rq->cmd_flags & REQ_FLUSH_SEQ))
-               bio_endio(bio, error);
-}
-
-void blk_mq_complete_request(struct request *rq, int error)
+bool blk_mq_end_io_partial(struct request *rq, int error, unsigned int nr_bytes)
 {
-       struct bio *bio = rq->bio;
-       unsigned int bytes = 0;
-
-       trace_block_rq_complete(rq->q, rq);
-
-       while (bio) {
-               struct bio *next = bio->bi_next;
-
-               bio->bi_next = NULL;
-               bytes += bio->bi_iter.bi_size;
-               blk_mq_bio_endio(rq, bio, error);
-               bio = next;
-       }
-
-       blk_account_io_completion(rq, bytes);
+       if (blk_update_request(rq, error, blk_rq_bytes(rq)))
+               return true;
 
        blk_account_io_done(rq);
 
@@ -329,49 +294,57 @@ void blk_mq_complete_request(struct request *rq, int error)
                rq->end_io(rq, error);
        else
                blk_mq_free_request(rq);
+       return false;
 }
+EXPORT_SYMBOL(blk_mq_end_io_partial);
 
-void __blk_mq_end_io(struct request *rq, int error)
-{
-       if (!blk_mark_rq_complete(rq))
-               blk_mq_complete_request(rq, error);
-}
-
-static void blk_mq_end_io_remote(void *data)
+static void __blk_mq_complete_request_remote(void *data)
 {
        struct request *rq = data;
 
-       __blk_mq_end_io(rq, rq->errors);
+       rq->q->softirq_done_fn(rq);
 }
 
-/*
- * End IO on this request on a multiqueue enabled driver. We'll either do
- * it directly inline, or punt to a local IPI handler on the matching
- * remote CPU.
- */
-void blk_mq_end_io(struct request *rq, int error)
+void __blk_mq_complete_request(struct request *rq)
 {
        struct blk_mq_ctx *ctx = rq->mq_ctx;
        int cpu;
 
-       if (!ctx->ipi_redirect)
-               return __blk_mq_end_io(rq, error);
+       if (!ctx->ipi_redirect) {
+               rq->q->softirq_done_fn(rq);
+               return;
+       }
 
        cpu = get_cpu();
        if (cpu != ctx->cpu && cpu_online(ctx->cpu)) {
-               rq->errors = error;
-               rq->csd.func = blk_mq_end_io_remote;
+               rq->csd.func = __blk_mq_complete_request_remote;
                rq->csd.info = rq;
                rq->csd.flags = 0;
                __smp_call_function_single(ctx->cpu, &rq->csd, 0);
        } else {
-               __blk_mq_end_io(rq, error);
+               rq->q->softirq_done_fn(rq);
        }
        put_cpu();
 }
-EXPORT_SYMBOL(blk_mq_end_io);
 
-static void blk_mq_start_request(struct request *rq)
+/**
+ * blk_mq_complete_request - end I/O on a request
+ * @rq:                the request being processed
+ *
+ * Description:
+ *     Ends all I/O on a request. It does not handle partial completions.
+ *     The actual completion happens out-of-order, through a IPI handler.
+ **/
+void blk_mq_complete_request(struct request *rq)
+{
+       if (unlikely(blk_should_fake_timeout(rq->q)))
+               return;
+       if (!blk_mark_rq_complete(rq))
+               __blk_mq_complete_request(rq);
+}
+EXPORT_SYMBOL(blk_mq_complete_request);
+
+static void blk_mq_start_request(struct request *rq, bool last)
 {
        struct request_queue *q = rq->q;
 
@@ -384,6 +357,25 @@ static void blk_mq_start_request(struct request *rq)
         */
        rq->deadline = jiffies + q->rq_timeout;
        set_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
+
+       if (q->dma_drain_size && blk_rq_bytes(rq)) {
+               /*
+                * Make sure space for the drain appears.  We know we can do
+                * this because max_hw_segments has been adjusted to be one
+                * fewer than the device can handle.
+                */
+               rq->nr_phys_segments++;
+       }
+
+       /*
+        * Flag the last request in the series so that drivers know when IO
+        * should be kicked off, if they don't do it on a per-request basis.
+        *
+        * Note: the flag isn't the only condition drivers should do kick off.
+        * If drive is busy, the last request might not have the bit set.
+        */
+       if (last)
+               rq->cmd_flags |= REQ_END;
 }
 
 static void blk_mq_requeue_request(struct request *rq)
@@ -392,6 +384,11 @@ static void blk_mq_requeue_request(struct request *rq)
 
        trace_block_rq_requeue(q, rq);
        clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
+
+       rq->cmd_flags &= ~REQ_END;
+
+       if (q->dma_drain_size && blk_rq_bytes(rq))
+               rq->nr_phys_segments--;
 }
 
 struct blk_mq_timeout_data {
@@ -559,19 +556,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
 
                rq = list_first_entry(&rq_list, struct request, queuelist);
                list_del_init(&rq->queuelist);
-               blk_mq_start_request(rq);
 
-               /*
-                * Last request in the series. Flag it as such, this
-                * enables drivers to know when IO should be kicked off,
-                * if they don't do it on a per-request basis.
-                *
-                * Note: the flag isn't the only condition drivers
-                * should do kick off. If drive is busy, the last
-                * request might not have the bit set.
-                */
-               if (list_empty(&rq_list))
-                       rq->cmd_flags |= REQ_END;
+               blk_mq_start_request(rq, list_empty(&rq_list));
 
                ret = q->mq_ops->queue_rq(hctx, rq);
                switch (ret) {
@@ -589,8 +575,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
                        break;
                default:
                        pr_err("blk-mq: bad return on queue: %d\n", ret);
-                       rq->errors = -EIO;
                case BLK_MQ_RQ_QUEUE_ERROR:
+                       rq->errors = -EIO;
                        blk_mq_end_io(rq, rq->errors);
                        break;
                }
@@ -693,13 +679,16 @@ static void blk_mq_work_fn(struct work_struct *work)
 }
 
 static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx,
-                                   struct request *rq)
+                                   struct request *rq, bool at_head)
 {
        struct blk_mq_ctx *ctx = rq->mq_ctx;
 
        trace_block_rq_insert(hctx->queue, rq);
 
-       list_add_tail(&rq->queuelist, &ctx->rq_list);
+       if (at_head)
+               list_add(&rq->queuelist, &ctx->rq_list);
+       else
+               list_add_tail(&rq->queuelist, &ctx->rq_list);
        blk_mq_hctx_mark_pending(hctx, ctx);
 
        /*
@@ -708,61 +697,28 @@ static void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx,
        blk_mq_add_timer(rq);
 }
 
-void blk_mq_insert_request(struct request_queue *q, struct request *rq,
-                          bool run_queue)
+void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue,
+               bool async)
 {
+       struct request_queue *q = rq->q;
        struct blk_mq_hw_ctx *hctx;
-       struct blk_mq_ctx *ctx, *current_ctx;
+       struct blk_mq_ctx *ctx = rq->mq_ctx, *current_ctx;
+
+       current_ctx = blk_mq_get_ctx(q);
+       if (!cpu_online(ctx->cpu))
+               rq->mq_ctx = ctx = current_ctx;
 
-       ctx = rq->mq_ctx;
        hctx = q->mq_ops->map_queue(q, ctx->cpu);
 
-       if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) {
+       if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA) &&
+           !(rq->cmd_flags & (REQ_FLUSH_SEQ))) {
                blk_insert_flush(rq);
        } else {
-               current_ctx = blk_mq_get_ctx(q);
-
-               if (!cpu_online(ctx->cpu)) {
-                       ctx = current_ctx;
-                       hctx = q->mq_ops->map_queue(q, ctx->cpu);
-                       rq->mq_ctx = ctx;
-               }
                spin_lock(&ctx->lock);
-               __blk_mq_insert_request(hctx, rq);
+               __blk_mq_insert_request(hctx, rq, at_head);
                spin_unlock(&ctx->lock);
-
-               blk_mq_put_ctx(current_ctx);
        }
 
-       if (run_queue)
-               __blk_mq_run_hw_queue(hctx);
-}
-EXPORT_SYMBOL(blk_mq_insert_request);
-
-/*
- * This is a special version of blk_mq_insert_request to bypass FLUSH request
- * check. Should only be used internally.
- */
-void blk_mq_run_request(struct request *rq, bool run_queue, bool async)
-{
-       struct request_queue *q = rq->q;
-       struct blk_mq_hw_ctx *hctx;
-       struct blk_mq_ctx *ctx, *current_ctx;
-
-       current_ctx = blk_mq_get_ctx(q);
-
-       ctx = rq->mq_ctx;
-       if (!cpu_online(ctx->cpu)) {
-               ctx = current_ctx;
-               rq->mq_ctx = ctx;
-       }
-       hctx = q->mq_ops->map_queue(q, ctx->cpu);
-
-       /* ctx->cpu might be offline */
-       spin_lock(&ctx->lock);
-       __blk_mq_insert_request(hctx, rq);
-       spin_unlock(&ctx->lock);
-
        blk_mq_put_ctx(current_ctx);
 
        if (run_queue)
@@ -798,7 +754,7 @@ static void blk_mq_insert_requests(struct request_queue *q,
                rq = list_first_entry(list, struct request, queuelist);
                list_del_init(&rq->queuelist);
                rq->mq_ctx = ctx;
-               __blk_mq_insert_request(hctx, rq);
+               __blk_mq_insert_request(hctx, rq, false);
        }
        spin_unlock(&ctx->lock);
 
@@ -888,6 +844,11 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
        blk_queue_bounce(q, &bio);
 
+       if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
+               bio_endio(bio, -EIO);
+               return;
+       }
+
        if (use_plug && blk_attempt_plug_merge(q, bio, &request_count))
                return;
 
@@ -899,6 +860,8 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
        ctx = blk_mq_get_ctx(q);
        hctx = q->mq_ops->map_queue(q, ctx->cpu);
 
+       if (is_sync)
+               rw |= REQ_SYNC;
        trace_block_getrq(q, bio, rw);
        rq = __blk_mq_alloc_request(hctx, GFP_ATOMIC, false);
        if (likely(rq))
@@ -950,7 +913,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
                __blk_mq_free_request(hctx, ctx, rq);
        else {
                blk_mq_bio_to_request(rq, bio);
-               __blk_mq_insert_request(hctx, rq);
+               __blk_mq_insert_request(hctx, rq, false);
        }
 
        spin_unlock(&ctx->lock);
@@ -1309,15 +1272,6 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg,
                reg->queue_depth = BLK_MQ_MAX_DEPTH;
        }
 
-       /*
-        * Set aside a tag for flush requests.  It will only be used while
-        * another flush request is in progress but outside the driver.
-        *
-        * TODO: only allocate if flushes are supported
-        */
-       reg->queue_depth++;
-       reg->reserved_tags++;
-
        if (reg->queue_depth < (reg->reserved_tags + BLK_MQ_TAG_MIN))
                return ERR_PTR(-EINVAL);
 
@@ -1360,17 +1314,27 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg,
        q->mq_ops = reg->ops;
        q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;
 
+       q->sg_reserved_size = INT_MAX;
+
        blk_queue_make_request(q, blk_mq_make_request);
        blk_queue_rq_timed_out(q, reg->ops->timeout);
        if (reg->timeout)
                blk_queue_rq_timeout(q, reg->timeout);
 
+       if (reg->ops->complete)
+               blk_queue_softirq_done(q, reg->ops->complete);
+
        blk_mq_init_flush(q);
        blk_mq_init_cpu_queues(q, reg->nr_hw_queues);
 
-       if (blk_mq_init_hw_queues(q, reg, driver_data))
+       q->flush_rq = kzalloc(round_up(sizeof(struct request) + reg->cmd_size,
+                               cache_line_size()), GFP_KERNEL);
+       if (!q->flush_rq)
                goto err_hw;
 
+       if (blk_mq_init_hw_queues(q, reg, driver_data))
+               goto err_flush_rq;
+
        blk_mq_map_swqueue(q);
 
        mutex_lock(&all_q_mutex);
@@ -1378,6 +1342,9 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_reg *reg,
        mutex_unlock(&all_q_mutex);
 
        return q;
+
+err_flush_rq:
+       kfree(q->flush_rq);
 err_hw:
        kfree(q->mq_map);
 err_map:
index 5c3917984b005f13ea35254074744ec91f2e5bd3..72beba1f9d55efa827e8667535a7f2956dd2b924 100644 (file)
@@ -22,13 +22,12 @@ struct blk_mq_ctx {
        struct kobject          kobj;
 };
 
-void __blk_mq_end_io(struct request *rq, int error);
-void blk_mq_complete_request(struct request *rq, int error);
-void blk_mq_run_request(struct request *rq, bool run_queue, bool async);
+void __blk_mq_complete_request(struct request *rq);
 void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
 void blk_mq_init_flush(struct request_queue *q);
 void blk_mq_drain_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
+void blk_mq_rq_init(struct blk_mq_hw_ctx *hctx, struct request *rq);
 
 /*
  * CPU hotplug helpers
index 8095c4a21fc0f53e6e46ff191de283500dcc97de..7500f876dae40e0b124b90adab21c60c1e3676b6 100644 (file)
@@ -549,6 +549,8 @@ static void blk_release_queue(struct kobject *kobj)
        if (q->mq_ops)
                blk_mq_free_queue(q);
 
+       kfree(q->flush_rq);
+
        blk_trace_shutdown(q);
 
        bdi_destroy(&q->backing_dev_info);
index bba81c9348e1cca630fc9d2515f27633d997c03a..d96f7061c6fd8727de9eb9fc02fae7b07dd357c1 100644 (file)
@@ -91,7 +91,7 @@ static void blk_rq_timed_out(struct request *req)
        case BLK_EH_HANDLED:
                /* Can we use req->errors here? */
                if (q->mq_ops)
-                       blk_mq_complete_request(req, req->errors);
+                       __blk_mq_complete_request(req);
                else
                        __blk_complete_request(req);
                break;
index c90e1d8f7a2b39466d91a9e1881bd16a0f71b2b9..d23b415b8a28f90e0ff83c713e0c2677a1e00f96 100644 (file)
@@ -113,7 +113,7 @@ static inline struct request *__elv_next_request(struct request_queue *q)
                        q->flush_queue_delayed = 1;
                        return NULL;
                }
-               if (unlikely(blk_queue_dying(q)) ||
+               if (unlikely(blk_queue_bypass(q)) ||
                    !q->elevator->type->ops.elevator_dispatch_fn(q, 0))
                        return NULL;
        }
index e7515aa43d6bd62c3ec0e33fb6781d2a9f2f27a7..6f190bc2b8b784bf7e09425b77c560fa60f04b90 100644 (file)
@@ -243,6 +243,8 @@ static int acpi_ac_resume(struct device *dev)
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
        return 0;
 }
+#else
+#define acpi_ac_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
 
index 470e7542bf31a3c2d571385e9b418de0a28eb140..797a6938d0515edb7ce7e5ce3f4f1648c538e515 100644 (file)
@@ -549,7 +549,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
 {
        unsigned long x;
        struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
-       if (sscanf(buf, "%ld\n", &x) == 1)
+       if (sscanf(buf, "%lu\n", &x) == 1)
                battery->alarm = x/1000;
        if (acpi_battery_present(battery))
                acpi_battery_set_alarm(battery);
@@ -841,6 +841,8 @@ static int acpi_battery_resume(struct device *dev)
        acpi_battery_update(battery);
        return 0;
 }
+#else
+#define acpi_battery_resume NULL
 #endif
 
 static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
index 10e4964d051a9c295e6185db1cfebe20b0ce5a9d..afec4526c48aa04e2921a199396e8fb2ea7489be 100644 (file)
@@ -260,14 +260,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
        },
        {
        .callback = dmi_disable_osi_win8,
-       .ident = "Dell Inspiron 15R SE",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
        .ident = "ThinkPad Edge E530",
        .matches = {
                     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -322,56 +314,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
                },
        },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ProBook 2013 models",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
-                    DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP EliteBook 2013 models",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
-                    DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ZBook 14",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ZBook 15",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP ZBook 17",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
-               },
-       },
-       {
-       .callback = dmi_disable_osi_win8,
-       .ident = "HP EliteBook 8780w",
-       .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
-               },
-       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index 11c11f6b8fa1453a4a28c3931f0cf8618750fecc..714e957a871a8034ed18be2104b8c107d0b4ced9 100644 (file)
@@ -80,6 +80,8 @@ static void acpi_button_notify(struct acpi_device *device, u32 event);
 
 #ifdef CONFIG_PM_SLEEP
 static int acpi_button_resume(struct device *dev);
+#else
+#define acpi_button_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
 
index 0b6ae6eb5c4a8f3dad1a40ec4c2f9f6928322b09..368f9ddb8480777420b2d5633facfeb238db1e27 100644 (file)
@@ -79,9 +79,10 @@ static int container_device_attach(struct acpi_device *adev,
        ACPI_COMPANION_SET(dev, adev);
        dev->release = acpi_container_release;
        ret = device_register(dev);
-       if (ret)
+       if (ret) {
+               put_device(dev);
                return ret;
-
+       }
        adev->driver_data = dev;
        return 1;
 }
index c431c88faaffa1f46f4d1e1b4de042f3314a2b9f..5bfd769fc91fa5bfd0890a146a4eed13ac342ff0 100644 (file)
@@ -609,7 +609,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
 static void dock_notify(struct dock_station *ds, u32 event)
 {
        acpi_handle handle = ds->handle;
-       struct acpi_device *ad;
+       struct acpi_device *adev = NULL;
        int surprise_removal = 0;
 
        /*
@@ -632,7 +632,8 @@ static void dock_notify(struct dock_station *ds, u32 event)
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
        case ACPI_NOTIFY_DEVICE_CHECK:
-               if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) {
+               acpi_bus_get_device(handle, &adev);
+               if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
                        begin_dock(ds);
                        dock(ds);
                        if (!dock_present(ds)) {
@@ -712,13 +713,11 @@ static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl,
 static ssize_t show_docked(struct device *dev,
                           struct device_attribute *attr, char *buf)
 {
-       struct acpi_device *tmp;
-
        struct dock_station *dock_station = dev->platform_data;
+       struct acpi_device *adev = NULL;
 
-       if (!acpi_bus_get_device(dock_station->handle, &tmp))
-               return snprintf(buf, PAGE_SIZE, "1\n");
-       return snprintf(buf, PAGE_SIZE, "0\n");
+       acpi_bus_get_device(dock_station->handle, &adev);
+       return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
 }
 static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
 
index 959d41acc108a847308773f754fdb4fff3b1fd26..d7d32c28829b17834507bf8683f2c2a5c77d0a0d 100644 (file)
@@ -67,6 +67,8 @@ enum ec_command {
 #define ACPI_EC_DELAY          500     /* Wait 500ms max. during EC ops */
 #define ACPI_EC_UDELAY_GLK     1000    /* Wait 1ms max. to get global lock */
 #define ACPI_EC_MSI_UDELAY     550     /* Wait 550us for MSI EC */
+#define ACPI_EC_CLEAR_MAX      100     /* Maximum number of events to query
+                                        * when trying to clear the EC */
 
 enum {
        EC_FLAGS_QUERY_PENDING,         /* Query is pending */
@@ -116,6 +118,7 @@ EXPORT_SYMBOL(first_ec);
 static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
 static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
 static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
+static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
 
 /* --------------------------------------------------------------------------
                              Transaction Management
@@ -440,6 +443,29 @@ acpi_handle ec_get_handle(void)
 
 EXPORT_SYMBOL(ec_get_handle);
 
+static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data);
+
+/*
+ * Clears stale _Q events that might have accumulated in the EC.
+ * Run with locked ec mutex.
+ */
+static void acpi_ec_clear(struct acpi_ec *ec)
+{
+       int i, status;
+       u8 value = 0;
+
+       for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
+               status = acpi_ec_query_unlocked(ec, &value);
+               if (status || !value)
+                       break;
+       }
+
+       if (unlikely(i == ACPI_EC_CLEAR_MAX))
+               pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
+       else
+               pr_info("%d stale EC events cleared\n", i);
+}
+
 void acpi_ec_block_transactions(void)
 {
        struct acpi_ec *ec = first_ec;
@@ -463,6 +489,10 @@ void acpi_ec_unblock_transactions(void)
        mutex_lock(&ec->mutex);
        /* Allow transactions to be carried out again */
        clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
+
+       if (EC_FLAGS_CLEAR_ON_RESUME)
+               acpi_ec_clear(ec);
+
        mutex_unlock(&ec->mutex);
 }
 
@@ -821,6 +851,13 @@ static int acpi_ec_add(struct acpi_device *device)
 
        /* EC is fully operational, allow queries */
        clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+
+       /* Clear stale _Q events if hardware might require that */
+       if (EC_FLAGS_CLEAR_ON_RESUME) {
+               mutex_lock(&ec->mutex);
+               acpi_ec_clear(ec);
+               mutex_unlock(&ec->mutex);
+       }
        return ret;
 }
 
@@ -922,6 +959,30 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
        return 0;
 }
 
+/*
+ * On some hardware it is necessary to clear events accumulated by the EC during
+ * sleep. These ECs stop reporting GPEs until they are manually polled, if too
+ * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=44161
+ *
+ * Ideally, the EC should also be instructed NOT to accumulate events during
+ * sleep (which Windows seems to do somehow), but the interface to control this
+ * behaviour is not known at this time.
+ *
+ * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
+ * however it is very likely that other Samsung models are affected.
+ *
+ * On systems which don't accumulate _Q events during sleep, this extra check
+ * should be harmless.
+ */
+static int ec_clear_on_resume(const struct dmi_system_id *id)
+{
+       pr_debug("Detected system needing EC poll on resume.\n");
+       EC_FLAGS_CLEAR_ON_RESUME = 1;
+       return 0;
+}
+
 static struct dmi_system_id ec_dmi_table[] __initdata = {
        {
        ec_skip_dsdt_scan, "Compal JFL92", {
@@ -965,6 +1026,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
        DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
+       {
+       ec_clear_on_resume, "Samsung hardware", {
+       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
        {},
 };
 
index 1fb62900f32a9c57d329fd3e5480bc0dc7c305b8..09e423f3d8ad30fbd16d2d2b2e2766e69e64de82 100644 (file)
@@ -55,6 +55,9 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev);
 static int acpi_fan_resume(struct device *dev);
+#else
+#define acpi_fan_suspend NULL
+#define acpi_fan_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
 
index 52d45ea2bc4f63efcfb7e8912b087b1a568d49cc..361b40c10c3f522e28e2b334dd5f8976109bc772 100644 (file)
@@ -430,6 +430,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                                 pin_name(pin));
                }
 
+               kfree(entry);
                return 0;
        }
 
index 50fe34ffe932fbdc9b1e9166c551fb025754853e..75c28eae88604903ac518fc0fe4ebe83f2e2669e 100644 (file)
@@ -60,7 +60,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
                                seq_printf(seq, "%c%-8s  %s:%s\n",
                                        dev->wakeup.flags.run_wake ? '*' : ' ',
                                        (device_may_wakeup(&dev->dev) ||
-                                       (ldev && device_may_wakeup(ldev))) ?
+                                       device_may_wakeup(ldev)) ?
                                        "enabled" : "disabled",
                                        ldev->bus ? ldev->bus->name :
                                        "no-bus", dev_name(ldev));
index 28baa05b8018dd6c6e6e1db93c1a5ceed74d4d74..84243c32e29c515381634b6e7b2cc6f4d219635b 100644 (file)
@@ -56,6 +56,12 @@ struct throttling_tstate {
        int target_state;               /* target T-state */
 };
 
+struct acpi_processor_throttling_arg {
+       struct acpi_processor *pr;
+       int target_state;
+       bool force;
+};
+
 #define THROTTLING_PRECHANGE       (1)
 #define THROTTLING_POSTCHANGE      (2)
 
@@ -1060,16 +1066,24 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
        return 0;
 }
 
+static long acpi_processor_throttling_fn(void *data)
+{
+       struct acpi_processor_throttling_arg *arg = data;
+       struct acpi_processor *pr = arg->pr;
+
+       return pr->throttling.acpi_processor_set_throttling(pr,
+                       arg->target_state, arg->force);
+}
+
 int acpi_processor_set_throttling(struct acpi_processor *pr,
                                                int state, bool force)
 {
-       cpumask_var_t saved_mask;
        int ret = 0;
        unsigned int i;
        struct acpi_processor *match_pr;
        struct acpi_processor_throttling *p_throttling;
+       struct acpi_processor_throttling_arg arg;
        struct throttling_tstate t_state;
-       cpumask_var_t online_throttling_cpus;
 
        if (!pr)
                return -EINVAL;
@@ -1080,14 +1094,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
        if ((state < 0) || (state > (pr->throttling.state_count - 1)))
                return -EINVAL;
 
-       if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
-               return -ENOMEM;
-
-       if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
-               free_cpumask_var(saved_mask);
-               return -ENOMEM;
-       }
-
        if (cpu_is_offline(pr->id)) {
                /*
                 * the cpu pointed by pr->id is offline. Unnecessary to change
@@ -1096,17 +1102,15 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
                return -ENODEV;
        }
 
-       cpumask_copy(saved_mask, &current->cpus_allowed);
        t_state.target_state = state;
        p_throttling = &(pr->throttling);
-       cpumask_and(online_throttling_cpus, cpu_online_mask,
-                   p_throttling->shared_cpu_map);
+
        /*
         * The throttling notifier will be called for every
         * affected cpu in order to get one proper T-state.
         * The notifier event is THROTTLING_PRECHANGE.
         */
-       for_each_cpu(i, online_throttling_cpus) {
+       for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
                t_state.cpu = i;
                acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
                                                        &t_state);
@@ -1118,21 +1122,18 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
         * it can be called only for the cpu pointed by pr.
         */
        if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
-               /* FIXME: use work_on_cpu() */
-               if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
-                       /* Can't migrate to the pr->id CPU. Exit */
-                       ret = -ENODEV;
-                       goto exit;
-               }
-               ret = p_throttling->acpi_processor_set_throttling(pr,
-                                               t_state.target_state, force);
+               arg.pr = pr;
+               arg.target_state = state;
+               arg.force = force;
+               ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg);
        } else {
                /*
                 * When the T-state coordination is SW_ALL or HW_ALL,
                 * it is necessary to set T-state for every affected
                 * cpus.
                 */
-               for_each_cpu(i, online_throttling_cpus) {
+               for_each_cpu_and(i, cpu_online_mask,
+                   p_throttling->shared_cpu_map) {
                        match_pr = per_cpu(processors, i);
                        /*
                         * If the pointer is invalid, we will report the
@@ -1153,13 +1154,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
                                        "on CPU %d\n", i));
                                continue;
                        }
-                       t_state.cpu = i;
-                       /* FIXME: use work_on_cpu() */
-                       if (set_cpus_allowed_ptr(current, cpumask_of(i)))
-                               continue;
-                       ret = match_pr->throttling.
-                               acpi_processor_set_throttling(
-                               match_pr, t_state.target_state, force);
+
+                       arg.pr = match_pr;
+                       arg.target_state = state;
+                       arg.force = force;
+                       ret = work_on_cpu(pr->id, acpi_processor_throttling_fn,
+                               &arg);
                }
        }
        /*
@@ -1168,17 +1168,12 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
         * affected cpu to update the T-states.
         * The notifier event is THROTTLING_POSTCHANGE
         */
-       for_each_cpu(i, online_throttling_cpus) {
+       for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
                t_state.cpu = i;
                acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
                                                        &t_state);
        }
-       /* restore the previous state */
-       /* FIXME: use work_on_cpu() */
-       set_cpus_allowed_ptr(current, saved_mask);
-exit:
-       free_cpumask_var(online_throttling_cpus);
-       free_cpumask_var(saved_mask);
+
        return ret;
 }
 
index b7201fc6f1e19c06c798889900c1e9c689494c8d..0bdacc5e26a3b9411b82a5fe4772c2c9f9b7d490 100644 (file)
@@ -77,18 +77,24 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
        switch (ares->type) {
        case ACPI_RESOURCE_TYPE_MEMORY24:
                memory24 = &ares->data.memory24;
+               if (!memory24->address_length)
+                       return false;
                acpi_dev_get_memresource(res, memory24->minimum,
                                         memory24->address_length,
                                         memory24->write_protect);
                break;
        case ACPI_RESOURCE_TYPE_MEMORY32:
                memory32 = &ares->data.memory32;
+               if (!memory32->address_length)
+                       return false;
                acpi_dev_get_memresource(res, memory32->minimum,
                                         memory32->address_length,
                                         memory32->write_protect);
                break;
        case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
                fixed_memory32 = &ares->data.fixed_memory32;
+               if (!fixed_memory32->address_length)
+                       return false;
                acpi_dev_get_memresource(res, fixed_memory32->address,
                                         fixed_memory32->address_length,
                                         fixed_memory32->write_protect);
@@ -144,12 +150,16 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
        switch (ares->type) {
        case ACPI_RESOURCE_TYPE_IO:
                io = &ares->data.io;
+               if (!io->address_length)
+                       return false;
                acpi_dev_get_ioresource(res, io->minimum,
                                        io->address_length,
                                        io->io_decode);
                break;
        case ACPI_RESOURCE_TYPE_FIXED_IO:
                fixed_io = &ares->data.fixed_io;
+               if (!fixed_io->address_length)
+                       return false;
                acpi_dev_get_ioresource(res, fixed_io->address,
                                        fixed_io->address_length,
                                        ACPI_DECODE_10);
index d465ae6cdd004b9813cc333529c54ef29abcb16f..dbd48498b93863a1fa37ab0b23706f2dae89345d 100644 (file)
@@ -450,7 +450,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
 {
        unsigned long x;
        struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
-       if (sscanf(buf, "%ld\n", &x) == 1)
+       if (sscanf(buf, "%lu\n", &x) == 1)
                battery->alarm_capacity = x /
                        (1000 * acpi_battery_scale(battery));
        if (battery->present)
@@ -668,6 +668,8 @@ static int acpi_sbs_resume(struct device *dev)
        acpi_sbs_callback(sbs);
        return 0;
 }
+#else
+#define acpi_sbs_resume NULL
 #endif
 
 static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
index 7384158c7f8770ddc4cd78d1570171a4cce9aae9..57b053f424d13e23ef2dd4b43a191c0d9dda09da 100644 (file)
@@ -484,7 +484,6 @@ static void acpi_device_hotplug(void *data, u32 src)
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-       struct acpi_scan_handler *handler = data;
        struct acpi_device *adev;
        acpi_status status;
 
@@ -500,7 +499,10 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
                break;
        case ACPI_NOTIFY_EJECT_REQUEST:
                acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-               if (!handler->hotplug.enabled) {
+               if (!adev->handler)
+                       goto err_out;
+
+               if (!adev->handler->hotplug.enabled) {
                        acpi_handle_err(handle, "Eject disabled\n");
                        ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
                        goto err_out;
index b718806657cdac29d9ccb3a1cad3fe6528865176..c40fb2e81bbc5d4ce9266174c0c2d7614755c644 100644 (file)
@@ -71,6 +71,17 @@ static int acpi_sleep_prepare(u32 acpi_state)
        return 0;
 }
 
+static bool acpi_sleep_state_supported(u8 sleep_state)
+{
+       acpi_status status;
+       u8 type_a, type_b;
+
+       status = acpi_get_sleep_type_data(sleep_state, &type_a, &type_b);
+       return ACPI_SUCCESS(status) && (!acpi_gbl_reduced_hardware
+               || (acpi_gbl_FADT.sleep_control.address
+                       && acpi_gbl_FADT.sleep_status.address));
+}
+
 #ifdef CONFIG_ACPI_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
 
@@ -604,15 +615,9 @@ static void acpi_sleep_suspend_setup(void)
 {
        int i;
 
-       for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) {
-               acpi_status status;
-               u8 type_a, type_b;
-
-               status = acpi_get_sleep_type_data(i, &type_a, &type_b);
-               if (ACPI_SUCCESS(status)) {
+       for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++)
+               if (acpi_sleep_state_supported(i))
                        sleep_states[i] = 1;
-               }
-       }
 
        suspend_set_ops(old_suspend_ordering ?
                &acpi_suspend_ops_old : &acpi_suspend_ops);
@@ -740,11 +745,7 @@ static const struct platform_hibernation_ops acpi_hibernation_ops_old = {
 
 static void acpi_sleep_hibernate_setup(void)
 {
-       acpi_status status;
-       u8 type_a, type_b;
-
-       status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b);
-       if (ACPI_FAILURE(status))
+       if (!acpi_sleep_state_supported(ACPI_STATE_S4))
                return;
 
        hibernation_set_ops(old_suspend_ordering ?
@@ -793,8 +794,6 @@ static void acpi_power_off(void)
 
 int __init acpi_sleep_init(void)
 {
-       acpi_status status;
-       u8 type_a, type_b;
        char supported[ACPI_S_STATE_COUNT * 3 + 1];
        char *pos = supported;
        int i;
@@ -806,8 +805,7 @@ int __init acpi_sleep_init(void)
        acpi_sleep_suspend_setup();
        acpi_sleep_hibernate_setup();
 
-       status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
-       if (ACPI_SUCCESS(status)) {
+       if (acpi_sleep_state_supported(ACPI_STATE_S5)) {
                sleep_states[ACPI_STATE_S5] = 1;
                pm_power_off_prepare = acpi_power_off_prepare;
                pm_power_off = acpi_power_off;
index 8349a555b92b8aa6d6584f9c2c5c9ccf7a27737f..08626c851be7eef72c5a639522b708586736adc5 100644 (file)
@@ -102,6 +102,8 @@ MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
 
 #ifdef CONFIG_PM_SLEEP
 static int acpi_thermal_resume(struct device *dev);
+#else
+#define acpi_thermal_resume NULL
 #endif
 static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
 
index 0347a37eb4389dcbd5c497ca6833e867618acbf5..85e3b612bdc0d49f7df07d056b0d9c14f8aca89e 100644 (file)
@@ -99,10 +99,6 @@ acpi_extract_package(union acpi_object *package,
 
                union acpi_object *element = &(package->package.elements[i]);
 
-               if (!element) {
-                       return AE_BAD_DATA;
-               }
-
                switch (element->type) {
 
                case ACPI_TYPE_INTEGER:
index b727d105046d234ae8ef2a5669e53e61b82e7123..b6ba88ed31aeeb1854e48bb73b95fc59a4d58706 100644 (file)
@@ -81,11 +81,12 @@ static bool allow_duplicates;
 module_param(allow_duplicates, bool, 0644);
 
 /*
- * For Windows 8 systems: if set ture and the GPU driver has
- * registered a backlight interface, skip registering ACPI video's.
+ * For Windows 8 systems: used to decide if video module
+ * should skip registering backlight interface of its own.
  */
-static bool use_native_backlight = false;
-module_param(use_native_backlight, bool, 0644);
+static int use_native_backlight_param = -1;
+module_param_named(use_native_backlight, use_native_backlight_param, int, 0444);
+static bool use_native_backlight_dmi = false;
 
 static int register_count;
 static struct mutex video_list_lock;
@@ -231,9 +232,17 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
                                         int event);
 
+static bool acpi_video_use_native_backlight(void)
+{
+       if (use_native_backlight_param != -1)
+               return use_native_backlight_param;
+       else
+               return use_native_backlight_dmi;
+}
+
 static bool acpi_video_verify_backlight_support(void)
 {
-       if (acpi_osi_is_win8() && use_native_backlight &&
+       if (acpi_osi_is_win8() && acpi_video_use_native_backlight() &&
            backlight_device_registered(BACKLIGHT_RAW))
                return false;
        return acpi_video_backlight_support();
@@ -398,6 +407,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d)
        return 0;
 }
 
+static int __init video_set_use_native_backlight(const struct dmi_system_id *d)
+{
+       use_native_backlight_dmi = true;
+       return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] __initdata = {
        /*
         * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -442,6 +457,120 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
                },
        },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "ThinkPad T430s",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "ThinkPad X230",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "ThinkPad X1 Carbon",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Lenovo Yoga 13",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Dell Inspiron 7520",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Acer Aspire 5733Z",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
+               },
+       },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Acer Aspire V5-431",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ProBook 4340s",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ProBook 2013 models",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "),
+               DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP EliteBook 2013 models",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "),
+               DMI_MATCH(DMI_PRODUCT_NAME, " G1"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ZBook 14",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ZBook 15",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP ZBook 17",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"),
+               },
+       },
+       {
+       .callback = video_set_use_native_backlight,
+       .ident = "HP EliteBook 8780w",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
+               },
+       },
        {}
 };
 
@@ -685,6 +814,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
        union acpi_object *o;
        struct acpi_video_device_brightness *br = NULL;
        int result = -EINVAL;
+       u32 value;
 
        if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -715,7 +845,12 @@ acpi_video_init_brightness(struct acpi_video_device *device)
                        printk(KERN_ERR PREFIX "Invalid data\n");
                        continue;
                }
-               br->levels[count] = (u32) o->integer.value;
+               value = (u32) o->integer.value;
+               /* Skip duplicate entries */
+               if (count > 2 && br->levels[count - 1] == value)
+                       continue;
+
+               br->levels[count] = value;
 
                if (br->levels[count] > max_level)
                        max_level = br->levels[count];
index f0447d3daf2c433fce6ad97a981c378a2d8c38ae..19080c8e2f2a9c6d5df7f5475d581f5348ed9e8e 100644 (file)
@@ -168,14 +168,6 @@ static struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
                },
        },
-       {
-       .callback = video_detect_force_vendor,
-       .ident = "Lenovo Yoga 13",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-               DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
-               },
-       },
        { },
 };
 
index 4e737728aee207a5d644d6fa0d39b0e3c402bd47..20e03a7eb8b431f692e534f6a3d895a2c2cd9476 100644 (file)
@@ -11,13 +11,13 @@ config HAVE_PATA_PLATFORM
          to update the PATA_PLATFORM entry.
 
 menuconfig ATA
-       tristate "Serial ATA and Parallel ATA drivers"
+       tristate "Serial ATA and Parallel ATA drivers (libata)"
        depends on HAS_IOMEM
        depends on BLOCK
        depends on !(M32R || M68K || S390) || BROKEN
        select SCSI
        ---help---
-         If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or
+         If you want to use an ATA hard disk, ATA tape drive, ATA CD-ROM or
          any other ATA device under Linux, say Y and make sure that you know
          the name of your ATA host adapter (the card inside your computer
          that "speaks" the ATA protocol, also called ATA controller),
@@ -60,7 +60,7 @@ config ATA_ACPI
 
 config SATA_ZPODD
        bool "SATA Zero Power Optical Disc Drive (ZPODD) support"
-       depends on ATA_ACPI
+       depends on ATA_ACPI && PM_RUNTIME
        default n
        help
          This option adds support for SATA Zero Power Optical Disc
@@ -97,15 +97,48 @@ config SATA_AHCI_PLATFORM
 
          If unsure, say N.
 
+config AHCI_DA850
+       tristate "DaVinci DA850 AHCI SATA support"
+       depends on ARCH_DAVINCI_DA850
+       help
+         This option enables support for the DaVinci DA850 SoC's
+         onboard AHCI SATA.
+
+         If unsure, say N.
+
+config AHCI_ST
+       tristate "ST AHCI SATA support"
+       depends on ARCH_STI
+       help
+         This option enables support for ST AHCI SATA controller.
+
+         If unsure, say N.
+
 config AHCI_IMX
        tristate "Freescale i.MX AHCI SATA support"
-       depends on SATA_AHCI_PLATFORM && MFD_SYSCON
+       depends on MFD_SYSCON
        help
          This option enables support for the Freescale i.MX SoC's
          onboard AHCI SATA.
 
          If unsure, say N.
 
+config AHCI_SUNXI
+       tristate "Allwinner sunxi AHCI SATA support"
+       depends on ARCH_SUNXI
+       help
+         This option enables support for the Allwinner sunxi SoC's
+         onboard AHCI SATA.
+
+         If unsure, say N.
+
+config AHCI_XGENE
+       tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support"
+       depends on ARM64 || COMPILE_TEST
+       select PHY_XGENE
+       help
+        This option enables support for APM X-Gene SoC SATA host controller.
+
 config SATA_FSL
        tristate "Freescale 3.0Gbps SATA support"
        depends on FSL_SOC
@@ -239,6 +272,7 @@ config SATA_DWC_VDEBUG
 
 config SATA_HIGHBANK
        tristate "Calxeda Highbank SATA support"
+       depends on ARCH_HIGHBANK || COMPILE_TEST
        help
          This option enables support for the Calxeda Highbank SoC's
          onboard SATA.
@@ -247,6 +281,9 @@ config SATA_HIGHBANK
 
 config SATA_MV
        tristate "Marvell SATA support"
+       depends on PCI || ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \
+                  ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST
+       select GENERIC_PHY
        help
          This option enables support for the Marvell Serial ATA family.
          Currently supports 88SX[56]0[48][01] PCI(-X) chips,
@@ -272,6 +309,7 @@ config SATA_PROMISE
 
 config SATA_RCAR
        tristate "Renesas R-Car SATA support"
+       depends on ARCH_SHMOBILE || COMPILE_TEST
        help
          This option enables support for Renesas R-Car Serial ATA.
 
@@ -351,6 +389,7 @@ config PATA_AMD
 
 config PATA_ARASAN_CF
        tristate "ARASAN CompactFlash PATA Controller Support"
+       depends on ARCH_SPEAR13XX || COMPILE_TEST
        depends on DMADEVICES
        select DMA_ENGINE
        help
@@ -402,7 +441,7 @@ config PATA_CMD64X
 
 config PATA_CS5520
        tristate "CS5510/5520 PATA support"
-       depends on PCI
+       depends on PCI && (X86_32 || COMPILE_TEST)
        help
          This option enables support for the Cyrix 5510/5520
          companion chip used with the MediaGX/Geode processor family.
@@ -411,7 +450,7 @@ config PATA_CS5520
 
 config PATA_CS5530
        tristate "CS5530 PATA support"
-       depends on PCI
+       depends on PCI && (X86_32 || COMPILE_TEST)
        help
          This option enables support for the Cyrix/NatSemi/AMD CS5530
          companion chip used with the MediaGX/Geode processor family.
@@ -420,7 +459,7 @@ config PATA_CS5530
 
 config PATA_CS5535
        tristate "CS5535 PATA support (Experimental)"
-       depends on PCI && X86 && !X86_64
+       depends on PCI && X86_32
        help
          This option enables support for the NatSemi/AMD CS5535
          companion chip used with the Geode processor family.
@@ -429,7 +468,7 @@ config PATA_CS5535
 
 config PATA_CS5536
        tristate "CS5536 PATA support"
-       depends on PCI
+       depends on PCI && (X86_32 || MIPS || COMPILE_TEST)
        help
          This option enables support for the AMD CS5536
          companion chip used with the Geode LX processor family.
@@ -665,7 +704,7 @@ config PATA_RDC
 
 config PATA_SC1200
        tristate "SC1200 PATA support"
-       depends on PCI
+       depends on PCI && (X86_32 || COMPILE_TEST)
        help
          This option enables support for the NatSemi/AMD SC1200 SoC
          companion chip used with the Geode processor family.
index 46518c622460942cdf8e2971dd95f3b069961ada..44c8016e565c9b8771924fbc7f7b5a00d9c078c7 100644 (file)
@@ -4,13 +4,17 @@ obj-$(CONFIG_ATA)             += libata.o
 # non-SFF interface
 obj-$(CONFIG_SATA_AHCI)                += ahci.o libahci.o
 obj-$(CONFIG_SATA_ACARD_AHCI)  += acard-ahci.o libahci.o
-obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
+obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
 obj-$(CONFIG_SATA_FSL)         += sata_fsl.o
 obj-$(CONFIG_SATA_INIC162X)    += sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)       += sata_sil24.o
 obj-$(CONFIG_SATA_DWC)         += sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)    += sata_highbank.o libahci.o
-obj-$(CONFIG_AHCI_IMX)         += ahci_imx.o
+obj-$(CONFIG_AHCI_DA850)       += ahci_da850.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_IMX)         += ahci_imx.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_SUNXI)       += ahci_sunxi.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_ST)          += ahci_st.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_XGENE)       += ahci_xgene.o libahci.o libahci_platform.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)         += pdc_adma.o
index fd665d919df2e59a4b44c334bd9c96d14fd946b5..b51605ac597418f7aa352789dc9aeeb1b8ca015b 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index dc2756fb6f3369b95cdb015fb8b32f97ff64d887..a52a5b662f35ecceb992fd41943ef5f636834838 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -61,6 +60,7 @@ enum board_ids {
        /* board IDs by feature in alphabetical order */
        board_ahci,
        board_ahci_ign_iferr,
+       board_ahci_noncq,
        board_ahci_nosntf,
        board_ahci_yes_fbs,
 
@@ -121,6 +121,13 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
+       [board_ahci_noncq] = {
+               AHCI_HFLAGS     (AHCI_HFLAG_NO_NCQ),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
        [board_ahci_nosntf] = {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_SNTF),
                .flags          = AHCI_FLAG_COMMON,
@@ -452,6 +459,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },   /* ASM1061 */
        { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
+       /*
+        * Samsung SSDs found on some macbooks.  NCQ times out.
+        * https://bugzilla.kernel.org/show_bug.cgi?id=60731
+        */
+       { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq },
+
        /* Enmotus */
        { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
 
@@ -564,6 +577,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
                                 unsigned long deadline)
 {
        struct ata_port *ap = link->ap;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        bool online;
        int rc;
 
@@ -574,7 +588,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
        rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
                                 deadline, &online, NULL);
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 
        DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
 
@@ -589,6 +603,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
 {
        struct ata_port *ap = link->ap;
        struct ahci_port_priv *pp = ap->private_data;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
        struct ata_taskfile tf;
        bool online;
@@ -604,7 +619,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
        rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
                                 deadline, &online, NULL);
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 
        /* The pseudo configuration device on SIMG4726 attached to
         * ASUS P5W-DH Deluxe doesn't send signature FIS after
@@ -1170,8 +1185,10 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
 
        nvec = rc;
        rc = pci_enable_msi_block(pdev, nvec);
-       if (rc)
+       if (rc < 0)
                goto intx;
+       else if (rc > 0)
+               goto single_msi;
 
        return nvec;
 
index 2289efdf82030e388ce977957eeb5b26f26f19d2..51af275b3388541baad3f7bf021a098de9da9bf0 100644 (file)
@@ -37,6 +37,8 @@
 
 #include <linux/clk.h>
 #include <linux/libata.h>
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
 
 /* Enclosure Management Control */
 #define EM_CTRL_MSG_TYPE              0x000f0000
@@ -51,6 +53,7 @@
 
 enum {
        AHCI_MAX_PORTS          = 32,
+       AHCI_MAX_CLKS           = 3,
        AHCI_MAX_SG             = 168, /* hardware max is 64K */
        AHCI_DMA_BOUNDARY       = 0xffffffff,
        AHCI_MAX_CMDS           = 32,
@@ -321,8 +324,17 @@ struct ahci_host_priv {
        u32                     em_loc; /* enclosure management location */
        u32                     em_buf_sz;      /* EM buffer size in byte */
        u32                     em_msg_type;    /* EM message type */
-       struct clk              *clk;           /* Only for platforms supporting clk */
+       bool                    got_runtime_pm; /* Did we do pm_runtime_get? */
+       struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
+       struct regulator        *target_pwr;    /* Optional */
+       struct phy              *phy;           /* If platform uses phy */
        void                    *plat_data;     /* Other platform data */
+       /*
+        * Optional ahci_start_engine override, if not set this gets set to the
+        * default ahci_start_engine during ahci_save_initial_config, this can
+        * be overridden anytime before the host is activated.
+        */
+       void                    (*start_engine)(struct ata_port *ap);
 };
 
 extern int ahci_ignore_sss;
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
new file mode 100644 (file)
index 0000000..2c83613
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * DaVinci DA850 AHCI SATA platform driver
+ *
+ * This program is free software; you can redistribute 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/libata.h>
+#include <linux/ahci_platform.h>
+#include "ahci.h"
+
+/* SATA PHY Control Register offset from AHCI base */
+#define SATA_P0PHYCR_REG       0x178
+
+#define SATA_PHY_MPY(x)                ((x) << 0)
+#define SATA_PHY_LOS(x)                ((x) << 6)
+#define SATA_PHY_RXCDR(x)      ((x) << 10)
+#define SATA_PHY_RXEQ(x)       ((x) << 13)
+#define SATA_PHY_TXSWING(x)    ((x) << 19)
+#define SATA_PHY_ENPLL(x)      ((x) << 31)
+
+/*
+ * The multiplier needed for 1.5GHz PLL output.
+ *
+ * NOTE: This is currently hardcoded to be suitable for 100MHz crystal
+ * frequency (which is used by DA850 EVM board) and may need to be changed
+ * if you would like to use this driver on some other board.
+ */
+#define DA850_SATA_CLK_MULTIPLIER      7
+
+static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg,
+                           void __iomem *ahci_base)
+{
+       unsigned int val;
+
+       /* Enable SATA clock receiver */
+       val = readl(pwrdn_reg);
+       val &= ~BIT(0);
+       writel(val, pwrdn_reg);
+
+       val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) |
+             SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) |
+             SATA_PHY_ENPLL(1);
+
+       writel(val, ahci_base + SATA_P0PHYCR_REG);
+}
+
+static const struct ata_port_info ahci_da850_port_info = {
+       .flags          = AHCI_FLAG_COMMON,
+       .pio_mask       = ATA_PIO4,
+       .udma_mask      = ATA_UDMA6,
+       .port_ops       = &ahci_platform_ops,
+};
+
+static int ahci_da850_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ahci_host_priv *hpriv;
+       struct resource *res;
+       void __iomem *pwrdn_reg;
+       int rc;
+
+       hpriv = ahci_platform_get_resources(pdev);
+       if (IS_ERR(hpriv))
+               return PTR_ERR(hpriv);
+
+       rc = ahci_platform_enable_resources(hpriv);
+       if (rc)
+               return rc;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!res)
+               goto disable_resources;
+
+       pwrdn_reg = devm_ioremap(dev, res->start, resource_size(res));
+       if (!pwrdn_reg)
+               goto disable_resources;
+
+       da850_sata_init(dev, pwrdn_reg, hpriv->mmio);
+
+       rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, 0, 0);
+       if (rc)
+               goto disable_resources;
+
+       return 0;
+disable_resources:
+       ahci_platform_disable_resources(hpriv);
+       return rc;
+}
+
+static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend,
+                        ahci_platform_resume);
+
+static struct platform_driver ahci_da850_driver = {
+       .probe = ahci_da850_probe,
+       .remove = ata_platform_remove_one,
+       .driver = {
+               .name = "ahci_da850",
+               .owner = THIS_MODULE,
+               .pm = &ahci_da850_pm_ops,
+       },
+};
+module_platform_driver(ahci_da850_driver);
+
+MODULE_DESCRIPTION("DaVinci DA850 AHCI SATA platform driver");
+MODULE_AUTHOR("Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>");
+MODULE_LICENSE("GPL");
index dd4d6f74d7bd5067a62840019a53c016b74efd6e..497c7abe1c7df5ef79ccd246828b68a1251c5201 100644 (file)
@@ -42,13 +42,7 @@ enum ahci_imx_type {
 struct imx_ahci_priv {
        struct platform_device *ahci_pdev;
        enum ahci_imx_type type;
-
-       /* i.MX53 clock */
-       struct clk *sata_gate_clk;
-       /* Common clock */
-       struct clk *sata_ref_clk;
        struct clk *ahb_clk;
-
        struct regmap *gpr;
        bool no_device;
        bool first_time;
@@ -58,28 +52,52 @@ static int ahci_imx_hotplug;
 module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
 MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
 
-static int imx_sata_clock_enable(struct device *dev)
+static void ahci_imx_host_stop(struct ata_host *host);
+
+static int imx_sata_enable(struct ahci_host_priv *hpriv)
 {
-       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+       struct imx_ahci_priv *imxpriv = hpriv->plat_data;
        int ret;
 
-       if (imxpriv->type == AHCI_IMX53) {
-               ret = clk_prepare_enable(imxpriv->sata_gate_clk);
-               if (ret < 0) {
-                       dev_err(dev, "prepare-enable sata_gate clock err:%d\n",
-                               ret);
+       if (imxpriv->no_device)
+               return 0;
+
+       if (hpriv->target_pwr) {
+               ret = regulator_enable(hpriv->target_pwr);
+               if (ret)
                        return ret;
-               }
        }
 
-       ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-       if (ret < 0) {
-               dev_err(dev, "prepare-enable sata_ref clock err:%d\n",
-                       ret);
-               goto clk_err;
-       }
+       ret = ahci_platform_enable_clks(hpriv);
+       if (ret < 0)
+               goto disable_regulator;
 
        if (imxpriv->type == AHCI_IMX6Q) {
+               /*
+                * set PHY Paremeters, two steps to configure the GPR13,
+                * one write for rest of parameters, mask of first write
+                * is 0x07ffffff, and the other one write for setting
+                * the mpll_clk_en.
+                */
+               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+                                  IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
+                                  IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
+                                  IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
+                                  IMX6Q_GPR13_SATA_SPD_MODE_MASK |
+                                  IMX6Q_GPR13_SATA_MPLL_SS_EN |
+                                  IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
+                                  IMX6Q_GPR13_SATA_TX_BOOST_MASK |
+                                  IMX6Q_GPR13_SATA_TX_LVL_MASK |
+                                  IMX6Q_GPR13_SATA_MPLL_CLK_EN |
+                                  IMX6Q_GPR13_SATA_TX_EDGE_RATE,
+                                  IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
+                                  IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+                                  IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+                                  IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+                                  IMX6Q_GPR13_SATA_MPLL_SS_EN |
+                                  IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
+                                  IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
+                                  IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -89,15 +107,19 @@ static int imx_sata_clock_enable(struct device *dev)
 
        return 0;
 
-clk_err:
-       if (imxpriv->type == AHCI_IMX53)
-               clk_disable_unprepare(imxpriv->sata_gate_clk);
+disable_regulator:
+       if (hpriv->target_pwr)
+               regulator_disable(hpriv->target_pwr);
+
        return ret;
 }
 
-static void imx_sata_clock_disable(struct device *dev)
+static void imx_sata_disable(struct ahci_host_priv *hpriv)
 {
-       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+       struct imx_ahci_priv *imxpriv = hpriv->plat_data;
+
+       if (imxpriv->no_device)
+               return;
 
        if (imxpriv->type == AHCI_IMX6Q) {
                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
@@ -105,10 +127,10 @@ static void imx_sata_clock_disable(struct device *dev)
                                   !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
        }
 
-       clk_disable_unprepare(imxpriv->sata_ref_clk);
+       ahci_platform_disable_clks(hpriv);
 
-       if (imxpriv->type == AHCI_IMX53)
-               clk_disable_unprepare(imxpriv->sata_gate_clk);
+       if (hpriv->target_pwr)
+               regulator_disable(hpriv->target_pwr);
 }
 
 static void ahci_imx_error_handler(struct ata_port *ap)
@@ -118,7 +140,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
        struct ata_host *host = dev_get_drvdata(ap->dev);
        struct ahci_host_priv *hpriv = host->private_data;
        void __iomem *mmio = hpriv->mmio;
-       struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+       struct imx_ahci_priv *imxpriv = hpriv->plat_data;
 
        ahci_error_handler(ap);
 
@@ -136,7 +158,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
         */
        reg_val = readl(mmio + PORT_PHY_CTL);
        writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
-       imx_sata_clock_disable(ap->dev);
+       imx_sata_disable(hpriv);
        imxpriv->no_device = true;
 }
 
@@ -144,7 +166,9 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
                       unsigned long deadline)
 {
        struct ata_port *ap = link->ap;
-       struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+       struct ata_host *host = dev_get_drvdata(ap->dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       struct imx_ahci_priv *imxpriv = hpriv->plat_data;
        int ret = -EIO;
 
        if (imxpriv->type == AHCI_IMX53)
@@ -156,7 +180,8 @@ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
 }
 
 static struct ata_port_operations ahci_imx_ops = {
-       .inherits       = &ahci_platform_ops,
+       .inherits       = &ahci_ops,
+       .host_stop      = ahci_imx_host_stop,
        .error_handler  = ahci_imx_error_handler,
        .softreset      = ahci_imx_softreset,
 };
@@ -168,79 +193,6 @@ static const struct ata_port_info ahci_imx_port_info = {
        .port_ops       = &ahci_imx_ops,
 };
 
-static int imx_sata_init(struct device *dev, void __iomem *mmio)
-{
-       int ret = 0;
-       unsigned int reg_val;
-       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
-
-       ret = imx_sata_clock_enable(dev);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
-        * and IP vendor specific register HOST_TIMER1MS.
-        * Configure CAP_SSS (support stagered spin up).
-        * Implement the port0.
-        * Get the ahb clock rate, and configure the TIMER1MS register.
-        */
-       reg_val = readl(mmio + HOST_CAP);
-       if (!(reg_val & HOST_CAP_SSS)) {
-               reg_val |= HOST_CAP_SSS;
-               writel(reg_val, mmio + HOST_CAP);
-       }
-       reg_val = readl(mmio + HOST_PORTS_IMPL);
-       if (!(reg_val & 0x1)) {
-               reg_val |= 0x1;
-               writel(reg_val, mmio + HOST_PORTS_IMPL);
-       }
-
-       reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
-       writel(reg_val, mmio + HOST_TIMER1MS);
-
-       return 0;
-}
-
-static void imx_sata_exit(struct device *dev)
-{
-       imx_sata_clock_disable(dev);
-}
-
-static int imx_ahci_suspend(struct device *dev)
-{
-       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-
-       /*
-        * If no_device is set, The CLKs had been gated off in the
-        * initialization so don't do it again here.
-        */
-       if (!imxpriv->no_device)
-               imx_sata_clock_disable(dev);
-
-       return 0;
-}
-
-static int imx_ahci_resume(struct device *dev)
-{
-       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-       int ret = 0;
-
-       if (!imxpriv->no_device)
-               ret = imx_sata_clock_enable(dev);
-
-       return ret;
-}
-
-static struct ahci_platform_data imx_sata_pdata = {
-       .init           = imx_sata_init,
-       .exit           = imx_sata_exit,
-       .ata_port_info  = &ahci_imx_port_info,
-       .suspend        = imx_ahci_suspend,
-       .resume         = imx_ahci_resume,
-
-};
-
 static const struct of_device_id imx_ahci_of_match[] = {
        { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
        { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
@@ -251,151 +203,124 @@ MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
 static int imx_ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct resource *mem, *irq, res[2];
        const struct of_device_id *of_id;
-       enum ahci_imx_type type;
-       const struct ahci_platform_data *pdata = NULL;
+       struct ahci_host_priv *hpriv;
        struct imx_ahci_priv *imxpriv;
-       struct device *ahci_dev;
-       struct platform_device *ahci_pdev;
+       unsigned int reg_val;
        int ret;
 
        of_id = of_match_device(imx_ahci_of_match, dev);
        if (!of_id)
                return -EINVAL;
 
-       type = (enum ahci_imx_type)of_id->data;
-       pdata = &imx_sata_pdata;
-
        imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
-       if (!imxpriv) {
-               dev_err(dev, "can't alloc ahci_host_priv\n");
+       if (!imxpriv)
                return -ENOMEM;
-       }
-
-       ahci_pdev = platform_device_alloc("ahci", -1);
-       if (!ahci_pdev)
-               return -ENODEV;
-
-       ahci_dev = &ahci_pdev->dev;
-       ahci_dev->parent = dev;
 
        imxpriv->no_device = false;
        imxpriv->first_time = true;
-       imxpriv->type = type;
-
+       imxpriv->type = (enum ahci_imx_type)of_id->data;
        imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
        if (IS_ERR(imxpriv->ahb_clk)) {
                dev_err(dev, "can't get ahb clock.\n");
-               ret = PTR_ERR(imxpriv->ahb_clk);
-               goto err_out;
+               return PTR_ERR(imxpriv->ahb_clk);
        }
 
-       if (type == AHCI_IMX53) {
-               imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate");
-               if (IS_ERR(imxpriv->sata_gate_clk)) {
-                       dev_err(dev, "can't get sata_gate clock.\n");
-                       ret = PTR_ERR(imxpriv->sata_gate_clk);
-                       goto err_out;
+       if (imxpriv->type == AHCI_IMX6Q) {
+               imxpriv->gpr = syscon_regmap_lookup_by_compatible(
+                                                       "fsl,imx6q-iomuxc-gpr");
+               if (IS_ERR(imxpriv->gpr)) {
+                       dev_err(dev,
+                               "failed to find fsl,imx6q-iomux-gpr regmap\n");
+                       return PTR_ERR(imxpriv->gpr);
                }
        }
 
-       imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
-       if (IS_ERR(imxpriv->sata_ref_clk)) {
-               dev_err(dev, "can't get sata_ref clock.\n");
-               ret = PTR_ERR(imxpriv->sata_ref_clk);
-               goto err_out;
-       }
+       hpriv = ahci_platform_get_resources(pdev);
+       if (IS_ERR(hpriv))
+               return PTR_ERR(hpriv);
+
+       hpriv->plat_data = imxpriv;
 
-       imxpriv->ahci_pdev = ahci_pdev;
-       platform_set_drvdata(pdev, imxpriv);
+       ret = imx_sata_enable(hpriv);
+       if (ret)
+               return ret;
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!mem || !irq) {
-               dev_err(dev, "no mmio/irq resource\n");
-               ret = -ENOMEM;
-               goto err_out;
+       /*
+        * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
+        * and IP vendor specific register HOST_TIMER1MS.
+        * Configure CAP_SSS (support stagered spin up).
+        * Implement the port0.
+        * Get the ahb clock rate, and configure the TIMER1MS register.
+        */
+       reg_val = readl(hpriv->mmio + HOST_CAP);
+       if (!(reg_val & HOST_CAP_SSS)) {
+               reg_val |= HOST_CAP_SSS;
+               writel(reg_val, hpriv->mmio + HOST_CAP);
+       }
+       reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL);
+       if (!(reg_val & 0x1)) {
+               reg_val |= 0x1;
+               writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL);
        }
 
-       res[0] = *mem;
-       res[1] = *irq;
+       reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
+       writel(reg_val, hpriv->mmio + HOST_TIMER1MS);
 
-       ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
-       ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
-       ahci_dev->of_node = dev->of_node;
+       ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0);
+       if (ret)
+               imx_sata_disable(hpriv);
 
-       if (type == AHCI_IMX6Q) {
-               imxpriv->gpr = syscon_regmap_lookup_by_compatible(
-                                                       "fsl,imx6q-iomuxc-gpr");
-               if (IS_ERR(imxpriv->gpr)) {
-                       dev_err(dev,
-                               "failed to find fsl,imx6q-iomux-gpr regmap\n");
-                       ret = PTR_ERR(imxpriv->gpr);
-                       goto err_out;
-               }
+       return ret;
+}
 
-               /*
-                * Set PHY Paremeters, two steps to configure the GPR13,
-                * one write for rest of parameters, mask of first write
-                * is 0x07fffffe, and the other one write for setting
-                * the mpll_clk_en happens in imx_sata_clock_enable().
-                */
-               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
-                                  IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
-                                  IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
-                                  IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
-                                  IMX6Q_GPR13_SATA_SPD_MODE_MASK |
-                                  IMX6Q_GPR13_SATA_MPLL_SS_EN |
-                                  IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
-                                  IMX6Q_GPR13_SATA_TX_BOOST_MASK |
-                                  IMX6Q_GPR13_SATA_TX_LVL_MASK |
-                                  IMX6Q_GPR13_SATA_MPLL_CLK_EN |
-                                  IMX6Q_GPR13_SATA_TX_EDGE_RATE,
-                                  IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
-                                  IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
-                                  IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
-                                  IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
-                                  IMX6Q_GPR13_SATA_MPLL_SS_EN |
-                                  IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
-                                  IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
-                                  IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
-       }
+static void ahci_imx_host_stop(struct ata_host *host)
+{
+       struct ahci_host_priv *hpriv = host->private_data;
 
-       ret = platform_device_add_resources(ahci_pdev, res, 2);
-       if (ret)
-               goto err_out;
+       imx_sata_disable(hpriv);
+}
 
-       ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
-       if (ret)
-               goto err_out;
+#ifdef CONFIG_PM_SLEEP
+static int imx_ahci_suspend(struct device *dev)
+{
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       int ret;
 
-       ret = platform_device_add(ahci_pdev);
-       if (ret) {
-err_out:
-               platform_device_put(ahci_pdev);
+       ret = ahci_platform_suspend_host(dev);
+       if (ret)
                return ret;
-       }
+
+       imx_sata_disable(hpriv);
 
        return 0;
 }
 
-static int imx_ahci_remove(struct platform_device *pdev)
+static int imx_ahci_resume(struct device *dev)
 {
-       struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
-       struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       int ret;
 
-       platform_device_unregister(ahci_pdev);
-       return 0;
+       ret = imx_sata_enable(hpriv);
+       if (ret)
+               return ret;
+
+       return ahci_platform_resume_host(dev);
 }
+#endif
+
+static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
 
 static struct platform_driver imx_ahci_driver = {
        .probe = imx_ahci_probe,
-       .remove = imx_ahci_remove,
+       .remove = ata_platform_remove_one,
        .driver = {
                .name = "ahci-imx",
                .owner = THIS_MODULE,
                .of_match_table = imx_ahci_of_match,
+               .pm = &ahci_imx_pm_ops,
        },
 };
 module_platform_driver(imx_ahci_driver);
index 4b231baceb0995557c2cae40e501f6d3449dc365..ef67e79944f9962e3e32382dd43794404d866b01 100644 (file)
  * any later version.
  */
 
-#include <linux/clk.h>
 #include <linux/kernel.h>
-#include <linux/gfp.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/libata.h>
 #include <linux/ahci_platform.h>
 #include "ahci.h"
 
-static void ahci_host_stop(struct ata_host *host);
-
-enum ahci_type {
-       AHCI,           /* standard platform ahci */
-       IMX53_AHCI,     /* ahci on i.mx53 */
-       STRICT_AHCI,    /* delayed DMA engine start */
-};
-
-static struct platform_device_id ahci_devtype[] = {
-       {
-               .name = "ahci",
-               .driver_data = AHCI,
-       }, {
-               .name = "imx53-ahci",
-               .driver_data = IMX53_AHCI,
-       }, {
-               .name = "strict-ahci",
-               .driver_data = STRICT_AHCI,
-       }, {
-               /* sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(platform, ahci_devtype);
-
-struct ata_port_operations ahci_platform_ops = {
-       .inherits       = &ahci_ops,
-       .host_stop      = ahci_host_stop,
-};
-EXPORT_SYMBOL_GPL(ahci_platform_ops);
-
-static struct ata_port_operations ahci_platform_retry_srst_ops = {
-       .inherits       = &ahci_pmp_retry_srst_ops,
-       .host_stop      = ahci_host_stop,
-};
-
-static const struct ata_port_info ahci_port_info[] = {
-       /* by features */
-       [AHCI] = {
-               .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &ahci_platform_ops,
-       },
-       [IMX53_AHCI] = {
-               .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &ahci_platform_retry_srst_ops,
-       },
-       [STRICT_AHCI] = {
-               AHCI_HFLAGS     (AHCI_HFLAG_DELAY_ENGINE),
-               .flags          = AHCI_FLAG_COMMON,
-               .pio_mask       = ATA_PIO4,
-               .udma_mask      = ATA_UDMA6,
-               .port_ops       = &ahci_platform_ops,
-       },
-};
-
-static struct scsi_host_template ahci_platform_sht = {
-       AHCI_SHT("ahci_platform"),
+static const struct ata_port_info ahci_port_info = {
+       .flags          = AHCI_FLAG_COMMON,
+       .pio_mask       = ATA_PIO4,
+       .udma_mask      = ATA_UDMA6,
+       .port_ops       = &ahci_platform_ops,
 };
 
 static int ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
-       const struct platform_device_id *id = platform_get_device_id(pdev);
-       struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
-       const struct ata_port_info *ppi[] = { &pi, NULL };
        struct ahci_host_priv *hpriv;
-       struct ata_host *host;
-       struct resource *mem;
-       int irq;
-       int n_ports;
-       int i;
        int rc;
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(dev, "no mmio space\n");
-               return -EINVAL;
-       }
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq <= 0) {
-               dev_err(dev, "no irq\n");
-               return -EINVAL;
-       }
-
-       if (pdata && pdata->ata_port_info)
-               pi = *pdata->ata_port_info;
-
-       hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
-       if (!hpriv) {
-               dev_err(dev, "can't alloc ahci_host_priv\n");
-               return -ENOMEM;
-       }
-
-       hpriv->flags |= (unsigned long)pi.private_data;
-
-       hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
-       if (!hpriv->mmio) {
-               dev_err(dev, "can't map %pR\n", mem);
-               return -ENOMEM;
-       }
+       hpriv = ahci_platform_get_resources(pdev);
+       if (IS_ERR(hpriv))
+               return PTR_ERR(hpriv);
 
-       hpriv->clk = clk_get(dev, NULL);
-       if (IS_ERR(hpriv->clk)) {
-               dev_err(dev, "can't get clock\n");
-       } else {
-               rc = clk_prepare_enable(hpriv->clk);
-               if (rc) {
-                       dev_err(dev, "clock prepare enable failed");
-                       goto free_clk;
-               }
-       }
+       rc = ahci_platform_enable_resources(hpriv);
+       if (rc)
+               return rc;
 
        /*
         * Some platforms might need to prepare for mmio region access,
@@ -151,69 +52,10 @@ static int ahci_probe(struct platform_device *pdev)
        if (pdata && pdata->init) {
                rc = pdata->init(dev, hpriv->mmio);
                if (rc)
-                       goto disable_unprepare_clk;
-       }
-
-       ahci_save_initial_config(dev, hpriv,
-               pdata ? pdata->force_port_map : 0,
-               pdata ? pdata->mask_port_map  : 0);
-
-       /* prepare host */
-       if (hpriv->cap & HOST_CAP_NCQ)
-               pi.flags |= ATA_FLAG_NCQ;
-
-       if (hpriv->cap & HOST_CAP_PMP)
-               pi.flags |= ATA_FLAG_PMP;
-
-       ahci_set_em_messages(hpriv, &pi);
-
-       /* CAP.NP sometimes indicate the index of the last enabled
-        * port, at other times, that of the last possible port, so
-        * determining the maximum port number requires looking at
-        * both CAP.NP and port_map.
-        */
-       n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
-
-       host = ata_host_alloc_pinfo(dev, ppi, n_ports);
-       if (!host) {
-               rc = -ENOMEM;
-               goto pdata_exit;
-       }
-
-       host->private_data = hpriv;
-
-       if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
-               host->flags |= ATA_HOST_PARALLEL_SCAN;
-       else
-               dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
-
-       if (pi.flags & ATA_FLAG_EM)
-               ahci_reset_em(host);
-
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap = host->ports[i];
-
-               ata_port_desc(ap, "mmio %pR", mem);
-               ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
-
-               /* set enclosure management message type */
-               if (ap->flags & ATA_FLAG_EM)
-                       ap->em_message_type = hpriv->em_msg_type;
-
-               /* disabled/not-implemented port */
-               if (!(hpriv->port_map & (1 << i)))
-                       ap->ops = &ata_dummy_port_ops;
+                       goto disable_resources;
        }
 
-       rc = ahci_reset_controller(host);
-       if (rc)
-               goto pdata_exit;
-
-       ahci_init_controller(host);
-       ahci_print_info(host, "platform");
-
-       rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
-                              &ahci_platform_sht);
+       rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0);
        if (rc)
                goto pdata_exit;
 
@@ -221,115 +63,19 @@ static int ahci_probe(struct platform_device *pdev)
 pdata_exit:
        if (pdata && pdata->exit)
                pdata->exit(dev);
-disable_unprepare_clk:
-       if (!IS_ERR(hpriv->clk))
-               clk_disable_unprepare(hpriv->clk);
-free_clk:
-       if (!IS_ERR(hpriv->clk))
-               clk_put(hpriv->clk);
-       return rc;
-}
-
-static void ahci_host_stop(struct ata_host *host)
-{
-       struct device *dev = host->dev;
-       struct ahci_platform_data *pdata = dev_get_platdata(dev);
-       struct ahci_host_priv *hpriv = host->private_data;
-
-       if (pdata && pdata->exit)
-               pdata->exit(dev);
-
-       if (!IS_ERR(hpriv->clk)) {
-               clk_disable_unprepare(hpriv->clk);
-               clk_put(hpriv->clk);
-       }
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int ahci_suspend(struct device *dev)
-{
-       struct ahci_platform_data *pdata = dev_get_platdata(dev);
-       struct ata_host *host = dev_get_drvdata(dev);
-       struct ahci_host_priv *hpriv = host->private_data;
-       void __iomem *mmio = hpriv->mmio;
-       u32 ctl;
-       int rc;
-
-       if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
-               dev_err(dev, "firmware update required for suspend/resume\n");
-               return -EIO;
-       }
-
-       /*
-        * AHCI spec rev1.1 section 8.3.3:
-        * Software must disable interrupts prior to requesting a
-        * transition of the HBA to D3 state.
-        */
-       ctl = readl(mmio + HOST_CTL);
-       ctl &= ~HOST_IRQ_EN;
-       writel(ctl, mmio + HOST_CTL);
-       readl(mmio + HOST_CTL); /* flush */
-
-       rc = ata_host_suspend(host, PMSG_SUSPEND);
-       if (rc)
-               return rc;
-
-       if (pdata && pdata->suspend)
-               return pdata->suspend(dev);
-
-       if (!IS_ERR(hpriv->clk))
-               clk_disable_unprepare(hpriv->clk);
-
-       return 0;
-}
-
-static int ahci_resume(struct device *dev)
-{
-       struct ahci_platform_data *pdata = dev_get_platdata(dev);
-       struct ata_host *host = dev_get_drvdata(dev);
-       struct ahci_host_priv *hpriv = host->private_data;
-       int rc;
-
-       if (!IS_ERR(hpriv->clk)) {
-               rc = clk_prepare_enable(hpriv->clk);
-               if (rc) {
-                       dev_err(dev, "clock prepare enable failed");
-                       return rc;
-               }
-       }
-
-       if (pdata && pdata->resume) {
-               rc = pdata->resume(dev);
-               if (rc)
-                       goto disable_unprepare_clk;
-       }
-
-       if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
-               rc = ahci_reset_controller(host);
-               if (rc)
-                       goto disable_unprepare_clk;
-
-               ahci_init_controller(host);
-       }
-
-       ata_host_resume(host);
-
-       return 0;
-
-disable_unprepare_clk:
-       if (!IS_ERR(hpriv->clk))
-               clk_disable_unprepare(hpriv->clk);
-
+disable_resources:
+       ahci_platform_disable_resources(hpriv);
        return rc;
 }
-#endif
 
-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
+                        ahci_platform_resume);
 
 static const struct of_device_id ahci_of_match[] = {
        { .compatible = "snps,spear-ahci", },
        { .compatible = "snps,exynos5440-ahci", },
        { .compatible = "ibm,476gtr-ahci", },
+       { .compatible = "snps,dwc-ahci", },
        {},
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
@@ -343,7 +89,6 @@ static struct platform_driver ahci_driver = {
                .of_match_table = ahci_of_match,
                .pm = &ahci_pm_ops,
        },
-       .id_table       = ahci_devtype,
 };
 module_platform_driver(ahci_driver);
 
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
new file mode 100644 (file)
index 0000000..6332222
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2012 STMicroelectronics Limited
+ *
+ * Authors: Francesco Virlinzi <francesco.virlinzi@st.com>
+ *         Alexandre Torgue <alexandre.torgue@st.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/init.h>
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/ahci_platform.h>
+#include <linux/libata.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ahci.h"
+
+#define ST_AHCI_OOBR                   0xbc
+#define ST_AHCI_OOBR_WE                        BIT(31)
+#define ST_AHCI_OOBR_CWMIN_SHIFT       24
+#define ST_AHCI_OOBR_CWMAX_SHIFT       16
+#define ST_AHCI_OOBR_CIMIN_SHIFT       8
+#define ST_AHCI_OOBR_CIMAX_SHIFT       0
+
+struct st_ahci_drv_data {
+       struct platform_device *ahci;
+       struct reset_control *pwr;
+       struct reset_control *sw_rst;
+       struct reset_control *pwr_rst;
+       struct ahci_host_priv *hpriv;
+};
+
+static void st_ahci_configure_oob(void __iomem *mmio)
+{
+       unsigned long old_val, new_val;
+
+       new_val = (0x02 << ST_AHCI_OOBR_CWMIN_SHIFT) |
+                 (0x04 << ST_AHCI_OOBR_CWMAX_SHIFT) |
+                 (0x08 << ST_AHCI_OOBR_CIMIN_SHIFT) |
+                 (0x0C << ST_AHCI_OOBR_CIMAX_SHIFT);
+
+       old_val = readl(mmio + ST_AHCI_OOBR);
+       writel(old_val | ST_AHCI_OOBR_WE, mmio + ST_AHCI_OOBR);
+       writel(new_val | ST_AHCI_OOBR_WE, mmio + ST_AHCI_OOBR);
+       writel(new_val, mmio + ST_AHCI_OOBR);
+}
+
+static int st_ahci_deassert_resets(struct device *dev)
+{
+       struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
+       int err;
+
+       if (drv_data->pwr) {
+               err = reset_control_deassert(drv_data->pwr);
+               if (err) {
+                       dev_err(dev, "unable to bring out of pwrdwn\n");
+                       return err;
+               }
+       }
+
+       st_ahci_configure_oob(drv_data->hpriv->mmio);
+
+       if (drv_data->sw_rst) {
+               err = reset_control_deassert(drv_data->sw_rst);
+               if (err) {
+                       dev_err(dev, "unable to bring out of sw-rst\n");
+                       return err;
+               }
+       }
+
+       if (drv_data->pwr_rst) {
+               err = reset_control_deassert(drv_data->pwr_rst);
+               if (err) {
+                       dev_err(dev, "unable to bring out of pwr-rst\n");
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static void st_ahci_host_stop(struct ata_host *host)
+{
+       struct ahci_host_priv *hpriv = host->private_data;
+       struct device *dev = host->dev;
+       struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
+       int err;
+
+       if (drv_data->pwr) {
+               err = reset_control_assert(drv_data->pwr);
+               if (err)
+                       dev_err(dev, "unable to pwrdwn\n");
+       }
+
+       ahci_platform_disable_resources(hpriv);
+}
+
+static int st_ahci_probe_resets(struct platform_device *pdev)
+{
+       struct st_ahci_drv_data *drv_data = platform_get_drvdata(pdev);
+
+       drv_data->pwr = devm_reset_control_get(&pdev->dev, "pwr-dwn");
+       if (IS_ERR(drv_data->pwr)) {
+               dev_info(&pdev->dev, "power reset control not defined\n");
+               drv_data->pwr = NULL;
+       }
+
+       drv_data->sw_rst = devm_reset_control_get(&pdev->dev, "sw-rst");
+       if (IS_ERR(drv_data->sw_rst)) {
+               dev_info(&pdev->dev, "soft reset control not defined\n");
+               drv_data->sw_rst = NULL;
+       }
+
+       drv_data->pwr_rst = devm_reset_control_get(&pdev->dev, "pwr-rst");
+       if (IS_ERR(drv_data->pwr_rst)) {
+               dev_dbg(&pdev->dev, "power soft reset control not defined\n");
+               drv_data->pwr_rst = NULL;
+       }
+
+       return st_ahci_deassert_resets(&pdev->dev);
+}
+
+static struct ata_port_operations st_ahci_port_ops = {
+       .inherits       = &ahci_platform_ops,
+       .host_stop      = st_ahci_host_stop,
+};
+
+static const struct ata_port_info st_ahci_port_info = {
+       .flags          = AHCI_FLAG_COMMON,
+       .pio_mask       = ATA_PIO4,
+       .udma_mask      = ATA_UDMA6,
+       .port_ops       = &st_ahci_port_ops,
+};
+
+static int st_ahci_probe(struct platform_device *pdev)
+{
+       struct st_ahci_drv_data *drv_data;
+       struct ahci_host_priv *hpriv;
+       int err;
+
+       drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL);
+       if (!drv_data)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, drv_data);
+
+       hpriv = ahci_platform_get_resources(pdev);
+       if (IS_ERR(hpriv))
+               return PTR_ERR(hpriv);
+
+       drv_data->hpriv = hpriv;
+
+       err = st_ahci_probe_resets(pdev);
+       if (err)
+               return err;
+
+       err = ahci_platform_enable_resources(hpriv);
+       if (err)
+               return err;
+
+       err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 0, 0);
+       if (err) {
+               ahci_platform_disable_resources(hpriv);
+               return err;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int st_ahci_suspend(struct device *dev)
+{
+       struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = drv_data->hpriv;
+       int err;
+
+       err = ahci_platform_suspend_host(dev);
+       if (err)
+               return err;
+
+       if (drv_data->pwr) {
+               err = reset_control_assert(drv_data->pwr);
+               if (err) {
+                       dev_err(dev, "unable to pwrdwn");
+                       return err;
+               }
+       }
+
+       ahci_platform_disable_resources(hpriv);
+
+       return 0;
+}
+
+static int st_ahci_resume(struct device *dev)
+{
+       struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = drv_data->hpriv;
+       int err;
+
+       err = ahci_platform_enable_resources(hpriv);
+       if (err)
+               return err;
+
+       err = st_ahci_deassert_resets(dev);
+       if (err) {
+               ahci_platform_disable_resources(hpriv);
+               return err;
+       }
+
+       return ahci_platform_resume_host(dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(st_ahci_pm_ops, st_ahci_suspend, st_ahci_resume);
+
+static struct of_device_id st_ahci_match[] = {
+       { .compatible = "st,ahci", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, st_ahci_match);
+
+static struct platform_driver st_ahci_driver = {
+       .driver = {
+               .name = "st_ahci",
+               .owner = THIS_MODULE,
+               .pm = &st_ahci_pm_ops,
+               .of_match_table = of_match_ptr(st_ahci_match),
+       },
+       .probe = st_ahci_probe,
+       .remove = ata_platform_remove_one,
+};
+module_platform_driver(st_ahci_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_AUTHOR("Francesco Virlinzi <francesco.virlinzi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics SATA AHCI Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
new file mode 100644 (file)
index 0000000..42d3f64
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Allwinner sunxi AHCI SATA platform driver
+ * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
+ * Daniel Wang <danielwang@allwinnertech.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.
+ */
+
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include "ahci.h"
+
+#define AHCI_BISTAFR   0x00a0
+#define AHCI_BISTCR    0x00a4
+#define AHCI_BISTFCTR  0x00a8
+#define AHCI_BISTSR    0x00ac
+#define AHCI_BISTDECR  0x00b0
+#define AHCI_DIAGNR0   0x00b4
+#define AHCI_DIAGNR1   0x00b8
+#define AHCI_OOBR      0x00bc
+#define AHCI_PHYCS0R   0x00c0
+#define AHCI_PHYCS1R   0x00c4
+#define AHCI_PHYCS2R   0x00c8
+#define AHCI_TIMER1MS  0x00e0
+#define AHCI_GPARAM1R  0x00e8
+#define AHCI_GPARAM2R  0x00ec
+#define AHCI_PPARAMR   0x00f0
+#define AHCI_TESTR     0x00f4
+#define AHCI_VERSIONR  0x00f8
+#define AHCI_IDR       0x00fc
+#define AHCI_RWCR      0x00fc
+#define AHCI_P0DMACR   0x0170
+#define AHCI_P0PHYCR   0x0178
+#define AHCI_P0PHYSR   0x017c
+
+static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
+{
+       u32 reg_val;
+
+       reg_val = readl(reg);
+       reg_val &= ~(clr_val);
+       writel(reg_val, reg);
+}
+
+static void sunxi_setbits(void __iomem *reg, u32 set_val)
+{
+       u32 reg_val;
+
+       reg_val = readl(reg);
+       reg_val |= set_val;
+       writel(reg_val, reg);
+}
+
+static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
+{
+       u32 reg_val;
+
+       reg_val = readl(reg);
+       reg_val &= ~(clr_val);
+       reg_val |= set_val;
+       writel(reg_val, reg);
+}
+
+static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
+{
+       return (readl(reg) >> shift) & mask;
+}
+
+static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
+{
+       u32 reg_val;
+       int timeout;
+
+       /* This magic is from the original code */
+       writel(0, reg_base + AHCI_RWCR);
+       msleep(5);
+
+       sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
+       sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+                        (0x7 << 24),
+                        (0x5 << 24) | BIT(23) | BIT(18));
+       sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
+                        (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
+                        (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
+       sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
+       sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
+       sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
+                        (0x7 << 20), (0x3 << 20));
+       sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
+                        (0x1f << 5), (0x19 << 5));
+       msleep(5);
+
+       sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+       timeout = 250; /* Power up takes aprox 50 us */
+       do {
+               reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
+               if (reg_val == 0x02)
+                       break;
+
+               if (--timeout == 0) {
+                       dev_err(dev, "PHY power up failed.\n");
+                       return -EIO;
+               }
+               udelay(1);
+       } while (1);
+
+       sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
+
+       timeout = 100; /* Calibration takes aprox 10 us */
+       do {
+               reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
+               if (reg_val == 0x00)
+                       break;
+
+               if (--timeout == 0) {
+                       dev_err(dev, "PHY calibration failed.\n");
+                       return -EIO;
+               }
+               udelay(1);
+       } while (1);
+
+       msleep(15);
+
+       writel(0x7, reg_base + AHCI_RWCR);
+
+       return 0;
+}
+
+static void ahci_sunxi_start_engine(struct ata_port *ap)
+{
+       void __iomem *port_mmio = ahci_port_base(ap);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+
+       /* Setup DMA before DMA start */
+       sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400);
+
+       /* Start DMA */
+       sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
+}
+
+static const struct ata_port_info ahci_sunxi_port_info = {
+       AHCI_HFLAGS(AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
+                         AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
+       .flags          = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+       .pio_mask       = ATA_PIO4,
+       .udma_mask      = ATA_UDMA6,
+       .port_ops       = &ahci_platform_ops,
+};
+
+static int ahci_sunxi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ahci_host_priv *hpriv;
+       int rc;
+
+       hpriv = ahci_platform_get_resources(pdev);
+       if (IS_ERR(hpriv))
+               return PTR_ERR(hpriv);
+
+       hpriv->start_engine = ahci_sunxi_start_engine;
+
+       rc = ahci_platform_enable_resources(hpriv);
+       if (rc)
+               return rc;
+
+       rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
+       if (rc)
+               goto disable_resources;
+
+       rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 0, 0);
+       if (rc)
+               goto disable_resources;
+
+       return 0;
+
+disable_resources:
+       ahci_platform_disable_resources(hpriv);
+       return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ahci_sunxi_resume(struct device *dev)
+{
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       int rc;
+
+       rc = ahci_platform_enable_resources(hpriv);
+       if (rc)
+               return rc;
+
+       rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
+       if (rc)
+               goto disable_resources;
+
+       rc = ahci_platform_resume_host(dev);
+       if (rc)
+               goto disable_resources;
+
+       return 0;
+
+disable_resources:
+       ahci_platform_disable_resources(hpriv);
+       return rc;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
+                        ahci_sunxi_resume);
+
+static const struct of_device_id ahci_sunxi_of_match[] = {
+       { .compatible = "allwinner,sun4i-a10-ahci", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
+
+static struct platform_driver ahci_sunxi_driver = {
+       .probe = ahci_sunxi_probe,
+       .remove = ata_platform_remove_one,
+       .driver = {
+               .name = "ahci-sunxi",
+               .owner = THIS_MODULE,
+               .of_match_table = ahci_sunxi_of_match,
+               .pm = &ahci_sunxi_pm_ops,
+       },
+};
+module_platform_driver(ahci_sunxi_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
+MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
new file mode 100644 (file)
index 0000000..77c89bf
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * AppliedMicro X-Gene SoC SATA Host Controller Driver
+ *
+ * Copyright (c) 2014, Applied Micro Circuits Corporation
+ * Author: Loc Ho <lho@apm.com>
+ *         Tuan Phan <tphan@apm.com>
+ *         Suman Tripathi <stripathi@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * NOTE: PM support is not currently available.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/ahci_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/phy/phy.h>
+#include "ahci.h"
+
+/* Max # of disk per a controller */
+#define MAX_AHCI_CHN_PERCTR            2
+
+/* MUX CSR */
+#define SATA_ENET_CONFIG_REG           0x00000000
+#define  CFG_SATA_ENET_SELECT_MASK     0x00000001
+
+/* SATA core host controller CSR */
+#define SLVRDERRATTRIBUTES             0x00000000
+#define SLVWRERRATTRIBUTES             0x00000004
+#define MSTRDERRATTRIBUTES             0x00000008
+#define MSTWRERRATTRIBUTES             0x0000000c
+#define BUSCTLREG                      0x00000014
+#define IOFMSTRWAUX                    0x00000018
+#define INTSTATUSMASK                  0x0000002c
+#define ERRINTSTATUS                   0x00000030
+#define ERRINTSTATUSMASK               0x00000034
+
+/* SATA host AHCI CSR */
+#define PORTCFG                                0x000000a4
+#define  PORTADDR_SET(dst, src) \
+               (((dst) & ~0x0000003f) | (((u32)(src)) & 0x0000003f))
+#define PORTPHY1CFG            0x000000a8
+#define PORTPHY1CFG_FRCPHYRDY_SET(dst, src) \
+               (((dst) & ~0x00100000) | (((u32)(src) << 0x14) & 0x00100000))
+#define PORTPHY2CFG                    0x000000ac
+#define PORTPHY3CFG                    0x000000b0
+#define PORTPHY4CFG                    0x000000b4
+#define PORTPHY5CFG                    0x000000b8
+#define SCTL0                          0x0000012C
+#define PORTPHY5CFG_RTCHG_SET(dst, src) \
+               (((dst) & ~0xfff00000) | (((u32)(src) << 0x14) & 0xfff00000))
+#define PORTAXICFG_EN_CONTEXT_SET(dst, src) \
+               (((dst) & ~0x01000000) | (((u32)(src) << 0x18) & 0x01000000))
+#define PORTAXICFG                     0x000000bc
+#define PORTAXICFG_OUTTRANS_SET(dst, src) \
+               (((dst) & ~0x00f00000) | (((u32)(src) << 0x14) & 0x00f00000))
+
+/* SATA host controller AXI CSR */
+#define INT_SLV_TMOMASK                        0x00000010
+
+/* SATA diagnostic CSR */
+#define CFG_MEM_RAM_SHUTDOWN           0x00000070
+#define BLOCK_MEM_RDY                  0x00000074
+
+struct xgene_ahci_context {
+       struct ahci_host_priv *hpriv;
+       struct device *dev;
+       void __iomem *csr_core;         /* Core CSR address of IP */
+       void __iomem *csr_diag;         /* Diag CSR address of IP */
+       void __iomem *csr_axi;          /* AXI CSR address of IP */
+       void __iomem *csr_mux;          /* MUX CSR address of IP */
+};
+
+static int xgene_ahci_init_memram(struct xgene_ahci_context *ctx)
+{
+       dev_dbg(ctx->dev, "Release memory from shutdown\n");
+       writel(0x0, ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN);
+       readl(ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); /* Force a barrier */
+       msleep(1);      /* reset may take up to 1ms */
+       if (readl(ctx->csr_diag + BLOCK_MEM_RDY) != 0xFFFFFFFF) {
+               dev_err(ctx->dev, "failed to release memory from shutdown\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+/**
+ * xgene_ahci_read_id - Read ID data from the specified device
+ * @dev: device
+ * @tf: proposed taskfile
+ * @id: data buffer
+ *
+ * This custom read ID function is required due to the fact that the HW
+ * does not support DEVSLP and the controller state machine may get stuck
+ * after processing the ID query command.
+ */
+static unsigned int xgene_ahci_read_id(struct ata_device *dev,
+                                      struct ata_taskfile *tf, u16 *id)
+{
+       u32 err_mask;
+       void __iomem *port_mmio = ahci_port_base(dev->link->ap);
+
+       err_mask = ata_do_dev_read_id(dev, tf, id);
+       if (err_mask)
+               return err_mask;
+
+       /*
+        * Mask reserved area. Word78 spec of Link Power Management
+        * bit15-8: reserved
+        * bit7: NCQ autosence
+        * bit6: Software settings preservation supported
+        * bit5: reserved
+        * bit4: In-order sata delivery supported
+        * bit3: DIPM requests supported
+        * bit2: DMA Setup FIS Auto-Activate optimization supported
+        * bit1: DMA Setup FIX non-Zero buffer offsets supported
+        * bit0: Reserved
+        *
+        * Clear reserved bit 8 (DEVSLP bit) as we don't support DEVSLP
+        */
+       id[ATA_ID_FEATURE_SUPP] &= ~(1 << 8);
+
+       /*
+        * Due to HW errata, restart the port if no other command active.
+        * Otherwise the controller may get stuck.
+        */
+       if (!readl(port_mmio + PORT_CMD_ISSUE)) {
+               writel(PORT_CMD_FIS_RX, port_mmio + PORT_CMD);
+               readl(port_mmio + PORT_CMD);    /* Force a barrier */
+               writel(PORT_CMD_FIS_RX | PORT_CMD_START, port_mmio + PORT_CMD);
+               readl(port_mmio + PORT_CMD);    /* Force a barrier */
+       }
+       return 0;
+}
+
+static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
+{
+       void __iomem *mmio = ctx->hpriv->mmio;
+       u32 val;
+
+       dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n",
+               mmio, channel);
+       val = readl(mmio + PORTCFG);
+       val = PORTADDR_SET(val, channel == 0 ? 2 : 3);
+       writel(val, mmio + PORTCFG);
+       readl(mmio + PORTCFG);  /* Force a barrier */
+       /* Disable fix rate */
+       writel(0x0001fffe, mmio + PORTPHY1CFG);
+       readl(mmio + PORTPHY1CFG); /* Force a barrier */
+       writel(0x5018461c, mmio + PORTPHY2CFG);
+       readl(mmio + PORTPHY2CFG); /* Force a barrier */
+       writel(0x1c081907, mmio + PORTPHY3CFG);
+       readl(mmio + PORTPHY3CFG); /* Force a barrier */
+       writel(0x1c080815, mmio + PORTPHY4CFG);
+       readl(mmio + PORTPHY4CFG); /* Force a barrier */
+       /* Set window negotiation */
+       val = readl(mmio + PORTPHY5CFG);
+       val = PORTPHY5CFG_RTCHG_SET(val, 0x300);
+       writel(val, mmio + PORTPHY5CFG);
+       readl(mmio + PORTPHY5CFG); /* Force a barrier */
+       val = readl(mmio + PORTAXICFG);
+       val = PORTAXICFG_EN_CONTEXT_SET(val, 0x1); /* Enable context mgmt */
+       val = PORTAXICFG_OUTTRANS_SET(val, 0xe); /* Set outstanding */
+       writel(val, mmio + PORTAXICFG);
+       readl(mmio + PORTAXICFG); /* Force a barrier */
+}
+
+/**
+ * xgene_ahci_do_hardreset - Issue the actual COMRESET
+ * @link: link to reset
+ * @deadline: deadline jiffies for the operation
+ * @online: Return value to indicate if device online
+ *
+ * Due to the limitation of the hardware PHY, a difference set of setting is
+ * required for each supported disk speed - Gen3 (6.0Gbps), Gen2 (3.0Gbps),
+ * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will
+ * report disparity error and etc. In addition, during COMRESET, there can
+ * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and
+ * SERR_10B_8B_ERR, the PHY receiver line must be reseted. The following
+ * algorithm is followed to proper configure the hardware PHY during COMRESET:
+ *
+ * Alg Part 1:
+ * 1. Start the PHY at Gen3 speed (default setting)
+ * 2. Issue the COMRESET
+ * 3. If no link, go to Alg Part 3
+ * 4. If link up, determine if the negotiated speed matches the PHY
+ *    configured speed
+ * 5. If they matched, go to Alg Part 2
+ * 6. If they do not matched and first time, configure the PHY for the linked
+ *    up disk speed and repeat step 2
+ * 7. Go to Alg Part 2
+ *
+ * Alg Part 2:
+ * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error
+ *    reported in the register PORT_SCR_ERR, then reset the PHY receiver line
+ * 2. Go to Alg Part 3
+ *
+ * Alg Part 3:
+ * 1. Clear any pending from register PORT_SCR_ERR.
+ *
+ * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition
+ *       and until the underlying PHY supports an method to reset the receiver
+ *       line, on detection of SERR_DISPARITY or SERR_10B_8B_ERR errors,
+ *       an warning message will be printed.
+ */
+static int xgene_ahci_do_hardreset(struct ata_link *link,
+                                  unsigned long deadline, bool *online)
+{
+       const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+       struct ata_port *ap = link->ap;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       struct xgene_ahci_context *ctx = hpriv->plat_data;
+       struct ahci_port_priv *pp = ap->private_data;
+       u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       struct ata_taskfile tf;
+       int rc;
+       u32 val;
+
+       /* clear D2H reception area to properly wait for D2H FIS */
+       ata_tf_init(link->device, &tf);
+       tf.command = ATA_BUSY;
+       ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+       rc = sata_link_hardreset(link, timing, deadline, online,
+                                ahci_check_ready);
+
+       val = readl(port_mmio + PORT_SCR_ERR);
+       if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
+               dev_warn(ctx->dev, "link has error\n");
+
+       /* clear all errors if any pending */
+       val = readl(port_mmio + PORT_SCR_ERR);
+       writel(val, port_mmio + PORT_SCR_ERR);
+
+       return rc;
+}
+
+static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class,
+                               unsigned long deadline)
+{
+       struct ata_port *ap = link->ap;
+        struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *port_mmio = ahci_port_base(ap);
+       bool online;
+       int rc;
+       u32 portcmd_saved;
+       u32 portclb_saved;
+       u32 portclbhi_saved;
+       u32 portrxfis_saved;
+       u32 portrxfishi_saved;
+
+       /* As hardreset resets these CSR, save it to restore later */
+       portcmd_saved = readl(port_mmio + PORT_CMD);
+       portclb_saved = readl(port_mmio + PORT_LST_ADDR);
+       portclbhi_saved = readl(port_mmio + PORT_LST_ADDR_HI);
+       portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR);
+       portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI);
+
+       ahci_stop_engine(ap);
+
+       rc = xgene_ahci_do_hardreset(link, deadline, &online);
+
+       /* As controller hardreset clears them, restore them */
+       writel(portcmd_saved, port_mmio + PORT_CMD);
+       writel(portclb_saved, port_mmio + PORT_LST_ADDR);
+       writel(portclbhi_saved, port_mmio + PORT_LST_ADDR_HI);
+       writel(portrxfis_saved, port_mmio + PORT_FIS_ADDR);
+       writel(portrxfishi_saved, port_mmio + PORT_FIS_ADDR_HI);
+
+       hpriv->start_engine(ap);
+
+       if (online)
+               *class = ahci_dev_classify(ap);
+
+       return rc;
+}
+
+static void xgene_ahci_host_stop(struct ata_host *host)
+{
+       struct ahci_host_priv *hpriv = host->private_data;
+
+       ahci_platform_disable_resources(hpriv);
+}
+
+static struct ata_port_operations xgene_ahci_ops = {
+       .inherits = &ahci_ops,
+       .host_stop = xgene_ahci_host_stop,
+       .hardreset = xgene_ahci_hardreset,
+       .read_id = xgene_ahci_read_id,
+};
+
+static const struct ata_port_info xgene_ahci_port_info = {
+       AHCI_HFLAGS(AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ),
+       .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+       .pio_mask = ATA_PIO4,
+       .udma_mask = ATA_UDMA6,
+       .port_ops = &xgene_ahci_ops,
+};
+
+static int xgene_ahci_hw_init(struct ahci_host_priv *hpriv)
+{
+       struct xgene_ahci_context *ctx = hpriv->plat_data;
+       int i;
+       int rc;
+       u32 val;
+
+       /* Remove IP RAM out of shutdown */
+       rc = xgene_ahci_init_memram(ctx);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < MAX_AHCI_CHN_PERCTR; i++)
+               xgene_ahci_set_phy_cfg(ctx, i);
+
+       /* AXI disable Mask */
+       writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT);
+       readl(hpriv->mmio + HOST_IRQ_STAT); /* Force a barrier */
+       writel(0, ctx->csr_core + INTSTATUSMASK);
+       val = readl(ctx->csr_core + INTSTATUSMASK); /* Force a barrier */
+       dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n",
+               INTSTATUSMASK, val);
+
+       writel(0x0, ctx->csr_core + ERRINTSTATUSMASK);
+       readl(ctx->csr_core + ERRINTSTATUSMASK); /* Force a barrier */
+       writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK);
+       readl(ctx->csr_axi + INT_SLV_TMOMASK);
+
+       /* Enable AXI Interrupt */
+       writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES);
+       writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES);
+       writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES);
+       writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES);
+
+       /* Enable coherency */
+       val = readl(ctx->csr_core + BUSCTLREG);
+       val &= ~0x00000002;     /* Enable write coherency */
+       val &= ~0x00000001;     /* Enable read coherency */
+       writel(val, ctx->csr_core + BUSCTLREG);
+
+       val = readl(ctx->csr_core + IOFMSTRWAUX);
+       val |= (1 << 3);        /* Enable read coherency */
+       val |= (1 << 9);        /* Enable write coherency */
+       writel(val, ctx->csr_core + IOFMSTRWAUX);
+       val = readl(ctx->csr_core + IOFMSTRWAUX);
+       dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n",
+               IOFMSTRWAUX, val);
+
+       return rc;
+}
+
+static int xgene_ahci_mux_select(struct xgene_ahci_context *ctx)
+{
+       u32 val;
+
+       /* Check for optional MUX resource */
+       if (IS_ERR(ctx->csr_mux))
+               return 0;
+
+       val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG);
+       val &= ~CFG_SATA_ENET_SELECT_MASK;
+       writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG);
+       val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG);
+       return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0;
+}
+
+static int xgene_ahci_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ahci_host_priv *hpriv;
+       struct xgene_ahci_context *ctx;
+       struct resource *res;
+       int rc;
+
+       hpriv = ahci_platform_get_resources(pdev);
+       if (IS_ERR(hpriv))
+               return PTR_ERR(hpriv);
+
+       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       hpriv->plat_data = ctx;
+       ctx->hpriv = hpriv;
+       ctx->dev = dev;
+
+       /* Retrieve the IP core resource */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       ctx->csr_core = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ctx->csr_core))
+               return PTR_ERR(ctx->csr_core);
+
+       /* Retrieve the IP diagnostic resource */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       ctx->csr_diag = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ctx->csr_diag))
+               return PTR_ERR(ctx->csr_diag);
+
+       /* Retrieve the IP AXI resource */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       ctx->csr_axi = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ctx->csr_axi))
+               return PTR_ERR(ctx->csr_axi);
+
+       /* Retrieve the optional IP mux resource */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
+       ctx->csr_mux = devm_ioremap_resource(dev, res);
+
+       dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core,
+               hpriv->mmio);
+
+       /* Select ATA */
+       if ((rc = xgene_ahci_mux_select(ctx))) {
+               dev_err(dev, "SATA mux selection failed error %d\n", rc);
+               return -ENODEV;
+       }
+
+       /* Due to errata, HW requires full toggle transition */
+       rc = ahci_platform_enable_clks(hpriv);
+       if (rc)
+               goto disable_resources;
+       ahci_platform_disable_clks(hpriv);
+
+       rc = ahci_platform_enable_resources(hpriv);
+       if (rc)
+               goto disable_resources;
+
+       /* Configure the host controller */
+       xgene_ahci_hw_init(hpriv);
+
+       /*
+        * Setup DMA mask. This is preliminary until the DMA range is sorted
+        * out.
+        */
+       rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+       if (rc) {
+               dev_err(dev, "Unable to set dma mask\n");
+               goto disable_resources;
+       }
+
+       rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info, 0, 0);
+       if (rc)
+               goto disable_resources;
+
+       dev_dbg(dev, "X-Gene SATA host controller initialized\n");
+       return 0;
+
+disable_resources:
+       ahci_platform_disable_resources(hpriv);
+       return rc;
+}
+
+static const struct of_device_id xgene_ahci_of_match[] = {
+       {.compatible = "apm,xgene-ahci"},
+       {},
+};
+MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
+
+static struct platform_driver xgene_ahci_driver = {
+       .probe = xgene_ahci_probe,
+       .remove = ata_platform_remove_one,
+       .driver = {
+               .name = "xgene-ahci",
+               .owner = THIS_MODULE,
+               .of_match_table = xgene_ahci_of_match,
+       },
+};
+
+module_platform_driver(xgene_ahci_driver);
+
+MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver");
+MODULE_AUTHOR("Loc Ho <lho@apm.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.4");
index 7d196656adb5581533517a6ed0ec49d8c2966b58..9498a7d3846fef6e2c88bdd8596d3f2080e0349e 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 36605abe5a6786dd8282bceb798c10663e3b16f6..6bd4f660b4e15966ca2c351b4501c0521491de32 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -394,6 +393,9 @@ static ssize_t ahci_show_em_supported(struct device *dev,
  *
  *     If inconsistent, config values are fixed up by this function.
  *
+ *     If it is not set already this function sets hpriv->start_engine to
+ *     ahci_start_engine.
+ *
  *     LOCKING:
  *     None.
  */
@@ -500,6 +502,9 @@ void ahci_save_initial_config(struct device *dev,
        hpriv->cap = cap;
        hpriv->cap2 = cap2;
        hpriv->port_map = port_map;
+
+       if (!hpriv->start_engine)
+               hpriv->start_engine = ahci_start_engine;
 }
 EXPORT_SYMBOL_GPL(ahci_save_initial_config);
 
@@ -766,7 +771,7 @@ static void ahci_start_port(struct ata_port *ap)
 
        /* enable DMA */
        if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
-               ahci_start_engine(ap);
+               hpriv->start_engine(ap);
 
        /* turn on LEDs */
        if (ap->flags & ATA_FLAG_EM) {
@@ -1032,12 +1037,13 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
 static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
                                size_t size)
 {
-       int state;
+       unsigned int state;
        int pmp;
        struct ahci_port_priv *pp = ap->private_data;
        struct ahci_em_priv *emp;
 
-       state = simple_strtoul(buf, NULL, 0);
+       if (kstrtouint(buf, 0, &state) < 0)
+               return -EINVAL;
 
        /* get the slot number from the message */
        pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
@@ -1234,7 +1240,7 @@ int ahci_kick_engine(struct ata_port *ap)
 
        /* restart engine */
  out_restart:
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
        return rc;
 }
 EXPORT_SYMBOL_GPL(ahci_kick_engine);
@@ -1387,8 +1393,8 @@ static int ahci_bad_pmp_check_ready(struct ata_link *link)
        return ata_check_ready(status);
 }
 
-int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
-                               unsigned long deadline)
+static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
+                                   unsigned long deadline)
 {
        struct ata_port *ap = link->ap;
        void __iomem *port_mmio = ahci_port_base(ap);
@@ -1426,6 +1432,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
        const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
        struct ata_port *ap = link->ap;
        struct ahci_port_priv *pp = ap->private_data;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
        struct ata_taskfile tf;
        bool online;
@@ -1443,7 +1450,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
        rc = sata_link_hardreset(link, timing, deadline, &online,
                                 ahci_check_ready);
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 
        if (online)
                *class = ahci_dev_classify(ap);
@@ -1629,7 +1636,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
        }
 
        if (irq_stat & PORT_IRQ_UNK_FIS) {
-               u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
+               u32 *unk = pp->rx_fis + RX_FIS_UNK;
 
                active_ehi->err_mask |= AC_ERR_HSM;
                active_ehi->action |= ATA_EH_RESET;
@@ -2007,10 +2014,12 @@ static void ahci_thaw(struct ata_port *ap)
 
 void ahci_error_handler(struct ata_port *ap)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+
        if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
                /* restart engine */
                ahci_stop_engine(ap);
-               ahci_start_engine(ap);
+               hpriv->start_engine(ap);
        }
 
        sata_pmp_error_handler(ap);
@@ -2031,6 +2040,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 
 static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_device *dev = ap->link.device;
        u32 devslp, dm, dito, mdat, deto;
@@ -2094,7 +2104,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
                   PORT_DEVSLP_ADSE);
        writel(devslp, port_mmio + PORT_DEVSLP);
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 
        /* enable device sleep feature for the drive */
        err_mask = ata_dev_set_feature(dev,
@@ -2106,6 +2116,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
 
 static void ahci_enable_fbs(struct ata_port *ap)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        struct ahci_port_priv *pp = ap->private_data;
        void __iomem *port_mmio = ahci_port_base(ap);
        u32 fbs;
@@ -2134,11 +2145,12 @@ static void ahci_enable_fbs(struct ata_port *ap)
        } else
                dev_err(ap->host->dev, "Failed to enable FBS\n");
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 }
 
 static void ahci_disable_fbs(struct ata_port *ap)
 {
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        struct ahci_port_priv *pp = ap->private_data;
        void __iomem *port_mmio = ahci_port_base(ap);
        u32 fbs;
@@ -2166,7 +2178,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
                pp->fbs_enabled = false;
        }
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 }
 
 static void ahci_pmp_attach(struct ata_port *ap)
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
new file mode 100644 (file)
index 0000000..7cb3a85
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * AHCI SATA platform library
+ *
+ * Copyright 2004-2005  Red Hat, Inc.
+ *   Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2010  MontaVista Software, LLC.
+ *   Anton Vorontsov <avorontsov@ru.mvista.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, or (at your option)
+ * any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/libata.h>
+#include <linux/ahci_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+#include "ahci.h"
+
+static void ahci_host_stop(struct ata_host *host);
+
+struct ata_port_operations ahci_platform_ops = {
+       .inherits       = &ahci_ops,
+       .host_stop      = ahci_host_stop,
+};
+EXPORT_SYMBOL_GPL(ahci_platform_ops);
+
+static struct scsi_host_template ahci_platform_sht = {
+       AHCI_SHT("ahci_platform"),
+};
+
+/**
+ * ahci_platform_enable_clks - Enable platform clocks
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all the clks found in hpriv->clks, starting at
+ * index 0. If any clk fails to enable it disables all the clks already
+ * enabled in reverse order, and then returns an error.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
+{
+       int c, rc;
+
+       for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
+               rc = clk_prepare_enable(hpriv->clks[c]);
+               if (rc)
+                       goto disable_unprepare_clk;
+       }
+       return 0;
+
+disable_unprepare_clk:
+       while (--c >= 0)
+               clk_disable_unprepare(hpriv->clks[c]);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
+
+/**
+ * ahci_platform_disable_clks - Disable platform clocks
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all the clks found in hpriv->clks, in reverse
+ * order of ahci_platform_enable_clks (starting at the end of the array).
+ */
+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
+{
+       int c;
+
+       for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
+               if (hpriv->clks[c])
+                       clk_disable_unprepare(hpriv->clks[c]);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
+
+/**
+ * ahci_platform_enable_resources - Enable platform resources
+ * @hpriv: host private area to store config values
+ *
+ * This function enables all ahci_platform managed resources in the
+ * following order:
+ * 1) Regulator
+ * 2) Clocks (through ahci_platform_enable_clks)
+ * 3) Phy
+ *
+ * If resource enabling fails at any point the previous enabled resources
+ * are disabled in reverse order.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
+{
+       int rc;
+
+       if (hpriv->target_pwr) {
+               rc = regulator_enable(hpriv->target_pwr);
+               if (rc)
+                       return rc;
+       }
+
+       rc = ahci_platform_enable_clks(hpriv);
+       if (rc)
+               goto disable_regulator;
+
+       if (hpriv->phy) {
+               rc = phy_init(hpriv->phy);
+               if (rc)
+                       goto disable_clks;
+
+               rc = phy_power_on(hpriv->phy);
+               if (rc) {
+                       phy_exit(hpriv->phy);
+                       goto disable_clks;
+               }
+       }
+
+       return 0;
+
+disable_clks:
+       ahci_platform_disable_clks(hpriv);
+
+disable_regulator:
+       if (hpriv->target_pwr)
+               regulator_disable(hpriv->target_pwr);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
+
+/**
+ * ahci_platform_disable_resources - Disable platform resources
+ * @hpriv: host private area to store config values
+ *
+ * This function disables all ahci_platform managed resources in the
+ * following order:
+ * 1) Phy
+ * 2) Clocks (through ahci_platform_disable_clks)
+ * 3) Regulator
+ */
+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
+{
+       if (hpriv->phy) {
+               phy_power_off(hpriv->phy);
+               phy_exit(hpriv->phy);
+       }
+
+       ahci_platform_disable_clks(hpriv);
+
+       if (hpriv->target_pwr)
+               regulator_disable(hpriv->target_pwr);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
+
+static void ahci_platform_put_resources(struct device *dev, void *res)
+{
+       struct ahci_host_priv *hpriv = res;
+       int c;
+
+       if (hpriv->got_runtime_pm) {
+               pm_runtime_put_sync(dev);
+               pm_runtime_disable(dev);
+       }
+
+       for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
+               clk_put(hpriv->clks[c]);
+}
+
+/**
+ * ahci_platform_get_resources - Get platform resources
+ * @pdev: platform device to get resources for
+ *
+ * This function allocates an ahci_host_priv struct, and gets the following
+ * resources, storing a reference to them inside the returned struct:
+ *
+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
+ * 2) regulator for controlling the targets power (optional)
+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
+ *    or for non devicetree enabled platforms a single clock
+ *     4) phy (optional)
+ *
+ * RETURNS:
+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
+ */
+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ahci_host_priv *hpriv;
+       struct clk *clk;
+       int i, rc = -ENOMEM;
+
+       if (!devres_open_group(dev, NULL, GFP_KERNEL))
+               return ERR_PTR(-ENOMEM);
+
+       hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
+                            GFP_KERNEL);
+       if (!hpriv)
+               goto err_out;
+
+       devres_add(dev, hpriv);
+
+       hpriv->mmio = devm_ioremap_resource(dev,
+                             platform_get_resource(pdev, IORESOURCE_MEM, 0));
+       if (IS_ERR(hpriv->mmio)) {
+               dev_err(dev, "no mmio space\n");
+               rc = PTR_ERR(hpriv->mmio);
+               goto err_out;
+       }
+
+       hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
+       if (IS_ERR(hpriv->target_pwr)) {
+               rc = PTR_ERR(hpriv->target_pwr);
+               if (rc == -EPROBE_DEFER)
+                       goto err_out;
+               hpriv->target_pwr = NULL;
+       }
+
+       for (i = 0; i < AHCI_MAX_CLKS; i++) {
+               /*
+                * For now we must use clk_get(dev, NULL) for the first clock,
+                * because some platforms (da850, spear13xx) are not yet
+                * converted to use devicetree for clocks.  For new platforms
+                * this is equivalent to of_clk_get(dev->of_node, 0).
+                */
+               if (i == 0)
+                       clk = clk_get(dev, NULL);
+               else
+                       clk = of_clk_get(dev->of_node, i);
+
+               if (IS_ERR(clk)) {
+                       rc = PTR_ERR(clk);
+                       if (rc == -EPROBE_DEFER)
+                               goto err_out;
+                       break;
+               }
+               hpriv->clks[i] = clk;
+       }
+
+       hpriv->phy = devm_phy_get(dev, "sata-phy");
+       if (IS_ERR(hpriv->phy)) {
+               rc = PTR_ERR(hpriv->phy);
+               switch (rc) {
+               case -ENODEV:
+               case -ENOSYS:
+                       /* continue normally */
+                       hpriv->phy = NULL;
+                       break;
+
+               case -EPROBE_DEFER:
+                       goto err_out;
+
+               default:
+                       dev_err(dev, "couldn't get sata-phy\n");
+                       goto err_out;
+               }
+       }
+
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+       hpriv->got_runtime_pm = true;
+
+       devres_remove_group(dev, NULL);
+       return hpriv;
+
+err_out:
+       devres_release_group(dev, NULL);
+       return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
+
+/**
+ * ahci_platform_init_host - Bring up an ahci-platform host
+ * @pdev: platform device pointer for the host
+ * @hpriv: ahci-host private data for the host
+ * @pi_template: template for the ata_port_info to use
+ * @force_port_map: param passed to ahci_save_initial_config
+ * @mask_port_map: param passed to ahci_save_initial_config
+ *
+ * This function does all the usual steps needed to bring up an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be initialized / enabled before calling this.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_init_host(struct platform_device *pdev,
+                           struct ahci_host_priv *hpriv,
+                           const struct ata_port_info *pi_template,
+                           unsigned int force_port_map,
+                           unsigned int mask_port_map)
+{
+       struct device *dev = &pdev->dev;
+       struct ata_port_info pi = *pi_template;
+       const struct ata_port_info *ppi[] = { &pi, NULL };
+       struct ata_host *host;
+       int i, irq, n_ports, rc;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0) {
+               dev_err(dev, "no irq\n");
+               return -EINVAL;
+       }
+
+       /* prepare host */
+       hpriv->flags |= (unsigned long)pi.private_data;
+
+       ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
+
+       if (hpriv->cap & HOST_CAP_NCQ)
+               pi.flags |= ATA_FLAG_NCQ;
+
+       if (hpriv->cap & HOST_CAP_PMP)
+               pi.flags |= ATA_FLAG_PMP;
+
+       ahci_set_em_messages(hpriv, &pi);
+
+       /* CAP.NP sometimes indicate the index of the last enabled
+        * port, at other times, that of the last possible port, so
+        * determining the maximum port number requires looking at
+        * both CAP.NP and port_map.
+        */
+       n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+
+       host = ata_host_alloc_pinfo(dev, ppi, n_ports);
+       if (!host)
+               return -ENOMEM;
+
+       host->private_data = hpriv;
+
+       if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
+               host->flags |= ATA_HOST_PARALLEL_SCAN;
+       else
+               dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
+
+       if (pi.flags & ATA_FLAG_EM)
+               ahci_reset_em(host);
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+
+               ata_port_desc(ap, "mmio %pR",
+                             platform_get_resource(pdev, IORESOURCE_MEM, 0));
+               ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
+
+               /* set enclosure management message type */
+               if (ap->flags & ATA_FLAG_EM)
+                       ap->em_message_type = hpriv->em_msg_type;
+
+               /* disabled/not-implemented port */
+               if (!(hpriv->port_map & (1 << i)))
+                       ap->ops = &ata_dummy_port_ops;
+       }
+
+       rc = ahci_reset_controller(host);
+       if (rc)
+               return rc;
+
+       ahci_init_controller(host);
+       ahci_print_info(host, "platform");
+
+       return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
+                                &ahci_platform_sht);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_init_host);
+
+static void ahci_host_stop(struct ata_host *host)
+{
+       struct device *dev = host->dev;
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+
+       if (pdata && pdata->exit)
+               pdata->exit(dev);
+
+       ahci_platform_disable_resources(hpriv);
+}
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * ahci_platform_suspend_host - Suspend an ahci-platform host
+ * @dev: device pointer for the host
+ *
+ * This function does all the usual steps needed to suspend an
+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
+ * must be disabled after calling this.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_suspend_host(struct device *dev)
+{
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       void __iomem *mmio = hpriv->mmio;
+       u32 ctl;
+
+       if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
+               dev_err(dev, "firmware update required for suspend/resume\n");
+               return -EIO;
+       }
+
+       /*
+        * AHCI spec rev1.1 section 8.3.3:
+        * Software must disable interrupts prior to requesting a
+        * transition of the HBA to D3 state.
+        */
+       ctl = readl(mmio + HOST_CTL);
+       ctl &= ~HOST_IRQ_EN;
+       writel(ctl, mmio + HOST_CTL);
+       readl(mmio + HOST_CTL); /* flush */
+
+       return ata_host_suspend(host, PMSG_SUSPEND);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
+
+/**
+ * ahci_platform_resume_host - Resume an ahci-platform host
+ * @dev: device pointer for the host
+ *
+ * This function does all the usual steps needed to resume an ahci-platform
+ * host, note any necessary resources (ie clks, phy, etc.)  must be
+ * initialized / enabled before calling this.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_resume_host(struct device *dev)
+{
+       struct ata_host *host = dev_get_drvdata(dev);
+       int rc;
+
+       if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+               rc = ahci_reset_controller(host);
+               if (rc)
+                       return rc;
+
+               ahci_init_controller(host);
+       }
+
+       ata_host_resume(host);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
+
+/**
+ * ahci_platform_suspend - Suspend an ahci-platform device
+ * @dev: the platform device to suspend
+ *
+ * This function suspends the host associated with the device, followed by
+ * disabling all the resources of the device.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_suspend(struct device *dev)
+{
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       int rc;
+
+       rc = ahci_platform_suspend_host(dev);
+       if (rc)
+               return rc;
+
+       if (pdata && pdata->suspend) {
+               rc = pdata->suspend(dev);
+               if (rc)
+                       goto resume_host;
+       }
+
+       ahci_platform_disable_resources(hpriv);
+
+       return 0;
+
+resume_host:
+       ahci_platform_resume_host(dev);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_suspend);
+
+/**
+ * ahci_platform_resume - Resume an ahci-platform device
+ * @dev: the platform device to resume
+ *
+ * This function enables all the resources of the device followed by
+ * resuming the host associated with the device.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_resume(struct device *dev)
+{
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       int rc;
+
+       rc = ahci_platform_enable_resources(hpriv);
+       if (rc)
+               return rc;
+
+       if (pdata && pdata->resume) {
+               rc = pdata->resume(dev);
+               if (rc)
+                       goto disable_resources;
+       }
+
+       rc = ahci_platform_resume_host(dev);
+       if (rc)
+               goto disable_resources;
+
+       /* We resumed so update PM runtime state */
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       return 0;
+
+disable_resources:
+       ahci_platform_disable_resources(hpriv);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_resume);
+#endif
+
+MODULE_DESCRIPTION("AHCI SATA platform library");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
index 9e69a5308693de59abd5c596244033af43f7b3a8..b4f7cc2522d91a3d843c5c65478549bd0a79c601 100644 (file)
@@ -835,6 +835,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
                ata_for_each_dev(dev, &ap->link, ALL) {
                        ata_acpi_clear_gtf(dev);
                        if (ata_dev_enabled(dev) &&
+                           ata_dev_acpi_handle(dev) &&
                            ata_dev_get_GTF(dev, NULL) >= 0)
                                dev->flags |= ATA_DFLAG_ACPI_PENDING;
                }
index 1a3dbd1b196ecb121b1ee9d34388ecd00c307b71..34406f7fdd7a1274da79601489a30e6df774290c 100644 (file)
@@ -4175,6 +4175,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
        { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+       { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA },
 
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
@@ -4224,7 +4225,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* devices that don't properly handle queued TRIM commands */
        { "Micron_M500*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
-       { "Crucial_CT???M500SSD1",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M500SSD*",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
 
        /*
         * Some WD SATA-I drives spin up and down erratically when the link
@@ -5351,22 +5352,17 @@ bool ata_link_offline(struct ata_link *link)
 }
 
 #ifdef CONFIG_PM
-static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
-                              unsigned int action, unsigned int ehi_flags,
-                              int *async)
+static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
+                               unsigned int action, unsigned int ehi_flags,
+                               bool async)
 {
        struct ata_link *link;
        unsigned long flags;
-       int rc = 0;
 
        /* Previous resume operation might still be in
         * progress.  Wait for PM_PENDING to clear.
         */
        if (ap->pflags & ATA_PFLAG_PM_PENDING) {
-               if (async) {
-                       *async = -EAGAIN;
-                       return 0;
-               }
                ata_port_wait_eh(ap);
                WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
        }
@@ -5375,11 +5371,6 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
        spin_lock_irqsave(ap->lock, flags);
 
        ap->pm_mesg = mesg;
-       if (async)
-               ap->pm_result = async;
-       else
-               ap->pm_result = &rc;
-
        ap->pflags |= ATA_PFLAG_PM_PENDING;
        ata_for_each_link(link, ap, HOST_FIRST) {
                link->eh_info.action |= action;
@@ -5390,87 +5381,81 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
 
        spin_unlock_irqrestore(ap->lock, flags);
 
-       /* wait and check result */
        if (!async) {
                ata_port_wait_eh(ap);
                WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
        }
-
-       return rc;
 }
 
-static int __ata_port_suspend_common(struct ata_port *ap, pm_message_t mesg, int *async)
+/*
+ * On some hardware, device fails to respond after spun down for suspend.  As
+ * the device won't be used before being resumed, we don't need to touch the
+ * device.  Ask EH to skip the usual stuff and proceed directly to suspend.
+ *
+ * http://thread.gmane.org/gmane.linux.ide/46764
+ */
+static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
+                                                | ATA_EHI_NO_AUTOPSY
+                                                | ATA_EHI_NO_RECOVERY;
+
+static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
-       /*
-        * On some hardware, device fails to respond after spun down
-        * for suspend.  As the device won't be used before being
-        * resumed, we don't need to touch the device.  Ask EH to skip
-        * the usual stuff and proceed directly to suspend.
-        *
-        * http://thread.gmane.org/gmane.linux.ide/46764
-        */
-       unsigned int ehi_flags = ATA_EHI_QUIET | ATA_EHI_NO_AUTOPSY |
-                                ATA_EHI_NO_RECOVERY;
-       return ata_port_request_pm(ap, mesg, 0, ehi_flags, async);
+       ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
 }
 
-static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
+static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
 {
-       struct ata_port *ap = to_ata_port(dev);
-
-       return __ata_port_suspend_common(ap, mesg, NULL);
+       ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
 }
 
-static int ata_port_suspend(struct device *dev)
+static int ata_port_pm_suspend(struct device *dev)
 {
+       struct ata_port *ap = to_ata_port(dev);
+
        if (pm_runtime_suspended(dev))
                return 0;
 
-       return ata_port_suspend_common(dev, PMSG_SUSPEND);
+       ata_port_suspend(ap, PMSG_SUSPEND);
+       return 0;
 }
 
-static int ata_port_do_freeze(struct device *dev)
+static int ata_port_pm_freeze(struct device *dev)
 {
+       struct ata_port *ap = to_ata_port(dev);
+
        if (pm_runtime_suspended(dev))
                return 0;
 
-       return ata_port_suspend_common(dev, PMSG_FREEZE);
+       ata_port_suspend(ap, PMSG_FREEZE);
+       return 0;
 }
 
-static int ata_port_poweroff(struct device *dev)
+static int ata_port_pm_poweroff(struct device *dev)
 {
-       return ata_port_suspend_common(dev, PMSG_HIBERNATE);
+       ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE);
+       return 0;
 }
 
-static int __ata_port_resume_common(struct ata_port *ap, pm_message_t mesg,
-                                   int *async)
-{
-       int rc;
+static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY
+                                               | ATA_EHI_QUIET;
 
-       rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET,
-               ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async);
-       return rc;
+static void ata_port_resume(struct ata_port *ap, pm_message_t mesg)
+{
+       ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false);
 }
 
-static int ata_port_resume_common(struct device *dev, pm_message_t mesg)
+static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg)
 {
-       struct ata_port *ap = to_ata_port(dev);
-
-       return __ata_port_resume_common(ap, mesg, NULL);
+       ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true);
 }
 
-static int ata_port_resume(struct device *dev)
+static int ata_port_pm_resume(struct device *dev)
 {
-       int rc;
-
-       rc = ata_port_resume_common(dev, PMSG_RESUME);
-       if (!rc) {
-               pm_runtime_disable(dev);
-               pm_runtime_set_active(dev);
-               pm_runtime_enable(dev);
-       }
-
-       return rc;
+       ata_port_resume_async(to_ata_port(dev), PMSG_RESUME);
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+       return 0;
 }
 
 /*
@@ -5499,21 +5484,23 @@ static int ata_port_runtime_idle(struct device *dev)
 
 static int ata_port_runtime_suspend(struct device *dev)
 {
-       return ata_port_suspend_common(dev, PMSG_AUTO_SUSPEND);
+       ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND);
+       return 0;
 }
 
 static int ata_port_runtime_resume(struct device *dev)
 {
-       return ata_port_resume_common(dev, PMSG_AUTO_RESUME);
+       ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME);
+       return 0;
 }
 
 static const struct dev_pm_ops ata_port_pm_ops = {
-       .suspend = ata_port_suspend,
-       .resume = ata_port_resume,
-       .freeze = ata_port_do_freeze,
-       .thaw = ata_port_resume,
-       .poweroff = ata_port_poweroff,
-       .restore = ata_port_resume,
+       .suspend = ata_port_pm_suspend,
+       .resume = ata_port_pm_resume,
+       .freeze = ata_port_pm_freeze,
+       .thaw = ata_port_pm_resume,
+       .poweroff = ata_port_pm_poweroff,
+       .restore = ata_port_pm_resume,
 
        .runtime_suspend = ata_port_runtime_suspend,
        .runtime_resume = ata_port_runtime_resume,
@@ -5525,18 +5512,17 @@ static const struct dev_pm_ops ata_port_pm_ops = {
  * level. sas suspend/resume is async to allow parallel port recovery
  * since sas has multiple ata_port instances per Scsi_Host.
  */
-int ata_sas_port_async_suspend(struct ata_port *ap, int *async)
+void ata_sas_port_suspend(struct ata_port *ap)
 {
-       return __ata_port_suspend_common(ap, PMSG_SUSPEND, async);
+       ata_port_suspend_async(ap, PMSG_SUSPEND);
 }
-EXPORT_SYMBOL_GPL(ata_sas_port_async_suspend);
+EXPORT_SYMBOL_GPL(ata_sas_port_suspend);
 
-int ata_sas_port_async_resume(struct ata_port *ap, int *async)
+void ata_sas_port_resume(struct ata_port *ap)
 {
-       return __ata_port_resume_common(ap, PMSG_RESUME, async);
+       ata_port_resume_async(ap, PMSG_RESUME);
 }
-EXPORT_SYMBOL_GPL(ata_sas_port_async_resume);
-
+EXPORT_SYMBOL_GPL(ata_sas_port_resume);
 
 /**
  *     ata_host_suspend - suspend host
index 6d87570083187bbbe749fe566195f854707a641c..6760fc4e85b8c809e39655fd92adc83871e75fce 100644 (file)
@@ -95,12 +95,13 @@ enum {
  * represents timeout for that try.  The first try can be soft or
  * hardreset.  All others are hardreset if available.  In most cases
  * the first reset w/ 10sec timeout should succeed.  Following entries
- * are mostly for error handling, hotplug and retarded devices.
+ * are mostly for error handling, hotplug and those outlier devices that
+ * take an exceptionally long time to recover from reset.
  */
 static const unsigned long ata_eh_reset_timeouts[] = {
        10000,  /* most drives spin up by 10sec */
        10000,  /* > 99% working drives spin up before 20sec */
-       35000,  /* give > 30 secs of idleness for retarded devices */
+       35000,  /* give > 30 secs of idleness for outlier devices */
         5000,  /* and sweet one last chance */
        ULONG_MAX, /* > 1 min has elapsed, give up */
 };
@@ -4069,7 +4070,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
 
        ata_acpi_set_state(ap, ap->pm_mesg);
  out:
-       /* report result */
+       /* update the flags */
        spin_lock_irqsave(ap->lock, flags);
 
        ap->pflags &= ~ATA_PFLAG_PM_PENDING;
@@ -4078,11 +4079,6 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
        else if (ap->pflags & ATA_PFLAG_FROZEN)
                ata_port_schedule_eh(ap);
 
-       if (ap->pm_result) {
-               *ap->pm_result = rc;
-               ap->pm_result = NULL;
-       }
-
        spin_unlock_irqrestore(ap->lock, flags);
 
        return;
@@ -4134,13 +4130,9 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
        /* tell ACPI that we're resuming */
        ata_acpi_on_resume(ap);
 
-       /* report result */
+       /* update the flags */
        spin_lock_irqsave(ap->lock, flags);
        ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
-       if (ap->pm_result) {
-               *ap->pm_result = rc;
-               ap->pm_result = NULL;
-       }
        spin_unlock_irqrestore(ap->lock, flags);
 }
 #endif /* CONFIG_PM */
index 20fd337a57314a2928c9208bf706ffabed0c4dd5..7ccc084bf1dfb8f7b979f5e7ae777e030303d1b8 100644 (file)
@@ -447,8 +447,11 @@ static void sata_pmp_quirks(struct ata_port *ap)
                 * otherwise.  Don't try hard to recover it.
                 */
                ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
-       } else if (vendor == 0x197b && devid == 0x2352) {
-               /* chip found in Thermaltake BlackX Duet, jmicron JMB350? */
+       } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
+               /*
+                * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
+                * 0x0325: jmicron JMB394.
+                */
                ata_for_each_link(link, ap, EDGE) {
                        /* SRST breaks detection and disks get misclassified
                         * LPM disabled to avoid potential problems
index 88949c6d55ddd43b32b07accdb892256028d5e25..f3a65a3140d3c7e51bef6dce19f676de768abfdf 100644 (file)
@@ -85,21 +85,6 @@ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev)
                return ODD_MECH_TYPE_UNSUPPORTED;
 }
 
-static bool odd_can_poweroff(struct ata_device *ata_dev)
-{
-       acpi_handle handle;
-       struct acpi_device *acpi_dev;
-
-       handle = ata_dev_acpi_handle(ata_dev);
-       if (!handle)
-               return false;
-
-       if (acpi_bus_get_device(handle, &acpi_dev))
-               return false;
-
-       return acpi_device_can_poweroff(acpi_dev);
-}
-
 /* Test if ODD is zero power ready by sense code */
 static bool zpready(struct ata_device *dev)
 {
@@ -267,13 +252,11 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
 
 void zpodd_init(struct ata_device *dev)
 {
+       struct acpi_device *adev = ACPI_COMPANION(&dev->tdev);
        enum odd_mech_type mech_type;
        struct zpodd *zpodd;
 
-       if (dev->zpodd)
-               return;
-
-       if (!odd_can_poweroff(dev))
+       if (dev->zpodd || !adev || !acpi_device_can_poweroff(adev))
                return;
 
        mech_type = zpodd_get_mech_type(dev);
index 62c9ac80c6e96ed1f0a4421fb22b7ee3629ae2e9..5108b8744dce4c70d37d913fbf5b916984b36f6c 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index d23e2b3ca0b68a6c7109eef8e53b2e3e68048281..1206fa6b62cae199a00302729565915ed931509a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 73492dd4a4bce8aade1f79a7dbdfd3926c7f6f6b..6fac524c2f500381ac8d76b2a94bf4d88314f1e7 100644 (file)
@@ -356,7 +356,7 @@ static void cf_exit(struct arasan_cf_dev *acdev)
 
 static void dma_callback(void *dev)
 {
-       struct arasan_cf_dev *acdev = (struct arasan_cf_dev *) dev;
+       struct arasan_cf_dev *acdev = dev;
 
        complete(&acdev->dma_completion);
 }
index 1581dee2967a80368976303fc9e7865b1e69cef2..3aa4e655e3c64cb5a81f3759f5638e2eb003c5df 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index d63ee8f41a4f29e9c0bc9209236c97ca47259ab5..e9c87274a781551d4496ac81b213855dd766ae41 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/gfp.h>
 #include <scsi/scsi_host.h>
index 24e51056ac26a857c1db028b9eb71450a0608d45..30fa4ca4cef65607493a1e8fd1e5fe6bf13b5bbb 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 2ca5026f2c150f9e83b37e48e8227e944a18253f..7e73a0f1e3237698b2b7afcd70207655e53dc2d3 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 8fb69e5ca1b7f08be8ef7a635acdf8122765f577..57f1be64dbf239e8c631687ea5b5c28f1c1b5577 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
index 1275a8d4dedc06940cbce5660d24136d27aea0ef..6bca3505b9e9d5431d537e2fdf2fbcae917e76c6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index f10baabbf5db5ae2f266aed4f7559d258962f267..bcde4b786807079126aed18744edbbf972a86d3c 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index f07f2296acdcf5c986a0c33bd423736268f42c33..8afe854a5a50c24abeb2c9f96966264d09c0f8bc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 997e16a3a63f6154373d33854fed1c1532ee657f..2c0986fa4bb2ccd8efc1d2ead606c05e6d734ae1 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 0448860a2077526cea30354fc60b6c6c3cacada9..32ddcae5a360a387b010db88cf951287ab219bd6 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/libata.h>
index 810bc9964ddec6a12a72ca50206b7b67039c1183..3435bd6a5cc918984ba7aee85cfc8e4435e7106c 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 3c12fd7acd4126c256a3c87822b744c77af4a43b..f440892225f4d220603759f196cd2b5ca155a87f 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 980b88e109fcf5109e164d155dfca86de735c2c2..cad9d45749c419e51dbdf852fe67ee998796938b 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi_host.h>
 #include <linux/ata.h>
index 35b521348d311fbb7b2921618e348661a57edfb6..8e76f79689d371bd96fbd2f276d53ab265edc026 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index a9d74eff5fc4b159367b1f8f03d7aa842e331dba..3ba843f5cdc0f91a789e536b876a0b4bb292e645 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 4be0398c153d36b448cc5f23199514a48c8cc35b..b93c0f0729e7676e9e4b78d9611d3547ed8350b9 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 85cf2861e0b7d217eaabd6ffa446a6446de84c72..255c5aaff3a81e8c3ddce32dca7ba49a6dd0cf1d 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 26386f0b89a8f4583c397ca9da154a9c499c6d2f..e0872db913d65d1f120a753ac2f313162add41dd 100644 (file)
@@ -15,7 +15,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi_host.h>
 #include <linux/ata.h>
@@ -100,13 +99,9 @@ static int pata_imx_probe(struct platform_device *pdev)
        struct resource *io_res;
        int ret;
 
-       io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (io_res == NULL)
-               return -EINVAL;
-
        irq = platform_get_irq(pdev, 0);
-       if (irq <= 0)
-               return -EINVAL;
+       if (irq < 0)
+               return irq;
 
        priv = devm_kzalloc(&pdev->dev,
                                sizeof(struct pata_imx_priv), GFP_KERNEL);
@@ -119,7 +114,9 @@ static int pata_imx_probe(struct platform_device *pdev)
                return PTR_ERR(priv->clk);
        }
 
-       clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        host = ata_host_alloc(&pdev->dev, 1);
        if (!host) {
@@ -134,11 +131,10 @@ static int pata_imx_probe(struct platform_device *pdev)
        ap->pio_mask = ATA_PIO0;
        ap->flags |= ATA_FLAG_SLAVE_POSS;
 
-       priv->host_regs = devm_ioremap(&pdev->dev, io_res->start,
-               resource_size(io_res));
-       if (!priv->host_regs) {
-               dev_err(&pdev->dev, "failed to map IO/CTL base\n");
-               ret = -EBUSY;
+       io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       priv->host_regs = devm_ioremap_resource(&pdev->dev, io_res);
+       if (IS_ERR(priv->host_regs)) {
+               ret = PTR_ERR(priv->host_regs);
                goto err;
        }
 
@@ -212,7 +208,9 @@ static int pata_imx_resume(struct device *dev)
        struct ata_host *host = dev_get_drvdata(dev);
        struct pata_imx_priv *priv = host->private_data;
 
-       clk_prepare_enable(priv->clk);
+       int ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        __raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL);
 
index 2a8dd9527eccd4d435b65f7532091520cd5de40b..81369d187a5cb8f9e8e7d40158741533486d19a5 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 581e04d80367a9690c22513aaba376bf7dff643f..dc3d7877f29d7898a11780595e27cabb01d53a7e 100644 (file)
@@ -72,7 +72,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
index 76e739b031b6a3a15c036b082bcb8ba8d4f1ad06..b1cfa0258fd38017337e345b5095677a50567133 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index be816428b430fbb73135ef1591bbde2219097221..bce2a8ca4678ace5375b6a0f90699481b8ff9659 100644 (file)
@@ -916,7 +916,6 @@ static __init int probe_chip_type(struct legacy_probe *probe)
                        local_irq_restore(flags);
                        return BIOS;
                }
-               local_irq_restore(flags);
        }
 
        if (ht6560a & mask)
index a4f5e781c8c237dd794588b0bc0c050216763ce0..6bad3df3a13c7741095ac7e88c80d7d7e75d98c4 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 1f5f28bb0bb8082c5cb66dcb714af3fec6bed5e2..f39a5379e8165a0adf8e59f3fa34412822724289 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index ad1a0febd6207dc08521c245a8e650f30e149dff..e3b97093ef9a3cc60aa5a904bc39e7c31f2546b7 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 9513e071040da8f148dc63a6b2aca8f7d7018a83..56201a69af127322e0070b3f4b18c8a0d0355cec 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 0c424dae56e7e13a686bdf062baadcbb422d8fe6..6154c3ee11a5b32d94fd065e0b5abbf8c0109c79 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 16dc3a63a23d5f763b28c92d7fcc9170d0e2320e..d44df7ccfe43930fa51354ce4dab57545bb381f9 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index d77b2e1054efc25cf8207ec6b963ce853427255f..319b64491b7b504fd1fb67350d16e8374fd6cecf 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 4ea70cd22aee8fc70a75f9bfb5696122fee2bd32..fb042e0519d00f780d4a642e4b8a3e27bdec0d11 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 78ede3fd187559360d246cb8f52439fdbd2364ad..bb71ea214b9902ee63258acefaefc795bf18bbc8 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 40254f4df584f781100476dbd391941148042fc8..bcc4b968c0497cb74ec005c433a993054fe42273 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
index 9d874c85d64d7f5eb7f5d4c44fe785e8aa1c555a..1151f23177bb803df56a20fbc30be6032e382598 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index c34fc50070a6382fc48f9c428557c9f9bca5ee9b..defa050e17843d26db5ef685e8c4263fc64eb23b 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 2beb6b5045f8fd224e1f535c20254caa99aa9540..0b46be11705169b0cb8150d2a3792be72caae3c2 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 02794885de10be8329003300d19c2f8084ff9032..a5579b55e3329ee395cfbddd30eb034711e0aab1 100644 (file)
@@ -13,7 +13,6 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <scsi/scsi_host.h>
 #include <linux/ata.h>
index a6f05acad61ed01d68b0ec201698a8abc406cf44..73259bfda1e364e5e99b89aec1a6ae99400f6297 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/ata.h>
 #include <linux/libata.h>
index f582ba180a7d6e3c799a788f86c477ed43f36660..be3f10240dca4961f80d34437acaac78298dbea1 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 79a970f05a2e2bb54d60fcfa92211596f41791ec..521b2137ea3e39ccccb35cb78810316bebc26b72 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 040b093617a4ada5ffa76c61c2d20615644d5b35..caedc90855b2fdb931f39018b31f3d9f7b0effff 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index ce2f828c17b30f4ff5fa831c933d3174c6136d5d..96a232fffae6089ddfa77b8981e04115700e872a 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index f35f15f4d83e30288abf6506e9802c66f969ace7..f1f5b5ae33826356230f2689996c34065afb3f7a 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index d3830c45a369cd611ba99ff78bac235c5fc4e258..5a1cde0ea3601818456b44b51c0cc059ece726e0 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 96c6a79ef6066af0171b74864134f34a05ebb611..e27f31fe1b67b93a3c6c326be0d434a26d8d056a 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index c4b0b073ba8e8c7d13512a2c6930b987ba1a4745..73fe362d97161dffcb75a514c41b65fb9a5baf0b 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 1e8363640bf5e7bd16a065ce0222c161b745e459..78d913aa93c812f8eae1ccd572ad1c7ea1dfd22a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 6816911ac4229ba8e7dc46829cd2da9461015ef5..900f0e4a1faf61462b20f37b8b29176d194a17e0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index 94473da68c02d9664906f8c5c82a0f395d881d63..7bc78e264f9eda5cd4cd7eabc4a2acf6dae9bb7e 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
index c3ab9a6c3965b1c8df7045da6f6a1a10f414ca9b..f6c9632bdff6a11c6fbdcc18d7ff703d1c4b20cc 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
index 8ea6e6afd041db7736e6a69c88641253fa4b4078..f10631beffa87cd258950bb4c85778ce166205e0 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 523524b68022d3710f342d96f54926014de551ae..0bb2cabd2197bba01c0b4dd175f662a353eba076 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -462,8 +461,7 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)
        int chan;
        u32 tfr_reg, err_reg;
        unsigned long flags;
-       struct sata_dwc_device *hsdev =
-               (struct sata_dwc_device *)hsdev_instance;
+       struct sata_dwc_device *hsdev = hsdev_instance;
        struct ata_host *host = (struct ata_host *)hsdev->host;
        struct ata_port *ap;
        struct sata_dwc_device_port *hsdevp;
index 870b11eadc6d793d3abcebdcc6bb72c4cc326f45..65965cf5af06ba94c8c77ebfcf01ca584f81d0be 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -142,7 +141,7 @@ static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state,
                                        ssize_t size)
 {
        struct ahci_host_priv *hpriv =  ap->host->private_data;
-       struct ecx_plat_data *pdata = (struct ecx_plat_data *) hpriv->plat_data;
+       struct ecx_plat_data *pdata = hpriv->plat_data;
        struct ahci_port_priv *pp = ap->private_data;
        unsigned long flags;
        int pmp, i;
@@ -403,6 +402,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
        static const unsigned long timing[] = { 5, 100, 500};
        struct ata_port *ap = link->ap;
        struct ahci_port_priv *pp = ap->private_data;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
        struct ata_taskfile tf;
        bool online;
@@ -431,7 +431,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
                        break;
        } while (!online && retry--);
 
-       ahci_start_engine(ap);
+       hpriv->start_engine(ap);
 
        if (online)
                *class = ahci_dev_classify(ap);
index 20a7517bd3393d1a2adfcb6e4cb55afcd833e5f9..05c8a44adf8edea590ec983a7f843c1f5b6b1b55 100644 (file)
@@ -4104,7 +4104,6 @@ static int mv_platform_probe(struct platform_device *pdev)
        if (!hpriv->port_phys)
                return -ENOMEM;
        host->private_data = hpriv;
-       hpriv->n_ports = n_ports;
        hpriv->board_idx = chip_soc;
 
        host->iomap = NULL;
@@ -4126,17 +4125,24 @@ static int mv_platform_probe(struct platform_device *pdev)
                        clk_prepare_enable(hpriv->port_clks[port]);
 
                sprintf(port_number, "port%d", port);
-               hpriv->port_phys[port] = devm_phy_get(&pdev->dev, port_number);
+               hpriv->port_phys[port] = devm_phy_optional_get(&pdev->dev,
+                                                              port_number);
                if (IS_ERR(hpriv->port_phys[port])) {
                        rc = PTR_ERR(hpriv->port_phys[port]);
                        hpriv->port_phys[port] = NULL;
-                       if ((rc != -EPROBE_DEFER) && (rc != -ENODEV))
-                               dev_warn(&pdev->dev, "error getting phy");
+                       if (rc != -EPROBE_DEFER)
+                               dev_warn(&pdev->dev, "error getting phy %d", rc);
+
+                       /* Cleanup only the initialized ports */
+                       hpriv->n_ports = port;
                        goto err;
                } else
                        phy_power_on(hpriv->port_phys[port]);
        }
 
+       /* All the ports have been initialized */
+       hpriv->n_ports = n_ports;
+
        /*
         * (Re-)program MBUS remapping windows if we are asked to.
         */
@@ -4174,7 +4180,7 @@ err:
                clk_disable_unprepare(hpriv->clk);
                clk_put(hpriv->clk);
        }
-       for (port = 0; port < n_ports; port++) {
+       for (port = 0; port < hpriv->n_ports; port++) {
                if (!IS_ERR(hpriv->port_clks[port])) {
                        clk_disable_unprepare(hpriv->port_clks[port]);
                        clk_put(hpriv->port_clks[port]);
index d74def823d3ed865be0841d771fb7141ac1c1a07..ba5f27120332fe5b2e15d553cb7a7bc25aaa7a44 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 97f4acb54ad626795972ffb8e35572101d05d08d..3638887476f610a933d57b29cae7f84c4d6f229f 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 3b0dd57984e18370f5a659907c1c3326aed6fb49..9a6bd4cd29a0661cefd71f686e7c4bbc778911ed 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index d67fc351343ca841f7ea95b68e401f52f58953c2..3062f8605b2955956bff191d6034530ce7fbd636 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -157,6 +156,7 @@ static const struct sil_drivelist {
        { "ST380011ASL",        SIL_QUIRK_MOD15WRITE },
        { "ST3120022ASL",       SIL_QUIRK_MOD15WRITE },
        { "ST3160021ASL",       SIL_QUIRK_MOD15WRITE },
+       { "TOSHIBA MK2561GSYN", SIL_QUIRK_MOD15WRITE },
        { "Maxtor 4D060H3",     SIL_QUIRK_UDMA5MAX },
        { }
 };
index 1ad2f62d34b98fd0b41be9a239827e1634327c54..b513428171b3592a4033e597ec593a7e4189ab21 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index dc4f70179e7d37470dc358b02c96b328d8bbeeae..c630fa81262439939c3ad770f3538e48c0862522 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 9947010afc0f7973e2af77664f6ef39e53840358..39b5de60a1f96a93a80193b5a7ce8ec6e0ecea43 100644 (file)
@@ -82,7 +82,6 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -1021,8 +1020,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
        idx++;
        dist = ((long) (window_size - (offset + size))) >= 0 ? size :
                (long) (window_size - offset);
-       memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4),
-                     dist);
+       memcpy_fromio(psource, dimm_mmio + offset / 4, dist);
 
        psource += dist;
        size -= dist;
@@ -1031,8 +1029,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
                readl(mmio + PDC_GENERAL_CTLR);
                writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
                readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
-                             window_size / 4);
+               memcpy_fromio(psource, dimm_mmio, window_size / 4);
                psource += window_size;
                size -= window_size;
                idx++;
@@ -1043,8 +1040,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
                readl(mmio + PDC_GENERAL_CTLR);
                writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
                readl(mmio + PDC_DIMM_WINDOW_CTLR);
-               memcpy_fromio((char *) psource, (char *) (dimm_mmio),
-                             size / 4);
+               memcpy_fromio(psource, dimm_mmio, size / 4);
        }
 }
 #endif
index 6d6489118873fe50bd4f04a0cc3320e5eae5747c..08f98c3ed5c8e28f89d45ec467f3dec69f28d204 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index 87f056e54a9d7566504925ca812347baf6b3e62f..f72e84228c5c10e05db80755df5a64efd5606b38 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
index 44f304b3de63c6ee45fa87f88793e900359ac1be..29e847aac34be5ea88871ff03c99856b20c4492e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
index c53efe6c6d8eb49becd64f875857fc8d4888e955..c4778995cd728047d83a284d2e9248bbde89389f 100644 (file)
@@ -133,9 +133,16 @@ static int try_to_bring_up_master(struct master *master,
                        goto out;
                }
 
+               if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
                /* Found all components */
                ret = master->ops->bind(master->dev);
                if (ret < 0) {
+                       devres_release_group(master->dev, NULL);
+                       dev_info(master->dev, "master bind failed: %d\n", ret);
                        master_remove_components(master);
                        goto out;
                }
@@ -166,6 +173,7 @@ static void take_down_master(struct master *master)
 {
        if (master->bound) {
                master->ops->unbind(master->dev);
+               devres_release_group(master->dev, NULL);
                master->bound = false;
        }
 
index 1e16cbd61da27877bf372cc90f1323d950676db2..61d6d62cc0d35ff17d6e9736d9704ad3848e22a1 100644 (file)
@@ -616,36 +616,35 @@ static int dma_buf_describe(struct seq_file *s)
        if (ret)
                return ret;
 
-       seq_printf(s, "\nDma-buf Objects:\n");
-       seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n");
+       seq_puts(s, "\nDma-buf Objects:\n");
+       seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
 
        list_for_each_entry(buf_obj, &db_list.head, list_node) {
                ret = mutex_lock_interruptible(&buf_obj->lock);
 
                if (ret) {
-                       seq_printf(s,
-                                 "\tERROR locking buffer object: skipping\n");
+                       seq_puts(s,
+                                "\tERROR locking buffer object: skipping\n");
                        continue;
                }
 
-               seq_printf(s, "\t");
-
-               seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n",
-                               buf_obj->exp_name, buf_obj->size,
+               seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n",
+                               buf_obj->size,
                                buf_obj->file->f_flags, buf_obj->file->f_mode,
-                               (long)(buf_obj->file->f_count.counter));
+                               (long)(buf_obj->file->f_count.counter),
+                               buf_obj->exp_name);
 
-               seq_printf(s, "\t\tAttached Devices:\n");
+               seq_puts(s, "\tAttached Devices:\n");
                attach_count = 0;
 
                list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
-                       seq_printf(s, "\t\t");
+                       seq_puts(s, "\t");
 
-                       seq_printf(s, "%s\n", attach_obj->dev->init_name);
+                       seq_printf(s, "%s\n", dev_name(attach_obj->dev));
                        attach_count++;
                }
 
-               seq_printf(s, "\n\t\tTotal %d devices attached\n",
+               seq_printf(s, "Total %d devices attached\n\n",
                                attach_count);
 
                count++;
index 8a97ddfa61222db79506dcecebc619ab5a333865..c30df50e4440c3af5639af58dd567c37e8bf40e6 100644 (file)
@@ -1580,6 +1580,7 @@ static int fw_pm_notify(struct notifier_block *notify_block,
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
+       case PM_RESTORE_PREPARE:
                kill_requests_without_uevent();
                device_cache_fw_images();
                break;
index 8184451b57c04999bd23c286080e14ca7f069031..422b7d84f686b90147f97565210687d343a3d9eb 100644 (file)
@@ -874,7 +874,7 @@ bio_pageinc(struct bio *bio)
                /* Non-zero page count for non-head members of
                 * compound pages is no longer allowed by the kernel.
                 */
-               page = compound_trans_head(bv.bv_page);
+               page = compound_head(bv.bv_page);
                atomic_inc(&page->_count);
        }
 }
@@ -887,7 +887,7 @@ bio_pagedec(struct bio *bio)
        struct bvec_iter iter;
 
        bio_for_each_segment(bv, bio, iter) {
-               page = compound_trans_head(bv.bv_page);
+               page = compound_head(bv.bv_page);
                atomic_dec(&page->_count);
        }
 }
index 2023043ce7c0e94b0e3c3618eb0787a9ad5ddb73..8f5565bf34cda31504e526ccc3d79d4e7fe20fd2 100644 (file)
@@ -961,17 +961,31 @@ static void empty(void)
 {
 }
 
-static DECLARE_WORK(floppy_work, NULL);
+static void (*floppy_work_fn)(void);
+
+static void floppy_work_workfn(struct work_struct *work)
+{
+       floppy_work_fn();
+}
+
+static DECLARE_WORK(floppy_work, floppy_work_workfn);
 
 static void schedule_bh(void (*handler)(void))
 {
        WARN_ON(work_pending(&floppy_work));
 
-       PREPARE_WORK(&floppy_work, (work_func_t)handler);
+       floppy_work_fn = handler;
        queue_work(floppy_wq, &floppy_work);
 }
 
-static DECLARE_DELAYED_WORK(fd_timer, NULL);
+static void (*fd_timer_fn)(void) = NULL;
+
+static void fd_timer_workfn(struct work_struct *work)
+{
+       fd_timer_fn();
+}
+
+static DECLARE_DELAYED_WORK(fd_timer, fd_timer_workfn);
 
 static void cancel_activity(void)
 {
@@ -982,7 +996,7 @@ static void cancel_activity(void)
 
 /* this function makes sure that the disk stays in the drive during the
  * transfer */
-static void fd_watchdog(struct work_struct *arg)
+static void fd_watchdog(void)
 {
        debug_dcl(DP->flags, "calling disk change from watchdog\n");
 
@@ -993,7 +1007,7 @@ static void fd_watchdog(struct work_struct *arg)
                reset_fdc();
        } else {
                cancel_delayed_work(&fd_timer);
-               PREPARE_DELAYED_WORK(&fd_timer, fd_watchdog);
+               fd_timer_fn = fd_watchdog;
                queue_delayed_work(floppy_wq, &fd_timer, HZ / 10);
        }
 }
@@ -1005,7 +1019,8 @@ static void main_command_interrupt(void)
 }
 
 /* waits for a delay (spinup or select) to pass */
-static int fd_wait_for_completion(unsigned long expires, work_func_t function)
+static int fd_wait_for_completion(unsigned long expires,
+                                 void (*function)(void))
 {
        if (FDCS->reset) {
                reset_fdc();    /* do the reset during sleep to win time
@@ -1016,7 +1031,7 @@ static int fd_wait_for_completion(unsigned long expires, work_func_t function)
 
        if (time_before(jiffies, expires)) {
                cancel_delayed_work(&fd_timer);
-               PREPARE_DELAYED_WORK(&fd_timer, function);
+               fd_timer_fn = function;
                queue_delayed_work(floppy_wq, &fd_timer, expires - jiffies);
                return 1;
        }
@@ -1334,8 +1349,7 @@ static int fdc_dtr(void)
         * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
         */
        FDCS->dtr = raw_cmd->rate & 3;
-       return fd_wait_for_completion(jiffies + 2UL * HZ / 100,
-                                     (work_func_t)floppy_ready);
+       return fd_wait_for_completion(jiffies + 2UL * HZ / 100, floppy_ready);
 }                              /* fdc_dtr */
 
 static void tell_sector(void)
@@ -1440,7 +1454,7 @@ static void setup_rw_floppy(void)
        int flags;
        int dflags;
        unsigned long ready_date;
-       work_func_t function;
+       void (*function)(void);
 
        flags = raw_cmd->flags;
        if (flags & (FD_RAW_READ | FD_RAW_WRITE))
@@ -1454,9 +1468,9 @@ static void setup_rw_floppy(void)
                 */
                if (time_after(ready_date, jiffies + DP->select_delay)) {
                        ready_date -= DP->select_delay;
-                       function = (work_func_t)floppy_start;
+                       function = floppy_start;
                } else
-                       function = (work_func_t)setup_rw_floppy;
+                       function = setup_rw_floppy;
 
                /* wait until the floppy is spinning fast enough */
                if (fd_wait_for_completion(ready_date, function))
@@ -1486,7 +1500,7 @@ static void setup_rw_floppy(void)
                inr = result();
                cont->interrupt();
        } else if (flags & FD_RAW_NEED_DISK)
-               fd_watchdog(NULL);
+               fd_watchdog();
 }
 
 static int blind_seek;
@@ -1863,7 +1877,7 @@ static int start_motor(void (*function)(void))
 
        /* wait_for_completion also schedules reset if needed. */
        return fd_wait_for_completion(DRS->select_date + DP->select_delay,
-                                     (work_func_t)function);
+                                     function);
 }
 
 static void floppy_ready(void)
index 516026954be62d325a9e9d7c5541e5fbf51c7569..d777bb7cea93fd4338149fd9b91335305cce055b 100644 (file)
@@ -4498,7 +4498,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
        }
        dev_info(&pdev->dev, "NUMA node %d (closest: %d,%d, probe on %d:%d)\n",
                my_node, pcibus_to_node(pdev->bus), dev_to_node(&pdev->dev),
-               cpu_to_node(smp_processor_id()), smp_processor_id());
+               cpu_to_node(raw_smp_processor_id()), raw_smp_processor_id());
 
        dd = kzalloc_node(sizeof(struct driver_data), GFP_KERNEL, my_node);
        if (dd == NULL) {
index b52e9a6d6aad6d602bf3a9d6f73c9b4c277c7e17..54174cb32febe10a45eddd8e837d8267bfe594a1 100644 (file)
@@ -53,7 +53,7 @@
 #define MTIP_FTL_REBUILD_TIMEOUT_MS    2400000
 
 /* unaligned IO handling */
-#define MTIP_MAX_UNALIGNED_SLOTS       8
+#define MTIP_MAX_UNALIGNED_SLOTS       2
 
 /* Macro to extract the tag bit number from a tag value. */
 #define MTIP_TAG_BIT(tag)      (tag & 0x1F)
index 3107282a9741f96665a2805b08217d3209c27bf7..091b9ea14feb5856ceada49671197dfac567376c 100644 (file)
@@ -60,7 +60,9 @@ enum {
        NULL_IRQ_NONE           = 0,
        NULL_IRQ_SOFTIRQ        = 1,
        NULL_IRQ_TIMER          = 2,
+};
 
+enum {
        NULL_Q_BIO              = 0,
        NULL_Q_RQ               = 1,
        NULL_Q_MQ               = 2,
@@ -172,18 +174,20 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait)
 
 static void end_cmd(struct nullb_cmd *cmd)
 {
-       if (cmd->rq) {
-               if (queue_mode == NULL_Q_MQ)
-                       blk_mq_end_io(cmd->rq, 0);
-               else {
-                       INIT_LIST_HEAD(&cmd->rq->queuelist);
-                       blk_end_request_all(cmd->rq, 0);
-               }
-       } else if (cmd->bio)
+       switch (queue_mode)  {
+       case NULL_Q_MQ:
+               blk_mq_end_io(cmd->rq, 0);
+               return;
+       case NULL_Q_RQ:
+               INIT_LIST_HEAD(&cmd->rq->queuelist);
+               blk_end_request_all(cmd->rq, 0);
+               break;
+       case NULL_Q_BIO:
                bio_endio(cmd->bio, 0);
+               break;
+       }
 
-       if (queue_mode != NULL_Q_MQ)
-               free_cmd(cmd);
+       free_cmd(cmd);
 }
 
 static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
@@ -195,6 +199,7 @@ static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
        cq = &per_cpu(completion_queues, smp_processor_id());
 
        while ((entry = llist_del_all(&cq->list)) != NULL) {
+               entry = llist_reverse_order(entry);
                do {
                        cmd = container_of(entry, struct nullb_cmd, ll_list);
                        end_cmd(cmd);
@@ -221,61 +226,31 @@ static void null_cmd_end_timer(struct nullb_cmd *cmd)
 
 static void null_softirq_done_fn(struct request *rq)
 {
-       blk_end_request_all(rq, 0);
-}
-
-#ifdef CONFIG_SMP
-
-static void null_ipi_cmd_end_io(void *data)
-{
-       struct completion_queue *cq;
-       struct llist_node *entry, *next;
-       struct nullb_cmd *cmd;
-
-       cq = &per_cpu(completion_queues, smp_processor_id());
-
-       entry = llist_del_all(&cq->list);
-
-       while (entry) {
-               next = entry->next;
-               cmd = llist_entry(entry, struct nullb_cmd, ll_list);
-               end_cmd(cmd);
-               entry = next;
-       }
-}
-
-static void null_cmd_end_ipi(struct nullb_cmd *cmd)
-{
-       struct call_single_data *data = &cmd->csd;
-       int cpu = get_cpu();
-       struct completion_queue *cq = &per_cpu(completion_queues, cpu);
-
-       cmd->ll_list.next = NULL;
-
-       if (llist_add(&cmd->ll_list, &cq->list)) {
-               data->func = null_ipi_cmd_end_io;
-               data->flags = 0;
-               __smp_call_function_single(cpu, data, 0);
-       }
-
-       put_cpu();
+       end_cmd(rq->special);
 }
 
-#endif /* CONFIG_SMP */
-
 static inline void null_handle_cmd(struct nullb_cmd *cmd)
 {
        /* Complete IO by inline, softirq or timer */
        switch (irqmode) {
-       case NULL_IRQ_NONE:
-               end_cmd(cmd);
-               break;
        case NULL_IRQ_SOFTIRQ:
-#ifdef CONFIG_SMP
-               null_cmd_end_ipi(cmd);
-#else
+               switch (queue_mode)  {
+               case NULL_Q_MQ:
+                       blk_mq_complete_request(cmd->rq);
+                       break;
+               case NULL_Q_RQ:
+                       blk_complete_request(cmd->rq);
+                       break;
+               case NULL_Q_BIO:
+                       /*
+                        * XXX: no proper submitting cpu information available.
+                        */
+                       end_cmd(cmd);
+                       break;
+               }
+               break;
+       case NULL_IRQ_NONE:
                end_cmd(cmd);
-#endif
                break;
        case NULL_IRQ_TIMER:
                null_cmd_end_timer(cmd);
@@ -411,6 +386,7 @@ static struct blk_mq_ops null_mq_ops = {
        .queue_rq       = null_queue_rq,
        .map_queue      = blk_mq_map_queue,
        .init_hctx      = null_init_hctx,
+       .complete       = null_softirq_done_fn,
 };
 
 static struct blk_mq_reg null_mq_reg = {
@@ -609,13 +585,6 @@ static int __init null_init(void)
 {
        unsigned int i;
 
-#if !defined(CONFIG_SMP)
-       if (irqmode == NULL_IRQ_SOFTIRQ) {
-               pr_warn("null_blk: softirq completions not available.\n");
-               pr_warn("null_blk: using direct completions.\n");
-               irqmode = NULL_IRQ_NONE;
-       }
-#endif
        if (bs > PAGE_SIZE) {
                pr_warn("null_blk: invalid block size\n");
                pr_warn("null_blk: defaults block size to %lu\n", PAGE_SIZE);
index 1f14ac4039450e84137b4eab0dacf043aa46d16e..8459e4e7c71940462134eb6a7ad68c86f03ebb7a 100644 (file)
@@ -46,7 +46,6 @@
 #define NVME_Q_DEPTH 1024
 #define SQ_SIZE(depth)         (depth * sizeof(struct nvme_command))
 #define CQ_SIZE(depth)         (depth * sizeof(struct nvme_completion))
-#define NVME_MINORS 64
 #define ADMIN_TIMEOUT  (60 * HZ)
 
 static int nvme_major;
@@ -58,6 +57,17 @@ module_param(use_threaded_interrupts, int, 0);
 static DEFINE_SPINLOCK(dev_list_lock);
 static LIST_HEAD(dev_list);
 static struct task_struct *nvme_thread;
+static struct workqueue_struct *nvme_workq;
+
+static void nvme_reset_failed_dev(struct work_struct *ws);
+
+struct async_cmd_info {
+       struct kthread_work work;
+       struct kthread_worker *worker;
+       u32 result;
+       int status;
+       void *ctx;
+};
 
 /*
  * An NVM Express queue.  Each device has at least two (one for admin
@@ -66,6 +76,7 @@ static struct task_struct *nvme_thread;
 struct nvme_queue {
        struct device *q_dmadev;
        struct nvme_dev *dev;
+       char irqname[24];       /* nvme4294967295-65535\0 */
        spinlock_t q_lock;
        struct nvme_command *sq_cmds;
        volatile struct nvme_completion *cqes;
@@ -80,9 +91,11 @@ struct nvme_queue {
        u16 sq_head;
        u16 sq_tail;
        u16 cq_head;
+       u16 qid;
        u8 cq_phase;
        u8 cqe_seen;
        u8 q_suspended;
+       struct async_cmd_info cmdinfo;
        unsigned long cmdid_data[];
 };
 
@@ -97,6 +110,7 @@ static inline void _nvme_check_size(void)
        BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_features) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_format_cmd) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_abort_cmd) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_command) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096);
        BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096);
@@ -111,6 +125,7 @@ struct nvme_cmd_info {
        nvme_completion_fn fn;
        void *ctx;
        unsigned long timeout;
+       int aborted;
 };
 
 static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq)
@@ -154,6 +169,7 @@ static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx,
        info[cmdid].fn = handler;
        info[cmdid].ctx = ctx;
        info[cmdid].timeout = jiffies + timeout;
+       info[cmdid].aborted = 0;
        return cmdid;
 }
 
@@ -172,6 +188,7 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx,
 #define CMD_CTX_COMPLETED      (0x310 + CMD_CTX_BASE)
 #define CMD_CTX_INVALID                (0x314 + CMD_CTX_BASE)
 #define CMD_CTX_FLUSH          (0x318 + CMD_CTX_BASE)
+#define CMD_CTX_ABORT          (0x31C + CMD_CTX_BASE)
 
 static void special_completion(struct nvme_dev *dev, void *ctx,
                                                struct nvme_completion *cqe)
@@ -180,6 +197,10 @@ static void special_completion(struct nvme_dev *dev, void *ctx,
                return;
        if (ctx == CMD_CTX_FLUSH)
                return;
+       if (ctx == CMD_CTX_ABORT) {
+               ++dev->abort_limit;
+               return;
+       }
        if (ctx == CMD_CTX_COMPLETED) {
                dev_warn(&dev->pci_dev->dev,
                                "completed id %d twice on queue %d\n",
@@ -196,6 +217,15 @@ static void special_completion(struct nvme_dev *dev, void *ctx,
        dev_warn(&dev->pci_dev->dev, "Unknown special completion %p\n", ctx);
 }
 
+static void async_completion(struct nvme_dev *dev, void *ctx,
+                                               struct nvme_completion *cqe)
+{
+       struct async_cmd_info *cmdinfo = ctx;
+       cmdinfo->result = le32_to_cpup(&cqe->result);
+       cmdinfo->status = le16_to_cpup(&cqe->status) >> 1;
+       queue_kthread_work(cmdinfo->worker, &cmdinfo->work);
+}
+
 /*
  * Called with local interrupts disabled and the q_lock held.  May not sleep.
  */
@@ -693,7 +723,7 @@ static int nvme_process_cq(struct nvme_queue *nvmeq)
        if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
                return 0;
 
-       writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride));
+       writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
        nvmeq->cq_head = head;
        nvmeq->cq_phase = phase;
 
@@ -804,12 +834,34 @@ int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd,
        return cmdinfo.status;
 }
 
+static int nvme_submit_async_cmd(struct nvme_queue *nvmeq,
+                       struct nvme_command *cmd,
+                       struct async_cmd_info *cmdinfo, unsigned timeout)
+{
+       int cmdid;
+
+       cmdid = alloc_cmdid_killable(nvmeq, cmdinfo, async_completion, timeout);
+       if (cmdid < 0)
+               return cmdid;
+       cmdinfo->status = -EINTR;
+       cmd->common.command_id = cmdid;
+       nvme_submit_cmd(nvmeq, cmd);
+       return 0;
+}
+
 int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd,
                                                                u32 *result)
 {
        return nvme_submit_sync_cmd(dev->queues[0], cmd, result, ADMIN_TIMEOUT);
 }
 
+static int nvme_submit_admin_cmd_async(struct nvme_dev *dev,
+               struct nvme_command *cmd, struct async_cmd_info *cmdinfo)
+{
+       return nvme_submit_async_cmd(dev->queues[0], cmd, cmdinfo,
+                                                               ADMIN_TIMEOUT);
+}
+
 static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
 {
        int status;
@@ -919,6 +971,56 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
        return nvme_submit_admin_cmd(dev, &c, result);
 }
 
+/**
+ * nvme_abort_cmd - Attempt aborting a command
+ * @cmdid: Command id of a timed out IO
+ * @queue: The queue with timed out IO
+ *
+ * Schedule controller reset if the command was already aborted once before and
+ * still hasn't been returned to the driver, or if this is the admin queue.
+ */
+static void nvme_abort_cmd(int cmdid, struct nvme_queue *nvmeq)
+{
+       int a_cmdid;
+       struct nvme_command cmd;
+       struct nvme_dev *dev = nvmeq->dev;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+
+       if (!nvmeq->qid || info[cmdid].aborted) {
+               if (work_busy(&dev->reset_work))
+                       return;
+               list_del_init(&dev->node);
+               dev_warn(&dev->pci_dev->dev,
+                       "I/O %d QID %d timeout, reset controller\n", cmdid,
+                                                               nvmeq->qid);
+               dev->reset_workfn = nvme_reset_failed_dev;
+               queue_work(nvme_workq, &dev->reset_work);
+               return;
+       }
+
+       if (!dev->abort_limit)
+               return;
+
+       a_cmdid = alloc_cmdid(dev->queues[0], CMD_CTX_ABORT, special_completion,
+                                                               ADMIN_TIMEOUT);
+       if (a_cmdid < 0)
+               return;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.abort.opcode = nvme_admin_abort_cmd;
+       cmd.abort.cid = cmdid;
+       cmd.abort.sqid = cpu_to_le16(nvmeq->qid);
+       cmd.abort.command_id = a_cmdid;
+
+       --dev->abort_limit;
+       info[cmdid].aborted = 1;
+       info[cmdid].timeout = jiffies + ADMIN_TIMEOUT;
+
+       dev_warn(nvmeq->q_dmadev, "Aborting I/O %d QID %d\n", cmdid,
+                                                       nvmeq->qid);
+       nvme_submit_cmd(dev->queues[0], &cmd);
+}
+
 /**
  * nvme_cancel_ios - Cancel outstanding I/Os
  * @queue: The queue to cancel I/Os on
@@ -942,7 +1044,12 @@ static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout)
                        continue;
                if (info[cmdid].ctx == CMD_CTX_CANCELLED)
                        continue;
-               dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid);
+               if (timeout && nvmeq->dev->initialized) {
+                       nvme_abort_cmd(cmdid, nvmeq);
+                       continue;
+               }
+               dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d QID %d\n", cmdid,
+                                                               nvmeq->qid);
                ctx = cancel_cmdid(nvmeq, cmdid, &fn);
                fn(nvmeq->dev, ctx, &cqe);
        }
@@ -964,26 +1071,31 @@ static void nvme_free_queue(struct nvme_queue *nvmeq)
        kfree(nvmeq);
 }
 
-static void nvme_free_queues(struct nvme_dev *dev)
+static void nvme_free_queues(struct nvme_dev *dev, int lowest)
 {
        int i;
 
-       for (i = dev->queue_count - 1; i >= 0; i--) {
+       for (i = dev->queue_count - 1; i >= lowest; i--) {
                nvme_free_queue(dev->queues[i]);
                dev->queue_count--;
                dev->queues[i] = NULL;
        }
 }
 
-static void nvme_disable_queue(struct nvme_dev *dev, int qid)
+/**
+ * nvme_suspend_queue - put queue into suspended state
+ * @nvmeq - queue to suspend
+ *
+ * Returns 1 if already suspended, 0 otherwise.
+ */
+static int nvme_suspend_queue(struct nvme_queue *nvmeq)
 {
-       struct nvme_queue *nvmeq = dev->queues[qid];
-       int vector = dev->entry[nvmeq->cq_vector].vector;
+       int vector = nvmeq->dev->entry[nvmeq->cq_vector].vector;
 
        spin_lock_irq(&nvmeq->q_lock);
        if (nvmeq->q_suspended) {
                spin_unlock_irq(&nvmeq->q_lock);
-               return;
+               return 1;
        }
        nvmeq->q_suspended = 1;
        spin_unlock_irq(&nvmeq->q_lock);
@@ -991,18 +1103,35 @@ static void nvme_disable_queue(struct nvme_dev *dev, int qid)
        irq_set_affinity_hint(vector, NULL);
        free_irq(vector, nvmeq);
 
-       /* Don't tell the adapter to delete the admin queue */
-       if (qid) {
-               adapter_delete_sq(dev, qid);
-               adapter_delete_cq(dev, qid);
-       }
+       return 0;
+}
 
+static void nvme_clear_queue(struct nvme_queue *nvmeq)
+{
        spin_lock_irq(&nvmeq->q_lock);
        nvme_process_cq(nvmeq);
        nvme_cancel_ios(nvmeq, false);
        spin_unlock_irq(&nvmeq->q_lock);
 }
 
+static void nvme_disable_queue(struct nvme_dev *dev, int qid)
+{
+       struct nvme_queue *nvmeq = dev->queues[qid];
+
+       if (!nvmeq)
+               return;
+       if (nvme_suspend_queue(nvmeq))
+               return;
+
+       /* Don't tell the adapter to delete the admin queue.
+        * Don't tell a removed adapter to delete IO queues. */
+       if (qid && readl(&dev->bar->csts) != -1) {
+               adapter_delete_sq(dev, qid);
+               adapter_delete_cq(dev, qid);
+       }
+       nvme_clear_queue(nvmeq);
+}
+
 static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
                                                        int depth, int vector)
 {
@@ -1025,15 +1154,18 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 
        nvmeq->q_dmadev = dmadev;
        nvmeq->dev = dev;
+       snprintf(nvmeq->irqname, sizeof(nvmeq->irqname), "nvme%dq%d",
+                       dev->instance, qid);
        spin_lock_init(&nvmeq->q_lock);
        nvmeq->cq_head = 0;
        nvmeq->cq_phase = 1;
        init_waitqueue_head(&nvmeq->sq_full);
        init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread);
        bio_list_init(&nvmeq->sq_cong);
-       nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
+       nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
        nvmeq->q_depth = depth;
        nvmeq->cq_vector = vector;
+       nvmeq->qid = qid;
        nvmeq->q_suspended = 1;
        dev->queue_count++;
 
@@ -1052,11 +1184,10 @@ static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq,
 {
        if (use_threaded_interrupts)
                return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector,
-                                       nvme_irq_check, nvme_irq,
-                                       IRQF_DISABLED | IRQF_SHARED,
+                                       nvme_irq_check, nvme_irq, IRQF_SHARED,
                                        name, nvmeq);
        return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq,
-                               IRQF_DISABLED | IRQF_SHARED, name, nvmeq);
+                               IRQF_SHARED, name, nvmeq);
 }
 
 static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
@@ -1067,7 +1198,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
        nvmeq->sq_tail = 0;
        nvmeq->cq_head = 0;
        nvmeq->cq_phase = 1;
-       nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
+       nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
        memset(nvmeq->cmdid_data, 0, extra);
        memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq->q_depth));
        nvme_cancel_ios(nvmeq, false);
@@ -1087,13 +1218,13 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
        if (result < 0)
                goto release_cq;
 
-       result = queue_request_irq(dev, nvmeq, "nvme");
+       result = queue_request_irq(dev, nvmeq, nvmeq->irqname);
        if (result < 0)
                goto release_sq;
 
-       spin_lock(&nvmeq->q_lock);
+       spin_lock_irq(&nvmeq->q_lock);
        nvme_init_queue(nvmeq, qid);
-       spin_unlock(&nvmeq->q_lock);
+       spin_unlock_irq(&nvmeq->q_lock);
 
        return result;
 
@@ -1205,13 +1336,13 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
        if (result)
                return result;
 
-       result = queue_request_irq(dev, nvmeq, "nvme admin");
+       result = queue_request_irq(dev, nvmeq, nvmeq->irqname);
        if (result)
                return result;
 
-       spin_lock(&nvmeq->q_lock);
+       spin_lock_irq(&nvmeq->q_lock);
        nvme_init_queue(nvmeq, 0);
-       spin_unlock(&nvmeq->q_lock);
+       spin_unlock_irq(&nvmeq->q_lock);
        return result;
 }
 
@@ -1487,10 +1618,47 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
        }
 }
 
+#ifdef CONFIG_COMPAT
+static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode,
+                                       unsigned int cmd, unsigned long arg)
+{
+       struct nvme_ns *ns = bdev->bd_disk->private_data;
+
+       switch (cmd) {
+       case SG_IO:
+               return nvme_sg_io32(ns, arg);
+       }
+       return nvme_ioctl(bdev, mode, cmd, arg);
+}
+#else
+#define nvme_compat_ioctl      NULL
+#endif
+
+static int nvme_open(struct block_device *bdev, fmode_t mode)
+{
+       struct nvme_ns *ns = bdev->bd_disk->private_data;
+       struct nvme_dev *dev = ns->dev;
+
+       kref_get(&dev->kref);
+       return 0;
+}
+
+static void nvme_free_dev(struct kref *kref);
+
+static void nvme_release(struct gendisk *disk, fmode_t mode)
+{
+       struct nvme_ns *ns = disk->private_data;
+       struct nvme_dev *dev = ns->dev;
+
+       kref_put(&dev->kref, nvme_free_dev);
+}
+
 static const struct block_device_operations nvme_fops = {
        .owner          = THIS_MODULE,
        .ioctl          = nvme_ioctl,
-       .compat_ioctl   = nvme_ioctl,
+       .compat_ioctl   = nvme_compat_ioctl,
+       .open           = nvme_open,
+       .release        = nvme_release,
 };
 
 static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
@@ -1514,13 +1682,24 @@ static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
 
 static int nvme_kthread(void *data)
 {
-       struct nvme_dev *dev;
+       struct nvme_dev *dev, *next;
 
        while (!kthread_should_stop()) {
                set_current_state(TASK_INTERRUPTIBLE);
                spin_lock(&dev_list_lock);
-               list_for_each_entry(dev, &dev_list, node) {
+               list_for_each_entry_safe(dev, next, &dev_list, node) {
                        int i;
+                       if (readl(&dev->bar->csts) & NVME_CSTS_CFS &&
+                                                       dev->initialized) {
+                               if (work_busy(&dev->reset_work))
+                                       continue;
+                               list_del_init(&dev->node);
+                               dev_warn(&dev->pci_dev->dev,
+                                       "Failed status, reset controller\n");
+                               dev->reset_workfn = nvme_reset_failed_dev;
+                               queue_work(nvme_workq, &dev->reset_work);
+                               continue;
+                       }
                        for (i = 0; i < dev->queue_count; i++) {
                                struct nvme_queue *nvmeq = dev->queues[i];
                                if (!nvmeq)
@@ -1541,33 +1720,6 @@ static int nvme_kthread(void *data)
        return 0;
 }
 
-static DEFINE_IDA(nvme_index_ida);
-
-static int nvme_get_ns_idx(void)
-{
-       int index, error;
-
-       do {
-               if (!ida_pre_get(&nvme_index_ida, GFP_KERNEL))
-                       return -1;
-
-               spin_lock(&dev_list_lock);
-               error = ida_get_new(&nvme_index_ida, &index);
-               spin_unlock(&dev_list_lock);
-       } while (error == -EAGAIN);
-
-       if (error)
-               index = -1;
-       return index;
-}
-
-static void nvme_put_ns_idx(int index)
-{
-       spin_lock(&dev_list_lock);
-       ida_remove(&nvme_index_ida, index);
-       spin_unlock(&dev_list_lock);
-}
-
 static void nvme_config_discard(struct nvme_ns *ns)
 {
        u32 logical_block_size = queue_logical_block_size(ns->queue);
@@ -1601,7 +1753,7 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
        ns->dev = dev;
        ns->queue->queuedata = ns;
 
-       disk = alloc_disk(NVME_MINORS);
+       disk = alloc_disk(0);
        if (!disk)
                goto out_free_queue;
        ns->ns_id = nsid;
@@ -1614,12 +1766,12 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
                blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
 
        disk->major = nvme_major;
-       disk->minors = NVME_MINORS;
-       disk->first_minor = NVME_MINORS * nvme_get_ns_idx();
+       disk->first_minor = 0;
        disk->fops = &nvme_fops;
        disk->private_data = ns;
        disk->queue = ns->queue;
        disk->driverfs_dev = &dev->pci_dev->dev;
+       disk->flags = GENHD_FL_EXT_DEVT;
        sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
        set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
 
@@ -1635,15 +1787,6 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
        return NULL;
 }
 
-static void nvme_ns_free(struct nvme_ns *ns)
-{
-       int index = ns->disk->first_minor / NVME_MINORS;
-       put_disk(ns->disk);
-       nvme_put_ns_idx(index);
-       blk_cleanup_queue(ns->queue);
-       kfree(ns);
-}
-
 static int set_queue_count(struct nvme_dev *dev, int count)
 {
        int status;
@@ -1659,11 +1802,12 @@ static int set_queue_count(struct nvme_dev *dev, int count)
 
 static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
 {
-       return 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3));
+       return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
 }
 
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
+       struct nvme_queue *adminq = dev->queues[0];
        struct pci_dev *pdev = dev->pci_dev;
        int result, cpu, i, vecs, nr_io_queues, size, q_depth;
 
@@ -1690,7 +1834,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        }
 
        /* Deregister the admin queue's interrupt */
-       free_irq(dev->entry[0].vector, dev->queues[0]);
+       free_irq(dev->entry[0].vector, adminq);
 
        vecs = nr_io_queues;
        for (i = 0; i < vecs; i++)
@@ -1728,9 +1872,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
         */
        nr_io_queues = vecs;
 
-       result = queue_request_irq(dev, dev->queues[0], "nvme admin");
+       result = queue_request_irq(dev, adminq, adminq->irqname);
        if (result) {
-               dev->queues[0]->q_suspended = 1;
+               adminq->q_suspended = 1;
                goto free_queues;
        }
 
@@ -1739,9 +1883,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        for (i = dev->queue_count - 1; i > nr_io_queues; i--) {
                struct nvme_queue *nvmeq = dev->queues[i];
 
-               spin_lock(&nvmeq->q_lock);
+               spin_lock_irq(&nvmeq->q_lock);
                nvme_cancel_ios(nvmeq, false);
-               spin_unlock(&nvmeq->q_lock);
+               spin_unlock_irq(&nvmeq->q_lock);
 
                nvme_free_queue(nvmeq);
                dev->queue_count--;
@@ -1782,7 +1926,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        return 0;
 
  free_queues:
-       nvme_free_queues(dev);
+       nvme_free_queues(dev, 1);
        return result;
 }
 
@@ -1794,6 +1938,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
  */
 static int nvme_dev_add(struct nvme_dev *dev)
 {
+       struct pci_dev *pdev = dev->pci_dev;
        int res;
        unsigned nn, i;
        struct nvme_ns *ns;
@@ -1803,8 +1948,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
        dma_addr_t dma_addr;
        int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
 
-       mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr,
-                                                               GFP_KERNEL);
+       mem = dma_alloc_coherent(&pdev->dev, 8192, &dma_addr, GFP_KERNEL);
        if (!mem)
                return -ENOMEM;
 
@@ -1817,13 +1961,14 @@ static int nvme_dev_add(struct nvme_dev *dev)
        ctrl = mem;
        nn = le32_to_cpup(&ctrl->nn);
        dev->oncs = le16_to_cpup(&ctrl->oncs);
+       dev->abort_limit = ctrl->acl + 1;
        memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
        memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
        memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
        if (ctrl->mdts)
                dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
-       if ((dev->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
-                       (dev->pci_dev->device == 0x0953) && ctrl->vs[3])
+       if ((pdev->vendor == PCI_VENDOR_ID_INTEL) &&
+                       (pdev->device == 0x0953) && ctrl->vs[3])
                dev->stripe_size = 1 << (ctrl->vs[3] + shift);
 
        id_ns = mem;
@@ -1871,16 +2016,21 @@ static int nvme_dev_map(struct nvme_dev *dev)
            dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
                goto disable;
 
-       pci_set_drvdata(pdev, dev);
        dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
        if (!dev->bar)
                goto disable;
-
-       dev->db_stride = NVME_CAP_STRIDE(readq(&dev->bar->cap));
+       if (readl(&dev->bar->csts) == -1) {
+               result = -ENODEV;
+               goto unmap;
+       }
+       dev->db_stride = 1 << NVME_CAP_STRIDE(readq(&dev->bar->cap));
        dev->dbs = ((void __iomem *)dev->bar) + 4096;
 
        return 0;
 
+ unmap:
+       iounmap(dev->bar);
+       dev->bar = NULL;
  disable:
        pci_release_regions(pdev);
  disable_pci:
@@ -1898,37 +2048,183 @@ static void nvme_dev_unmap(struct nvme_dev *dev)
        if (dev->bar) {
                iounmap(dev->bar);
                dev->bar = NULL;
+               pci_release_regions(dev->pci_dev);
        }
 
-       pci_release_regions(dev->pci_dev);
        if (pci_is_enabled(dev->pci_dev))
                pci_disable_device(dev->pci_dev);
 }
 
+struct nvme_delq_ctx {
+       struct task_struct *waiter;
+       struct kthread_worker *worker;
+       atomic_t refcount;
+};
+
+static void nvme_wait_dq(struct nvme_delq_ctx *dq, struct nvme_dev *dev)
+{
+       dq->waiter = current;
+       mb();
+
+       for (;;) {
+               set_current_state(TASK_KILLABLE);
+               if (!atomic_read(&dq->refcount))
+                       break;
+               if (!schedule_timeout(ADMIN_TIMEOUT) ||
+                                       fatal_signal_pending(current)) {
+                       set_current_state(TASK_RUNNING);
+
+                       nvme_disable_ctrl(dev, readq(&dev->bar->cap));
+                       nvme_disable_queue(dev, 0);
+
+                       send_sig(SIGKILL, dq->worker->task, 1);
+                       flush_kthread_worker(dq->worker);
+                       return;
+               }
+       }
+       set_current_state(TASK_RUNNING);
+}
+
+static void nvme_put_dq(struct nvme_delq_ctx *dq)
+{
+       atomic_dec(&dq->refcount);
+       if (dq->waiter)
+               wake_up_process(dq->waiter);
+}
+
+static struct nvme_delq_ctx *nvme_get_dq(struct nvme_delq_ctx *dq)
+{
+       atomic_inc(&dq->refcount);
+       return dq;
+}
+
+static void nvme_del_queue_end(struct nvme_queue *nvmeq)
+{
+       struct nvme_delq_ctx *dq = nvmeq->cmdinfo.ctx;
+
+       nvme_clear_queue(nvmeq);
+       nvme_put_dq(dq);
+}
+
+static int adapter_async_del_queue(struct nvme_queue *nvmeq, u8 opcode,
+                                               kthread_work_func_t fn)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.delete_queue.opcode = opcode;
+       c.delete_queue.qid = cpu_to_le16(nvmeq->qid);
+
+       init_kthread_work(&nvmeq->cmdinfo.work, fn);
+       return nvme_submit_admin_cmd_async(nvmeq->dev, &c, &nvmeq->cmdinfo);
+}
+
+static void nvme_del_cq_work_handler(struct kthread_work *work)
+{
+       struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
+                                                       cmdinfo.work);
+       nvme_del_queue_end(nvmeq);
+}
+
+static int nvme_delete_cq(struct nvme_queue *nvmeq)
+{
+       return adapter_async_del_queue(nvmeq, nvme_admin_delete_cq,
+                                               nvme_del_cq_work_handler);
+}
+
+static void nvme_del_sq_work_handler(struct kthread_work *work)
+{
+       struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
+                                                       cmdinfo.work);
+       int status = nvmeq->cmdinfo.status;
+
+       if (!status)
+               status = nvme_delete_cq(nvmeq);
+       if (status)
+               nvme_del_queue_end(nvmeq);
+}
+
+static int nvme_delete_sq(struct nvme_queue *nvmeq)
+{
+       return adapter_async_del_queue(nvmeq, nvme_admin_delete_sq,
+                                               nvme_del_sq_work_handler);
+}
+
+static void nvme_del_queue_start(struct kthread_work *work)
+{
+       struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
+                                                       cmdinfo.work);
+       allow_signal(SIGKILL);
+       if (nvme_delete_sq(nvmeq))
+               nvme_del_queue_end(nvmeq);
+}
+
+static void nvme_disable_io_queues(struct nvme_dev *dev)
+{
+       int i;
+       DEFINE_KTHREAD_WORKER_ONSTACK(worker);
+       struct nvme_delq_ctx dq;
+       struct task_struct *kworker_task = kthread_run(kthread_worker_fn,
+                                       &worker, "nvme%d", dev->instance);
+
+       if (IS_ERR(kworker_task)) {
+               dev_err(&dev->pci_dev->dev,
+                       "Failed to create queue del task\n");
+               for (i = dev->queue_count - 1; i > 0; i--)
+                       nvme_disable_queue(dev, i);
+               return;
+       }
+
+       dq.waiter = NULL;
+       atomic_set(&dq.refcount, 0);
+       dq.worker = &worker;
+       for (i = dev->queue_count - 1; i > 0; i--) {
+               struct nvme_queue *nvmeq = dev->queues[i];
+
+               if (nvme_suspend_queue(nvmeq))
+                       continue;
+               nvmeq->cmdinfo.ctx = nvme_get_dq(&dq);
+               nvmeq->cmdinfo.worker = dq.worker;
+               init_kthread_work(&nvmeq->cmdinfo.work, nvme_del_queue_start);
+               queue_kthread_work(dq.worker, &nvmeq->cmdinfo.work);
+       }
+       nvme_wait_dq(&dq, dev);
+       kthread_stop(kworker_task);
+}
+
 static void nvme_dev_shutdown(struct nvme_dev *dev)
 {
        int i;
 
-       for (i = dev->queue_count - 1; i >= 0; i--)
-               nvme_disable_queue(dev, i);
+       dev->initialized = 0;
 
        spin_lock(&dev_list_lock);
        list_del_init(&dev->node);
        spin_unlock(&dev_list_lock);
 
-       if (dev->bar)
+       if (!dev->bar || (dev->bar && readl(&dev->bar->csts) == -1)) {
+               for (i = dev->queue_count - 1; i >= 0; i--) {
+                       struct nvme_queue *nvmeq = dev->queues[i];
+                       nvme_suspend_queue(nvmeq);
+                       nvme_clear_queue(nvmeq);
+               }
+       } else {
+               nvme_disable_io_queues(dev);
                nvme_shutdown_ctrl(dev);
+               nvme_disable_queue(dev, 0);
+       }
        nvme_dev_unmap(dev);
 }
 
 static void nvme_dev_remove(struct nvme_dev *dev)
 {
-       struct nvme_ns *ns, *next;
+       struct nvme_ns *ns;
 
-       list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
-               list_del(&ns->list);
-               del_gendisk(ns->disk);
-               nvme_ns_free(ns);
+       list_for_each_entry(ns, &dev->namespaces, list) {
+               if (ns->disk->flags & GENHD_FL_UP)
+                       del_gendisk(ns->disk);
+               if (!blk_queue_dying(ns->queue))
+                       blk_cleanup_queue(ns->queue);
        }
 }
 
@@ -1985,14 +2281,22 @@ static void nvme_release_instance(struct nvme_dev *dev)
        spin_unlock(&dev_list_lock);
 }
 
+static void nvme_free_namespaces(struct nvme_dev *dev)
+{
+       struct nvme_ns *ns, *next;
+
+       list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
+               list_del(&ns->list);
+               put_disk(ns->disk);
+               kfree(ns);
+       }
+}
+
 static void nvme_free_dev(struct kref *kref)
 {
        struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
-       nvme_dev_remove(dev);
-       nvme_dev_shutdown(dev);
-       nvme_free_queues(dev);
-       nvme_release_instance(dev);
-       nvme_release_prp_pools(dev);
+
+       nvme_free_namespaces(dev);
        kfree(dev->queues);
        kfree(dev->entry);
        kfree(dev);
@@ -2056,6 +2360,7 @@ static int nvme_dev_start(struct nvme_dev *dev)
        return result;
 
  disable:
+       nvme_disable_queue(dev, 0);
        spin_lock(&dev_list_lock);
        list_del_init(&dev->node);
        spin_unlock(&dev_list_lock);
@@ -2064,6 +2369,77 @@ static int nvme_dev_start(struct nvme_dev *dev)
        return result;
 }
 
+static int nvme_remove_dead_ctrl(void *arg)
+{
+       struct nvme_dev *dev = (struct nvme_dev *)arg;
+       struct pci_dev *pdev = dev->pci_dev;
+
+       if (pci_get_drvdata(pdev))
+               pci_stop_and_remove_bus_device(pdev);
+       kref_put(&dev->kref, nvme_free_dev);
+       return 0;
+}
+
+static void nvme_remove_disks(struct work_struct *ws)
+{
+       int i;
+       struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
+
+       nvme_dev_remove(dev);
+       spin_lock(&dev_list_lock);
+       for (i = dev->queue_count - 1; i > 0; i--) {
+               BUG_ON(!dev->queues[i] || !dev->queues[i]->q_suspended);
+               nvme_free_queue(dev->queues[i]);
+               dev->queue_count--;
+               dev->queues[i] = NULL;
+       }
+       spin_unlock(&dev_list_lock);
+}
+
+static int nvme_dev_resume(struct nvme_dev *dev)
+{
+       int ret;
+
+       ret = nvme_dev_start(dev);
+       if (ret && ret != -EBUSY)
+               return ret;
+       if (ret == -EBUSY) {
+               spin_lock(&dev_list_lock);
+               dev->reset_workfn = nvme_remove_disks;
+               queue_work(nvme_workq, &dev->reset_work);
+               spin_unlock(&dev_list_lock);
+       }
+       dev->initialized = 1;
+       return 0;
+}
+
+static void nvme_dev_reset(struct nvme_dev *dev)
+{
+       nvme_dev_shutdown(dev);
+       if (nvme_dev_resume(dev)) {
+               dev_err(&dev->pci_dev->dev, "Device failed to resume\n");
+               kref_get(&dev->kref);
+               if (IS_ERR(kthread_run(nvme_remove_dead_ctrl, dev, "nvme%d",
+                                                       dev->instance))) {
+                       dev_err(&dev->pci_dev->dev,
+                               "Failed to start controller remove task\n");
+                       kref_put(&dev->kref, nvme_free_dev);
+               }
+       }
+}
+
+static void nvme_reset_failed_dev(struct work_struct *ws)
+{
+       struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
+       nvme_dev_reset(dev);
+}
+
+static void nvme_reset_workfn(struct work_struct *work)
+{
+       struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
+       dev->reset_workfn(work);
+}
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int result = -ENOMEM;
@@ -2082,8 +2458,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto free;
 
        INIT_LIST_HEAD(&dev->namespaces);
+       dev->reset_workfn = nvme_reset_failed_dev;
+       INIT_WORK(&dev->reset_work, nvme_reset_workfn);
        dev->pci_dev = pdev;
-
+       pci_set_drvdata(pdev, dev);
        result = nvme_set_instance(dev);
        if (result)
                goto free;
@@ -2099,6 +2477,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto release_pools;
        }
 
+       kref_init(&dev->kref);
        result = nvme_dev_add(dev);
        if (result)
                goto shutdown;
@@ -2113,15 +2492,16 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (result)
                goto remove;
 
-       kref_init(&dev->kref);
+       dev->initialized = 1;
        return 0;
 
  remove:
        nvme_dev_remove(dev);
+       nvme_free_namespaces(dev);
  shutdown:
        nvme_dev_shutdown(dev);
  release_pools:
-       nvme_free_queues(dev);
+       nvme_free_queues(dev, 0);
        nvme_release_prp_pools(dev);
  release:
        nvme_release_instance(dev);
@@ -2132,10 +2512,28 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        return result;
 }
 
+static void nvme_shutdown(struct pci_dev *pdev)
+{
+       struct nvme_dev *dev = pci_get_drvdata(pdev);
+       nvme_dev_shutdown(dev);
+}
+
 static void nvme_remove(struct pci_dev *pdev)
 {
        struct nvme_dev *dev = pci_get_drvdata(pdev);
+
+       spin_lock(&dev_list_lock);
+       list_del_init(&dev->node);
+       spin_unlock(&dev_list_lock);
+
+       pci_set_drvdata(pdev, NULL);
+       flush_work(&dev->reset_work);
        misc_deregister(&dev->miscdev);
+       nvme_dev_remove(dev);
+       nvme_dev_shutdown(dev);
+       nvme_free_queues(dev, 0);
+       nvme_release_instance(dev);
+       nvme_release_prp_pools(dev);
        kref_put(&dev->kref, nvme_free_dev);
 }
 
@@ -2159,13 +2557,12 @@ static int nvme_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct nvme_dev *ndev = pci_get_drvdata(pdev);
-       int ret;
 
-       ret = nvme_dev_start(ndev);
-       /* XXX: should remove gendisks if resume fails */
-       if (ret)
-               nvme_free_queues(ndev);
-       return ret;
+       if (nvme_dev_resume(ndev) && !work_busy(&ndev->reset_work)) {
+               ndev->reset_workfn = nvme_reset_failed_dev;
+               queue_work(nvme_workq, &ndev->reset_work);
+       }
+       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(nvme_dev_pm_ops, nvme_suspend, nvme_resume);
@@ -2192,6 +2589,7 @@ static struct pci_driver nvme_driver = {
        .id_table       = nvme_id_table,
        .probe          = nvme_probe,
        .remove         = nvme_remove,
+       .shutdown       = nvme_shutdown,
        .driver         = {
                .pm     = &nvme_dev_pm_ops,
        },
@@ -2206,9 +2604,14 @@ static int __init nvme_init(void)
        if (IS_ERR(nvme_thread))
                return PTR_ERR(nvme_thread);
 
+       result = -ENOMEM;
+       nvme_workq = create_singlethread_workqueue("nvme");
+       if (!nvme_workq)
+               goto kill_kthread;
+
        result = register_blkdev(nvme_major, "nvme");
        if (result < 0)
-               goto kill_kthread;
+               goto kill_workq;
        else if (result > 0)
                nvme_major = result;
 
@@ -2219,6 +2622,8 @@ static int __init nvme_init(void)
 
  unregister_blkdev:
        unregister_blkdev(nvme_major, "nvme");
+ kill_workq:
+       destroy_workqueue(nvme_workq);
  kill_kthread:
        kthread_stop(nvme_thread);
        return result;
@@ -2228,6 +2633,7 @@ static void __exit nvme_exit(void)
 {
        pci_unregister_driver(&nvme_driver);
        unregister_blkdev(nvme_major, "nvme");
+       destroy_workqueue(nvme_workq);
        kthread_stop(nvme_thread);
 }
 
index 4a4ff4eb8e233141d879fd52da3cade426b838b5..4a0ceb64e26924b0b777d19d1580850b1e12901d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/bio.h>
 #include <linux/bitops.h>
 #include <linux/blkdev.h>
+#include <linux/compat.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -3038,6 +3039,152 @@ int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr)
        return retcode;
 }
 
+#ifdef CONFIG_COMPAT
+typedef struct sg_io_hdr32 {
+       compat_int_t interface_id;      /* [i] 'S' for SCSI generic (required) */
+       compat_int_t dxfer_direction;   /* [i] data transfer direction  */
+       unsigned char cmd_len;          /* [i] SCSI command length ( <= 16 bytes) */
+       unsigned char mx_sb_len;                /* [i] max length to write to sbp */
+       unsigned short iovec_count;     /* [i] 0 implies no scatter gather */
+       compat_uint_t dxfer_len;                /* [i] byte count of data transfer */
+       compat_uint_t dxferp;           /* [i], [*io] points to data transfer memory
+                                             or scatter gather list */
+       compat_uptr_t cmdp;             /* [i], [*i] points to command to perform */
+       compat_uptr_t sbp;              /* [i], [*o] points to sense_buffer memory */
+       compat_uint_t timeout;          /* [i] MAX_UINT->no timeout (unit: millisec) */
+       compat_uint_t flags;            /* [i] 0 -> default, see SG_FLAG... */
+       compat_int_t pack_id;           /* [i->o] unused internally (normally) */
+       compat_uptr_t usr_ptr;          /* [i->o] unused internally */
+       unsigned char status;           /* [o] scsi status */
+       unsigned char masked_status;    /* [o] shifted, masked scsi status */
+       unsigned char msg_status;               /* [o] messaging level data (optional) */
+       unsigned char sb_len_wr;                /* [o] byte count actually written to sbp */
+       unsigned short host_status;     /* [o] errors from host adapter */
+       unsigned short driver_status;   /* [o] errors from software driver */
+       compat_int_t resid;             /* [o] dxfer_len - actual_transferred */
+       compat_uint_t duration;         /* [o] time taken by cmd (unit: millisec) */
+       compat_uint_t info;             /* [o] auxiliary information */
+} sg_io_hdr32_t;  /* 64 bytes long (on sparc32) */
+
+typedef struct sg_iovec32 {
+       compat_uint_t iov_base;
+       compat_uint_t iov_len;
+} sg_iovec32_t;
+
+static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count)
+{
+       sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1);
+       sg_iovec32_t __user *iov32 = dxferp;
+       int i;
+
+       for (i = 0; i < iovec_count; i++) {
+               u32 base, len;
+
+               if (get_user(base, &iov32[i].iov_base) ||
+                   get_user(len, &iov32[i].iov_len) ||
+                   put_user(compat_ptr(base), &iov[i].iov_base) ||
+                   put_user(len, &iov[i].iov_len))
+                       return -EFAULT;
+       }
+
+       if (put_user(iov, &sgio->dxferp))
+               return -EFAULT;
+       return 0;
+}
+
+int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg)
+{
+       sg_io_hdr32_t __user *sgio32 = (sg_io_hdr32_t __user *)arg;
+       sg_io_hdr_t __user *sgio;
+       u16 iovec_count;
+       u32 data;
+       void __user *dxferp;
+       int err;
+       int interface_id;
+
+       if (get_user(interface_id, &sgio32->interface_id))
+               return -EFAULT;
+       if (interface_id != 'S')
+               return -EINVAL;
+
+       if (get_user(iovec_count, &sgio32->iovec_count))
+               return -EFAULT;
+
+       {
+               void __user *top = compat_alloc_user_space(0);
+               void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) +
+                                      (iovec_count * sizeof(sg_iovec_t)));
+               if (new > top)
+                       return -EINVAL;
+
+               sgio = new;
+       }
+
+       /* Ok, now construct.  */
+       if (copy_in_user(&sgio->interface_id, &sgio32->interface_id,
+                        (2 * sizeof(int)) +
+                        (2 * sizeof(unsigned char)) +
+                        (1 * sizeof(unsigned short)) +
+                        (1 * sizeof(unsigned int))))
+               return -EFAULT;
+
+       if (get_user(data, &sgio32->dxferp))
+               return -EFAULT;
+       dxferp = compat_ptr(data);
+       if (iovec_count) {
+               if (sg_build_iovec(sgio, dxferp, iovec_count))
+                       return -EFAULT;
+       } else {
+               if (put_user(dxferp, &sgio->dxferp))
+                       return -EFAULT;
+       }
+
+       {
+               unsigned char __user *cmdp;
+               unsigned char __user *sbp;
+
+               if (get_user(data, &sgio32->cmdp))
+                       return -EFAULT;
+               cmdp = compat_ptr(data);
+
+               if (get_user(data, &sgio32->sbp))
+                       return -EFAULT;
+               sbp = compat_ptr(data);
+
+               if (put_user(cmdp, &sgio->cmdp) ||
+                   put_user(sbp, &sgio->sbp))
+                       return -EFAULT;
+       }
+
+       if (copy_in_user(&sgio->timeout, &sgio32->timeout,
+                        3 * sizeof(int)))
+               return -EFAULT;
+
+       if (get_user(data, &sgio32->usr_ptr))
+               return -EFAULT;
+       if (put_user(compat_ptr(data), &sgio->usr_ptr))
+               return -EFAULT;
+
+       err = nvme_sg_io(ns, sgio);
+       if (err >= 0) {
+               void __user *datap;
+
+               if (copy_in_user(&sgio32->pack_id, &sgio->pack_id,
+                                sizeof(int)) ||
+                   get_user(datap, &sgio->usr_ptr) ||
+                   put_user((u32)(unsigned long)datap,
+                            &sgio32->usr_ptr) ||
+                   copy_in_user(&sgio32->status, &sgio->status,
+                                (4 * sizeof(unsigned char)) +
+                                (2 * sizeof(unsigned short)) +
+                                (3 * sizeof(int))))
+                       err = -EFAULT;
+       }
+
+       return err;
+}
+#endif
+
 int nvme_sg_get_version_num(int __user *ip)
 {
        return put_user(sg_version_num, ip);
index b365e0dfccb66f7c256a9d07d7fd976fba17ae95..34898d53395b10eae386e06fef3d12b9635fe93a 100644 (file)
@@ -2109,7 +2109,6 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_request)
        rbd_assert(img_request->obj_request_count > 0);
        rbd_assert(which != BAD_WHICH);
        rbd_assert(which < img_request->obj_request_count);
-       rbd_assert(which >= img_request->next_completion);
 
        spin_lock_irq(&img_request->completion_lock);
        if (which != img_request->next_completion)
index 6a680d4de7f1c3dcfa7999e45efc98b4b14d99fc..b1cb3f4c4db45543c653fd86ce28e75b67522430 100644 (file)
@@ -110,9 +110,9 @@ static int __virtblk_add_req(struct virtqueue *vq,
        return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
 }
 
-static inline void virtblk_request_done(struct virtblk_req *vbr)
+static inline void virtblk_request_done(struct request *req)
 {
-       struct request *req = vbr->req;
+       struct virtblk_req *vbr = req->special;
        int error = virtblk_result(vbr);
 
        if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
@@ -138,7 +138,7 @@ static void virtblk_done(struct virtqueue *vq)
        do {
                virtqueue_disable_cb(vq);
                while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
-                       virtblk_request_done(vbr);
+                       blk_mq_complete_request(vbr->req);
                        req_done = true;
                }
                if (unlikely(virtqueue_is_broken(vq)))
@@ -479,6 +479,7 @@ static struct blk_mq_ops virtio_mq_ops = {
        .map_queue      = blk_mq_map_queue,
        .alloc_hctx     = blk_mq_alloc_single_hw_queue,
        .free_hctx      = blk_mq_free_single_hw_queue,
+       .complete       = virtblk_request_done,
 };
 
 static struct blk_mq_reg virtio_mq_reg = {
index da18046d0e0773bf0986d1ef4510d3b0349e59d3..64c60edcdfbc5546cd84538986b5d26625f9f248 100644 (file)
@@ -285,7 +285,8 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
                        !rb_next(&persistent_gnt->node)) {
-                       ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
+                       ret = gnttab_unmap_refs(unmap, NULL, pages,
+                               segs_to_unmap);
                        BUG_ON(ret);
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
@@ -298,7 +299,7 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
        BUG_ON(num != 0);
 }
 
-static void unmap_purged_grants(struct work_struct *work)
+void xen_blkbk_unmap_purged_grants(struct work_struct *work)
 {
        struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
@@ -320,7 +321,8 @@ static void unmap_purged_grants(struct work_struct *work)
                pages[segs_to_unmap] = persistent_gnt->page;
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
+                       ret = gnttab_unmap_refs(unmap, NULL, pages,
+                               segs_to_unmap);
                        BUG_ON(ret);
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
@@ -328,7 +330,7 @@ static void unmap_purged_grants(struct work_struct *work)
                kfree(persistent_gnt);
        }
        if (segs_to_unmap > 0) {
-               ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
+               ret = gnttab_unmap_refs(unmap, NULL, pages, segs_to_unmap);
                BUG_ON(ret);
                put_free_pages(blkif, pages, segs_to_unmap);
        }
@@ -373,7 +375,7 @@ static void purge_persistent_gnt(struct xen_blkif *blkif)
 
        pr_debug(DRV_PFX "Going to purge %u persistent grants\n", num_clean);
 
-       INIT_LIST_HEAD(&blkif->persistent_purge_list);
+       BUG_ON(!list_empty(&blkif->persistent_purge_list));
        root = &blkif->persistent_gnts;
 purge_list:
        foreach_grant_safe(persistent_gnt, n, root, node) {
@@ -418,7 +420,6 @@ finished:
        blkif->vbd.overflow_max_grants = 0;
 
        /* We can defer this work */
-       INIT_WORK(&blkif->persistent_purge_work, unmap_purged_grants);
        schedule_work(&blkif->persistent_purge_work);
        pr_debug(DRV_PFX "Purged %u/%u\n", (total - num_clean), total);
        return;
@@ -623,9 +624,23 @@ purge_gnt_list:
                        print_stats(blkif);
        }
 
-       /* Since we are shutting down remove all pages from the buffer */
-       shrink_free_pagepool(blkif, 0 /* All */);
+       /* Drain pending purge work */
+       flush_work(&blkif->persistent_purge_work);
 
+       if (log_stats)
+               print_stats(blkif);
+
+       blkif->xenblkd = NULL;
+       xen_blkif_put(blkif);
+
+       return 0;
+}
+
+/*
+ * Remove persistent grants and empty the pool of free pages
+ */
+void xen_blkbk_free_caches(struct xen_blkif *blkif)
+{
        /* Free all persistent grant pages */
        if (!RB_EMPTY_ROOT(&blkif->persistent_gnts))
                free_persistent_gnts(blkif, &blkif->persistent_gnts,
@@ -634,13 +649,8 @@ purge_gnt_list:
        BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts));
        blkif->persistent_gnt_c = 0;
 
-       if (log_stats)
-               print_stats(blkif);
-
-       blkif->xenblkd = NULL;
-       xen_blkif_put(blkif);
-
-       return 0;
+       /* Since we are shutting down remove all pages from the buffer */
+       shrink_free_pagepool(blkif, 0 /* All */);
 }
 
 /*
@@ -668,14 +678,15 @@ static void xen_blkbk_unmap(struct xen_blkif *blkif,
                                    GNTMAP_host_map, pages[i]->handle);
                pages[i]->handle = BLKBACK_INVALID_HANDLE;
                if (++invcount == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, unmap_pages, invcount);
+                       ret = gnttab_unmap_refs(unmap, NULL, unmap_pages,
+                                               invcount);
                        BUG_ON(ret);
                        put_free_pages(blkif, unmap_pages, invcount);
                        invcount = 0;
                }
        }
        if (invcount) {
-               ret = gnttab_unmap_refs(unmap, unmap_pages, invcount);
+               ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
                BUG_ON(ret);
                put_free_pages(blkif, unmap_pages, invcount);
        }
@@ -737,7 +748,7 @@ again:
        }
 
        if (segs_to_map) {
-               ret = gnttab_map_refs(map, pages_to_gnt, segs_to_map);
+               ret = gnttab_map_refs(map, NULL, pages_to_gnt, segs_to_map);
                BUG_ON(ret);
        }
 
@@ -835,7 +846,7 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
        struct grant_page **pages = pending_req->indirect_pages;
        struct xen_blkif *blkif = pending_req->blkif;
        int indirect_grefs, rc, n, nseg, i;
-       struct blkif_request_segment_aligned *segments = NULL;
+       struct blkif_request_segment *segments = NULL;
 
        nseg = pending_req->nr_pages;
        indirect_grefs = INDIRECT_PAGES(nseg);
@@ -931,9 +942,7 @@ static void xen_blk_drain_io(struct xen_blkif *blkif)
 {
        atomic_set(&blkif->drain, 1);
        do {
-               /* The initial value is one, and one refcnt taken at the
-                * start of the xen_blkif_schedule thread. */
-               if (atomic_read(&blkif->refcnt) <= 2)
+               if (atomic_read(&blkif->inflight) == 0)
                        break;
                wait_for_completion_interruptible_timeout(
                                &blkif->drain_complete, HZ);
@@ -973,17 +982,30 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
         * the proper response on the ring.
         */
        if (atomic_dec_and_test(&pending_req->pendcnt)) {
-               xen_blkbk_unmap(pending_req->blkif,
+               struct xen_blkif *blkif = pending_req->blkif;
+
+               xen_blkbk_unmap(blkif,
                                pending_req->segments,
                                pending_req->nr_pages);
-               make_response(pending_req->blkif, pending_req->id,
+               make_response(blkif, pending_req->id,
                              pending_req->operation, pending_req->status);
-               xen_blkif_put(pending_req->blkif);
-               if (atomic_read(&pending_req->blkif->refcnt) <= 2) {
-                       if (atomic_read(&pending_req->blkif->drain))
-                               complete(&pending_req->blkif->drain_complete);
+               free_req(blkif, pending_req);
+               /*
+                * Make sure the request is freed before releasing blkif,
+                * or there could be a race between free_req and the
+                * cleanup done in xen_blkif_free during shutdown.
+                *
+                * NB: The fact that we might try to wake up pending_free_wq
+                * before drain_complete (in case there's a drain going on)
+                * it's not a problem with our current implementation
+                * because we can assure there's no thread waiting on
+                * pending_free_wq if there's a drain going on, but it has
+                * to be taken into account if the current model is changed.
+                */
+               if (atomic_dec_and_test(&blkif->inflight) && atomic_read(&blkif->drain)) {
+                       complete(&blkif->drain_complete);
                }
-               free_req(pending_req->blkif, pending_req);
+               xen_blkif_put(blkif);
        }
 }
 
@@ -1237,6 +1259,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
         * below (in "!bio") if we are handling a BLKIF_OP_DISCARD.
         */
        xen_blkif_get(blkif);
+       atomic_inc(&blkif->inflight);
 
        for (i = 0; i < nseg; i++) {
                while ((bio == NULL) ||
index 8d8807563d9967afd28b70dcb0cd072bed35e8ec..be052773ad03c186666af7602e1c7c1b0c4d6329 100644 (file)
@@ -57,7 +57,7 @@
 #define MAX_INDIRECT_SEGMENTS 256
 
 #define SEGS_PER_INDIRECT_FRAME \
-       (PAGE_SIZE/sizeof(struct blkif_request_segment_aligned))
+       (PAGE_SIZE/sizeof(struct blkif_request_segment))
 #define MAX_INDIRECT_PAGES \
        ((MAX_INDIRECT_SEGMENTS + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
 #define INDIRECT_PAGES(_segs) \
@@ -278,6 +278,7 @@ struct xen_blkif {
        /* for barrier (drain) requests */
        struct completion       drain_complete;
        atomic_t                drain;
+       atomic_t                inflight;
        /* One thread per one blkif. */
        struct task_struct      *xenblkd;
        unsigned int            waiting_reqs;
@@ -376,6 +377,7 @@ int xen_blkif_xenbus_init(void);
 irqreturn_t xen_blkif_be_int(int irq, void *dev_id);
 int xen_blkif_schedule(void *arg);
 int xen_blkif_purge_persistent(void *arg);
+void xen_blkbk_free_caches(struct xen_blkif *blkif);
 
 int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
                              struct backend_info *be, int state);
@@ -383,6 +385,7 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
 int xen_blkbk_barrier(struct xenbus_transaction xbt,
                      struct backend_info *be, int state);
 struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be);
+void xen_blkbk_unmap_purged_grants(struct work_struct *work);
 
 static inline void blkif_get_x86_32_req(struct blkif_request *dst,
                                        struct blkif_x86_32_request *src)
index c2014a0aa206b2ec1b1ee328e84bde4407026616..9a547e6b6ebf02ab9bba0a48167f0b0b1b0915b2 100644 (file)
@@ -125,8 +125,11 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
        blkif->persistent_gnts.rb_node = NULL;
        spin_lock_init(&blkif->free_pages_lock);
        INIT_LIST_HEAD(&blkif->free_pages);
+       INIT_LIST_HEAD(&blkif->persistent_purge_list);
        blkif->free_pages_num = 0;
        atomic_set(&blkif->persistent_gnt_in_use, 0);
+       atomic_set(&blkif->inflight, 0);
+       INIT_WORK(&blkif->persistent_purge_work, xen_blkbk_unmap_purged_grants);
 
        INIT_LIST_HEAD(&blkif->pending_free);
 
@@ -259,6 +262,17 @@ static void xen_blkif_free(struct xen_blkif *blkif)
        if (!atomic_dec_and_test(&blkif->refcnt))
                BUG();
 
+       /* Remove all persistent grants and the cache of ballooned pages. */
+       xen_blkbk_free_caches(blkif);
+
+       /* Make sure everything is drained before shutting down */
+       BUG_ON(blkif->persistent_gnt_c != 0);
+       BUG_ON(atomic_read(&blkif->persistent_gnt_in_use) != 0);
+       BUG_ON(blkif->free_pages_num != 0);
+       BUG_ON(!list_empty(&blkif->persistent_purge_list));
+       BUG_ON(!list_empty(&blkif->free_pages));
+       BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts));
+
        /* Check that there is no request in use */
        list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) {
                list_del(&req->free_list);
index 8dcfb54f160302e0e1d91c232387f758b2f8e0f6..efe1b4761735a79faa30867ad625fdd51e043081 100644 (file)
@@ -162,7 +162,7 @@ static DEFINE_SPINLOCK(minor_lock);
 #define DEV_NAME       "xvd"   /* name in /dev */
 
 #define SEGS_PER_INDIRECT_FRAME \
-       (PAGE_SIZE/sizeof(struct blkif_request_segment_aligned))
+       (PAGE_SIZE/sizeof(struct blkif_request_segment))
 #define INDIRECT_GREFS(_segs) \
        ((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
 
@@ -393,7 +393,7 @@ static int blkif_queue_request(struct request *req)
        unsigned long id;
        unsigned int fsect, lsect;
        int i, ref, n;
-       struct blkif_request_segment_aligned *segments = NULL;
+       struct blkif_request_segment *segments = NULL;
 
        /*
         * Used to store if we are able to queue the request by just using
@@ -550,7 +550,7 @@ static int blkif_queue_request(struct request *req)
                        } else {
                                n = i % SEGS_PER_INDIRECT_FRAME;
                                segments[n] =
-                                       (struct blkif_request_segment_aligned) {
+                                       (struct blkif_request_segment) {
                                                        .gref       = ref,
                                                        .first_sect = fsect,
                                                        .last_sect  = lsect };
@@ -1904,13 +1904,16 @@ static void blkback_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateConnected:
                blkfront_connect(info);
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's Closing state -- fallthrough */
        case XenbusStateClosing:
                blkfront_closing(info);
                break;
index 011e55d820b1811a3379a65a4ef754fcc785f3ef..51c557cfd92b37cf6b7aecdfa50d212fdacc05ee 100644 (file)
@@ -612,6 +612,8 @@ static ssize_t disksize_store(struct device *dev,
 
        disksize = PAGE_ALIGN(disksize);
        meta = zram_meta_alloc(disksize);
+       if (!meta)
+               return -ENOMEM;
        down_write(&zram->init_lock);
        if (zram->init_done) {
                up_write(&zram->init_lock);
index fa3243d71c76d0b9f14dde9066a2bff60a18165c..1386749b48ffd6e2711316a9083e913c560eabb6 100644 (file)
@@ -499,6 +499,7 @@ config RAW_DRIVER
 config MAX_RAW_DEVS
        int "Maximum number of RAW devices to support (1-65536)"
        depends on RAW_DRIVER
+       range 1 65536
        default "256"
        help
          The maximum number of RAW devices that are supported.
index f3223aac4df11c41959a744bee67af2d2df232e5..6e8d65e9b1d3c196ea2d2bd76b78530dd0387920 100644 (file)
@@ -190,7 +190,7 @@ static int bind_get(int number, dev_t *dev)
        struct raw_device_data *rawdev;
        struct block_device *bdev;
 
-       if (number <= 0 || number >= MAX_RAW_MINORS)
+       if (number <= 0 || number >= max_raw_minors)
                return -EINVAL;
 
        rawdev = &raw_devices[number];
index feea87cc6b8fb60a5972be32fee027697006ddf2..6928d094451d607795b4f2a07d7599e01712f824 100644 (file)
@@ -890,12 +890,10 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
        } else {
                /* Failback to copying a page */
                struct page *page = alloc_page(GFP_KERNEL);
-               char *src = buf->ops->map(pipe, buf, 1);
-               char *dst;
+               char *src;
 
                if (!page)
                        return -ENOMEM;
-               dst = kmap(page);
 
                offset = sd->pos & ~PAGE_MASK;
 
@@ -903,9 +901,8 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
                if (len + offset > PAGE_SIZE)
                        len = PAGE_SIZE - offset;
 
-               memcpy(dst + offset, src + buf->offset, len);
-
-               kunmap(page);
+               src = buf->ops->map(pipe, buf, 1);
+               memcpy(page_address(page) + offset, src + buf->offset, len);
                buf->ops->unmap(pipe, buf, src);
 
                sg_set_page(&(sgl->sg[sgl->n]), page, len, offset);
index bd313f7816a8d9461deba6889b99415b87010467..c1af80bcdf2082c8d0d7b32e28eb9122c59ac53f 100644 (file)
@@ -242,7 +242,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
 
        irq = irq_of_parse_and_map(np, 0);
        if (!irq)
-               return;
+               goto out_free_characteristics;
 
        clk = at91_clk_register_master(pmc, irq, name, num_parents,
                                       parent_names, layout,
index 6a934a5296bd4ca2867146dc06272ea1003e238e..05e04ce0f1488f7301ad5153f687860bf872f8bc 100644 (file)
@@ -494,6 +494,9 @@ static const struct file_operations nomadik_src_clk_debugfs_ops = {
 
 static int __init nomadik_src_clk_init_debugfs(void)
 {
+       /* Vital for multiplatform */
+       if (!src_base)
+               return -ENODEV;
        src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
        src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
        debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
index 5517944495d893cc3c8dd60569b58e67e9289765..c42e608af6bbe0980717a74e69a143cdc742f1b1 100644 (file)
@@ -2226,24 +2226,25 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
  */
 int __clk_get(struct clk *clk)
 {
-       if (clk && !try_module_get(clk->owner))
-               return 0;
+       if (clk) {
+               if (!try_module_get(clk->owner))
+                       return 0;
 
-       kref_get(&clk->ref);
+               kref_get(&clk->ref);
+       }
        return 1;
 }
 
 void __clk_put(struct clk *clk)
 {
-       if (WARN_ON_ONCE(IS_ERR(clk)))
+       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
                return;
 
        clk_prepare_lock();
        kref_put(&clk->ref, __clk_release);
        clk_prepare_unlock();
 
-       if (clk)
-               module_put(clk->owner);
+       module_put(clk->owner);
 }
 
 /***        clk rate change notifiers        ***/
index 17a598398a53df461e110ca5c16d29e7bc92e6f5..86f1e362eafb8e29c02fae393620d39d32278529 100644 (file)
@@ -179,6 +179,7 @@ static struct clk *clk_register_psc(struct device *dev,
 
        init.name = name;
        init.ops = &clk_psc_ops;
+       init.flags = 0;
        init.parent_names = (parent_name ? &parent_name : NULL);
        init.num_parents = (parent_name ? 1 : 0);
 
index 81a202d12a7ad89ab56909fce6782baa7fb94ec2..bef198a83863aaa79e21ca1c4e1401238cae31b7 100644 (file)
@@ -141,13 +141,6 @@ static const struct coreclk_soc_desc a370_coreclks = {
        .num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
 };
 
-static void __init a370_coreclk_init(struct device_node *np)
-{
-       mvebu_coreclk_setup(np, &a370_coreclks);
-}
-CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock",
-              a370_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -168,9 +161,15 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
        { }
 };
 
-static void __init a370_clk_gating_init(struct device_node *np)
+static void __init a370_clk_init(struct device_node *np)
 {
-       mvebu_clk_gating_setup(np, a370_gating_desc);
+       struct device_node *cgnp =
+               of_find_compatible_node(NULL, NULL, "marvell,armada-370-gating-clock");
+
+       mvebu_coreclk_setup(np, &a370_coreclks);
+
+       if (cgnp)
+               mvebu_clk_gating_setup(cgnp, a370_gating_desc);
 }
-CLK_OF_DECLARE(a370_clk_gating, "marvell,armada-370-gating-clock",
-              a370_clk_gating_init);
+CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init);
+
index 9922c4475aa8b3f7d01c2881c8a757b94f9027af..b3094315a3c0faa89926dcf7442d5034f39b4f15 100644 (file)
@@ -158,13 +158,6 @@ static const struct coreclk_soc_desc axp_coreclks = {
        .num_ratios = ARRAY_SIZE(axp_coreclk_ratios),
 };
 
-static void __init axp_coreclk_init(struct device_node *np)
-{
-       mvebu_coreclk_setup(np, &axp_coreclks);
-}
-CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock",
-              axp_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -202,9 +195,14 @@ static const struct clk_gating_soc_desc axp_gating_desc[] __initconst = {
        { }
 };
 
-static void __init axp_clk_gating_init(struct device_node *np)
+static void __init axp_clk_init(struct device_node *np)
 {
-       mvebu_clk_gating_setup(np, axp_gating_desc);
+       struct device_node *cgnp =
+               of_find_compatible_node(NULL, NULL, "marvell,armada-xp-gating-clock");
+
+       mvebu_coreclk_setup(np, &axp_coreclks);
+
+       if (cgnp)
+               mvebu_clk_gating_setup(cgnp, axp_gating_desc);
 }
-CLK_OF_DECLARE(axp_clk_gating, "marvell,armada-xp-gating-clock",
-              axp_clk_gating_init);
+CLK_OF_DECLARE(axp_clk, "marvell,armada-xp-core-clock", axp_clk_init);
index 38aee1e3f242b237079aaeb775aa2fd8dae89453..b8c2424ac9261dea5c36553b09f5262bba359299 100644 (file)
@@ -154,12 +154,6 @@ static const struct coreclk_soc_desc dove_coreclks = {
        .num_ratios = ARRAY_SIZE(dove_coreclk_ratios),
 };
 
-static void __init dove_coreclk_init(struct device_node *np)
-{
-       mvebu_coreclk_setup(np, &dove_coreclks);
-}
-CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -186,9 +180,14 @@ static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = {
        { }
 };
 
-static void __init dove_clk_gating_init(struct device_node *np)
+static void __init dove_clk_init(struct device_node *np)
 {
-       mvebu_clk_gating_setup(np, dove_gating_desc);
+       struct device_node *cgnp =
+               of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock");
+
+       mvebu_coreclk_setup(np, &dove_coreclks);
+
+       if (cgnp)
+               mvebu_clk_gating_setup(cgnp, dove_gating_desc);
 }
-CLK_OF_DECLARE(dove_clk_gating, "marvell,dove-gating-clock",
-              dove_clk_gating_init);
+CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init);
index 2636a55f29f9403df92aec0c11e5a504fc7f9deb..ddb666a86500964201db0ad6d3a3724511302b59 100644 (file)
@@ -193,13 +193,6 @@ static const struct coreclk_soc_desc kirkwood_coreclks = {
        .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
 };
 
-static void __init kirkwood_coreclk_init(struct device_node *np)
-{
-       mvebu_coreclk_setup(np, &kirkwood_coreclks);
-}
-CLK_OF_DECLARE(kirkwood_core_clk, "marvell,kirkwood-core-clock",
-              kirkwood_coreclk_init);
-
 static const struct coreclk_soc_desc mv88f6180_coreclks = {
        .get_tclk_freq = kirkwood_get_tclk_freq,
        .get_cpu_freq = mv88f6180_get_cpu_freq,
@@ -208,13 +201,6 @@ static const struct coreclk_soc_desc mv88f6180_coreclks = {
        .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
 };
 
-static void __init mv88f6180_coreclk_init(struct device_node *np)
-{
-       mvebu_coreclk_setup(np, &mv88f6180_coreclks);
-}
-CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock",
-              mv88f6180_coreclk_init);
-
 /*
  * Clock Gating Control
  */
@@ -239,9 +225,21 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
        { }
 };
 
-static void __init kirkwood_clk_gating_init(struct device_node *np)
+static void __init kirkwood_clk_init(struct device_node *np)
 {
-       mvebu_clk_gating_setup(np, kirkwood_gating_desc);
+       struct device_node *cgnp =
+               of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock");
+
+
+       if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock"))
+               mvebu_coreclk_setup(np, &mv88f6180_coreclks);
+       else
+               mvebu_coreclk_setup(np, &kirkwood_coreclks);
+
+       if (cgnp)
+               mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
 }
-CLK_OF_DECLARE(kirkwood_clk_gating, "marvell,kirkwood-gating-clock",
-              kirkwood_clk_gating_init);
+CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
+              kirkwood_clk_init);
+CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock",
+              kirkwood_clk_init);
index a59ec217a12437785ea1c689b28744bfcd19ac3d..99c27b1c625b8e3eaf514895a0a13ebf8b94fdef 100644 (file)
@@ -26,6 +26,8 @@ struct rcar_gen2_cpg {
        void __iomem *reg;
 };
 
+#define CPG_FRQCRB                     0x00000004
+#define CPG_FRQCRB_KICK                        BIT(31)
 #define CPG_SDCKCR                     0x00000074
 #define CPG_PLL0CR                     0x000000d8
 #define CPG_FRQCRC                     0x000000e0
@@ -45,6 +47,7 @@ struct rcar_gen2_cpg {
 struct cpg_z_clk {
        struct clk_hw hw;
        void __iomem *reg;
+       void __iomem *kick_reg;
 };
 
 #define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
@@ -83,17 +86,45 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct cpg_z_clk *zclk = to_z_clk(hw);
        unsigned int mult;
-       u32 val;
+       u32 val, kick;
+       unsigned int i;
 
        mult = div_u64((u64)rate * 32, parent_rate);
        mult = clamp(mult, 1U, 32U);
 
+       if (clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+               return -EBUSY;
+
        val = clk_readl(zclk->reg);
        val &= ~CPG_FRQCRC_ZFC_MASK;
        val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
        clk_writel(val, zclk->reg);
 
-       return 0;
+       /*
+        * Set KICK bit in FRQCRB to update hardware setting and wait for
+        * clock change completion.
+        */
+       kick = clk_readl(zclk->kick_reg);
+       kick |= CPG_FRQCRB_KICK;
+       clk_writel(kick, zclk->kick_reg);
+
+       /*
+        * Note: There is no HW information about the worst case latency.
+        *
+        * Using experimental measurements, it seems that no more than
+        * ~10 iterations are needed, independently of the CPU rate.
+        * Since this value might be dependant of external xtal rate, pll1
+        * rate or even the other emulation clocks rate, use 1000 as a
+        * "super" safe value.
+        */
+       for (i = 1000; i; i--) {
+               if (!(clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+                       return 0;
+
+               cpu_relax();
+       }
+
+       return -ETIMEDOUT;
 }
 
 static const struct clk_ops cpg_z_clk_ops = {
@@ -120,6 +151,7 @@ static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg)
        init.num_parents = 1;
 
        zclk->reg = cpg->reg + CPG_FRQCRC;
+       zclk->kick_reg = cpg->reg + CPG_FRQCRB;
        zclk->hw.init = &init;
 
        clk = clk_register(NULL, &zclk->hw);
@@ -186,7 +218,7 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
                             const char *name)
 {
        const struct clk_div_table *table = NULL;
-       const char *parent_name = "main";
+       const char *parent_name;
        unsigned int shift;
        unsigned int mult = 1;
        unsigned int div = 1;
@@ -201,23 +233,31 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
                 * the multiplier value.
                 */
                u32 value = clk_readl(cpg->reg + CPG_PLL0CR);
+               parent_name = "main";
                mult = ((value >> 24) & ((1 << 7) - 1)) + 1;
        } else if (!strcmp(name, "pll1")) {
+               parent_name = "main";
                mult = config->pll1_mult / 2;
        } else if (!strcmp(name, "pll3")) {
+               parent_name = "main";
                mult = config->pll3_mult;
        } else if (!strcmp(name, "lb")) {
+               parent_name = "pll1_div2";
                div = cpg_mode & BIT(18) ? 36 : 24;
        } else if (!strcmp(name, "qspi")) {
+               parent_name = "pll1_div2";
                div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2)
-                   ? 16 : 20;
+                   ? 8 : 10;
        } else if (!strcmp(name, "sdh")) {
+               parent_name = "pll1_div2";
                table = cpg_sdh_div_table;
                shift = 8;
        } else if (!strcmp(name, "sd0")) {
+               parent_name = "pll1_div2";
                table = cpg_sd01_div_table;
                shift = 4;
        } else if (!strcmp(name, "sd1")) {
+               parent_name = "pll1_div2";
                table = cpg_sd01_div_table;
                shift = 0;
        } else if (!strcmp(name, "z")) {
index 4d75b1f37e3a4b74ee4606ce33d54b8a771beb6a..290f9c1a37498ccf16ae0b09804ca15e722a2da2 100644 (file)
@@ -59,7 +59,7 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate,
                return 0;
 
        if (divider_ux1 > get_max_div(divider))
-               return -EINVAL;
+               return get_max_div(divider);
 
        return divider_ux1;
 }
index cf0c323f2c36ec453deed1c5374fbbce4df543b2..c39613c519af85aa5faf14cc02857219cde56a3b 100644 (file)
@@ -180,9 +180,13 @@ enum clk_id {
        tegra_clk_sbc6_8,
        tegra_clk_sclk,
        tegra_clk_sdmmc1,
+       tegra_clk_sdmmc1_8,
        tegra_clk_sdmmc2,
+       tegra_clk_sdmmc2_8,
        tegra_clk_sdmmc3,
+       tegra_clk_sdmmc3_8,
        tegra_clk_sdmmc4,
+       tegra_clk_sdmmc4_8,
        tegra_clk_se,
        tegra_clk_soc_therm,
        tegra_clk_sor0,
index 5c35885f4a7cee9a4ecb9309f93c345befe28a2e..1fa5c3f33b2033a5e4a32716706d2221d548adf1 100644 (file)
@@ -371,9 +371,7 @@ static const char *mux_pllp3_pllc_clkm[] = {
 static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = {
        "pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m"
 };
-static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = {
-       [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
-};
+#define mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx NULL
 
 static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = {
        "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4",
@@ -465,6 +463,10 @@ static struct tegra_periph_init_data periph_clks[] = {
        MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
        MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
        MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
+       MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1_8),
+       MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2_8),
+       MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3_8),
+       MUX8("sdmmc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4_8),
        MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8),
        MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8),
        MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8),
@@ -492,7 +494,7 @@ static struct tegra_periph_init_data periph_clks[] = {
        UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
        UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
        UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
-       UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte),
+       UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte),
        XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
        XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
        XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
index 05dce4aa2c11e2a0d3e73cb84f4dc6231537b08d..feb3201c85ce5df6d8786eaf2e4a0408e5890ec0 100644 (file)
@@ -120,7 +120,7 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
                                        ARRAY_SIZE(cclk_lp_parents),
                                        CLK_SET_RATE_PARENT,
                                        clk_base + CCLKLP_BURST_POLICY,
-                                       0, 4, 8, 9, NULL);
+                                       TEGRA_DIVIDER_2, 4, 8, 9, NULL);
                *dt_clk = clk;
        }
 
index 90d9d25f2228195308f328a9d7c05c1a5bbe5a40..80431f0fb2688f84557383b20ea39513ed2ffcc4 100644 (file)
@@ -682,12 +682,12 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
        [tegra_clk_timer] = { .dt_id = TEGRA114_CLK_TIMER, .present = true },
        [tegra_clk_uarta] = { .dt_id = TEGRA114_CLK_UARTA, .present = true },
        [tegra_clk_uartd] = { .dt_id = TEGRA114_CLK_UARTD, .present = true },
-       [tegra_clk_sdmmc2] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true },
+       [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA114_CLK_SDMMC2, .present = true },
        [tegra_clk_i2s1] = { .dt_id = TEGRA114_CLK_I2S1, .present = true },
        [tegra_clk_i2c1] = { .dt_id = TEGRA114_CLK_I2C1, .present = true },
        [tegra_clk_ndflash] = { .dt_id = TEGRA114_CLK_NDFLASH, .present = true },
-       [tegra_clk_sdmmc1] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true },
-       [tegra_clk_sdmmc4] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true },
+       [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA114_CLK_SDMMC1, .present = true },
+       [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA114_CLK_SDMMC4, .present = true },
        [tegra_clk_pwm] = { .dt_id = TEGRA114_CLK_PWM, .present = true },
        [tegra_clk_i2s0] = { .dt_id = TEGRA114_CLK_I2S0, .present = true },
        [tegra_clk_i2s2] = { .dt_id = TEGRA114_CLK_I2S2, .present = true },
@@ -723,7 +723,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
        [tegra_clk_bsev] = { .dt_id = TEGRA114_CLK_BSEV, .present = true },
        [tegra_clk_i2c3] = { .dt_id = TEGRA114_CLK_I2C3, .present = true },
        [tegra_clk_sbc4_8] = { .dt_id = TEGRA114_CLK_SBC4, .present = true },
-       [tegra_clk_sdmmc3] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true },
+       [tegra_clk_sdmmc3_8] = { .dt_id = TEGRA114_CLK_SDMMC3, .present = true },
        [tegra_clk_owr] = { .dt_id = TEGRA114_CLK_OWR, .present = true },
        [tegra_clk_csite] = { .dt_id = TEGRA114_CLK_CSITE, .present = true },
        [tegra_clk_la] = { .dt_id = TEGRA114_CLK_LA, .present = true },
index aff86b5bc7455c190fbf5ebaf2be08c204262e26..166e02f16c8a25f28f4441584dc6e8babc448f3b 100644 (file)
@@ -516,11 +516,11 @@ static struct div_nmp pllp_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-       {12000000, 216000000, 432, 12, 1, 8},
-       {13000000, 216000000, 432, 13, 1, 8},
-       {16800000, 216000000, 360, 14, 1, 8},
-       {19200000, 216000000, 360, 16, 1, 8},
-       {26000000, 216000000, 432, 26, 1, 8},
+       {12000000, 408000000, 408, 12, 0, 8},
+       {13000000, 408000000, 408, 13, 0, 8},
+       {16800000, 408000000, 340, 14, 0, 8},
+       {19200000, 408000000, 340, 16, 0, 8},
+       {26000000, 408000000, 408, 26, 0, 8},
        {0, 0, 0, 0, 0, 0},
 };
 
@@ -570,6 +570,15 @@ static struct tegra_clk_pll_params pll_a_params = {
        .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
 };
 
+static struct div_nmp plld_nmp = {
+       .divm_shift = 0,
+       .divm_width = 5,
+       .divn_shift = 8,
+       .divn_width = 11,
+       .divp_shift = 20,
+       .divp_width = 3,
+};
+
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
        {12000000, 216000000, 864, 12, 4, 12},
        {13000000, 216000000, 864, 13, 4, 12},
@@ -603,19 +612,18 @@ static struct tegra_clk_pll_params pll_d_params = {
        .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
-       .div_nmp = &pllp_nmp,
+       .div_nmp = &plld_nmp,
        .freq_table = pll_d_freq_table,
        .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
                 TEGRA_PLL_USE_LOCK,
 };
 
 static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = {
-       { 12000000, 148500000,  99, 1, 8},
-       { 12000000, 594000000,  99, 1, 1},
-       { 13000000, 594000000,  91, 1, 1},      /* actual: 591.5 MHz */
-       { 16800000, 594000000,  71, 1, 1},      /* actual: 596.4 MHz */
-       { 19200000, 594000000,  62, 1, 1},      /* actual: 595.2 MHz */
-       { 26000000, 594000000,  91, 2, 1},      /* actual: 591.5 MHz */
+       { 12000000, 594000000,  99, 1, 2},
+       { 13000000, 594000000,  91, 1, 2},      /* actual: 591.5 MHz */
+       { 16800000, 594000000,  71, 1, 2},      /* actual: 596.4 MHz */
+       { 19200000, 594000000,  62, 1, 2},      /* actual: 595.2 MHz */
+       { 26000000, 594000000,  91, 2, 2},      /* actual: 591.5 MHz */
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -753,21 +761,19 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
        [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true },
        [tegra_clk_timer] = { .dt_id = TEGRA124_CLK_TIMER, .present = true },
        [tegra_clk_uarta] = { .dt_id = TEGRA124_CLK_UARTA, .present = true },
-       [tegra_clk_sdmmc2] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true },
+       [tegra_clk_sdmmc2_8] = { .dt_id = TEGRA124_CLK_SDMMC2, .present = true },
        [tegra_clk_i2s1] = { .dt_id = TEGRA124_CLK_I2S1, .present = true },
        [tegra_clk_i2c1] = { .dt_id = TEGRA124_CLK_I2C1, .present = true },
        [tegra_clk_ndflash] = { .dt_id = TEGRA124_CLK_NDFLASH, .present = true },
-       [tegra_clk_sdmmc1] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true },
-       [tegra_clk_sdmmc4] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true },
+       [tegra_clk_sdmmc1_8] = { .dt_id = TEGRA124_CLK_SDMMC1, .present = true },
+       [tegra_clk_sdmmc4_8] = { .dt_id = TEGRA124_CLK_SDMMC4, .present = true },
        [tegra_clk_pwm] = { .dt_id = TEGRA124_CLK_PWM, .present = true },
        [tegra_clk_i2s2] = { .dt_id = TEGRA124_CLK_I2S2, .present = true },
-       [tegra_clk_gr2d] = { .dt_id = TEGRA124_CLK_GR_2D, .present = true },
        [tegra_clk_usbd] = { .dt_id = TEGRA124_CLK_USBD, .present = true },
        [tegra_clk_isp_8] = { .dt_id = TEGRA124_CLK_ISP, .present = true },
-       [tegra_clk_gr3d] = { .dt_id = TEGRA124_CLK_GR_3D, .present = true },
        [tegra_clk_disp2] = { .dt_id = TEGRA124_CLK_DISP2, .present = true },
        [tegra_clk_disp1] = { .dt_id = TEGRA124_CLK_DISP1, .present = true },
-       [tegra_clk_host1x] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true },
+       [tegra_clk_host1x_8] = { .dt_id = TEGRA124_CLK_HOST1X, .present = true },
        [tegra_clk_vcp] = { .dt_id = TEGRA124_CLK_VCP, .present = true },
        [tegra_clk_i2s0] = { .dt_id = TEGRA124_CLK_I2S0, .present = true },
        [tegra_clk_apbdma] = { .dt_id = TEGRA124_CLK_APBDMA, .present = true },
@@ -794,7 +800,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
        [tegra_clk_uartd] = { .dt_id = TEGRA124_CLK_UARTD, .present = true },
        [tegra_clk_i2c3] = { .dt_id = TEGRA124_CLK_I2C3, .present = true },
        [tegra_clk_sbc4] = { .dt_id = TEGRA124_CLK_SBC4, .present = true },
-       [tegra_clk_sdmmc3] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true },
+       [tegra_clk_sdmmc3_8] = { .dt_id = TEGRA124_CLK_SDMMC3, .present = true },
        [tegra_clk_pcie] = { .dt_id = TEGRA124_CLK_PCIE, .present = true },
        [tegra_clk_owr] = { .dt_id = TEGRA124_CLK_OWR, .present = true },
        [tegra_clk_afi] = { .dt_id = TEGRA124_CLK_AFI, .present = true },
@@ -1286,9 +1292,9 @@ static void __init tegra124_pll_init(void __iomem *clk_base,
        clk_register_clkdev(clk, "pll_d2", NULL);
        clks[TEGRA124_CLK_PLL_D2] = clk;
 
-       /* PLLD2_OUT0 ?? */
+       /* PLLD2_OUT0 */
        clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
-                                       CLK_SET_RATE_PARENT, 1, 2);
+                                       CLK_SET_RATE_PARENT, 1, 1);
        clk_register_clkdev(clk, "pll_d2_out0", NULL);
        clks[TEGRA124_CLK_PLL_D2_OUT0] = clk;
 
index dbace152b2faa9e4f1699b8369d935683900df89..dace2b1b5ae66dafab4fe4639e6291872491119d 100644 (file)
@@ -574,6 +574,8 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
        [tegra_clk_tvdac] = { .dt_id = TEGRA20_CLK_TVDAC, .present = true },
        [tegra_clk_vi_sensor] = { .dt_id = TEGRA20_CLK_VI_SENSOR, .present = true },
        [tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
+       [tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true },
+       [tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true },
 };
 
 static unsigned long tegra20_clk_measure_input_freq(void)
index 974b2db2fe1087b05499a8dc2aaaa53338c985e4..0595dc6c453e6ee4a97cfb4dd30865f76c351366 100644 (file)
@@ -99,31 +99,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw)
        return;
 }
 
-static void __init kona_timers_init(struct device_node *node)
-{
-       u32 freq;
-       struct clk *external_clk;
-
-       external_clk = of_clk_get_by_name(node, NULL);
-
-       if (!IS_ERR(external_clk)) {
-               arch_timer_rate = clk_get_rate(external_clk);
-               clk_prepare_enable(external_clk);
-       } else if (!of_property_read_u32(node, "clock-frequency", &freq)) {
-               arch_timer_rate = freq;
-       } else {
-               panic("unable to determine clock-frequency");
-       }
-
-       /* Setup IRQ numbers */
-       timers.tmr_irq = irq_of_parse_and_map(node, 0);
-
-       /* Setup IO addresses */
-       timers.tmr_regs = of_iomap(node, 0);
-
-       kona_timer_disable_and_clear(timers.tmr_regs);
-}
-
 static int kona_timer_set_next_event(unsigned long clc,
                                  struct clock_event_device *unused)
 {
@@ -198,7 +173,34 @@ static struct irqaction kona_timer_irq = {
 
 static void __init kona_timer_init(struct device_node *node)
 {
-       kona_timers_init(node);
+       u32 freq;
+       struct clk *external_clk;
+
+       if (!of_device_is_available(node)) {
+               pr_info("Kona Timer v1 marked as disabled in device tree\n");
+               return;
+       }
+
+       external_clk = of_clk_get_by_name(node, NULL);
+
+       if (!IS_ERR(external_clk)) {
+               arch_timer_rate = clk_get_rate(external_clk);
+               clk_prepare_enable(external_clk);
+       } else if (!of_property_read_u32(node, "clock-frequency", &freq)) {
+               arch_timer_rate = freq;
+       } else {
+               pr_err("Kona Timer v1 unable to determine clock-frequency");
+               return;
+       }
+
+       /* Setup IRQ numbers */
+       timers.tmr_irq = irq_of_parse_and_map(node, 0);
+
+       /* Setup IO addresses */
+       timers.tmr_regs = of_iomap(node, 0);
+
+       kona_timer_disable_and_clear(timers.tmr_regs);
+
        kona_timer_clockevents_init();
        setup_irq(timers.tmr_irq, &kona_timer_irq);
        kona_timer_set_next_event((arch_timer_rate / HZ), NULL);
index 02821b06a39e33be4cb403b202286deb530ff399..a918bc481c52c46a83f2e1ff1a50a96dc4180082 100644 (file)
@@ -54,7 +54,7 @@ static inline void pit_irq_acknowledge(void)
 
 static u64 pit_read_sched_clock(void)
 {
-       return __raw_readl(clksrc_base + PITCVAL);
+       return ~__raw_readl(clksrc_base + PITCVAL);
 }
 
 static int __init pit_clocksource_init(unsigned long rate)
index 4b029c0944af5ef55b9bdb02a266cbcb3ecd2d23..1fbe11f2a14603e499042974e7fc8064414978a4 100644 (file)
@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86"
 endmenu
 
 menu "ARM CPU frequency scaling drivers"
-depends on ARM
+depends on ARM || ARM64
 source "drivers/cpufreq/Kconfig.arm"
 endmenu
 
index 08ca8c9f41cdeb27f6e4bb4879b2912798e1a72e..199b52b7c3e1ad6e9d00102905a215137901b71d 100644 (file)
@@ -1109,12 +1109,27 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
                goto err_set_policy_cpu;
        }
 
+       /* related cpus should atleast have policy->cpus */
+       cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
+
+       /*
+        * affected cpus must always be the one, which are online. We aren't
+        * managing offline cpus here.
+        */
+       cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
+
+       if (!frozen) {
+               policy->user_policy.min = policy->min;
+               policy->user_policy.max = policy->max;
+       }
+
+       down_write(&policy->rwsem);
        write_lock_irqsave(&cpufreq_driver_lock, flags);
        for_each_cpu(j, policy->cpus)
                per_cpu(cpufreq_cpu_data, j) = policy;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-       if (cpufreq_driver->get) {
+       if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
                policy->cur = cpufreq_driver->get(policy->cpu);
                if (!policy->cur) {
                        pr_err("%s: ->get() failed\n", __func__);
@@ -1162,20 +1177,6 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
                }
        }
 
-       /* related cpus should atleast have policy->cpus */
-       cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
-
-       /*
-        * affected cpus must always be the one, which are online. We aren't
-        * managing offline cpus here.
-        */
-       cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
-
-       if (!frozen) {
-               policy->user_policy.min = policy->min;
-               policy->user_policy.max = policy->max;
-       }
-
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                     CPUFREQ_START, policy);
 
@@ -1206,6 +1207,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
                policy->user_policy.policy = policy->policy;
                policy->user_policy.governor = policy->governor;
        }
+       up_write(&policy->rwsem);
 
        kobject_uevent(&policy->kobj, KOBJ_ADD);
        up_read(&cpufreq_rwsem);
@@ -1323,8 +1325,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
        up_read(&policy->rwsem);
 
        if (cpu != policy->cpu) {
-               if (!frozen)
-                       sysfs_remove_link(&dev->kobj, "cpufreq");
+               sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
                new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
                if (new_cpu >= 0) {
@@ -1547,23 +1548,16 @@ static unsigned int __cpufreq_get(unsigned int cpu)
  */
 unsigned int cpufreq_get(unsigned int cpu)
 {
-       struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
        unsigned int ret_freq = 0;
 
-       if (cpufreq_disabled() || !cpufreq_driver)
-               return -ENOENT;
-
-       BUG_ON(!policy);
-
-       if (!down_read_trylock(&cpufreq_rwsem))
-               return 0;
-
-       down_read(&policy->rwsem);
-
-       ret_freq = __cpufreq_get(cpu);
+       if (policy) {
+               down_read(&policy->rwsem);
+               ret_freq = __cpufreq_get(cpu);
+               up_read(&policy->rwsem);
 
-       up_read(&policy->rwsem);
-       up_read(&cpufreq_rwsem);
+               cpufreq_cpu_put(policy);
+       }
 
        return ret_freq;
 }
@@ -2149,7 +2143,7 @@ int cpufreq_update_policy(unsigned int cpu)
         * BIOS might change freq behind our back
         * -> ask driver for current freq and notify governors about a change
         */
-       if (cpufreq_driver->get) {
+       if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
                new_policy.cur = cpufreq_driver->get(cpu);
                if (!policy->cur) {
                        pr_debug("Driver did not initialize current freq");
index 5793e1447fb177f476f5f38ee117857444ba98c0..79911a27a48a90768c16a197633a2d1592fda27c 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/cpufreq.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <asm/cputime.h>
+#include <linux/cputime.h>
 
 static spinlock_t cpufreq_stats_lock;
 
index 7e257b2336025c3b2afd6faff9c0ae091fc7228f..2cd36b9297f3de01a4b5f2ed246d738e123d7991 100644 (file)
 
 #define SAMPLE_COUNT           3
 
-#define BYT_RATIOS     0x66a
-#define BYT_VIDS        0x66b
+#define BYT_RATIOS             0x66a
+#define BYT_VIDS               0x66b
+#define BYT_TURBO_RATIOS       0x66c
 
-#define FRAC_BITS 8
+
+#define FRAC_BITS 6
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
+#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS)
 
 static inline int32_t mul_fp(int32_t x, int32_t y)
 {
@@ -51,12 +54,11 @@ static inline int32_t div_fp(int32_t x, int32_t y)
        return div_s64((int64_t)x << FRAC_BITS, (int64_t)y);
 }
 
-static u64 energy_divisor;
-
 struct sample {
        int32_t core_pct_busy;
        u64 aperf;
        u64 mperf;
+       unsigned long long tsc;
        int freq;
 };
 
@@ -96,6 +98,7 @@ struct cpudata {
 
        u64     prev_aperf;
        u64     prev_mperf;
+       unsigned long long prev_tsc;
        int     sample_ptr;
        struct sample samples[SAMPLE_COUNT];
 };
@@ -357,7 +360,7 @@ static int byt_get_min_pstate(void)
 {
        u64 value;
        rdmsrl(BYT_RATIOS, value);
-       return value & 0xFF;
+       return (value >> 8) & 0xFF;
 }
 
 static int byt_get_max_pstate(void)
@@ -367,6 +370,13 @@ static int byt_get_max_pstate(void)
        return (value >> 16) & 0xFF;
 }
 
+static int byt_get_turbo_pstate(void)
+{
+       u64 value;
+       rdmsrl(BYT_TURBO_RATIOS, value);
+       return value & 0x3F;
+}
+
 static void byt_set_pstate(struct cpudata *cpudata, int pstate)
 {
        u64 val;
@@ -469,7 +479,7 @@ static struct cpu_defaults byt_params = {
        .funcs = {
                .get_max = byt_get_max_pstate,
                .get_min = byt_get_min_pstate,
-               .get_turbo = byt_get_max_pstate,
+               .get_turbo = byt_get_turbo_pstate,
                .set = byt_set_pstate,
                .get_vid = byt_get_vid,
        },
@@ -547,31 +557,48 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 static inline void intel_pstate_calc_busy(struct cpudata *cpu,
                                        struct sample *sample)
 {
-       u64 core_pct;
-       core_pct = div64_u64(int_tofp(sample->aperf * 100),
-                            sample->mperf);
-       sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000);
+       int32_t core_pct;
+       int32_t c0_pct;
+
+       core_pct = div_fp(int_tofp((sample->aperf)),
+                       int_tofp((sample->mperf)));
+       core_pct = mul_fp(core_pct, int_tofp(100));
+       FP_ROUNDUP(core_pct);
+
+       c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc));
 
-       sample->core_pct_busy = core_pct;
+       sample->freq = fp_toint(
+               mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
+
+       sample->core_pct_busy = mul_fp(core_pct, c0_pct);
 }
 
 static inline void intel_pstate_sample(struct cpudata *cpu)
 {
        u64 aperf, mperf;
+       unsigned long long tsc;
 
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
+       tsc = native_read_tsc();
+
+       aperf = aperf >> FRAC_BITS;
+       mperf = mperf >> FRAC_BITS;
+       tsc = tsc >> FRAC_BITS;
 
        cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
        cpu->samples[cpu->sample_ptr].aperf = aperf;
        cpu->samples[cpu->sample_ptr].mperf = mperf;
+       cpu->samples[cpu->sample_ptr].tsc = tsc;
        cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
        cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
+       cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc;
 
        intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
 
        cpu->prev_aperf = aperf;
        cpu->prev_mperf = mperf;
+       cpu->prev_tsc = tsc;
 }
 
 static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
@@ -590,7 +617,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
        core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy;
        max_pstate = int_tofp(cpu->pstate.max_pstate);
        current_pstate = int_tofp(cpu->pstate.current_pstate);
-       return mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+       core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+       return FP_ROUNDUP(core_busy);
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
@@ -617,12 +645,10 @@ static void intel_pstate_timer_func(unsigned long __data)
 {
        struct cpudata *cpu = (struct cpudata *) __data;
        struct sample *sample;
-       u64 energy;
 
        intel_pstate_sample(cpu);
 
        sample = &cpu->samples[cpu->sample_ptr];
-       rdmsrl(MSR_PKG_ENERGY_STATUS, energy);
 
        intel_pstate_adjust_busy_pstate(cpu);
 
@@ -631,7 +657,6 @@ static void intel_pstate_timer_func(unsigned long __data)
                        cpu->pstate.current_pstate,
                        sample->mperf,
                        sample->aperf,
-                       div64_u64(energy, energy_divisor),
                        sample->freq);
 
        intel_pstate_set_sample_time(cpu);
@@ -913,7 +938,6 @@ static int __init intel_pstate_init(void)
        int cpu, rc = 0;
        const struct x86_cpu_id *id;
        struct cpu_defaults *cpu_info;
-       u64 units;
 
        if (no_load)
                return -ENODEV;
@@ -947,9 +971,6 @@ static int __init intel_pstate_init(void)
        if (rc)
                goto out;
 
-       rdmsrl(MSR_RAPL_POWER_UNIT, units);
-       energy_divisor = 1 << ((units >> 8) & 0x1f); /* bits{12:8} */
-
        intel_pstate_debug_expose_params();
        intel_pstate_sysfs_expose_params();
 
index e10b646634d77ff3a4bcf0c54d154a91c7c35805..6684e0342792517577fde32d56542b3ad84d15af 100644 (file)
@@ -1076,7 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
        struct powernow_k8_data *data;
        struct init_on_cpu init_on_cpu;
-       int rc;
+       int rc, cpu;
 
        smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
        if (rc)
@@ -1140,7 +1140,9 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
        pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
                 data->currfid, data->currvid);
 
-       per_cpu(powernow_data, pol->cpu) = data;
+       /* Point all the CPUs in this policy to the same data */
+       for_each_cpu(cpu, pol->cpus)
+               per_cpu(powernow_data, cpu) = data;
 
        return 0;
 
@@ -1155,6 +1157,7 @@ err_out:
 static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 {
        struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+       int cpu;
 
        if (!data)
                return -EINVAL;
@@ -1165,7 +1168,8 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 
        kfree(data->powernow_table);
        kfree(data);
-       per_cpu(powernow_data, pol->cpu) = NULL;
+       for_each_cpu(cpu, pol->cpus)
+               per_cpu(powernow_data, cpu) = NULL;
 
        return 0;
 }
index 78fd174c57e86dfb4608a12f4af44d334ab1da7c..f48607cd254024f07501bd802112e90991d697b1 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/runlatch.h>
 
 struct cpuidle_driver powernv_idle_driver = {
        .name             = "powernv_idle",
@@ -30,12 +31,14 @@ static int snooze_loop(struct cpuidle_device *dev,
        local_irq_enable();
        set_thread_flag(TIF_POLLING_NRFLAG);
 
+       ppc64_runlatch_off();
        while (!need_resched()) {
                HMT_low();
                HMT_very_low();
        }
 
        HMT_medium();
+       ppc64_runlatch_on();
        clear_thread_flag(TIF_POLLING_NRFLAG);
        smp_mb();
        return index;
@@ -45,7 +48,9 @@ static int nap_loop(struct cpuidle_device *dev,
                        struct cpuidle_driver *drv,
                        int index)
 {
+       ppc64_runlatch_off();
        power7_idle();
+       ppc64_runlatch_on();
        return index;
 }
 
index 7ab564aa0b1c8c141e0b64f750592dc44bbbba3f..6f7b019568850c68478abcaae6de2238a4fac934 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/reg.h>
 #include <asm/machdep.h>
 #include <asm/firmware.h>
+#include <asm/runlatch.h>
 #include <asm/plpar_wrappers.h>
 
 struct cpuidle_driver pseries_idle_driver = {
@@ -29,6 +30,7 @@ static struct cpuidle_state *cpuidle_state_table;
 
 static inline void idle_loop_prolog(unsigned long *in_purr)
 {
+       ppc64_runlatch_off();
        *in_purr = mfspr(SPRN_PURR);
        /*
         * Indicate to the HV that we are idle. Now would be
@@ -45,6 +47,10 @@ static inline void idle_loop_epilog(unsigned long in_purr)
        wait_cycles += mfspr(SPRN_PURR) - in_purr;
        get_lppaca()->wait_state_cycles = cpu_to_be64(wait_cycles);
        get_lppaca()->idle = 0;
+
+       if (irqs_disabled())
+               local_irq_enable();
+       ppc64_runlatch_on();
 }
 
 static int snooze_loop(struct cpuidle_device *dev,
index 6c4c000671c50d88885bb39618c5ae9e4ceabe42..1e5481d88a262c655aec0d381574341531f5f4ae 100644 (file)
@@ -158,6 +158,15 @@ static inline unsigned long nx842_get_scatterlist_size(
        return sl->entry_nr * sizeof(struct nx842_slentry);
 }
 
+static inline unsigned long nx842_get_pa(void *addr)
+{
+       if (is_vmalloc_addr(addr))
+               return page_to_phys(vmalloc_to_page(addr))
+                      + offset_in_page(addr);
+       else
+               return __pa(addr);
+}
+
 static int nx842_build_scatterlist(unsigned long buf, int len,
                        struct nx842_scatterlist *sl)
 {
@@ -168,7 +177,7 @@ static int nx842_build_scatterlist(unsigned long buf, int len,
 
        entry = sl->entries;
        while (len) {
-               entry->ptr = __pa(buf);
+               entry->ptr = nx842_get_pa((void *)buf);
                nextpage = ALIGN(buf + 1, NX842_HW_PAGE_SIZE);
                if (nextpage < buf + len) {
                        /* we aren't at the end yet */
@@ -370,8 +379,8 @@ int nx842_compress(const unsigned char *in, unsigned int inlen,
        op.flags = NX842_OP_COMPRESS;
        csbcpb = &workmem->csbcpb;
        memset(csbcpb, 0, sizeof(*csbcpb));
-       op.csbcpb = __pa(csbcpb);
-       op.out = __pa(slout.entries);
+       op.csbcpb = nx842_get_pa(csbcpb);
+       op.out = nx842_get_pa(slout.entries);
 
        for (i = 0; i < hdr->blocks_nr; i++) {
                /*
@@ -401,13 +410,13 @@ int nx842_compress(const unsigned char *in, unsigned int inlen,
                 */
                if (likely(max_sync_size == NX842_HW_PAGE_SIZE)) {
                        /* Create direct DDE */
-                       op.in = __pa(inbuf);
+                       op.in = nx842_get_pa((void *)inbuf);
                        op.inlen = max_sync_size;
 
                } else {
                        /* Create indirect DDE (scatterlist) */
                        nx842_build_scatterlist(inbuf, max_sync_size, &slin);
-                       op.in = __pa(slin.entries);
+                       op.in = nx842_get_pa(slin.entries);
                        op.inlen = -nx842_get_scatterlist_size(&slin);
                }
 
@@ -565,7 +574,7 @@ int nx842_decompress(const unsigned char *in, unsigned int inlen,
        op.flags = NX842_OP_DECOMPRESS;
        csbcpb = &workmem->csbcpb;
        memset(csbcpb, 0, sizeof(*csbcpb));
-       op.csbcpb = __pa(csbcpb);
+       op.csbcpb = nx842_get_pa(csbcpb);
 
        /*
         * max_sync_size may have changed since compression,
@@ -597,12 +606,12 @@ int nx842_decompress(const unsigned char *in, unsigned int inlen,
                if (likely((inbuf & NX842_HW_PAGE_MASK) ==
                        ((inbuf + hdr->sizes[i] - 1) & NX842_HW_PAGE_MASK))) {
                        /* Create direct DDE */
-                       op.in = __pa(inbuf);
+                       op.in = nx842_get_pa((void *)inbuf);
                        op.inlen = hdr->sizes[i];
                } else {
                        /* Create indirect DDE (scatterlist) */
                        nx842_build_scatterlist(inbuf, hdr->sizes[i] , &slin);
-                       op.in = __pa(slin.entries);
+                       op.in = nx842_get_pa(slin.entries);
                        op.inlen = -nx842_get_scatterlist_size(&slin);
                }
 
@@ -613,12 +622,12 @@ int nx842_decompress(const unsigned char *in, unsigned int inlen,
                 */
                if (likely(max_sync_size == NX842_HW_PAGE_SIZE)) {
                        /* Create direct DDE */
-                       op.out = __pa(outbuf);
+                       op.out = nx842_get_pa((void *)outbuf);
                        op.outlen = max_sync_size;
                } else {
                        /* Create indirect DDE (scatterlist) */
                        nx842_build_scatterlist(outbuf, max_sync_size, &slout);
-                       op.out = __pa(slout.entries);
+                       op.out = nx842_get_pa(slout.entries);
                        op.outlen = -nx842_get_scatterlist_size(&slout);
                }
 
index 9bed1a2a67a12e44cde304995b6895e3f8296c2a..605b016bcea49dcea25d9515b2cec276ae974372 100644 (file)
@@ -346,6 +346,7 @@ config MOXART_DMA
        tristate "MOXART DMA support"
        depends on ARCH_MOXART
        select DMA_ENGINE
+       select DMA_OF
        select DMA_VIRTUAL_CHANNELS
        help
          Enable support for the MOXA ART SoC DMA controller.
index 4e7918339b1263a2720c3da11d271714dd9669ad..19041cefabb1c0ce8649ed8cf5ea41707fa7824f 100644 (file)
@@ -449,6 +449,7 @@ static const struct of_device_id sdma_dt_ids[] = {
        { .compatible = "fsl,imx51-sdma", .data = &sdma_imx51, },
        { .compatible = "fsl,imx35-sdma", .data = &sdma_imx35, },
        { .compatible = "fsl,imx31-sdma", .data = &sdma_imx31, },
+       { .compatible = "fsl,imx25-sdma", .data = &sdma_imx25, },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sdma_dt_ids);
index 87529181efccb9851467cc04be04bd91fecb15b3..4e3549a161324f29159775312b3c9d8075914359 100644 (file)
@@ -77,7 +77,8 @@ static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)
        attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
        for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
                chan = ioat_chan_by_index(instance, bit);
-               tasklet_schedule(&chan->cleanup_task);
+               if (test_bit(IOAT_RUN, &chan->state))
+                       tasklet_schedule(&chan->cleanup_task);
        }
 
        writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
@@ -93,7 +94,8 @@ static irqreturn_t ioat_dma_do_interrupt_msix(int irq, void *data)
 {
        struct ioat_chan_common *chan = data;
 
-       tasklet_schedule(&chan->cleanup_task);
+       if (test_bit(IOAT_RUN, &chan->state))
+               tasklet_schedule(&chan->cleanup_task);
 
        return IRQ_HANDLED;
 }
@@ -116,7 +118,6 @@ void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *c
        chan->timer.function = device->timer_fn;
        chan->timer.data = data;
        tasklet_init(&chan->cleanup_task, device->cleanup_fn, data);
-       tasklet_disable(&chan->cleanup_task);
 }
 
 /**
@@ -354,13 +355,49 @@ static int ioat1_dma_alloc_chan_resources(struct dma_chan *c)
        writel(((u64) chan->completion_dma) >> 32,
               chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
-       tasklet_enable(&chan->cleanup_task);
+       set_bit(IOAT_RUN, &chan->state);
        ioat1_dma_start_null_desc(ioat);  /* give chain to dma device */
        dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n",
                __func__, ioat->desccount);
        return ioat->desccount;
 }
 
+void ioat_stop(struct ioat_chan_common *chan)
+{
+       struct ioatdma_device *device = chan->device;
+       struct pci_dev *pdev = device->pdev;
+       int chan_id = chan_num(chan);
+       struct msix_entry *msix;
+
+       /* 1/ stop irq from firing tasklets
+        * 2/ stop the tasklet from re-arming irqs
+        */
+       clear_bit(IOAT_RUN, &chan->state);
+
+       /* flush inflight interrupts */
+       switch (device->irq_mode) {
+       case IOAT_MSIX:
+               msix = &device->msix_entries[chan_id];
+               synchronize_irq(msix->vector);
+               break;
+       case IOAT_MSI:
+       case IOAT_INTX:
+               synchronize_irq(pdev->irq);
+               break;
+       default:
+               break;
+       }
+
+       /* flush inflight timers */
+       del_timer_sync(&chan->timer);
+
+       /* flush inflight tasklet runs */
+       tasklet_kill(&chan->cleanup_task);
+
+       /* final cleanup now that everything is quiesced and can't re-arm */
+       device->cleanup_fn((unsigned long) &chan->common);
+}
+
 /**
  * ioat1_dma_free_chan_resources - release all the descriptors
  * @chan: the channel to be cleaned
@@ -379,9 +416,7 @@ static void ioat1_dma_free_chan_resources(struct dma_chan *c)
        if (ioat->desccount == 0)
                return;
 
-       tasklet_disable(&chan->cleanup_task);
-       del_timer_sync(&chan->timer);
-       ioat1_cleanup(ioat);
+       ioat_stop(chan);
 
        /* Delay 100ms after reset to allow internal DMA logic to quiesce
         * before removing DMA descriptor resources.
@@ -526,8 +561,11 @@ ioat1_dma_prep_memcpy(struct dma_chan *c, dma_addr_t dma_dest,
 static void ioat1_cleanup_event(unsigned long data)
 {
        struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
+       struct ioat_chan_common *chan = &ioat->base;
 
        ioat1_cleanup(ioat);
+       if (!test_bit(IOAT_RUN, &chan->state))
+               return;
        writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
index 11fb877ddca9a9b0888d23952dea8fb48245b617..e982f00a984399a3838f7b47ef2e21a2aab84495 100644 (file)
@@ -356,6 +356,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
 int ioat_dma_setup_interrupts(struct ioatdma_device *device);
+void ioat_stop(struct ioat_chan_common *chan);
 extern const struct sysfs_ops ioat_sysfs_ops;
 extern struct ioat_sysfs_entry ioat_version_attr;
 extern struct ioat_sysfs_entry ioat_cap_attr;
index 5d3affe7e976165ec5576ac8c6551dd438af7786..8d1058085eeb85beb3fb2d6ab88c57160ef0cf15 100644 (file)
@@ -190,8 +190,11 @@ static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
 void ioat2_cleanup_event(unsigned long data)
 {
        struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+       struct ioat_chan_common *chan = &ioat->base;
 
        ioat2_cleanup(ioat);
+       if (!test_bit(IOAT_RUN, &chan->state))
+               return;
        writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
@@ -553,10 +556,10 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
        ioat->issued = 0;
        ioat->tail = 0;
        ioat->alloc_order = order;
+       set_bit(IOAT_RUN, &chan->state);
        spin_unlock_bh(&ioat->prep_lock);
        spin_unlock_bh(&chan->cleanup_lock);
 
-       tasklet_enable(&chan->cleanup_task);
        ioat2_start_null_desc(ioat);
 
        /* check that we got off the ground */
@@ -566,7 +569,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c)
        } while (i++ < 20 && !is_ioat_active(status) && !is_ioat_idle(status));
 
        if (is_ioat_active(status) || is_ioat_idle(status)) {
-               set_bit(IOAT_RUN, &chan->state);
                return 1 << ioat->alloc_order;
        } else {
                u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
@@ -809,11 +811,8 @@ void ioat2_free_chan_resources(struct dma_chan *c)
        if (!ioat->ring)
                return;
 
-       tasklet_disable(&chan->cleanup_task);
-       del_timer_sync(&chan->timer);
-       device->cleanup_fn((unsigned long) c);
+       ioat_stop(chan);
        device->reset_hw(chan);
-       clear_bit(IOAT_RUN, &chan->state);
 
        spin_lock_bh(&chan->cleanup_lock);
        spin_lock_bh(&ioat->prep_lock);
index 820817e97e626a498561a9e5f0f3a61f22ffc9fa..b9b38a1cf92fbdc4147e70af93508f0d9caf6867 100644 (file)
@@ -464,8 +464,11 @@ static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
 static void ioat3_cleanup_event(unsigned long data)
 {
        struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+       struct ioat_chan_common *chan = &ioat->base;
 
        ioat3_cleanup(ioat);
+       if (!test_bit(IOAT_RUN, &chan->state))
+               return;
        writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
index 53fb0c8365b0b27f29a893a3072103c9fb2360e9..766b68ed505c4d2b3964bfb1f0de6ab5ae1ff3a9 100644 (file)
@@ -497,8 +497,8 @@ mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
                if (!mv_can_chain(grp_start))
                        goto submit_done;
 
-               dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %x\n",
-                       old_chain_tail->async_tx.phys);
+               dev_dbg(mv_chan_to_devp(mv_chan), "Append to last desc %pa\n",
+                       &old_chain_tail->async_tx.phys);
 
                /* fix up the hardware chain */
                mv_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
@@ -527,7 +527,8 @@ submit_done:
 /* returns the number of allocated descriptors */
 static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
 {
-       char *hw_desc;
+       void *virt_desc;
+       dma_addr_t dma_desc;
        int idx;
        struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
        struct mv_xor_desc_slot *slot = NULL;
@@ -542,17 +543,16 @@ static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
                                " %d descriptor slots", idx);
                        break;
                }
-               hw_desc = (char *) mv_chan->dma_desc_pool_virt;
-               slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+               virt_desc = mv_chan->dma_desc_pool_virt;
+               slot->hw_desc = virt_desc + idx * MV_XOR_SLOT_SIZE;
 
                dma_async_tx_descriptor_init(&slot->async_tx, chan);
                slot->async_tx.tx_submit = mv_xor_tx_submit;
                INIT_LIST_HEAD(&slot->chain_node);
                INIT_LIST_HEAD(&slot->slot_node);
                INIT_LIST_HEAD(&slot->tx_list);
-               hw_desc = (char *) mv_chan->dma_desc_pool;
-               slot->async_tx.phys =
-                       (dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+               dma_desc = mv_chan->dma_desc_pool;
+               slot->async_tx.phys = dma_desc + idx * MV_XOR_SLOT_SIZE;
                slot->idx = idx++;
 
                spin_lock_bh(&mv_chan->lock);
@@ -582,8 +582,8 @@ mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
        int slot_cnt;
 
        dev_dbg(mv_chan_to_devp(mv_chan),
-               "%s dest: %x src %x len: %u flags: %ld\n",
-               __func__, dest, src, len, flags);
+               "%s dest: %pad src %pad len: %u flags: %ld\n",
+               __func__, &dest, &src, len, flags);
        if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
                return NULL;
 
@@ -626,8 +626,8 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
        BUG_ON(len > MV_XOR_MAX_BYTE_COUNT);
 
        dev_dbg(mv_chan_to_devp(mv_chan),
-               "%s src_cnt: %d len: dest %x %u flags: %ld\n",
-               __func__, src_cnt, len, dest, flags);
+               "%s src_cnt: %d len: %u dest %pad flags: %ld\n",
+               __func__, src_cnt, len, &dest, flags);
 
        spin_lock_bh(&mv_chan->lock);
        slot_cnt = mv_chan_xor_slot_count(len, src_cnt);
index 00a2de957b234da060fe5e03592b171f50fa53d1..bf18c786ed40fbaae2a487246df5da85457fbec1 100644 (file)
@@ -1641,6 +1641,7 @@ static void dma_tasklet(unsigned long data)
        struct d40_chan *d40c = (struct d40_chan *) data;
        struct d40_desc *d40d;
        unsigned long flags;
+       bool callback_active;
        dma_async_tx_callback callback;
        void *callback_param;
 
@@ -1668,6 +1669,7 @@ static void dma_tasklet(unsigned long data)
        }
 
        /* Callback to client */
+       callback_active = !!(d40d->txd.flags & DMA_PREP_INTERRUPT);
        callback = d40d->txd.callback;
        callback_param = d40d->txd.callback_param;
 
@@ -1690,7 +1692,7 @@ static void dma_tasklet(unsigned long data)
 
        spin_unlock_irqrestore(&d40c->lock, flags);
 
-       if (callback && (d40d->txd.flags & DMA_PREP_INTERRUPT))
+       if (callback_active && callback)
                callback(callback_param);
 
        return;
index e8c9ef03495be4a450944ec996cbe85bb11156e3..33edd67663443123ab73dc91ee18550c1a9b62fb 100644 (file)
@@ -559,7 +559,8 @@ static void edac_mc_workq_function(struct work_struct *work_req)
  *
  *             called with the mem_ctls_mutex held
  */
-static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
+static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
+                               bool init)
 {
        edac_dbg(0, "\n");
 
@@ -567,7 +568,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
        if (mci->op_state != OP_RUNNING_POLL)
                return;
 
-       INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
+       if (init)
+               INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
+
        mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
 }
 
@@ -601,7 +604,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
  *     user space has updated our poll period value, need to
  *     reset our workq delays
  */
-void edac_mc_reset_delay_period(int value)
+void edac_mc_reset_delay_period(unsigned long value)
 {
        struct mem_ctl_info *mci;
        struct list_head *item;
@@ -611,7 +614,7 @@ void edac_mc_reset_delay_period(int value)
        list_for_each(item, &mc_devices) {
                mci = list_entry(item, struct mem_ctl_info, link);
 
-               edac_mc_workq_setup(mci, (unsigned long) value);
+               edac_mc_workq_setup(mci, value, false);
        }
 
        mutex_unlock(&mem_ctls_mutex);
@@ -782,7 +785,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
                /* This instance is NOW RUNNING */
                mci->op_state = OP_RUNNING_POLL;
 
-               edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
+               edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
        } else {
                mci->op_state = OP_RUNNING_INTERRUPT;
        }
index 51c0362acf5c456db84eb0786722c284849b30b9..b335c6ab5efe02e0ef9b5742e8691e617b5a30af 100644 (file)
@@ -52,18 +52,20 @@ int edac_mc_get_poll_msec(void)
 
 static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
 {
-       long l;
+       unsigned long l;
        int ret;
 
        if (!val)
                return -EINVAL;
 
-       ret = kstrtol(val, 0, &l);
+       ret = kstrtoul(val, 0, &l);
        if (ret)
                return ret;
-       if ((int)l != l)
+
+       if (l < 1000)
                return -EINVAL;
-       *((int *)kp->arg) = l;
+
+       *((unsigned long *)kp->arg) = l;
 
        /* notify edac_mc engine to reset the poll period */
        edac_mc_reset_delay_period(l);
index 3d139c6e7fe325719b7ddaf4b38127f5895f8bb8..f2118bfcf8dfbd861d24754320ac0a0439cfb9ed 100644 (file)
@@ -52,7 +52,7 @@ extern void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
 extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev);
 extern void edac_device_reset_delay_period(struct edac_device_ctl_info
                                           *edac_dev, unsigned long value);
-extern void edac_mc_reset_delay_period(int value);
+extern void edac_mc_reset_delay_period(unsigned long value);
 
 extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
 
index d63f4798f7d09127872f97ed925a5af64a75f81f..57e96a3350f0595ab002a5ff1285d85b44dd6e3f 100644 (file)
@@ -943,33 +943,35 @@ static int i7300_get_devices(struct mem_ctl_info *mci)
 
        /* Attempt to 'get' the MCH register we want */
        pdev = NULL;
-       while (!pvt->pci_dev_16_1_fsb_addr_map ||
-              !pvt->pci_dev_16_2_fsb_err_regs) {
-               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                     PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev);
-               if (!pdev) {
-                       /* End of list, leave */
-                       i7300_printk(KERN_ERR,
-                               "'system address,Process Bus' "
-                               "device not found:"
-                               "vendor 0x%x device 0x%x ERR funcs "
-                               "(broken BIOS?)\n",
-                               PCI_VENDOR_ID_INTEL,
-                               PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
-                       goto error;
-               }
-
+       while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_I7300_MCH_ERR,
+                                     pdev))) {
                /* Store device 16 funcs 1 and 2 */
                switch (PCI_FUNC(pdev->devfn)) {
                case 1:
-                       pvt->pci_dev_16_1_fsb_addr_map = pdev;
+                       if (!pvt->pci_dev_16_1_fsb_addr_map)
+                               pvt->pci_dev_16_1_fsb_addr_map =
+                                                       pci_dev_get(pdev);
                        break;
                case 2:
-                       pvt->pci_dev_16_2_fsb_err_regs = pdev;
+                       if (!pvt->pci_dev_16_2_fsb_err_regs)
+                               pvt->pci_dev_16_2_fsb_err_regs =
+                                                       pci_dev_get(pdev);
                        break;
                }
        }
 
+       if (!pvt->pci_dev_16_1_fsb_addr_map ||
+           !pvt->pci_dev_16_2_fsb_err_regs) {
+               /* At least one device was not found */
+               i7300_printk(KERN_ERR,
+                       "'system address,Process Bus' device not found:"
+                       "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n",
+                       PCI_VENDOR_ID_INTEL,
+                       PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
+               goto error;
+       }
+
        edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
                 pci_name(pvt->pci_dev_16_0_fsb_ctlr),
                 pvt->pci_dev_16_0_fsb_ctlr->vendor,
index 87533ca7752e0105683210913f83731a9b988aab..d871275196f6f04b6542e4941ee433e41fcfdf64 100644 (file)
@@ -1334,14 +1334,19 @@ static int i7core_get_onedevice(struct pci_dev **prev,
         * is at addr 8086:2c40, instead of 8086:2c41. So, we need
         * to probe for the alternate address in case of failure
         */
-       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) {
+               pci_dev_get(*prev);     /* pci_get_device will put it */
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+       }
 
-       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE &&
+           !pdev) {
+               pci_dev_get(*prev);     /* pci_get_device will put it */
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
                                      *prev);
+       }
 
        if (!pdev) {
                if (*prev) {
index c20602f601ee22732635aa3fa04fe94e44ed6020..98a14f6143a7087accee9c5d2b127c99c300b81d 100644 (file)
@@ -222,27 +222,19 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info)
        struct snd_soc_dapm_context *dapm = arizona->dapm;
        int ret;
 
-       mutex_lock(&dapm->card->dapm_mutex);
-
        ret = snd_soc_dapm_force_enable_pin(dapm, widget);
        if (ret != 0)
                dev_warn(arizona->dev, "Failed to enable %s: %d\n",
                         widget, ret);
 
-       mutex_unlock(&dapm->card->dapm_mutex);
-
        snd_soc_dapm_sync(dapm);
 
        if (!arizona->pdata.micd_force_micbias) {
-               mutex_lock(&dapm->card->dapm_mutex);
-
                ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
                if (ret != 0)
                        dev_warn(arizona->dev, "Failed to disable %s: %d\n",
                                 widget, ret);
 
-               mutex_unlock(&dapm->card->dapm_mutex);
-
                snd_soc_dapm_sync(dapm);
        }
 }
@@ -304,16 +296,12 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
                                 ARIZONA_MICD_ENA, 0,
                                 &change);
 
-       mutex_lock(&dapm->card->dapm_mutex);
-
        ret = snd_soc_dapm_disable_pin(dapm, widget);
        if (ret != 0)
                dev_warn(arizona->dev,
                         "Failed to disable %s: %d\n",
                         widget, ret);
 
-       mutex_unlock(&dapm->card->dapm_mutex);
-
        snd_soc_dapm_sync(dapm);
 
        if (info->micd_reva) {
index de4aa409abe2988d8dc5b421e969ab5256fb4009..2c6d5e118ac129e5ab9c24f09557b27e3248f3ea 100644 (file)
@@ -916,7 +916,7 @@ static int lookup_existing_device(struct device *dev, void *data)
                old->config_rom_retries = 0;
                fw_notice(card, "rediscovered device %s\n", dev_name(dev));
 
-               PREPARE_DELAYED_WORK(&old->work, fw_device_update);
+               old->workfn = fw_device_update;
                fw_schedule_device_work(old, 0);
 
                if (current_node == card->root_node)
@@ -1075,7 +1075,7 @@ static void fw_device_init(struct work_struct *work)
        if (atomic_cmpxchg(&device->state,
                           FW_DEVICE_INITIALIZING,
                           FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
-               PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+               device->workfn = fw_device_shutdown;
                fw_schedule_device_work(device, SHUTDOWN_DELAY);
        } else {
                fw_notice(card, "created device %s: GUID %08x%08x, S%d00\n",
@@ -1196,13 +1196,20 @@ static void fw_device_refresh(struct work_struct *work)
                  dev_name(&device->device), fw_rcode_string(ret));
  gone:
        atomic_set(&device->state, FW_DEVICE_GONE);
-       PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+       device->workfn = fw_device_shutdown;
        fw_schedule_device_work(device, SHUTDOWN_DELAY);
  out:
        if (node_id == card->root_node->node_id)
                fw_schedule_bm_work(card, 0);
 }
 
+static void fw_device_workfn(struct work_struct *work)
+{
+       struct fw_device *device = container_of(to_delayed_work(work),
+                                               struct fw_device, work);
+       device->workfn(work);
+}
+
 void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
 {
        struct fw_device *device;
@@ -1252,7 +1259,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                 * power-up after getting plugged in.  We schedule the
                 * first config rom scan half a second after bus reset.
                 */
-               INIT_DELAYED_WORK(&device->work, fw_device_init);
+               device->workfn = fw_device_init;
+               INIT_DELAYED_WORK(&device->work, fw_device_workfn);
                fw_schedule_device_work(device, INITIAL_DELAY);
                break;
 
@@ -1268,7 +1276,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                if (atomic_cmpxchg(&device->state,
                            FW_DEVICE_RUNNING,
                            FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
-                       PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
+                       device->workfn = fw_device_refresh;
                        fw_schedule_device_work(device,
                                device->is_local ? 0 : INITIAL_DELAY);
                }
@@ -1283,7 +1291,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                smp_wmb();  /* update node_id before generation */
                device->generation = card->generation;
                if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
-                       PREPARE_DELAYED_WORK(&device->work, fw_device_update);
+                       device->workfn = fw_device_update;
                        fw_schedule_device_work(device, 0);
                }
                break;
@@ -1308,7 +1316,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
                device = node->data;
                if (atomic_xchg(&device->state,
                                FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
-                       PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+                       device->workfn = fw_device_shutdown;
                        fw_schedule_device_work(device,
                                list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
                }
index 6b895986dc225115573add201958e60897934853..4af0a7bad7f21561cc4e7a29031c238a34f0135d 100644 (file)
@@ -929,8 +929,6 @@ static void fwnet_write_complete(struct fw_card *card, int rcode,
        if (rcode == RCODE_COMPLETE) {
                fwnet_transmit_packet_done(ptask);
        } else {
-               fwnet_transmit_packet_failed(ptask);
-
                if (printk_timed_ratelimit(&j,  1000) || rcode != last_rcode) {
                        dev_err(&ptask->dev->netdev->dev,
                                "fwnet_write_complete failed: %x (skipped %d)\n",
@@ -938,8 +936,10 @@ static void fwnet_write_complete(struct fw_card *card, int rcode,
 
                        errors_skipped = 0;
                        last_rcode = rcode;
-               } else
+               } else {
                        errors_skipped++;
+               }
+               fwnet_transmit_packet_failed(ptask);
        }
 }
 
index 6f74d8d3f70015a089f02948294454863cb6bcd7..8db66321956068701cde997e0bc25e167e781eb3 100644 (file)
@@ -290,7 +290,6 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 #define QUIRK_NO_MSI                   0x10
 #define QUIRK_TI_SLLZ059               0x20
 #define QUIRK_IR_WAKE                  0x40
-#define QUIRK_PHY_LCTRL_TIMEOUT                0x80
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
@@ -303,10 +302,7 @@ static const struct {
                QUIRK_BE_HEADERS},
 
        {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
-               QUIRK_PHY_LCTRL_TIMEOUT | QUIRK_NO_MSI},
-
-       {PCI_VENDOR_ID_ATT, PCI_ANY_ID, PCI_ANY_ID,
-               QUIRK_PHY_LCTRL_TIMEOUT},
+               QUIRK_NO_MSI},
 
        {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
                QUIRK_RESET_PACKET},
@@ -353,7 +349,6 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
        ", disable MSI = "              __stringify(QUIRK_NO_MSI)
        ", TI SLLZ059 erratum = "       __stringify(QUIRK_TI_SLLZ059)
        ", IR wake unreliable = "       __stringify(QUIRK_IR_WAKE)
-       ", phy LCtrl timeout = "        __stringify(QUIRK_PHY_LCTRL_TIMEOUT)
        ")");
 
 #define OHCI_PARAM_DEBUG_AT_AR         1
@@ -2299,9 +2294,6 @@ static int ohci_enable(struct fw_card *card,
         * TI TSB82AA2 + TSB81BA3(A) cards signal LPS enabled early but
         * cannot actually use the phy at that time.  These need tens of
         * millisecods pause between LPS write and first phy access too.
-        *
-        * But do not wait for 50msec on Agere/LSI cards.  Their phy
-        * arbitration state machine may time out during such a long wait.
         */
 
        reg_write(ohci, OHCI1394_HCControlSet,
@@ -2309,11 +2301,8 @@ static int ohci_enable(struct fw_card *card,
                  OHCI1394_HCControl_postedWriteEnable);
        flush_writes(ohci);
 
-       if (!(ohci->quirks & QUIRK_PHY_LCTRL_TIMEOUT))
+       for (lps = 0, i = 0; !lps && i < 3; i++) {
                msleep(50);
-
-       for (lps = 0, i = 0; !lps && i < 150; i++) {
-               msleep(1);
                lps = reg_read(ohci, OHCI1394_HCControlSet) &
                      OHCI1394_HCControl_LPS;
        }
index 281029daf98c7ea291886d46ecf05378bfa98718..7aef911fdc716d4874b7152b3c0d6e27bc8c1642 100644 (file)
@@ -146,6 +146,7 @@ struct sbp2_logical_unit {
         */
        int generation;
        int retries;
+       work_func_t workfn;
        struct delayed_work work;
        bool has_sdev;
        bool blocked;
@@ -864,7 +865,7 @@ static void sbp2_login(struct work_struct *work)
        /* set appropriate retry limit(s) in BUSY_TIMEOUT register */
        sbp2_set_busy_timeout(lu);
 
-       PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
+       lu->workfn = sbp2_reconnect;
        sbp2_agent_reset(lu);
 
        /* This was a re-login. */
@@ -918,7 +919,7 @@ static void sbp2_login(struct work_struct *work)
         * If a bus reset happened, sbp2_update will have requeued
         * lu->work already.  Reset the work from reconnect to login.
         */
-       PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+       lu->workfn = sbp2_login;
 }
 
 static void sbp2_reconnect(struct work_struct *work)
@@ -952,7 +953,7 @@ static void sbp2_reconnect(struct work_struct *work)
                    lu->retries++ >= 5) {
                        dev_err(tgt_dev(tgt), "failed to reconnect\n");
                        lu->retries = 0;
-                       PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+                       lu->workfn = sbp2_login;
                }
                sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
 
@@ -972,6 +973,13 @@ static void sbp2_reconnect(struct work_struct *work)
        sbp2_conditionally_unblock(lu);
 }
 
+static void sbp2_lu_workfn(struct work_struct *work)
+{
+       struct sbp2_logical_unit *lu = container_of(to_delayed_work(work),
+                                               struct sbp2_logical_unit, work);
+       lu->workfn(work);
+}
+
 static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
 {
        struct sbp2_logical_unit *lu;
@@ -998,7 +1006,8 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
        lu->blocked  = false;
        ++tgt->dont_block;
        INIT_LIST_HEAD(&lu->orb_list);
-       INIT_DELAYED_WORK(&lu->work, sbp2_login);
+       lu->workfn = sbp2_login;
+       INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn);
 
        list_add_tail(&lu->link, &tgt->lu_list);
        return 0;
index 1b5e8e46226d5f3d6bebdb770d8b29de9f04fc43..7160c43c59fcc31af1fbbbf79c1b44d87a68e22f 100644 (file)
@@ -584,7 +584,7 @@ static struct platform_driver dcdbas_driver = {
        .remove         = dcdbas_remove,
 };
 
-static const struct platform_device_info dcdbas_dev_info __initdata = {
+static const struct platform_device_info dcdbas_dev_info __initconst = {
        .name           = DRIVER_NAME,
        .id             = -1,
        .dma_mask       = DMA_BIT_MASK(32),
index b6bffbfd3be7a14131c7735960a12db3f43b122d..ff50aeebf0d98828072eea4b40944ebfa7594c77 100644 (file)
@@ -16,18 +16,6 @@ struct file_info {
        u64 size;
 };
 
-
-
-
-static void efi_char16_printk(efi_system_table_t *sys_table_arg,
-                             efi_char16_t *str)
-{
-       struct efi_simple_text_output_protocol *out;
-
-       out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
-       efi_call_phys2(out->output_string, out, str);
-}
-
 static void efi_printk(efi_system_table_t *sys_table_arg, char *str)
 {
        char *s8;
@@ -65,20 +53,23 @@ again:
         * allocation which may be in a new descriptor region.
         */
        *map_size += sizeof(*m);
-       status = efi_call_phys3(sys_table_arg->boottime->allocate_pool,
-                               EFI_LOADER_DATA, *map_size, (void **)&m);
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               *map_size, (void **)&m);
        if (status != EFI_SUCCESS)
                goto fail;
 
-       status = efi_call_phys5(sys_table_arg->boottime->get_memory_map,
-                               map_size, m, &key, desc_size, &desc_version);
+       *desc_size = 0;
+       key = 0;
+       status = efi_call_early(get_memory_map, map_size, m,
+                               &key, desc_size, &desc_version);
        if (status == EFI_BUFFER_TOO_SMALL) {
-               efi_call_phys1(sys_table_arg->boottime->free_pool, m);
+               efi_call_early(free_pool, m);
                goto again;
        }
 
        if (status != EFI_SUCCESS)
-               efi_call_phys1(sys_table_arg->boottime->free_pool, m);
+               efi_call_early(free_pool, m);
+
        if (key_ptr && status == EFI_SUCCESS)
                *key_ptr = key;
        if (desc_ver && status == EFI_SUCCESS)
@@ -158,7 +149,7 @@ again:
        if (!max_addr)
                status = EFI_NOT_FOUND;
        else {
-               status = efi_call_phys4(sys_table_arg->boottime->allocate_pages,
+               status = efi_call_early(allocate_pages,
                                        EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
                                        nr_pages, &max_addr);
                if (status != EFI_SUCCESS) {
@@ -170,8 +161,7 @@ again:
                *addr = max_addr;
        }
 
-       efi_call_phys1(sys_table_arg->boottime->free_pool, map);
-
+       efi_call_early(free_pool, map);
 fail:
        return status;
 }
@@ -231,7 +221,7 @@ static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
                if ((start + size) > end)
                        continue;
 
-               status = efi_call_phys4(sys_table_arg->boottime->allocate_pages,
+               status = efi_call_early(allocate_pages,
                                        EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
                                        nr_pages, &start);
                if (status == EFI_SUCCESS) {
@@ -243,7 +233,7 @@ static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
        if (i == map_size / desc_size)
                status = EFI_NOT_FOUND;
 
-       efi_call_phys1(sys_table_arg->boottime->free_pool, map);
+       efi_call_early(free_pool, map);
 fail:
        return status;
 }
@@ -257,7 +247,7 @@ static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
                return;
 
        nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-       efi_call_phys2(sys_table_arg->boottime->free_pages, addr, nr_pages);
+       efi_call_early(free_pages, addr, nr_pages);
 }
 
 
@@ -276,9 +266,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 {
        struct file_info *files;
        unsigned long file_addr;
-       efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
        u64 file_size_total;
-       efi_file_io_interface_t *io;
        efi_file_handle_t *fh;
        efi_status_t status;
        int nr_files;
@@ -319,10 +307,8 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
        if (!nr_files)
                return EFI_SUCCESS;
 
-       status = efi_call_phys3(sys_table_arg->boottime->allocate_pool,
-                               EFI_LOADER_DATA,
-                               nr_files * sizeof(*files),
-                               (void **)&files);
+       status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+                               nr_files * sizeof(*files), (void **)&files);
        if (status != EFI_SUCCESS) {
                efi_printk(sys_table_arg, "Failed to alloc mem for file handle list\n");
                goto fail;
@@ -331,13 +317,8 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
        str = cmd_line;
        for (i = 0; i < nr_files; i++) {
                struct file_info *file;
-               efi_file_handle_t *h;
-               efi_file_info_t *info;
                efi_char16_t filename_16[256];
-               unsigned long info_sz;
-               efi_guid_t info_guid = EFI_FILE_INFO_ID;
                efi_char16_t *p;
-               u64 file_sz;
 
                str = strstr(str, option_string);
                if (!str)
@@ -368,71 +349,18 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
 
                /* Only open the volume once. */
                if (!i) {
-                       efi_boot_services_t *boottime;
-
-                       boottime = sys_table_arg->boottime;
-
-                       status = efi_call_phys3(boottime->handle_protocol,
-                                       image->device_handle, &fs_proto,
-                                               (void **)&io);
-                       if (status != EFI_SUCCESS) {
-                               efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
-                               goto free_files;
-                       }
-
-                       status = efi_call_phys2(io->open_volume, io, &fh);
-                       if (status != EFI_SUCCESS) {
-                               efi_printk(sys_table_arg, "Failed to open volume\n");
+                       status = efi_open_volume(sys_table_arg, image,
+                                                (void **)&fh);
+                       if (status != EFI_SUCCESS)
                                goto free_files;
-                       }
                }
 
-               status = efi_call_phys5(fh->open, fh, &h, filename_16,
-                                       EFI_FILE_MODE_READ, (u64)0);
-               if (status != EFI_SUCCESS) {
-                       efi_printk(sys_table_arg, "Failed to open file: ");
-                       efi_char16_printk(sys_table_arg, filename_16);
-                       efi_printk(sys_table_arg, "\n");
+               status = efi_file_size(sys_table_arg, fh, filename_16,
+                                      (void **)&file->handle, &file->size);
+               if (status != EFI_SUCCESS)
                        goto close_handles;
-               }
 
-               file->handle = h;
-
-               info_sz = 0;
-               status = efi_call_phys4(h->get_info, h, &info_guid,
-                                       &info_sz, NULL);
-               if (status != EFI_BUFFER_TOO_SMALL) {
-                       efi_printk(sys_table_arg, "Failed to get file info size\n");
-                       goto close_handles;
-               }
-
-grow:
-               status = efi_call_phys3(sys_table_arg->boottime->allocate_pool,
-                                       EFI_LOADER_DATA, info_sz,
-                                       (void **)&info);
-               if (status != EFI_SUCCESS) {
-                       efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
-                       goto close_handles;
-               }
-
-               status = efi_call_phys4(h->get_info, h, &info_guid,
-                                       &info_sz, info);
-               if (status == EFI_BUFFER_TOO_SMALL) {
-                       efi_call_phys1(sys_table_arg->boottime->free_pool,
-                                      info);
-                       goto grow;
-               }
-
-               file_sz = info->file_size;
-               efi_call_phys1(sys_table_arg->boottime->free_pool, info);
-
-               if (status != EFI_SUCCESS) {
-                       efi_printk(sys_table_arg, "Failed to get file info\n");
-                       goto close_handles;
-               }
-
-               file->size = file_sz;
-               file_size_total += file_sz;
+               file_size_total += file->size;
        }
 
        if (file_size_total) {
@@ -468,10 +396,10 @@ grow:
                                        chunksize = EFI_READ_CHUNK_SIZE;
                                else
                                        chunksize = size;
-                               status = efi_call_phys3(fh->read,
-                                                       files[j].handle,
-                                                       &chunksize,
-                                                       (void *)addr);
+
+                               status = efi_file_read(fh, files[j].handle,
+                                                      &chunksize,
+                                                      (void *)addr);
                                if (status != EFI_SUCCESS) {
                                        efi_printk(sys_table_arg, "Failed to read file\n");
                                        goto free_file_total;
@@ -480,12 +408,12 @@ grow:
                                size -= chunksize;
                        }
 
-                       efi_call_phys1(fh->close, files[j].handle);
+                       efi_file_close(fh, files[j].handle);
                }
 
        }
 
-       efi_call_phys1(sys_table_arg->boottime->free_pool, files);
+       efi_call_early(free_pool, files);
 
        *load_addr = file_addr;
        *load_size = file_size_total;
@@ -497,9 +425,9 @@ free_file_total:
 
 close_handles:
        for (k = j; k < i; k++)
-               efi_call_phys1(fh->close, files[k].handle);
+               efi_file_close(fh, files[k].handle);
 free_files:
-       efi_call_phys1(sys_table_arg->boottime->free_pool, files);
+       efi_call_early(free_pool, files);
 fail:
        *load_addr = 0;
        *load_size = 0;
@@ -545,7 +473,7 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
         * as possible while respecting the required alignment.
         */
        nr_pages = round_up(alloc_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-       status = efi_call_phys4(sys_table_arg->boottime->allocate_pages,
+       status = efi_call_early(allocate_pages,
                                EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
                                nr_pages, &efi_addr);
        new_addr = efi_addr;
index 4753bac652798501cc79caeb50bd6c9ebd2b2dd3..af20f17123374f9ba4f6b4ab2d1e4faa47ef43c5 100644 (file)
@@ -233,7 +233,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
        {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
        {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
        {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
-       {NULL_GUID, NULL, 0},
+       {NULL_GUID, NULL, NULL},
 };
 
 static __init int match_config_table(efi_guid_t *guid,
@@ -313,5 +313,8 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
        }
        pr_cont("\n");
        early_iounmap(config_tables, efi.systab->nr_tables * sz);
+
+       set_bit(EFI_CONFIG_TABLES, &efi.flags);
+
        return 0;
 }
index 3dc24823919749ebb110f62b9ca5696cdaf67511..50ea412a25e64058a58b3de92b8f141f5db4e5a5 100644 (file)
@@ -227,7 +227,7 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
        memcpy(&entry->var, new_var, count);
 
        err = efivar_entry_set(entry, new_var->Attributes,
-                              new_var->DataSize, new_var->Data, false);
+                              new_var->DataSize, new_var->Data, NULL);
        if (err) {
                printk(KERN_WARNING "efivars: set_variable() failed: status=%d\n", err);
                return -EIO;
index ee5b47904130bdaab802fb3ddb6bce0f5f73c215..9bb2cbd5c9f265e421ded04a69b72f37141a2663 100644 (file)
@@ -27,7 +27,7 @@ FMC_PARAM_BUSID(fwe_drv);
 /* The "file=" is like the generic "gateware=" used elsewhere */
 static char *fwe_file[FMC_MAX_CARDS];
 static int fwe_file_n;
-module_param_array_named(file, fwe_file, charp, &fwe_file_n, 444);
+module_param_array_named(file, fwe_file, charp, &fwe_file_n, 0444);
 
 static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw,
        int write)
index 697338772b64802fae727a8b6788756e28d15939..903f24d28ba065f5fdaceff34cbf55cf287c26f0 100644 (file)
@@ -403,6 +403,7 @@ config GPIO_GRGPIO
 
 config GPIO_TB10X
        bool
+       select GENERIC_IRQ_CHIP
        select OF_GPIO
 
 comment "I2C GPIO expanders:"
index 233d088ac59fd69e389c8b759fab75bb5af231eb..f32357e2d78d89cf5b645512279122eb87c78ccc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Broadcom Corporation
+ * Copyright (C) 2012-2014 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -657,6 +657,6 @@ static struct platform_driver bcm_kona_gpio_driver = {
 
 module_platform_driver(bcm_kona_gpio_driver);
 
-MODULE_AUTHOR("Broadcom");
+MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
 MODULE_DESCRIPTION("Broadcom Kona GPIO Driver");
 MODULE_LICENSE("GPL v2");
index d3550274b8f7e64c293bc8d53ef7cd51598ed5f6..3c2ba2ad0ada7a0fa21d38021baeedf4a9a50583 100644 (file)
@@ -97,3 +97,4 @@ module_platform_driver(clps711x_gpio_driver);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
 MODULE_DESCRIPTION("CLPS711X GPIO driver");
+MODULE_ALIAS("platform:clps711x-gpio");
index d1b50ef5fab86928346ac741e7cbfc1c40d64ea0..e585163f1ad55202ecebd56d882992f8765e72fd 100644 (file)
@@ -394,8 +394,8 @@ static const struct irq_domain_ops intel_gpio_irq_ops = {
 
 static int intel_gpio_runtime_idle(struct device *dev)
 {
-       pm_schedule_suspend(dev, 500);
-       return -EBUSY;
+       int err = pm_schedule_suspend(dev, 500);
+       return err ?: -EBUSY;
 }
 
 static const struct dev_pm_ops intel_gpio_pm_ops = {
index 1d136eceda62db25575d0f4b86e2848ff26256a5..7081304d6797b4d27c6dab1309e4c0169a19dcd2 100644 (file)
@@ -40,6 +40,8 @@
 #error GPIO32 option is not enabled for your xtensa core variant
 #endif
 
+#if XCHAL_HAVE_CP
+
 static inline unsigned long enable_cp(unsigned long *cpenable)
 {
        unsigned long flags;
@@ -57,6 +59,20 @@ static inline void disable_cp(unsigned long flags, unsigned long cpenable)
        local_irq_restore(flags);
 }
 
+#else
+
+static inline unsigned long enable_cp(unsigned long *cpenable)
+{
+       *cpenable = 0; /* avoid uninitialized value warning */
+       return 0;
+}
+
+static inline void disable_cp(unsigned long flags, unsigned long cpenable)
+{
+}
+
+#endif /* XCHAL_HAVE_CP */
+
 static int xtensa_impwire_get_direction(struct gpio_chip *gc, unsigned offset)
 {
        return 1; /* input only */
index acf3a36c9ebc453737b1a849aa6715f41b241d68..32982da82694be753d1072c90136d842a8a866ec 100644 (file)
@@ -68,15 +68,7 @@ void __armada_drm_queue_unref_work(struct drm_device *dev,
 {
        struct armada_private *priv = dev->dev_private;
 
-       /*
-        * Yes, we really must jump through these hoops just to store a
-        * _pointer_ to something into the kfifo.  This is utterly insane
-        * and idiotic, because it kfifo requires the _data_ pointed to by
-        * the pointer const, not the pointer itself.  Not only that, but
-        * you have to pass a pointer _to_ the pointer you want stored.
-        */
-       const struct drm_framebuffer *silly_api_alert = fb;
-       WARN_ON(!kfifo_put(&priv->fb_unref, &silly_api_alert));
+       WARN_ON(!kfifo_put(&priv->fb_unref, fb));
        schedule_work(&priv->fb_unref_work);
 }
 
index 3f65dd6676b2c1354a4faef7d723f171ad840c67..a28640f47c2749e5848d129af85673fd8ccbc973 100644 (file)
@@ -65,7 +65,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
         * then the BO is being moved and we should
         * store up the damage until later.
         */
-       if (!drm_can_sleep())
+       if (drm_can_sleep())
                ret = ast_bo_reserve(bo, true);
        if (ret) {
                if (ret != -EBUSY)
index c8fcf12019f09c1eaffff1d72ea72c74714325e2..5f8b0c2b9a4461d2e07b1d7a3abb25f69837fc90 100644 (file)
@@ -2,6 +2,7 @@ config DRM_BOCHS
        tristate "DRM Support for bochs dispi vga interface (qemu stdvga)"
        depends on DRM && PCI
        select DRM_KMS_HELPER
+       select DRM_KMS_FB_HELPER
        select FB_SYS_FILLRECT
        select FB_SYS_COPYAREA
        select FB_SYS_IMAGEBLIT
index 2fd4a92162cb8880b3c0834ee294184b57b7edf7..32bbba0a787bc9e85d68556756c62771b06c5adb 100644 (file)
@@ -39,7 +39,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
         * then the BO is being moved and we should
         * store up the damage until later.
         */
-       if (!drm_can_sleep())
+       if (drm_can_sleep())
                ret = cirrus_bo_reserve(bo, true);
        if (ret) {
                if (ret != -EBUSY)
index bb8f58012189af7651c20c2d9b1da1ed390ebcfd..534cb89b160d686d60218dad53082be9b0f331ea 100644 (file)
 #include <drm/drmP.h>
 
 #if defined(CONFIG_X86)
+
+/*
+ * clflushopt is an unordered instruction which needs fencing with mfence or
+ * sfence to avoid ordering issues.  For drm_clflush_page this fencing happens
+ * in the caller.
+ */
 static void
 drm_clflush_page(struct page *page)
 {
@@ -44,7 +50,7 @@ drm_clflush_page(struct page *page)
 
        page_virtual = kmap_atomic(page);
        for (i = 0; i < PAGE_SIZE; i += size)
-               clflush(page_virtual + i);
+               clflushopt(page_virtual + i);
        kunmap_atomic(page_virtual);
 }
 
@@ -133,7 +139,7 @@ drm_clflush_virt_range(char *addr, unsigned long length)
                mb();
                for (; addr < end; addr += boot_cpu_data.x86_clflush_size)
                        clflush(addr);
-               clflush(end - 1);
+               clflushopt(end - 1);
                mb();
                return;
        }
index dffc836144cc96266a616902aa457b46c0ef1b33..f4dc9b7a3831f32d43f0e53cd8ed9791cac665ad 100644 (file)
@@ -296,6 +296,18 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
        case DRM_CAP_ASYNC_PAGE_FLIP:
                req->value = dev->mode_config.async_page_flip;
                break;
+       case DRM_CAP_CURSOR_WIDTH:
+               if (dev->mode_config.cursor_width)
+                       req->value = dev->mode_config.cursor_width;
+               else
+                       req->value = 64;
+               break;
+       case DRM_CAP_CURSOR_HEIGHT:
+               if (dev->mode_config.cursor_height)
+                       req->value = dev->mode_config.cursor_height;
+               else
+                       req->value = 64;
+               break;
        default:
                return -EINVAL;
        }
index 5736aaa7e86cb069d30fd458b5842fd42defae17..f7af69bcf3f452aff52647d830e3f1497ad21dca 100644 (file)
@@ -468,8 +468,8 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
        } else {
                list_for_each_entry_safe(dev, tmp, &driver->legacy_dev_list,
                                         legacy_dev_list) {
-                       drm_put_dev(dev);
                        list_del(&dev->legacy_dev_list);
+                       drm_put_dev(dev);
                }
        }
        DRM_INFO("Module unloaded\n");
index f227f544aa36f2104df33bbeacb5a8dc1e18bbd2..6e1a1a20cf6b4ab94a0f06f43d6470416dfcc879 100644 (file)
@@ -51,7 +51,7 @@ config DRM_EXYNOS_G2D
 
 config DRM_EXYNOS_IPP
        bool "Exynos DRM IPP"
-       depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM
+       depends on DRM_EXYNOS
        help
          Choose this option if you want to use IPP feature for DRM.
 
@@ -69,6 +69,6 @@ config DRM_EXYNOS_ROTATOR
 
 config DRM_EXYNOS_GSC
        bool "Exynos DRM GSC"
-       depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5
+       depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
        help
          Choose this option if you want to use Exynos GSC for DRM.
index 9d096a0c5f8d5f6bf0583d37f5efe433085504e4..c204b4e3356e80db01b736595d854075065768c0 100644 (file)
@@ -171,22 +171,28 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
        file->driver_priv = file_priv;
 
        ret = exynos_drm_subdrv_open(dev, file);
-       if (ret) {
-               kfree(file_priv);
-               file->driver_priv = NULL;
-       }
+       if (ret)
+               goto err_file_priv_free;
 
        anon_filp = anon_inode_getfile("exynos_gem", &exynos_drm_gem_fops,
                                        NULL, 0);
        if (IS_ERR(anon_filp)) {
-               kfree(file_priv);
-               return PTR_ERR(anon_filp);
+               ret = PTR_ERR(anon_filp);
+               goto err_subdrv_close;
        }
 
        anon_filp->f_mode = FMODE_READ | FMODE_WRITE;
        file_priv->anon_filp = anon_filp;
 
        return ret;
+
+err_subdrv_close:
+       exynos_drm_subdrv_close(dev, file);
+
+err_file_priv_free:
+       kfree(file_priv);
+       file->driver_priv = NULL;
+       return ret;
 }
 
 static void exynos_drm_preclose(struct drm_device *dev,
index 380aec28840b7e5ec4245e71207f0586f05efe75..6c1885eedfdfbd381d463763bf4d605e54e1c922 100644 (file)
@@ -607,7 +607,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
                reg_type = REG_TYPE_NONE;
                DRM_ERROR("Unknown register offset![%d]\n", reg_offset);
                break;
-       };
+       }
 
        return reg_type;
 }
index d519a4e5fe4022bd9101ede7a1e0edd2a4883dba..09312b8774709478f43ea8690f802651fa85feb4 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
-#include <plat/map-base.h>
 
 #include <drm/drmP.h>
 #include <drm/exynos_drm.h>
@@ -826,7 +825,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
                DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e);
 
                /*
-                * quf == NULL condition means all event deletion.
+                * qbuf == NULL condition means all event deletion.
                 * stop operations want to delete all event list.
                 * another case delete only same buf id.
                 */
index a0e10aeb0e674bf6472e4f5dee45a8f1322790cc..c021ddc1ffb4b4e982ac01874953dbb7239ddc31 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/hdmi.h>
 
 #include <drm/exynos_drm.h>
 
 #define HDMI_AUI_VERSION       0x01
 #define HDMI_AUI_LENGTH        0x0A
 
-/* HDMI infoframe to configure HDMI out packet header, AUI and AVI */
-enum HDMI_PACKET_TYPE {
-       /* refer to Table 5-8 Packet Type in HDMI specification v1.4a */
-       /* InfoFrame packet type */
-       HDMI_PACKET_TYPE_INFOFRAME = 0x80,
-       /* Vendor-Specific InfoFrame */
-       HDMI_PACKET_TYPE_VSI = HDMI_PACKET_TYPE_INFOFRAME + 1,
-       /* Auxiliary Video information InfoFrame */
-       HDMI_PACKET_TYPE_AVI = HDMI_PACKET_TYPE_INFOFRAME + 2,
-       /* Audio information InfoFrame */
-       HDMI_PACKET_TYPE_AUI = HDMI_PACKET_TYPE_INFOFRAME + 4
-};
-
 enum hdmi_type {
        HDMI_TYPE13,
        HDMI_TYPE14,
@@ -379,12 +367,6 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
        },
 };
 
-struct hdmi_infoframe {
-       enum HDMI_PACKET_TYPE type;
-       u8 ver;
-       u8 len;
-};
-
 static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
 {
        return readl(hdata->regs + reg_id);
@@ -682,7 +664,7 @@ static u8 hdmi_chksum(struct hdmi_context *hdata,
 }
 
 static void hdmi_reg_infoframe(struct hdmi_context *hdata,
-                       struct hdmi_infoframe *infoframe)
+                       union hdmi_infoframe *infoframe)
 {
        u32 hdr_sum;
        u8 chksum;
@@ -700,13 +682,15 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
                return;
        }
 
-       switch (infoframe->type) {
-       case HDMI_PACKET_TYPE_AVI:
+       switch (infoframe->any.type) {
+       case HDMI_INFOFRAME_TYPE_AVI:
                hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
-               hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type);
-               hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver);
-               hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len);
-               hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
+               hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
+               hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
+                               infoframe->any.version);
+               hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
+               hdr_sum = infoframe->any.type + infoframe->any.version +
+                         infoframe->any.length;
 
                /* Output format zero hardcoded ,RGB YBCR selection */
                hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
@@ -722,18 +706,20 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
                hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
 
                chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
-                                       infoframe->len, hdr_sum);
+                                       infoframe->any.length, hdr_sum);
                DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
                hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
                break;
-       case HDMI_PACKET_TYPE_AUI:
+       case HDMI_INFOFRAME_TYPE_AUDIO:
                hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
-               hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type);
-               hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver);
-               hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len);
-               hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
+               hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
+               hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
+                               infoframe->any.version);
+               hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
+               hdr_sum = infoframe->any.type + infoframe->any.version +
+                         infoframe->any.length;
                chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
-                                       infoframe->len, hdr_sum);
+                                       infoframe->any.length, hdr_sum);
                DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
                hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
                break;
@@ -985,7 +971,7 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
 
 static void hdmi_conf_init(struct hdmi_context *hdata)
 {
-       struct hdmi_infoframe infoframe;
+       union hdmi_infoframe infoframe;
 
        /* disable HPD interrupts from HDMI IP block, use GPIO instead */
        hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
@@ -1021,14 +1007,14 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
                hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
                hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
        } else {
-               infoframe.type = HDMI_PACKET_TYPE_AVI;
-               infoframe.ver = HDMI_AVI_VERSION;
-               infoframe.len = HDMI_AVI_LENGTH;
+               infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
+               infoframe.any.version = HDMI_AVI_VERSION;
+               infoframe.any.length = HDMI_AVI_LENGTH;
                hdmi_reg_infoframe(hdata, &infoframe);
 
-               infoframe.type = HDMI_PACKET_TYPE_AUI;
-               infoframe.ver = HDMI_AUI_VERSION;
-               infoframe.len = HDMI_AUI_LENGTH;
+               infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
+               infoframe.any.version = HDMI_AUI_VERSION;
+               infoframe.any.length = HDMI_AUI_LENGTH;
                hdmi_reg_infoframe(hdata, &infoframe);
 
                /* enable AVI packet every vsync, fixes purple line problem */
index 49bac41beefb3251ecc6a63f04e86d0d36de9974..c3e67ba94446d34a24b420c72804e029384948d7 100644 (file)
@@ -520,7 +520,7 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
 
        driver->has_clflush = 0;
 
-       if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+       if (boot_cpu_has(X86_FEATURE_CLFLUSH)) {
                uint32_t tfms, misc, cap0, cap4, clflush_size;
 
                /*
index 400b0c4a10fba3138bbb2fc4cc260058be62cffc..faa77f543a077da2c624e47638693b6566b146ff 100644 (file)
@@ -208,7 +208,7 @@ struct tda998x_priv {
 # define PLL_SERIAL_1_SRL_IZ(x)   (((x) & 3) << 1)
 # define PLL_SERIAL_1_SRL_MAN_IZ  (1 << 6)
 #define REG_PLL_SERIAL_2          REG(0x02, 0x01)     /* read/write */
-# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0)
+# define PLL_SERIAL_2_SRL_NOSC(x) ((x) << 0)
 # define PLL_SERIAL_2_SRL_PR(x)   (((x) & 0xf) << 4)
 #define REG_PLL_SERIAL_3          REG(0x02, 0x02)     /* read/write */
 # define PLL_SERIAL_3_SRL_CCIR    (1 << 0)
@@ -528,10 +528,10 @@ tda998x_write_aif(struct drm_encoder *encoder, struct tda998x_encoder_params *p)
 {
        uint8_t buf[PB(5) + 1];
 
+       memset(buf, 0, sizeof(buf));
        buf[HB(0)] = 0x84;
        buf[HB(1)] = 0x01;
        buf[HB(2)] = 10;
-       buf[PB(0)] = 0;
        buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */
        buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */
        buf[PB(4)] = p->audio_frame[4];
@@ -824,6 +824,11 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
        }
 
        div = 148500 / mode->clock;
+       if (div != 0) {
+               div--;
+               if (div > 3)
+                       div = 3;
+       }
 
        /* mute the audio FIFO: */
        reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
@@ -913,7 +918,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
 
        if (priv->rev == TDA19988) {
                /* let incoming pixels fill the active space (if any) */
-               reg_write(encoder, REG_ENABLE_SPACE, 0x01);
+               reg_write(encoder, REG_ENABLE_SPACE, 0x00);
        }
 
        /* must be last register set: */
@@ -1094,6 +1099,8 @@ tda998x_encoder_destroy(struct drm_encoder *encoder)
 {
        struct tda998x_priv *priv = to_tda998x_priv(encoder);
        drm_i2c_encoder_destroy(encoder);
+       if (priv->cec)
+               i2c_unregister_device(priv->cec);
        kfree(priv);
 }
 
@@ -1142,8 +1149,12 @@ tda998x_encoder_init(struct i2c_client *client,
        priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
        priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
 
-       priv->current_page = 0;
+       priv->current_page = 0xff;
        priv->cec = i2c_new_dummy(client->adapter, 0x34);
+       if (!priv->cec) {
+               kfree(priv);
+               return -ENODEV;
+       }
        priv->dpms = DRM_MODE_DPMS_OFF;
 
        encoder_slave->slave_priv = priv;
index 04f1f02c4019f57873caeb0c70fea14e0816ddeb..ec7bb0fc71bcfc8c19c2231c9bb0e3165f89e047 100644 (file)
@@ -403,7 +403,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 void intel_detect_pch(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct pci_dev *pch;
+       struct pci_dev *pch = NULL;
 
        /* In all current cases, num_pipes is equivalent to the PCH_NOP setting
         * (which really amounts to a PCH but no South Display).
@@ -424,12 +424,9 @@ void intel_detect_pch(struct drm_device *dev)
         * all the ISA bridge devices and check for the first match, instead
         * of only checking the first one.
         */
-       pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-       while (pch) {
-               struct pci_dev *curr = pch;
+       while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
                if (pch->vendor == PCI_VENDOR_ID_INTEL) {
-                       unsigned short id;
-                       id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
+                       unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
                        dev_priv->pch_id = id;
 
                        if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
@@ -461,18 +458,16 @@ void intel_detect_pch(struct drm_device *dev)
                                DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
                                WARN_ON(!IS_HASWELL(dev));
                                WARN_ON(!IS_ULT(dev));
-                       } else {
-                               goto check_next;
-                       }
-                       pci_dev_put(pch);
+                       } else
+                               continue;
+
                        break;
                }
-check_next:
-               pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr);
-               pci_dev_put(curr);
        }
        if (!pch)
-               DRM_DEBUG_KMS("No PCH found?\n");
+               DRM_DEBUG_KMS("No PCH found.\n");
+
+       pci_dev_put(pch);
 }
 
 bool i915_semaphore_is_enabled(struct drm_device *dev)
index 4a2bf8e3f739bff7b2b9f6e018100ec98e8b9c0e..df77e20e3c3d00ee9173d4c160274f0e837c26de 100644 (file)
@@ -1831,6 +1831,14 @@ struct drm_i915_file_private {
 
 /* Early gen2 have a totally busted CS tlb and require pinned batches. */
 #define HAS_BROKEN_CS_TLB(dev)         (IS_I830(dev) || IS_845G(dev))
+/*
+ * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
+ * even when in MSI mode. This results in spurious interrupt warnings if the
+ * legacy irq no. is shared with another device. The kernel then disables that
+ * interrupt source and so prevents the other device from working properly.
+ */
+#define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
+#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
 
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
index 40a2b36b276baa774028b56ae60b6ae6c59e919d..d278be110805ba50965f1e071213720434cb9e78 100644 (file)
@@ -842,7 +842,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
        dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
                                       dev_priv->gtt.base.start / PAGE_SIZE,
                                       dev_priv->gtt.base.total / PAGE_SIZE,
-                                      false);
+                                      true);
 }
 
 void i915_gem_restore_gtt_mappings(struct drm_device *dev)
index 1a24e84f231578ae772d40ad75adda4c356b8d68..28d24caa49f3f7720c63e208c4831c79f5433d8d 100644 (file)
@@ -82,9 +82,22 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
        r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size,
                                    "Graphics Stolen Memory");
        if (r == NULL) {
-               DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
-                         base, base + (uint32_t)dev_priv->gtt.stolen_size);
-               base = 0;
+               /*
+                * One more attempt but this time requesting region from
+                * base + 1, as we have seen that this resolves the region
+                * conflict with the PCI Bus.
+                * This is a BIOS w/a: Some BIOS wrap stolen in the root
+                * PCI bus, but have an off-by-one error. Hence retry the
+                * reservation starting from 1 instead of 0.
+                */
+               r = devm_request_mem_region(dev->dev, base + 1,
+                                           dev_priv->gtt.stolen_size - 1,
+                                           "Graphics Stolen Memory");
+               if (r == NULL) {
+                       DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
+                                 base, base + (uint32_t)dev_priv->gtt.stolen_size);
+                       base = 0;
+               }
        }
 
        return base;
@@ -201,6 +214,13 @@ int i915_gem_init_stolen(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int bios_reserved = 0;
 
+#ifdef CONFIG_INTEL_IOMMU
+       if (intel_iommu_gfx_mapped) {
+               DRM_INFO("DMAR active, disabling use of stolen memory\n");
+               return 0;
+       }
+#endif
+
        if (dev_priv->gtt.stolen_size == 0)
                return 0;
 
index d7fd2fd2f0a5e1ba6ed25f9a4dce0c20dc03b9e3..990cf8f43efda908ecb1565cb5e8a786efe68306 100644 (file)
@@ -146,7 +146,10 @@ static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
                va_list tmp;
 
                va_copy(tmp, args);
-               if (!__i915_error_seek(e, vsnprintf(NULL, 0, f, tmp)))
+               len = vsnprintf(NULL, 0, f, tmp);
+               va_end(tmp);
+
+               if (!__i915_error_seek(e, len))
                        return;
        }
 
index 17d8fcb1b6f7ac113b4c0c035088979b1c8083b4..d554169ac59274fbcaeaa2978078d0c71b822a33 100644 (file)
@@ -567,8 +567,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
 
                vbl_start = mode->crtc_vblank_start * mode->crtc_htotal;
        } else {
-               enum transcoder cpu_transcoder =
-                       intel_pipe_to_cpu_transcoder(dev_priv, pipe);
+               enum transcoder cpu_transcoder = (enum transcoder) pipe;
                u32 htotal;
 
                htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1;
@@ -619,33 +618,25 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
 
 /* raw reads, only for fast reads of display block, no need for forcewake etc. */
 #define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
-#define __raw_i915_read16(dev_priv__, reg__) readw((dev_priv__)->regs + (reg__))
 
 static bool ilk_pipe_in_vblank_locked(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t status;
-
-       if (INTEL_INFO(dev)->gen < 7) {
-               status = pipe == PIPE_A ?
-                       DE_PIPEA_VBLANK :
-                       DE_PIPEB_VBLANK;
+       int reg;
+
+       if (INTEL_INFO(dev)->gen >= 8) {
+               status = GEN8_PIPE_VBLANK;
+               reg = GEN8_DE_PIPE_ISR(pipe);
+       } else if (INTEL_INFO(dev)->gen >= 7) {
+               status = DE_PIPE_VBLANK_IVB(pipe);
+               reg = DEISR;
        } else {
-               switch (pipe) {
-               default:
-               case PIPE_A:
-                       status = DE_PIPEA_VBLANK_IVB;
-                       break;
-               case PIPE_B:
-                       status = DE_PIPEB_VBLANK_IVB;
-                       break;
-               case PIPE_C:
-                       status = DE_PIPEC_VBLANK_IVB;
-                       break;
-               }
+               status = DE_PIPE_VBLANK(pipe);
+               reg = DEISR;
        }
 
-       return __raw_i915_read32(dev_priv, DEISR) & status;
+       return __raw_i915_read32(dev_priv, reg) & status;
 }
 
 static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
@@ -703,7 +694,28 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
                else
                        position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
 
-               if (HAS_PCH_SPLIT(dev)) {
+               if (HAS_DDI(dev)) {
+                       /*
+                        * On HSW HDMI outputs there seems to be a 2 line
+                        * difference, whereas eDP has the normal 1 line
+                        * difference that earlier platforms have. External
+                        * DP is unknown. For now just check for the 2 line
+                        * difference case on all output types on HSW+.
+                        *
+                        * This might misinterpret the scanline counter being
+                        * one line too far along on eDP, but that's less
+                        * dangerous than the alternative since that would lead
+                        * the vblank timestamp code astray when it sees a
+                        * scanline count before vblank_start during a vblank
+                        * interrupt.
+                        */
+                       in_vbl = ilk_pipe_in_vblank_locked(dev, pipe);
+                       if ((in_vbl && (position == vbl_start - 2 ||
+                                       position == vbl_start - 1)) ||
+                           (!in_vbl && (position == vbl_end - 2 ||
+                                        position == vbl_end - 1)))
+                               position = (position + 2) % vtotal;
+               } else if (HAS_PCH_SPLIT(dev)) {
                        /*
                         * The scanline counter increments at the leading edge
                         * of hsync, ie. it completely misses the active portion
@@ -2770,10 +2782,9 @@ static void ibx_irq_postinstall(struct drm_device *dev)
                return;
 
        if (HAS_PCH_IBX(dev)) {
-               mask = SDE_GMBUS | SDE_AUX_MASK | SDE_TRANSB_FIFO_UNDER |
-                      SDE_TRANSA_FIFO_UNDER | SDE_POISON;
+               mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
        } else {
-               mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT | SDE_ERROR_CPT;
+               mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
 
                I915_WRITE(SERR_INT, I915_READ(SERR_INT));
        }
@@ -2833,20 +2844,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
                display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
                                DE_PCH_EVENT_IVB | DE_PLANEC_FLIP_DONE_IVB |
                                DE_PLANEB_FLIP_DONE_IVB |
-                               DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB |
-                               DE_ERR_INT_IVB);
+                               DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB);
                extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
-                             DE_PIPEA_VBLANK_IVB);
+                             DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB);
 
                I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
        } else {
                display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
                                DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
                                DE_AUX_CHANNEL_A |
-                               DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN |
                                DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE |
                                DE_POISON);
-               extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT;
+               extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT |
+                               DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN;
        }
 
        dev_priv->irq_mask = ~display_mask;
@@ -2962,9 +2972,9 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
        struct drm_device *dev = dev_priv->dev;
        uint32_t de_pipe_masked = GEN8_PIPE_FLIP_DONE |
                GEN8_PIPE_CDCLK_CRC_DONE |
-               GEN8_PIPE_FIFO_UNDERRUN |
                GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
-       uint32_t de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK;
+       uint32_t de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
+               GEN8_PIPE_FIFO_UNDERRUN;
        int pipe;
        dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked;
        dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
index e06b9e017d6ba918b87557de301df47076852434..234ac5f7bc5aba1013f2ad62650baa05c1d1559a 100644 (file)
@@ -1244,6 +1244,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
+               ironlake_edp_panel_vdd_on(intel_dp);
                ironlake_edp_panel_off(intel_dp);
        }
 
index 9fa24347963a38d360e365cfa20bf7cefed8beaa..9b8a7c7ea7fc1925610b4dcb11ca9f768057fd41 100644 (file)
@@ -1092,12 +1092,12 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
        struct drm_device *dev = dev_priv->dev;
        bool cur_state;
 
-       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-               cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE;
-       else if (IS_845G(dev) || IS_I865G(dev))
+       if (IS_845G(dev) || IS_I865G(dev))
                cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE;
-       else
+       else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev))
                cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
+       else
+               cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE;
 
        WARN(cur_state != state,
             "cursor on pipe %c assertion failure (expected %s, current %s)\n",
@@ -8586,6 +8586,20 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
        if (ring->id == RCS)
                len += 6;
 
+       /*
+        * BSpec MI_DISPLAY_FLIP for IVB:
+        * "The full packet must be contained within the same cache line."
+        *
+        * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
+        * cacheline, if we ever start emitting more commands before
+        * the MI_DISPLAY_FLIP we may need to first emit everything else,
+        * then do the cacheline alignment, and finally emit the
+        * MI_DISPLAY_FLIP.
+        */
+       ret = intel_ring_cacheline_align(ring);
+       if (ret)
+               goto err_unpin;
+
        ret = intel_ring_begin(ring, len);
        if (ret)
                goto err_unpin;
index 5ede4e8e290df5cc2f3e1b7046ec409b9f50d538..2688f6d64bb9f3e6883e5a8a9216a38fd794d880 100644 (file)
@@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        int i, ret, recv_bytes;
        uint32_t status;
        int try, precharge, clock = 0;
-       bool has_aux_irq = true;
+       bool has_aux_irq = HAS_AUX_IRQ(dev);
        uint32_t timeout;
 
        /* dp aux is extremely sensitive to irq latency, hence request the
@@ -537,6 +537,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
        uint8_t msg[20];
        int msg_bytes;
        uint8_t ack;
+       int retry;
 
        if (WARN_ON(send_bytes > 16))
                return -E2BIG;
@@ -548,19 +549,21 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
        msg[3] = send_bytes - 1;
        memcpy(&msg[4], send, send_bytes);
        msg_bytes = send_bytes + 4;
-       for (;;) {
+       for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
                if (ret < 0)
                        return ret;
                ack >>= 4;
                if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
-                       break;
+                       return send_bytes;
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(100);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
-       return send_bytes;
+
+       DRM_ERROR("too many retries, giving up\n");
+       return -EIO;
 }
 
 /* Write a single byte to the aux channel in native mode */
@@ -582,6 +585,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
        int reply_bytes;
        uint8_t ack;
        int ret;
+       int retry;
 
        if (WARN_ON(recv_bytes > 19))
                return -E2BIG;
@@ -595,7 +599,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
        msg_bytes = 4;
        reply_bytes = recv_bytes + 1;
 
-       for (;;) {
+       for (retry = 0; retry < 7; retry++) {
                ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
                                      reply, reply_bytes);
                if (ret == 0)
@@ -608,10 +612,13 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
                        return ret - 1;
                }
                else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
-                       udelay(100);
+                       usleep_range(400, 500);
                else
                        return -EIO;
        }
+
+       DRM_ERROR("too many retries, giving up\n");
+       return -EIO;
 }
 
 static int
@@ -1242,17 +1249,24 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
        DRM_DEBUG_KMS("Turn eDP power off\n");
 
+       WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
+
        pp = ironlake_get_pp_control(intel_dp);
        /* We need to switch off panel power _and_ force vdd, for otherwise some
         * panels get very unhappy and cease to work. */
-       pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
        I915_WRITE(pp_ctrl_reg, pp);
        POSTING_READ(pp_ctrl_reg);
 
+       intel_dp->want_panel_vdd = false;
+
        ironlake_wait_panel_off(intel_dp);
+
+       /* We got a reference when we enabled the VDD. */
+       intel_runtime_pm_put(dev_priv);
 }
 
 void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1632,7 +1646,7 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
                val |= EDP_PSR_LINK_DISABLE;
 
        I915_WRITE(EDP_PSR_CTL(dev), val |
-                  IS_BROADWELL(dev) ? 0 : link_entry_time |
+                  (IS_BROADWELL(dev) ? 0 : link_entry_time) |
                   max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
                   idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
                   EDP_PSR_ENABLE);
@@ -1777,6 +1791,7 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
+       ironlake_edp_panel_vdd_on(intel_dp);
        ironlake_edp_backlight_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
        ironlake_edp_panel_off(intel_dp);
@@ -1869,10 +1884,12 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
        mutex_unlock(&dev_priv->dpio_lock);
 
-       /* init power sequencer on this pipe and port */
-       intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-                                                     &power_seq);
+       if (is_edp(intel_dp)) {
+               /* init power sequencer on this pipe and port */
+               intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+                                                             &power_seq);
+       }
 
        intel_enable_dp(encoder);
 
index 6db0d9d17f47e7b5ce5c43a7aa7795de71ea6346..ee3181ebcc9236078835ee18a48fe86c97525ff9 100644 (file)
@@ -845,7 +845,7 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
 {
        struct drm_device *dev = intel_hdmi_to_dev(hdmi);
 
-       if (IS_G4X(dev))
+       if (!hdmi->has_hdmi_sink || IS_G4X(dev))
                return 165000;
        else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
                return 300000;
@@ -899,8 +899,8 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
         * outputs. We also need to check that the higher clock still fits
         * within limits.
         */
-       if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit
-           && HAS_PCH_SPLIT(dev)) {
+       if (pipe_config->pipe_bpp > 8*3 && intel_hdmi->has_hdmi_sink &&
+           clock_12bpc <= portclock_limit && HAS_PCH_SPLIT(dev)) {
                DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
                desired_bpp = 12*3;
 
index b1dc33f478991755ec114fe66fbad7bc40fec4c0..d33b61d0dd3331b6bd073806d0482b19aeb0eb08 100644 (file)
@@ -258,13 +258,6 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
        algo->data = bus;
 }
 
-/*
- * gmbus on gen4 seems to be able to generate legacy interrupts even when in MSI
- * mode. This results in spurious interrupt warnings if the legacy irq no. is
- * shared with another device. The kernel then disables that interrupt source
- * and so prevents the other device from working properly.
- */
-#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
 static int
 gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
                     u32 gmbus2_status,
index 4e960ec7419fb6802398b9b118b3b3a513199350..acde2945eb8a73e075c2fa60493f4b22e89bb666 100644 (file)
@@ -226,6 +226,8 @@ struct opregion_asle {
 #define ACPI_DIGITAL_OUTPUT (3<<8)
 #define ACPI_LVDS_OUTPUT (4<<8)
 
+#define MAX_DSLP       1500
+
 #ifdef CONFIG_ACPI
 static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
 {
@@ -260,10 +262,11 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
                /* The spec says 2ms should be the default, but it's too small
                 * for some machines. */
                dslp = 50;
-       } else if (dslp > 500) {
+       } else if (dslp > MAX_DSLP) {
                /* Hey bios, trust must be earned. */
-               WARN_ONCE(1, "excessive driver sleep timeout (DSPL) %u\n", dslp);
-               dslp = 500;
+               DRM_INFO_ONCE("ACPI BIOS requests an excessive sleep of %u ms, "
+                             "using %u ms instead\n", dslp, MAX_DSLP);
+               dslp = MAX_DSLP;
        }
 
        /* The spec tells us to do this, but we are the only user... */
index 350de359123af9cbd42354c182424f356281aa16..079ea38f14d9b4b54092a1ebeca4cd77dac27cec 100644 (file)
@@ -698,7 +698,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector)
                freq /= 0xff;
 
        ctl = freq << 17;
-       if (IS_GEN2(dev) && panel->backlight.combination_mode)
+       if (panel->backlight.combination_mode)
                ctl |= BLM_LEGACY_MODE;
        if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
                ctl |= BLM_POLARITY_PNV;
@@ -979,7 +979,7 @@ static int i9xx_setup_backlight(struct intel_connector *connector)
 
        ctl = I915_READ(BLC_PWM_CTL);
 
-       if (IS_GEN2(dev))
+       if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
                panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
 
        if (IS_PINEVIEW(dev))
index d77cc81900f92100ba2f61d7130bc9b0b60454b5..e1fc35a726564cc9f3526231780672d09d151838 100644 (file)
@@ -3493,6 +3493,8 @@ static void valleyview_setup_pctx(struct drm_device *dev)
        u32 pcbr;
        int pctx_size = 24*1024;
 
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
        pcbr = I915_READ(VLV_PCBR);
        if (pcbr) {
                /* BIOS set it up already, grab the pre-alloc'd space */
@@ -3542,8 +3544,6 @@ static void valleyview_enable_rps(struct drm_device *dev)
                I915_WRITE(GTFIFODBG, gtfifodbg);
        }
 
-       valleyview_setup_pctx(dev);
-
        /* If VLV, Forcewake all wells, else re-direct to regular path */
        gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
@@ -4395,6 +4395,8 @@ void intel_enable_gt_powersave(struct drm_device *dev)
                ironlake_enable_rc6(dev);
                intel_init_emon(dev);
        } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
+               if (IS_VALLEYVIEW(dev))
+                       valleyview_setup_pctx(dev);
                /*
                 * PCU communication is slow and this doesn't need to be
                 * done at any specific time, so do this out of our fast path
index b7f1742caf878250c3fb6dc98b5bdbe63ae4a601..31b36c5ac8941e844cd9f995b0c4e575219fc8ea 100644 (file)
@@ -1653,6 +1653,27 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
        return 0;
 }
 
+/* Align the ring tail to a cacheline boundary */
+int intel_ring_cacheline_align(struct intel_ring_buffer *ring)
+{
+       int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t);
+       int ret;
+
+       if (num_dwords == 0)
+               return 0;
+
+       ret = intel_ring_begin(ring, num_dwords);
+       if (ret)
+               return ret;
+
+       while (num_dwords--)
+               intel_ring_emit(ring, MI_NOOP);
+
+       intel_ring_advance(ring);
+
+       return 0;
+}
+
 void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
 {
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
index 71a73f4fe252fdb90b4c24d8947e936b37ad0f5b..0b243ce337147d51f7e9cb4b09d774f4cc33e856 100644 (file)
@@ -233,6 +233,7 @@ intel_write_status_page(struct intel_ring_buffer *ring,
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 
 int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
+int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring);
 static inline void intel_ring_emit(struct intel_ring_buffer *ring,
                                   u32 data)
 {
index f9adc27ef32a05fdee5b66a23e35b7e6df21fd3d..13b7dd83faa9ca7e6e05157d002be0199f3bd667 100644 (file)
@@ -41,7 +41,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,
         * then the BO is being moved and we should
         * store up the damage until later.
         */
-       if (!drm_can_sleep())
+       if (drm_can_sleep())
                ret = mgag200_bo_reserve(bo, true);
        if (ret) {
                if (ret != -EBUSY)
index b8583f275e80519dd46d922d1f5c1a0ed9c8bcbf..968374776db9c32e2545b2409acc88322fe3f3f9 100644 (file)
@@ -1519,11 +1519,11 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
                (mga_vga_calculate_mode_bandwidth(mode, bpp)
                        > (32700 * 1024))) {
                return MODE_BANDWIDTH;
-       } else if (mode->type == G200_EH &&
+       } else if (mdev->type == G200_EH &&
                (mga_vga_calculate_mode_bandwidth(mode, bpp)
                        > (37500 * 1024))) {
                return MODE_BANDWIDTH;
-       } else if (mode->type == G200_ER &&
+       } else if (mdev->type == G200_ER &&
                (mga_vga_calculate_mode_bandwidth(mode,
                        bpp) > (55000 * 1024))) {
                return MODE_BANDWIDTH;
index 1964f4f0d452377c87d2e2db4bd218a1f0451ff5..84c5b13b33c9ed2649a58d2a9d499d6d22ba0a21 100644 (file)
@@ -39,6 +39,7 @@ struct mdp4_crtc {
                spinlock_t lock;
                bool stale;
                uint32_t width, height;
+               uint32_t x, y;
 
                /* next cursor to scan-out: */
                uint32_t next_iova;
@@ -57,9 +58,16 @@ struct mdp4_crtc {
 #define PENDING_FLIP   0x2
        atomic_t pending;
 
-       /* the fb that we currently hold a scanout ref to: */
+       /* the fb that we logically (from PoV of KMS API) hold a ref
+        * to.  Which we may not yet be scanning out (we may still
+        * be scanning out previous in case of page_flip while waiting
+        * for gpu rendering to complete:
+        */
        struct drm_framebuffer *fb;
 
+       /* the fb that we currently hold a scanout ref to: */
+       struct drm_framebuffer *scanout_fb;
+
        /* for unref'ing framebuffers after scanout completes: */
        struct drm_flip_work unref_fb_work;
 
@@ -77,24 +85,73 @@ static struct mdp4_kms *get_kms(struct drm_crtc *crtc)
        return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-static void update_fb(struct drm_crtc *crtc, bool async,
-               struct drm_framebuffer *new_fb)
+static void request_pending(struct drm_crtc *crtc, uint32_t pending)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct drm_framebuffer *old_fb = mdp4_crtc->fb;
 
-       if (old_fb)
-               drm_flip_work_queue(&mdp4_crtc->unref_fb_work, old_fb);
+       atomic_or(pending, &mdp4_crtc->pending);
+       mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
+}
+
+static void crtc_flush(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       uint32_t i, flush = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
+               struct drm_plane *plane = mdp4_crtc->planes[i];
+               if (plane) {
+                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
+                       flush |= pipe2flush(pipe_id);
+               }
+       }
+       flush |= ovlp2flush(mdp4_crtc->ovlp);
+
+       DBG("%s: flush=%08x", mdp4_crtc->name, flush);
+
+       mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
+}
+
+static void update_fb(struct drm_crtc *crtc, struct drm_framebuffer *new_fb)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct drm_framebuffer *old_fb = mdp4_crtc->fb;
 
        /* grab reference to incoming scanout fb: */
        drm_framebuffer_reference(new_fb);
        mdp4_crtc->base.fb = new_fb;
        mdp4_crtc->fb = new_fb;
 
-       if (!async) {
-               /* enable vblank to pick up the old_fb */
-               mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
-       }
+       if (old_fb)
+               drm_flip_work_queue(&mdp4_crtc->unref_fb_work, old_fb);
+}
+
+/* unlike update_fb(), take a ref to the new scanout fb *before* updating
+ * plane, then call this.  Needed to ensure we don't unref the buffer that
+ * is actually still being scanned out.
+ *
+ * Note that this whole thing goes away with atomic.. since we can defer
+ * calling into driver until rendering is done.
+ */
+static void update_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+
+       /* flush updates, to make sure hw is updated to new scanout fb,
+        * so that we can safely queue unref to current fb (ie. next
+        * vblank we know hw is done w/ previous scanout_fb).
+        */
+       crtc_flush(crtc);
+
+       if (mdp4_crtc->scanout_fb)
+               drm_flip_work_queue(&mdp4_crtc->unref_fb_work,
+                               mdp4_crtc->scanout_fb);
+
+       mdp4_crtc->scanout_fb = fb;
+
+       /* enable vblank to complete flip: */
+       request_pending(crtc, PENDING_FLIP);
 }
 
 /* if file!=NULL, this is preclose potential cancel-flip path */
@@ -120,34 +177,6 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void crtc_flush(struct drm_crtc *crtc)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       uint32_t i, flush = 0;
-
-       for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
-               struct drm_plane *plane = mdp4_crtc->planes[i];
-               if (plane) {
-                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
-                       flush |= pipe2flush(pipe_id);
-               }
-       }
-       flush |= ovlp2flush(mdp4_crtc->ovlp);
-
-       DBG("%s: flush=%08x", mdp4_crtc->name, flush);
-
-       mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
-}
-
-static void request_pending(struct drm_crtc *crtc, uint32_t pending)
-{
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-
-       atomic_or(pending, &mdp4_crtc->pending);
-       mdp_irq_register(&get_kms(crtc)->base, &mdp4_crtc->vblank);
-}
-
 static void pageflip_cb(struct msm_fence_cb *cb)
 {
        struct mdp4_crtc *mdp4_crtc =
@@ -158,11 +187,9 @@ static void pageflip_cb(struct msm_fence_cb *cb)
        if (!fb)
                return;
 
+       drm_framebuffer_reference(fb);
        mdp4_plane_set_scanout(mdp4_crtc->plane, fb);
-       crtc_flush(crtc);
-
-       /* enable vblank to complete flip: */
-       request_pending(crtc, PENDING_FLIP);
+       update_scanout(crtc, fb);
 }
 
 static void unref_fb_worker(struct drm_flip_work *work, void *val)
@@ -320,6 +347,20 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
                        mode->vsync_end, mode->vtotal,
                        mode->type, mode->flags);
 
+       /* grab extra ref for update_scanout() */
+       drm_framebuffer_reference(crtc->fb);
+
+       ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
+                       0, 0, mode->hdisplay, mode->vdisplay,
+                       x << 16, y << 16,
+                       mode->hdisplay << 16, mode->vdisplay << 16);
+       if (ret) {
+               drm_framebuffer_unreference(crtc->fb);
+               dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
+                               mdp4_crtc->name, ret);
+               return ret;
+       }
+
        mdp4_write(mdp4_kms, REG_MDP4_DMA_SRC_SIZE(dma),
                        MDP4_DMA_SRC_SIZE_WIDTH(mode->hdisplay) |
                        MDP4_DMA_SRC_SIZE_HEIGHT(mode->vdisplay));
@@ -341,24 +382,15 @@ static int mdp4_crtc_mode_set(struct drm_crtc *crtc,
 
        mdp4_write(mdp4_kms, REG_MDP4_OVLP_CFG(ovlp), 1);
 
-       update_fb(crtc, false, crtc->fb);
-
-       ret = mdp4_plane_mode_set(mdp4_crtc->plane, crtc, crtc->fb,
-                       0, 0, mode->hdisplay, mode->vdisplay,
-                       x << 16, y << 16,
-                       mode->hdisplay << 16, mode->vdisplay << 16);
-       if (ret) {
-               dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
-                               mdp4_crtc->name, ret);
-               return ret;
-       }
-
        if (dma == DMA_E) {
                mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(0), 0x00ff0000);
                mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(1), 0x00ff0000);
                mdp4_write(mdp4_kms, REG_MDP4_DMA_E_QUANT(2), 0x00ff0000);
        }
 
+       update_fb(crtc, crtc->fb);
+       update_scanout(crtc, crtc->fb);
+
        return 0;
 }
 
@@ -385,13 +417,24 @@ static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
        struct drm_plane *plane = mdp4_crtc->plane;
        struct drm_display_mode *mode = &crtc->mode;
+       int ret;
 
-       update_fb(crtc, false, crtc->fb);
+       /* grab extra ref for update_scanout() */
+       drm_framebuffer_reference(crtc->fb);
 
-       return mdp4_plane_mode_set(plane, crtc, crtc->fb,
+       ret = mdp4_plane_mode_set(plane, crtc, crtc->fb,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
+       if (ret) {
+               drm_framebuffer_unreference(crtc->fb);
+               return ret;
+       }
+
+       update_fb(crtc, crtc->fb);
+       update_scanout(crtc, crtc->fb);
+
+       return 0;
 }
 
 static void mdp4_crtc_load_lut(struct drm_crtc *crtc)
@@ -419,7 +462,7 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc,
        mdp4_crtc->event = event;
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       update_fb(crtc, true, new_fb);
+       update_fb(crtc, new_fb);
 
        return msm_gem_queue_inactive_cb(obj, &mdp4_crtc->pageflip_cb);
 }
@@ -442,12 +485,12 @@ static int mdp4_crtc_set_property(struct drm_crtc *crtc,
 static void update_cursor(struct drm_crtc *crtc)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
        enum mdp4_dma dma = mdp4_crtc->dma;
        unsigned long flags;
 
        spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags);
        if (mdp4_crtc->cursor.stale) {
-               struct mdp4_kms *mdp4_kms = get_kms(crtc);
                struct drm_gem_object *next_bo = mdp4_crtc->cursor.next_bo;
                struct drm_gem_object *prev_bo = mdp4_crtc->cursor.scanout_bo;
                uint32_t iova = mdp4_crtc->cursor.next_iova;
@@ -479,6 +522,11 @@ static void update_cursor(struct drm_crtc *crtc)
                mdp4_crtc->cursor.scanout_bo = next_bo;
                mdp4_crtc->cursor.stale = false;
        }
+
+       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_POS(dma),
+                       MDP4_DMA_CURSOR_POS_X(mdp4_crtc->cursor.x) |
+                       MDP4_DMA_CURSOR_POS_Y(mdp4_crtc->cursor.y));
+
        spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags);
 }
 
@@ -530,6 +578,7 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
                drm_gem_object_unreference_unlocked(old_bo);
        }
 
+       crtc_flush(crtc);
        request_pending(crtc, PENDING_CURSOR);
 
        return 0;
@@ -542,12 +591,15 @@ fail:
 static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 {
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       enum mdp4_dma dma = mdp4_crtc->dma;
+       unsigned long flags;
 
-       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_POS(dma),
-                       MDP4_DMA_CURSOR_POS_X(x) |
-                       MDP4_DMA_CURSOR_POS_Y(y));
+       spin_lock_irqsave(&mdp4_crtc->cursor.lock, flags);
+       mdp4_crtc->cursor.x = x;
+       mdp4_crtc->cursor.y = y;
+       spin_unlock_irqrestore(&mdp4_crtc->cursor.lock, flags);
+
+       crtc_flush(crtc);
+       request_pending(crtc, PENDING_CURSOR);
 
        return 0;
 }
@@ -713,6 +765,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
        crtc = &mdp4_crtc->base;
 
        mdp4_crtc->plane = plane;
+       mdp4_crtc->id = id;
 
        mdp4_crtc->ovlp = ovlp_id;
        mdp4_crtc->dma = dma_id;
index 2406027200ec597e5d6a10674e82db82f122adff..1e893dd13859817ae33e199b99f0810c59c49732 100644 (file)
@@ -170,8 +170,8 @@ int mdp4_plane_mode_set(struct drm_plane *plane,
                        MDP4_PIPE_DST_SIZE_HEIGHT(crtc_h));
 
        mdp4_write(mdp4_kms, REG_MDP4_PIPE_DST_XY(pipe),
-                       MDP4_PIPE_SRC_XY_X(crtc_x) |
-                       MDP4_PIPE_SRC_XY_Y(crtc_y));
+                       MDP4_PIPE_DST_XY_X(crtc_x) |
+                       MDP4_PIPE_DST_XY_Y(crtc_y));
 
        mdp4_plane_set_scanout(plane, fb);
 
index 71a3b2345eb38909d53c5a57e2370fcdcbd5e0c7..f2794021f086f53fc509dea1f3136cf4facfe27d 100644 (file)
@@ -296,6 +296,7 @@ static int mdp5_crtc_mode_set(struct drm_crtc *crtc,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
        if (ret) {
+               drm_framebuffer_unreference(crtc->fb);
                dev_err(crtc->dev->dev, "%s: failed to set mode on plane: %d\n",
                                mdp5_crtc->name, ret);
                return ret;
@@ -343,11 +344,15 @@ static int mdp5_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                        0, 0, mode->hdisplay, mode->vdisplay,
                        x << 16, y << 16,
                        mode->hdisplay << 16, mode->vdisplay << 16);
+       if (ret) {
+               drm_framebuffer_unreference(crtc->fb);
+               return ret;
+       }
 
        update_fb(crtc, crtc->fb);
        update_scanout(crtc, crtc->fb);
 
-       return ret;
+       return 0;
 }
 
 static void mdp5_crtc_load_lut(struct drm_crtc *crtc)
index d8d60c969ac7858bce0e6114f092a5f1aad450aa..3da8264d3039017bd358ccaca48197356f932f68 100644 (file)
@@ -644,7 +644,7 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,
 
 fail:
        if (obj)
-               drm_gem_object_unreference_unlocked(obj);
+               drm_gem_object_unreference(obj);
 
        return ERR_PTR(ret);
 }
index 5281d4bc37f750e2162e4bd1f17859e4921c45cc..5423e914e491691a7a4d511a9ec2ae84caef8414 100644 (file)
@@ -163,7 +163,7 @@ retry:
 
 
                /* if locking succeeded, pin bo: */
-               ret = msm_gem_get_iova(&msm_obj->base,
+               ret = msm_gem_get_iova_locked(&msm_obj->base,
                                submit->gpu->id, &iova);
 
                /* this would break the logic in the fail path.. there is no
@@ -247,7 +247,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
        /* For now, just map the entire thing.  Eventually we probably
         * to do it page-by-page, w/ kmap() if not vmap()d..
         */
-       ptr = msm_gem_vaddr(&obj->base);
+       ptr = msm_gem_vaddr_locked(&obj->base);
 
        if (IS_ERR(ptr)) {
                ret = PTR_ERR(ptr);
@@ -307,14 +307,12 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool fail)
 {
        unsigned i;
 
-       mutex_lock(&submit->dev->struct_mutex);
        for (i = 0; i < submit->nr_bos; i++) {
                struct msm_gem_object *msm_obj = submit->bos[i].obj;
                submit_unlock_unpin_bo(submit, i);
                list_del_init(&msm_obj->submit_entry);
                drm_gem_object_unreference(&msm_obj->base);
        }
-       mutex_unlock(&submit->dev->struct_mutex);
 
        ww_acquire_fini(&submit->ticket);
        kfree(submit);
@@ -342,6 +340,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        if (args->nr_cmds > MAX_CMDS)
                return -EINVAL;
 
+       mutex_lock(&dev->struct_mutex);
+
        submit = submit_create(dev, gpu, args->nr_bos);
        if (!submit) {
                ret = -ENOMEM;
@@ -410,5 +410,6 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 out:
        if (submit)
                submit_cleanup(submit, !!ret);
+       mutex_unlock(&dev->struct_mutex);
        return ret;
 }
index 4ebce8be489db6cdf51f6ba88fb8f7bfd1dbd5ce..0cfe3f426ee4f4523d9e34c85427cd7cd37649a1 100644 (file)
@@ -298,8 +298,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
        struct msm_drm_private *priv = dev->dev_private;
        int i, ret;
 
-       mutex_lock(&dev->struct_mutex);
-
        submit->fence = ++priv->next_fence;
 
        gpu->submitted_fence = submit->fence;
@@ -331,7 +329,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                        msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
        }
        hangcheck_timer_reset(gpu);
-       mutex_unlock(&dev->struct_mutex);
 
        return ret;
 }
index e88145ba1bf515429a3b85753bde5df7d28bde70..d310c195bdfed1d467abbd1f5933da703e207e13 100644 (file)
@@ -141,6 +141,7 @@ nouveau-y += core/subdev/mc/base.o
 nouveau-y += core/subdev/mc/nv04.o
 nouveau-y += core/subdev/mc/nv40.o
 nouveau-y += core/subdev/mc/nv44.o
+nouveau-y += core/subdev/mc/nv4c.o
 nouveau-y += core/subdev/mc/nv50.o
 nouveau-y += core/subdev/mc/nv94.o
 nouveau-y += core/subdev/mc/nv98.o
index 1b653dd74a7046ceaae41bca181f3097827dcccd..08b88591ed6036924c76d51efcf0d1d32c91210e 100644 (file)
@@ -311,7 +311,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -334,7 +334,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass;
@@ -357,7 +357,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -380,7 +380,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
@@ -403,7 +403,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass;
index 940eaa5d8b9a4bb0e3ea224cfe2ced8ec8585b44..9ad722e4e087007df76e77473c5a5f98ce24be74 100644 (file)
@@ -1142,7 +1142,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
        if (conf != ~0) {
                if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
                        u32 soff = (ffs(outp.or) - 1) * 0x08;
-                       u32 ctrl = nv_rd32(priv, 0x610798 + soff);
+                       u32 ctrl = nv_rd32(priv, 0x610794 + soff);
                        u32 datarate;
 
                        switch ((ctrl & 0x000f0000) >> 16) {
index 9a850fe19515fe2ddcd513c3497c7d87c86cba8a..54c1b5b471cdfa5682a83587a1d490455d6828c1 100644 (file)
@@ -112,7 +112,7 @@ nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)
 
        nv_wr32(priv, 0x002270, cur->addr >> 12);
        nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3));
-       if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000))
+       if (!nv_wait(priv, 0x002284 + (engine * 8), 0x00100000, 0x00000000))
                nv_error(priv, "runlist %d update timeout\n", engine);
        mutex_unlock(&nv_subdev(priv)->mutex);
 }
index 30ed19c52e05ca0cd6a1e759a8fc426f61f246a7..7a367c4029786f9d3b0941b62d697902b3681e93 100644 (file)
@@ -539,7 +539,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,
                                ustatus &= ~0x04030000;
                        }
                        if (ustatus && display) {
-                               nv_error("%s - TP%d:", name, i);
+                               nv_error(priv, "%s - TP%d:", name, i);
                                nouveau_bitfield_print(nv50_mpc_traps, ustatus);
                                pr_cont("\n");
                                ustatus = 0;
index adc88b73d9118e4b7d50ed21209675fbc47a8820..3c6738edd127040337ff8fc53b6125a47e812ad7 100644 (file)
@@ -47,6 +47,7 @@ struct nouveau_mc_oclass {
 extern struct nouveau_oclass *nv04_mc_oclass;
 extern struct nouveau_oclass *nv40_mc_oclass;
 extern struct nouveau_oclass *nv44_mc_oclass;
+extern struct nouveau_oclass *nv4c_mc_oclass;
 extern struct nouveau_oclass *nv50_mc_oclass;
 extern struct nouveau_oclass *nv94_mc_oclass;
 extern struct nouveau_oclass *nv98_mc_oclass;
index aa0fbbec7f08212cd8b3106ecb57ec4ff491403b..ef0c9c4a8cc3925f9f8df1279417fc028a39f2f9 100644 (file)
@@ -130,6 +130,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
        u16 pcir;
        int i;
 
+       /* there is no prom on nv4x IGP's */
+       if (device->card_type == NV_40 && device->chipset >= 0x4c)
+               return;
+
        /* enable access to rom */
        if (device->card_type >= NV_50)
                pcireg = 0x088050;
index 9159a5ccee930d21172884bf9f23972c222669b5..265d1253624a337d7ebf8604a9ca1207113ee1cf 100644 (file)
@@ -36,7 +36,7 @@ nv1a_fb_oclass = &(struct nv04_fb_impl) {
                .fini = _nouveau_fb_fini,
        },
        .base.memtype = nv04_fb_memtype_valid,
-       .base.ram = &nv10_ram_oclass,
+       .base.ram = &nv1a_ram_oclass,
        .tile.regions = 8,
        .tile.init = nv10_fb_tile_init,
        .tile.fini = nv10_fb_tile_fini,
index b0d5c31606c1c50e0686f1aa000c8dc2876062c2..81a408e7d034636f6b940107839394b9a03b0cab 100644 (file)
@@ -14,6 +14,7 @@ int  nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *,
 extern const struct nouveau_mc_intr nv04_mc_intr[];
 int  nv04_mc_init(struct nouveau_object *);
 void nv40_mc_msi_rearm(struct nouveau_mc *);
+int  nv44_mc_init(struct nouveau_object *object);
 int  nv50_mc_init(struct nouveau_object *);
 extern const struct nouveau_mc_intr nv50_mc_intr[];
 extern const struct nouveau_mc_intr nvc0_mc_intr[];
index 3bfee5c6c4f21e3bd25430bb693e5d634c86773a..cc4d0d2d886e679612ca269459b4cc756cc5ab31 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "nv04.h"
 
-static int
+int
 nv44_mc_init(struct nouveau_object *object)
 {
        struct nv04_mc_priv *priv = (void *)object;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c
new file mode 100644 (file)
index 0000000..a75c35c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Ilia Mirkin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ilia Mirkin
+ */
+
+#include "nv04.h"
+
+static void
+nv4c_mc_msi_rearm(struct nouveau_mc *pmc)
+{
+       struct nv04_mc_priv *priv = (void *)pmc;
+       nv_wr08(priv, 0x088050, 0xff);
+}
+
+struct nouveau_oclass *
+nv4c_mc_oclass = &(struct nouveau_mc_oclass) {
+       .base.handle = NV_SUBDEV(MC, 0x4c),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv04_mc_ctor,
+               .dtor = _nouveau_mc_dtor,
+               .init = nv44_mc_init,
+               .fini = _nouveau_mc_fini,
+       },
+       .intr = nv04_mc_intr,
+       .msi_rearm = nv4c_mc_msi_rearm,
+}.base;
index 4ef83df2b246fb335dc8ce05bafead80ed7ac180..83face3f608f020f70d7d11dda363c5817102238 100644 (file)
@@ -106,6 +106,29 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *
        return 0;
 }
 
+/*
+ * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special
+ * requirements on the fourth parameter, so a private implementation
+ * instead of using acpi_check_dsm().
+ */
+static int nouveau_check_optimus_dsm(acpi_handle handle)
+{
+       int result;
+
+       /*
+        * Function 0 returns a Buffer containing available functions.
+        * The args parameter is ignored for function 0, so just put 0 in it
+        */
+       if (nouveau_optimus_dsm(handle, 0, 0, &result))
+               return 0;
+
+       /*
+        * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported.
+        * If the n-th bit is enabled, function n is supported
+        */
+       return result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS);
+}
+
 static int nouveau_dsm(acpi_handle handle, int func, int arg)
 {
        int ret = 0;
@@ -207,8 +230,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
                           1 << NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
-       if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100,
-                          1 << NOUVEAU_DSM_OPTIMUS_CAPS))
+       if (nouveau_check_optimus_dsm(dhandle))
                retval |= NOUVEAU_DSM_HAS_OPT;
 
        if (retval & NOUVEAU_DSM_HAS_OPT) {
index 488686d490c0c7a96ba016e0f55a4beffcda6e4f..4aed1714b9ab7d289bbadc867f9af40b046825f2 100644 (file)
@@ -1249,7 +1249,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
                        mem->bus.is_iomem = !dev->agp->cant_use_aperture;
                }
 #endif
-               if (!node->memtype)
+               if (nv_device(drm->device)->card_type < NV_50 || !node->memtype)
                        /* untiled */
                        break;
                /* fallthrough, tiled memory */
index 78c8e7146d56b2c5f7d189e372e542f4d9b43717..4ee702ac8907bcc3d486000b525ad61857cdf5ff 100644 (file)
@@ -376,6 +376,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto fail_device;
 
+       dev->irq_enabled = true;
+
        /* workaround an odd issue on nvc1 by disabling the device's
         * nosnoop capability.  hopefully won't cause issues until a
         * better fix is found - assuming there is one...
@@ -475,6 +477,7 @@ nouveau_drm_remove(struct pci_dev *pdev)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_object *device;
 
+       dev->irq_enabled = false;
        device = drm->client.base.device;
        drm_put_dev(dev);
 
@@ -863,13 +866,16 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
        int ret;
 
-       if (nouveau_runtime_pm == 0)
-               return -EINVAL;
+       if (nouveau_runtime_pm == 0) {
+               pm_runtime_forbid(dev);
+               return -EBUSY;
+       }
 
        /* are we optimus enabled? */
        if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
                DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
-               return -EINVAL;
+               pm_runtime_forbid(dev);
+               return -EBUSY;
        }
 
        nv_debug_level(SILENT);
@@ -920,12 +926,15 @@ static int nouveau_pmops_runtime_idle(struct device *dev)
        struct nouveau_drm *drm = nouveau_drm(drm_dev);
        struct drm_crtc *crtc;
 
-       if (nouveau_runtime_pm == 0)
+       if (nouveau_runtime_pm == 0) {
+               pm_runtime_forbid(dev);
                return -EBUSY;
+       }
 
        /* are we optimus enabled? */
        if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
                DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+               pm_runtime_forbid(dev);
                return -EBUSY;
        }
 
index 81638d7f2efff69cdce86ac515aac2c19191aefe..471347edc27eb869816e5d5cfed1ccd01f4c7b6f 100644 (file)
@@ -14,7 +14,9 @@ nouveau_vga_set_decode(void *priv, bool state)
 {
        struct nouveau_device *device = nouveau_dev(priv);
 
-       if (device->chipset >= 0x40)
+       if (device->card_type == NV_40 && device->chipset >= 0x4c)
+               nv_wr32(device, 0x088060, state);
+       else if (device->chipset >= 0x40)
                nv_wr32(device, 0x088054, state);
        else
                nv_wr32(device, 0x001854, state);
index a9338c85630fe0548336e8c8c492361ce797dd5a..daa4dd375ab15367266d6f0041af84386d6699bb 100644 (file)
@@ -559,7 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
        u32 adjusted_clock = mode->clock;
        int encoder_mode = atombios_get_encoder_mode(encoder);
        u32 dp_clock = mode->clock;
-       int bpc = radeon_get_monitor_bpc(connector);
+       int bpc = radeon_crtc->bpc;
        bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
 
        /* reset the pll flags */
@@ -1176,7 +1176,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
                /* Set NUM_BANKS. */
-               if (rdev->family >= CHIP_BONAIRE) {
+               if (rdev->family >= CHIP_TAHITI) {
                        unsigned tileb, index, num_banks, tile_split_bytes;
 
                        /* Calculate the macrotile mode index. */
@@ -1194,13 +1194,14 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                                return -EINVAL;
                        }
 
-                       num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       if (rdev->family >= CHIP_BONAIRE)
+                               num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
+                       else
+                               num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;
                        fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
                } else {
-                       /* SI and older. */
-                       if (rdev->family >= CHIP_TAHITI)
-                               tmp = rdev->config.si.tile_config;
-                       else if (rdev->family >= CHIP_CAYMAN)
+                       /* NI and older. */
+                       if (rdev->family >= CHIP_CAYMAN)
                                tmp = rdev->config.cayman.tile_config;
                        else
                                tmp = rdev->config.evergreen.tile_config;
@@ -1773,6 +1774,20 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                        return ATOM_PPLL1;
                DRM_ERROR("unable to allocate a PPLL\n");
                return ATOM_PPLL_INVALID;
+       } else if (ASIC_IS_DCE41(rdev)) {
+               /* Don't share PLLs on DCE4.1 chips */
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+                       if (rdev->clock.dp_extclk)
+                               /* skip PPLL programming if using ext clock */
+                               return ATOM_PPLL_INVALID;
+               }
+               pll_in_use = radeon_get_pll_use_mask(crtc);
+               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 if (ASIC_IS_DCE4(rdev)) {
                /* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
                 * depending on the asic:
@@ -1800,7 +1815,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                                if (pll != ATOM_PPLL_INVALID)
                                        return pll;
                        }
-               } else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */
+               } else {
                        /* use the same PPLL for all monitors with the same clock */
                        pll = radeon_get_shared_nondp_ppll(crtc);
                        if (pll != ATOM_PPLL_INVALID)
index a42d61571f49fa877e6c42564b7edeb9b1e2ef5b..607dc14d195e3540f103bf798d2e6f0e10e5634f 100644 (file)
@@ -464,11 +464,12 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)
 
 static u8 radeon_atom_get_bpc(struct drm_encoder *encoder)
 {
-       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        int bpc = 8;
 
-       if (connector)
-               bpc = radeon_get_monitor_bpc(connector);
+       if (encoder->crtc) {
+               struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+               bpc = radeon_crtc->bpc;
+       }
 
        switch (bpc) {
        case 0:
@@ -1313,7 +1314,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        }
                        if (is_dp)
                                args.v5.ucLaneNum = dp_lane_count;
-                       else if (radeon_encoder->pixel_clock > 165000)
+                       else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
                                args.v5.ucLaneNum = 8;
                        else
                                args.v5.ucLaneNum = 4;
index 0fbd36f3d4e9da34b65bc5f8ed302dc143b2d3c7..ea103ccdf4bd517205b95e82a1437e4cf510f8f2 100644 (file)
@@ -29,6 +29,7 @@
 #include "cypress_dpm.h"
 #include "btc_dpm.h"
 #include "atom.h"
+#include <linux/seq_file.h>
 
 #define MC_CG_ARB_FREQ_F0           0x0a
 #define MC_CG_ARB_FREQ_F1           0x0b
@@ -2756,6 +2757,37 @@ void btc_dpm_fini(struct radeon_device *rdev)
        r600_free_extended_power_table(rdev);
 }
 
+void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
+                                                    struct seq_file *m)
+{
+       struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       struct radeon_ps *rps = &eg_pi->current_rps;
+       struct rv7xx_ps *ps = rv770_get_ps(rps);
+       struct rv7xx_pl *pl;
+       u32 current_index =
+               (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
+               CURRENT_PROFILE_INDEX_SHIFT;
+
+       if (current_index > 2) {
+               seq_printf(m, "invalid dpm profile %d\n", current_index);
+       } else {
+               if (current_index == 0)
+                       pl = &ps->low;
+               else if (current_index == 1)
+                       pl = &ps->medium;
+               else /* current_index == 2 */
+                       pl = &ps->high;
+               seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
+               if (rdev->family >= CHIP_CEDAR) {
+                       seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
+                                  current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
+               } else {
+                       seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u\n",
+                                  current_index, pl->sclk, pl->mclk, pl->vddc);
+               }
+       }
+}
+
 u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low)
 {
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
index 29e32de7e02546e98951d6656703c6848a4de03d..9c65be2d55a91bedd525a8fdf4ce448184b69433 100644 (file)
 #       define DYN_SPREAD_SPECTRUM_EN                   (1 << 23)
 #       define AC_DC_SW                                 (1 << 24)
 
+#define TARGET_AND_CURRENT_PROFILE_INDEX                  0x66c
+#       define CURRENT_PROFILE_INDEX_MASK                 (0xf << 4)
+#       define CURRENT_PROFILE_INDEX_SHIFT                4
+
 #define        CG_BIF_REQ_AND_RSP                              0x7f4
 #define                CG_CLIENT_REQ(x)                        ((x) << 0)
 #define                CG_CLIENT_REQ_MASK                      (0xff << 0)
index e6419ca7cd375d6958ebcd339fb68a004c56cd1a..bbb17841a9e57ad2fdc44425a26d658848892f4c 100644 (file)
@@ -3046,7 +3046,7 @@ static u32 cik_create_bitmask(u32 bit_width)
 }
 
 /**
- * cik_select_se_sh - select which SE, SH to address
+ * cik_get_rb_disabled - computes the mask of disabled RBs
  *
  * @rdev: radeon_device pointer
  * @max_rb_num: max RBs (render backends) for the asic
@@ -4134,8 +4134,11 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable)
 {
        if (enable)
                WREG32(CP_MEC_CNTL, 0);
-       else
+       else {
                WREG32(CP_MEC_CNTL, (MEC_ME1_HALT | MEC_ME2_HALT));
+               rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
+               rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
+       }
        udelay(50);
 }
 
@@ -7902,7 +7905,8 @@ int cik_resume(struct radeon_device *rdev)
        /* init golden registers */
        cik_init_golden_registers(rdev);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.pm_method == PM_METHOD_DPM)
+               radeon_pm_resume(rdev);
 
        rdev->accel_working = true;
        r = cik_startup(rdev);
index 1ecb3f1070e35c6ed3516e5f325eeeb61bc795b2..94626ea90fa57abc5efca249ab4d0d08cfc9566d 100644 (file)
@@ -264,6 +264,8 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev)
                WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
                WREG32(SDMA0_GFX_IB_CNTL + reg_offset, 0);
        }
+       rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false;
+       rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false;
 }
 
 /**
@@ -291,6 +293,11 @@ void cik_sdma_enable(struct radeon_device *rdev, bool enable)
        u32 me_cntl, reg_offset;
        int i;
 
+       if (enable == false) {
+               cik_sdma_gfx_stop(rdev);
+               cik_sdma_rlc_stop(rdev);
+       }
+
        for (i = 0; i < 2; i++) {
                if (i == 0)
                        reg_offset = SDMA0_REGISTER_OFFSET;
@@ -420,10 +427,6 @@ static int cik_sdma_load_microcode(struct radeon_device *rdev)
        if (!rdev->sdma_fw)
                return -EINVAL;
 
-       /* stop the gfx rings and rlc compute queues */
-       cik_sdma_gfx_stop(rdev);
-       cik_sdma_rlc_stop(rdev);
-
        /* halt the MEs */
        cik_sdma_enable(rdev, false);
 
@@ -492,9 +495,6 @@ int cik_sdma_resume(struct radeon_device *rdev)
  */
 void cik_sdma_fini(struct radeon_device *rdev)
 {
-       /* stop the gfx rings and rlc compute queues */
-       cik_sdma_gfx_stop(rdev);
-       cik_sdma_rlc_stop(rdev);
        /* halt the MEs */
        cik_sdma_enable(rdev, false);
        radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]);
index 713a5d35990102ea315fa078a93c11d6c1aae1f5..94e85875199481ca46e3c84cef453aaec3970356 100644 (file)
@@ -278,13 +278,15 @@ static int dce6_audio_chipset_supported(struct radeon_device *rdev)
        return !ASIC_IS_NODCE(rdev);
 }
 
-static void dce6_audio_enable(struct radeon_device *rdev,
-                             struct r600_audio_pin *pin,
-                             bool enable)
+void dce6_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable)
 {
+       if (!pin)
+               return;
+
        WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL,
-                       AUDIO_ENABLED);
-       DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
+                       enable ? AUDIO_ENABLED : 0);
 }
 
 static const u32 pin_offsets[7] =
@@ -323,7 +325,8 @@ int dce6_audio_init(struct radeon_device *rdev)
                rdev->audio.pin[i].connected = false;
                rdev->audio.pin[i].offset = pin_offsets[i];
                rdev->audio.pin[i].id = i;
-               dce6_audio_enable(rdev, &rdev->audio.pin[i], true);
+               /* disable audio.  it will be set up later */
+               dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
        }
 
        return 0;
index f2b9e21ce4da063a03004c4705a3662b2e78c437..27b0ff16082ebbbe10eb385b8bce24e127b5091d 100644 (file)
@@ -1680,7 +1680,7 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
        case RADEON_HPD_6:
                if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
                        connected = true;
-                       break;
+               break;
        default:
                break;
        }
@@ -5299,7 +5299,8 @@ int evergreen_resume(struct radeon_device *rdev)
        /* init golden registers */
        evergreen_init_golden_registers(rdev);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.pm_method == PM_METHOD_DPM)
+               radeon_pm_resume(rdev);
 
        rdev->accel_working = true;
        r = evergreen_startup(rdev);
@@ -5475,9 +5476,9 @@ void evergreen_fini(struct radeon_device *rdev)
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       evergreen_pcie_gart_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_fini(rdev);
+       evergreen_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
index 0c6d5cef4cf121770c63fcb559bf6cc187640292..05b0c95813fd79ff4c31ade3a90c0ad1880d028d 100644 (file)
@@ -306,6 +306,15 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
                return;
        offset = dig->afmt->offset;
 
+       /* disable audio prior to setting up hw */
+       if (ASIC_IS_DCE6(rdev)) {
+               dig->afmt->pin = dce6_audio_get_pin(rdev);
+               dce6_audio_enable(rdev, dig->afmt->pin, false);
+       } else {
+               dig->afmt->pin = r600_audio_get_pin(rdev);
+               r600_audio_enable(rdev, dig->afmt->pin, false);
+       }
+
        evergreen_audio_set_dto(encoder, mode->clock);
 
        WREG32(HDMI_VBI_PACKET_CONTROL + offset,
@@ -409,12 +418,16 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
        WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
        WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
        WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
+
+       /* enable audio after to setting up hw */
+       if (ASIC_IS_DCE6(rdev))
+               dce6_audio_enable(rdev, dig->afmt->pin, true);
+       else
+               r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
 void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
 {
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
@@ -427,15 +440,6 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!enable && !dig->afmt->enabled)
                return;
 
-       if (enable) {
-               if (ASIC_IS_DCE6(rdev))
-                       dig->afmt->pin = dce6_audio_get_pin(rdev);
-               else
-                       dig->afmt->pin = r600_audio_get_pin(rdev);
-       } else {
-               dig->afmt->pin = NULL;
-       }
-
        dig->afmt->enabled = enable;
 
        DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
index 76ada8cfe902a4d9eaa9890404c390371f856621..3a03ba37d04346fb5200d67ee002716ae549a600 100644 (file)
@@ -57,7 +57,7 @@ typedef struct SMC_Evergreen_MCRegisters SMC_Evergreen_MCRegisters;
 
 #define EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION 0x100
 
-#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters   0x0
+#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters   0x8
 #define EVERGREEN_SMC_FIRMWARE_HEADER_stateTable      0xC
 #define EVERGREEN_SMC_FIRMWARE_HEADER_mcRegisterTable 0x20
 
index b6e01d5d2cced24edc67e773c84cba33a6d5fef8..351db361239db1d2800f845b2e9e9d02d541cc2b 100644 (file)
@@ -1223,7 +1223,7 @@ int kv_dpm_enable(struct radeon_device *rdev)
 
 int kv_dpm_late_enable(struct radeon_device *rdev)
 {
-       int ret;
+       int ret = 0;
 
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
index ea932ac66fc6647da43a8cf775b60ade25d478de..bf6300cfd62d0799deaefbd698027cf8d811dbc6 100644 (file)
@@ -2105,7 +2105,8 @@ int cayman_resume(struct radeon_device *rdev)
        /* init golden registers */
        ni_init_golden_registers(rdev);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.pm_method == PM_METHOD_DPM)
+               radeon_pm_resume(rdev);
 
        rdev->accel_working = true;
        r = cayman_startup(rdev);
index c351226ecb31b0d9fa2d94a32ac23d504d61952b..ca814276b07539741b53c167abc1a0bd5105173a 100644 (file)
@@ -2588,7 +2588,7 @@ static int ni_populate_sq_ramping_values(struct radeon_device *rdev,
        if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
                enable_sq_ramping = false;
 
-       if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+       if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
                enable_sq_ramping = false;
 
        for (i = 0; i < state->performance_level_count; i++) {
@@ -3945,7 +3945,6 @@ static void ni_parse_pplib_clock_info(struct radeon_device *rdev,
        struct rv7xx_power_info *pi = rv770_get_pi(rdev);
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
        struct ni_ps *ps = ni_get_ps(rps);
-       u16 vddc;
        struct rv7xx_pl *pl = &ps->performance_levels[index];
 
        ps->performance_level_count = index + 1;
@@ -3961,8 +3960,8 @@ static void ni_parse_pplib_clock_info(struct radeon_device *rdev,
 
        /* patch up vddc if necessary */
        if (pl->vddc == 0xff01) {
-               if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc) == 0)
-                       pl->vddc = vddc;
+               if (pi->max_vddc)
+                       pl->vddc = pi->max_vddc;
        }
 
        if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
@@ -4322,7 +4321,8 @@ void ni_dpm_print_power_state(struct radeon_device *rdev,
 void ni_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
                                                    struct seq_file *m)
 {
-       struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+       struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       struct radeon_ps *rps = &eg_pi->current_rps;
        struct ni_ps *ps = ni_get_ps(rps);
        struct rv7xx_pl *pl;
        u32 current_index =
index ef024ce3f7ccfd39b1be47be9840a401b588b1dc..3cc78bb66042fc5509f26825560847374888288e 100644 (file)
@@ -3942,8 +3942,6 @@ int r100_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = r100_startup(rdev);
        if (r) {
index 7c63ef840e86abaf04f216201b32ee2f40323b9b..0b658b34b33ab1d2874c0c85a668b4fa48da0ecc 100644 (file)
@@ -1430,8 +1430,6 @@ int r300_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = r300_startup(rdev);
        if (r) {
index 3768aab2710b3943261312c4fcc5184b4f18a6fb..802b19220a21358712dc304a894db892ec3537fb 100644 (file)
@@ -325,8 +325,6 @@ int r420_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = r420_startup(rdev);
        if (r) {
index e209eb75024f9dc1c441518cbe8f8d70a41844f5..98d6053c36c678aaf598e7a0b63193d00d042f5b 100644 (file)
@@ -240,8 +240,6 @@ int r520_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = r520_startup(rdev);
        if (r) {
index 56140b4e5bb2e9fa7fc72339cc29f88b398aff1c..647ef407921764692758c56e03f92b737202e317 100644 (file)
@@ -2968,7 +2968,8 @@ int r600_resume(struct radeon_device *rdev)
        /* post card */
        atom_asic_init(rdev->mode_info.atom_context);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.pm_method == PM_METHOD_DPM)
+               radeon_pm_resume(rdev);
 
        rdev->accel_working = true;
        r = r600_startup(rdev);
@@ -3991,6 +3992,10 @@ restart_ih:
                                break;
                        }
                        break;
+               case 124: /* UVD */
+                       DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
+                       radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
+                       break;
                case 176: /* CP_INT in ring buffer */
                case 177: /* CP_INT in IB1 */
                case 178: /* CP_INT in IB2 */
index 47fc2b88697928b4272a0878927d189762a82000..bffac10c4296b3b4c28d9f7a52322fe51e9ae7c5 100644 (file)
@@ -142,12 +142,15 @@ void r600_audio_update_hdmi(struct work_struct *work)
 }
 
 /* enable the audio stream */
-static void r600_audio_enable(struct radeon_device *rdev,
-                             struct r600_audio_pin *pin,
-                             bool enable)
+void r600_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable)
 {
        u32 value = 0;
 
+       if (!pin)
+               return;
+
        if (ASIC_IS_DCE4(rdev)) {
                if (enable) {
                        value |= 0x81000000; /* Required to enable audio */
@@ -158,7 +161,6 @@ static void r600_audio_enable(struct radeon_device *rdev,
                WREG32_P(R600_AUDIO_ENABLE,
                         enable ? 0x81000000 : 0x0, ~0x81000000);
        }
-       DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
 }
 
 /*
@@ -178,8 +180,8 @@ int r600_audio_init(struct radeon_device *rdev)
        rdev->audio.pin[0].status_bits = 0;
        rdev->audio.pin[0].category_code = 0;
        rdev->audio.pin[0].id = 0;
-
-       r600_audio_enable(rdev, &rdev->audio.pin[0], true);
+       /* disable audio.  it will be set up later */
+       r600_audio_enable(rdev, &rdev->audio.pin[0], false);
 
        return 0;
 }
index 7b399dc5fd5492d1e53dcaa5b5be728164dc85b2..2812c7d1ae6f21b5d4ba6550755b5ecc3fc8ef61 100644 (file)
@@ -1007,8 +1007,22 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_008C64_SQ_VSTMP_RING_SIZE:
        case R_0288C8_SQ_GS_VERT_ITEMSIZE:
                /* get value to populate the IB don't remove */
-               tmp =radeon_get_ib_value(p, idx);
-               ib[idx] = 0;
+               /*tmp =radeon_get_ib_value(p, idx);
+                 ib[idx] = 0;*/
+               break;
+       case SQ_ESGS_RING_BASE:
+       case SQ_GSVS_RING_BASE:
+       case SQ_ESTMP_RING_BASE:
+       case SQ_GSTMP_RING_BASE:
+       case SQ_PSTMP_RING_BASE:
+       case SQ_VSTMP_RING_BASE:
+               r = radeon_cs_packet_next_reloc(p, &reloc, 0);
+               if (r) {
+                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                       "0x%04X\n", reg);
+                       return -EINVAL;
+               }
+               ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                break;
        case SQ_CONFIG:
                track->sq_config = radeon_get_ib_value(p, idx);
index 3016fc14f502c49a61c2343c3b2ca877d2590109..85a2bb28aed27699e464edc54a8573c8d1d41b39 100644 (file)
@@ -329,9 +329,6 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
-       /* XXX: setting this register causes hangs on some asics */
-       return;
-
        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
                if (connector->encoder == encoder) {
                        radeon_connector = to_radeon_connector(connector);
@@ -460,6 +457,10 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
                return;
        offset = dig->afmt->offset;
 
+       /* disable audio prior to setting up hw */
+       dig->afmt->pin = r600_audio_get_pin(rdev);
+       r600_audio_enable(rdev, dig->afmt->pin, false);
+
        r600_audio_set_dto(encoder, mode->clock);
 
        WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
@@ -531,6 +532,9 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
        WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
 
        r600_hdmi_audio_workaround(encoder);
+
+       /* enable audio after to setting up hw */
+       r600_audio_enable(rdev, dig->afmt->pin, true);
 }
 
 /*
@@ -651,11 +655,6 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!enable && !dig->afmt->enabled)
                return;
 
-       if (enable)
-               dig->afmt->pin = r600_audio_get_pin(rdev);
-       else
-               dig->afmt->pin = NULL;
-
        /* Older chipsets require setting HDMI and routing manually */
        if (!ASIC_IS_DCE3(rdev)) {
                if (enable)
index 4a8ac1cd6b4c65582690e035e026aa6f1b125e00..e887d027b6d01fda8082305d11ff1b27bad06db9 100644 (file)
@@ -135,6 +135,9 @@ extern int radeon_hard_reset;
 /* R600+ */
 #define R600_RING_TYPE_UVD_INDEX       5
 
+/* number of hw syncs before falling back on blocking */
+#define RADEON_NUM_SYNCS                       4
+
 /* hardcode those limit for now */
 #define RADEON_VA_IB_OFFSET                    (1 << 20)
 #define RADEON_VA_RESERVED_SIZE                        (8 << 20)
@@ -554,7 +557,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
 /*
  * Semaphores.
  */
-/* everything here is constant */
 struct radeon_semaphore {
        struct radeon_sa_bo             *sa_bo;
        signed                          waiters;
@@ -2745,6 +2747,12 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
 void r600_audio_update_hdmi(struct work_struct *work);
 struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev);
 struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev);
+void r600_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable);
+void dce6_audio_enable(struct radeon_device *rdev,
+                      struct r600_audio_pin *pin,
+                      bool enable);
 
 /*
  * R600 vram scratch functions
index f74db43346fd86f4658e11cc62e6e08134127936..dda02bfc10a49b55497479e3a911167b91397481 100644 (file)
@@ -1555,7 +1555,7 @@ static struct radeon_asic btc_asic = {
                .get_sclk = &btc_dpm_get_sclk,
                .get_mclk = &btc_dpm_get_mclk,
                .print_power_state = &rv770_dpm_print_power_state,
-               .debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
+               .debugfs_print_current_performance_level = &btc_dpm_debugfs_print_current_performance_level,
                .force_performance_level = &rv770_dpm_force_performance_level,
                .vblank_too_short = &btc_dpm_vblank_too_short,
        },
index b3bc433eed4c3bd832424051306a845461c90aa8..ae637cfda783285a0f2638435e6620c6026fb534 100644 (file)
@@ -551,6 +551,8 @@ void btc_dpm_fini(struct radeon_device *rdev);
 u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low);
 u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low);
 bool btc_dpm_vblank_too_short(struct radeon_device *rdev);
+void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
+                                                    struct seq_file *m);
 int sumo_dpm_init(struct radeon_device *rdev);
 int sumo_dpm_enable(struct radeon_device *rdev);
 int sumo_dpm_late_enable(struct radeon_device *rdev);
index 485848f889f55c9f4b86bf61bd8c019e2ad96a27..fa9a9c02751ea865251f7854665c3757caa48e00 100644 (file)
@@ -219,7 +219,8 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
        memcpy(&output, info->buffer.pointer, size);
 
        /* TODO: check version? */
-       printk("ATPX version %u\n", output.version);
+       printk("ATPX version %u, functions 0x%08x\n",
+              output.version, output.function_bits);
 
        radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
 
index b012cbbc3ed5a9b892b433eff0ee5f3134a130de..044bc98fb459e46fac62b929696ad047f835360d 100644 (file)
@@ -1521,13 +1521,16 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        if (r)
                DRM_ERROR("ib ring test failed (%d).\n", r);
 
-       if (rdev->pm.dpm_enabled) {
+       if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
                /* do dpm late init */
                r = radeon_pm_late_init(rdev);
                if (r) {
                        rdev->pm.dpm_enabled = false;
                        DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
                }
+       } else {
+               /* resume old pm late */
+               radeon_pm_resume(rdev);
        }
 
        radeon_restore_bios_scratch_regs(rdev);
index d680608f6f5bc9a80e879b4f24769f8a9ffb1e8c..fbd8b930f2bec75276a5baf781653e658a023eaa 100644 (file)
@@ -571,6 +571,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
                radeon_crtc->max_cursor_width = CURSOR_WIDTH;
                radeon_crtc->max_cursor_height = CURSOR_HEIGHT;
        }
+       dev->mode_config.cursor_width = radeon_crtc->max_cursor_width;
+       dev->mode_config.cursor_height = radeon_crtc->max_cursor_height;
 
 #if 0
        radeon_crtc->mode_set.crtc = &radeon_crtc->base;
index ec8c388eec176e8c36e343ff4182634d3708bc84..f633c2782170b09bcc8722d1568cbe0a8c665f12 100644 (file)
  *   2.34.0 - Add CIK tiling mode array query
  *   2.35.0 - Add CIK macrotile mode array query
  *   2.36.0 - Fix CIK DCE tiling setup
+ *   2.37.0 - allow GS ring setup on r6xx/r7xx
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       36
+#define KMS_DRIVER_MINOR       37
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -402,11 +403,15 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
        int ret;
 
-       if (radeon_runtime_pm == 0)
-               return -EINVAL;
+       if (radeon_runtime_pm == 0) {
+               pm_runtime_forbid(dev);
+               return -EBUSY;
+       }
 
-       if (radeon_runtime_pm == -1 && !radeon_is_px())
-               return -EINVAL;
+       if (radeon_runtime_pm == -1 && !radeon_is_px()) {
+               pm_runtime_forbid(dev);
+               return -EBUSY;
+       }
 
        drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
        drm_kms_helper_poll_disable(drm_dev);
@@ -455,12 +460,15 @@ static int radeon_pmops_runtime_idle(struct device *dev)
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
        struct drm_crtc *crtc;
 
-       if (radeon_runtime_pm == 0)
+       if (radeon_runtime_pm == 0) {
+               pm_runtime_forbid(dev);
                return -EBUSY;
+       }
 
        /* are we PX enabled? */
        if (radeon_runtime_pm == -1 && !radeon_is_px()) {
                DRM_DEBUG_DRIVER("failing to power off - not px\n");
+               pm_runtime_forbid(dev);
                return -EBUSY;
        }
 
index 114d1672d616d0b5d7b85ab5d739da66f2db823e..66ed3ea7144010e7c95bc0d07c01ad5499242947 100644 (file)
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+
+#if defined(CONFIG_VGA_SWITCHEROO)
+bool radeon_is_px(void);
+#else
+static inline bool radeon_is_px(void) { return false; }
+#endif
+
 /**
  * radeon_driver_unload_kms - Main unload function for KMS.
  *
@@ -130,7 +137,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
                                "Error during ACPI methods call\n");
        }
 
-       if (radeon_runtime_pm != 0) {
+       if ((radeon_runtime_pm == 1) ||
+           ((radeon_runtime_pm == -1) && radeon_is_px())) {
                pm_runtime_use_autosuspend(dev->dev);
                pm_runtime_set_autosuspend_delay(dev->dev, 5000);
                pm_runtime_set_active(dev->dev);
@@ -537,6 +545,10 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
 
                radeon_vm_init(rdev, &fpriv->vm);
 
+               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+               if (r)
+                       return r;
+
                /* map the ib pool buffer read only into
                 * virtual address space */
                bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
@@ -544,6 +556,8 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
                                          RADEON_VM_PAGE_READABLE |
                                          RADEON_VM_PAGE_SNOOPED);
+
+               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
                if (r) {
                        radeon_vm_fini(rdev, &fpriv->vm);
                        kfree(fpriv);
index 1b783f0e6d3ad084b0a62629a4b5d67c9e92453f..15e44a7281ab96f6b14592ed2e4e840ddae0b74f 100644 (file)
@@ -139,7 +139,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
        }
 
        /* 64 dwords should be enough for fence too */
-       r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8);
+       r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
        if (r) {
                dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
                return r;
index 2b42aa1914f2006dabddee990cd14fc919668d59..9006b32d5eed0433d336ef56e1bfb17c6fffa0de 100644 (file)
 int radeon_semaphore_create(struct radeon_device *rdev,
                            struct radeon_semaphore **semaphore)
 {
+       uint32_t *cpu_addr;
        int i, r;
 
        *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
        if (*semaphore == NULL) {
                return -ENOMEM;
        }
-       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo,
-                            &(*semaphore)->sa_bo, 8, 8, true);
+       r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo,
+                            8 * RADEON_NUM_SYNCS, 8, true);
        if (r) {
                kfree(*semaphore);
                *semaphore = NULL;
@@ -49,7 +50,10 @@ int radeon_semaphore_create(struct radeon_device *rdev,
        }
        (*semaphore)->waiters = 0;
        (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo);
-       *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0;
+
+       cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo);
+       for (i = 0; i < RADEON_NUM_SYNCS; ++i)
+               cpu_addr[i] = 0;
 
        for (i = 0; i < RADEON_NUM_RINGS; ++i)
                (*semaphore)->sync_to[i] = NULL;
@@ -125,6 +129,7 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
                                struct radeon_semaphore *semaphore,
                                int ring)
 {
+       unsigned count = 0;
        int i, r;
 
         for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -140,6 +145,12 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
                        return -EINVAL;
                }
 
+               if (++count > RADEON_NUM_SYNCS) {
+                       /* not enough room, wait manually */
+                       radeon_fence_wait_locked(fence);
+                       continue;
+               }
+
                /* allocate enough space for sync command */
                r = radeon_ring_alloc(rdev, &rdev->ring[i], 16);
                if (r) {
@@ -164,6 +175,8 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
 
                radeon_ring_commit(rdev, &rdev->ring[i]);
                radeon_fence_note_sync(fence, ring);
+
+               semaphore->gpu_addr += 8;
        }
 
        return 0;
index 77f5b0c3edb8d8b1f4835620d626c3981171c7a6..040a2a10ea17e8136a4274decc83de131ad79e3f 100644 (file)
@@ -714,6 +714,9 @@ int radeon_ttm_init(struct radeon_device *rdev)
                DRM_ERROR("Failed initializing VRAM heap.\n");
                return r;
        }
+       /* Change the size here instead of the init above so only lpfn is affected */
+       radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+
        r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true,
                             RADEON_GEM_DOMAIN_VRAM,
                             NULL, &rdev->stollen_vga_memory);
@@ -935,7 +938,7 @@ static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf,
        while (size) {
                loff_t p = *pos / PAGE_SIZE;
                unsigned off = *pos & ~PAGE_MASK;
-               ssize_t cur_size = min(size, PAGE_SIZE - off);
+               size_t cur_size = min_t(size_t, size, PAGE_SIZE - off);
                struct page *page;
                void *ptr;
 
index 6781fee1eaadc21a68e50de696dd353be0a3e9e5..3e6804b2b2ef748e9727e34817243aa31e7f9210 100644 (file)
@@ -171,6 +171,8 @@ void radeon_uvd_fini(struct radeon_device *rdev)
 
        radeon_bo_unref(&rdev->uvd.vcpu_bo);
 
+       radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
+
        release_firmware(rdev->uvd_fw);
 }
 
index 20bfbda7b3f1bdcf0eff27332bf2b9812af696b4..ec0c6829c1dcdb9a96460101b4b205177c7a98d7 100644 (file)
@@ -18,6 +18,7 @@ r600 0x9400
 0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
 0x00028A40 VGT_GS_MODE
 0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x00028B38 VGT_GS_MAX_VERT_OUT
 0x000088C8 VGT_GS_PER_ES
 0x000088E8 VGT_GS_PER_VS
 0x000088D4 VGT_GS_VERTEX_REUSE
index b5c2369cda2fe28ca043fe91f4fcfe12fc227fc6..130d5cc50d436fd90c1d3055bd03e177ba2dce6c 100644 (file)
@@ -474,8 +474,6 @@ int rs400_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = rs400_startup(rdev);
        if (r) {
index fdcde7693032c28cc30008b494fd573fd82e58f3..72d3616de08e054efe6199fcd529f59cef3e18d5 100644 (file)
@@ -1048,8 +1048,6 @@ int rs600_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = rs600_startup(rdev);
        if (r) {
index 35950738bd5e449465e0e5062d096e3e8ae9ff0e..3462b64369bfe6142a4c8acfaec09e0bb7d8826c 100644 (file)
@@ -756,8 +756,6 @@ int rs690_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r = rs690_startup(rdev);
        if (r) {
index 98e8138ff77945ecdba447bdcb94310c30dcb1c7..237dd29d9f1c893b1e17600fec59660848b394c3 100644 (file)
@@ -586,8 +586,6 @@ int rv515_resume(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
 
-       radeon_pm_resume(rdev);
-
        rdev->accel_working = true;
        r =  rv515_startup(rdev);
        if (r) {
index 6c772e58c7845e7d4170287d3e583afd64c5a3e8..fef310773aadc71260888372b896df0afcced749 100644 (file)
@@ -1811,7 +1811,8 @@ int rv770_resume(struct radeon_device *rdev)
        /* init golden registers */
        rv770_init_golden_registers(rdev);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.pm_method == PM_METHOD_DPM)
+               radeon_pm_resume(rdev);
 
        rdev->accel_working = true;
        r = rv770_startup(rdev);
@@ -1955,9 +1956,9 @@ void rv770_fini(struct radeon_device *rdev)
        radeon_wb_fini(rdev);
        radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
-       rv770_pcie_gart_fini(rdev);
        uvd_v1_0_fini(rdev);
        radeon_uvd_fini(rdev);
+       rv770_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
        radeon_gem_fini(rdev);
        radeon_fence_driver_fini(rdev);
index 80c595aba359b53c4f748feae3aeab9d207f5db8..b5f63f5e22a324dd6b2714834d58c339359ab918 100644 (file)
@@ -2174,7 +2174,6 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
        struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
        struct rv7xx_ps *ps = rv770_get_ps(rps);
        u32 sclk, mclk;
-       u16 vddc;
        struct rv7xx_pl *pl;
 
        switch (index) {
@@ -2214,8 +2213,8 @@ static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
 
        /* patch up vddc if necessary */
        if (pl->vddc == 0xff01) {
-               if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc) == 0)
-                       pl->vddc = vddc;
+               if (pi->max_vddc)
+                       pl->vddc = pi->max_vddc;
        }
 
        if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
@@ -2527,14 +2526,7 @@ u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low)
 bool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
 {
        u32 vblank_time = r600_dpm_get_vblank_time(rdev);
-       u32 switch_limit = 300;
-
-       /* quirks */
-       /* ASUS K70AF */
-       if ((rdev->pdev->device == 0x9553) &&
-           (rdev->pdev->subsystem_vendor == 0x1043) &&
-           (rdev->pdev->subsystem_device == 0x1c42))
-               switch_limit = 200;
+       u32 switch_limit = 200; /* 300 */
 
        /* RV770 */
        /* mclk switching doesn't seem to work reliably on desktop RV770s */
index 09ec4f6c53bb2202dec2e9c039a3877593d2c4fe..9a124d0608b36f3ae594709ac92c4d4ad563b6d7 100644 (file)
@@ -6338,6 +6338,10 @@ restart_ih:
                                break;
                        }
                        break;
+               case 124: /* UVD */
+                       DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
+                       radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
+                       break;
                case 146:
                case 147:
                        addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR);
@@ -6614,7 +6618,8 @@ int si_resume(struct radeon_device *rdev)
        /* init golden registers */
        si_init_golden_registers(rdev);
 
-       radeon_pm_resume(rdev);
+       if (rdev->pm.pm_method == PM_METHOD_DPM)
+               radeon_pm_resume(rdev);
 
        rdev->accel_working = true;
        r = si_startup(rdev);
index 0471501338fbbeb9e7b72ee572b2bda126ab475a..0a2f5b4bca430bf94a8d1e49dd9f786437772186 100644 (file)
@@ -2395,7 +2395,7 @@ static int si_populate_sq_ramping_values(struct radeon_device *rdev,
        if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
                enable_sq_ramping = false;
 
-       if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+       if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
                enable_sq_ramping = false;
 
        for (i = 0; i < state->performance_level_count; i++) {
@@ -6472,7 +6472,8 @@ void si_dpm_fini(struct radeon_device *rdev)
 void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
                                                    struct seq_file *m)
 {
-       struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+       struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
+       struct radeon_ps *rps = &eg_pi->current_rps;
        struct ni_ps *ps = ni_get_ps(rps);
        struct rv7xx_pl *pl;
        u32 current_index =
index f121efe12dc5c10a4fd6f1c5283ee7f87e8b0797..8b47b3cd0357cf7065aace2c90fa0751b203b506 100644 (file)
@@ -1807,7 +1807,7 @@ void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev
                                                      struct seq_file *m)
 {
        struct sumo_power_info *pi = sumo_get_pi(rdev);
-       struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+       struct radeon_ps *rps = &pi->current_rps;
        struct sumo_ps *ps = sumo_get_ps(rps);
        struct sumo_pl *pl;
        u32 current_index =
index 2d447192d6f7356b1f37af690e1242932b23d7bf..2da0e17eb96060e3027e185106e5f4366561d799 100644 (file)
@@ -1926,7 +1926,8 @@ void trinity_dpm_print_power_state(struct radeon_device *rdev,
 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
                                                         struct seq_file *m)
 {
-       struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+       struct trinity_power_info *pi = trinity_get_pi(rdev);
+       struct radeon_ps *rps = &pi->current_rps;
        struct trinity_ps *ps = trinity_get_ps(rps);
        struct trinity_pl *pl;
        u32 current_index =
index 824550db3fed59e2220953e9e9976b8b28443260..d1771004cb52ecee46ae22dc7665bd54adb477b6 100644 (file)
@@ -57,7 +57,6 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, PACKET0(UVD_GPCOM_VCPU_CMD, 0));
        radeon_ring_write(ring, 2);
-       return;
 }
 
 /**
index 88a529008ce0e59210e917422b2cfe07570a0d7d..c71594754f46fa18810d5b654d2c2d31288f6c3a 100644 (file)
@@ -104,7 +104,7 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
 
 static void tegra_drm_lastclose(struct drm_device *drm)
 {
-#ifdef CONFIG_TEGRA_DRM_FBDEV
+#ifdef CONFIG_DRM_TEGRA_FBDEV
        struct tegra_drm *tegra = drm->dev_private;
 
        tegra_fbdev_restore_mode(tegra->fbdev);
index 338f7f6561d701d601a92b2f6362782536d03e2e..0266fb40479eae05f5176e9835d7c2a1ede75519 100644 (file)
@@ -15,6 +15,7 @@
 struct tegra_rgb {
        struct tegra_output output;
        struct tegra_dc *dc;
+       bool enabled;
 
        struct clk *clk_parent;
        struct clk *clk;
@@ -89,6 +90,9 @@ static int tegra_output_rgb_enable(struct tegra_output *output)
        struct tegra_rgb *rgb = to_rgb(output);
        unsigned long value;
 
+       if (rgb->enabled)
+               return 0;
+
        tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
        value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
@@ -122,6 +126,8 @@ static int tegra_output_rgb_enable(struct tegra_output *output)
        tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
        tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
 
+       rgb->enabled = true;
+
        return 0;
 }
 
@@ -130,6 +136,9 @@ static int tegra_output_rgb_disable(struct tegra_output *output)
        struct tegra_rgb *rgb = to_rgb(output);
        unsigned long value;
 
+       if (!rgb->enabled)
+               return 0;
+
        value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL);
        value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
                   PW4_ENABLE | PM0_ENABLE | PM1_ENABLE);
@@ -144,6 +153,8 @@ static int tegra_output_rgb_disable(struct tegra_output *output)
 
        tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
+       rgb->enabled = false;
+
        return 0;
 }
 
index 3302f99e7497002edf15f842d1b0abcebb71fbe4..764be36397fd2363d7bf9039574af51a6557136c 100644 (file)
@@ -126,6 +126,7 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_bo_device *bdev,
        agp_be->ttm.func = &ttm_agp_func;
 
        if (ttm_tt_init(&agp_be->ttm, bdev, size, page_flags, dummy_read_page)) {
+               kfree(agp_be);
                return NULL;
        }
 
index a066513093880a218d185624589ec07efce66b0b..214b7992a3aa74296eeb2a083b28398c08c3cb4d 100644 (file)
@@ -351,9 +351,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
 
 moved:
        if (bo->evicted) {
-               ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
-               if (ret)
-                       pr_err("Can not flush read caches\n");
+               if (bdev->driver->invalidate_caches) {
+                       ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
+                       if (ret)
+                               pr_err("Can not flush read caches\n");
+               }
                bo->evicted = false;
        }
 
index 801231c9ae483980afe0e93a0af73a7f07123864..0ce48e5a9cb4a70b56461f0ceb529e2c48ed58aa 100644 (file)
@@ -339,11 +339,13 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
        vma->vm_private_data = bo;
 
        /*
-        * PFNMAP is faster than MIXEDMAP due to reduced page
-        * administration. So use MIXEDMAP only if private VMA, where
-        * we need to support COW.
+        * We'd like to use VM_PFNMAP on shared mappings, where
+        * (vma->vm_flags & VM_SHARED) != 0, for performance reasons,
+        * but for some reason VM_PFNMAP + x86 PAT + write-combine is very
+        * bad for performance. Until that has been sorted out, use
+        * VM_MIXEDMAP on all mappings. See freedesktop.org bug #75719
         */
-       vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP;
+       vma->vm_flags |= VM_MIXEDMAP;
        vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
        return 0;
 out_unref:
@@ -359,7 +361,7 @@ int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo)
 
        vma->vm_ops = &ttm_bo_vm_ops;
        vma->vm_private_data = ttm_bo_reference(bo);
-       vma->vm_flags |= (vma->vm_flags & VM_SHARED) ? VM_PFNMAP : VM_MIXEDMAP;
+       vma->vm_flags |= VM_MIXEDMAP;
        vma->vm_flags |= VM_IO | VM_DONTEXPAND;
        return 0;
 }
index 37079859afc86e6cef120cd4d8a924388c3f6e3b..53b51c4e671a76cfc7f01cf73c5bba39531ead74 100644 (file)
@@ -292,7 +292,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
 
                if (ret == 0) {
                        ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
-                       if (!kref_get_unless_zero(&ref->kref)) {
+                       if (kref_get_unless_zero(&ref->kref)) {
                                rcu_read_unlock();
                                break;
                        }
index 9af99084b344413dcb07c2a368916bff647fc119..75f319090043a69021467e0d8fc9840fa796067d 100644 (file)
@@ -380,6 +380,9 @@ static void ttm_tt_clear_mapping(struct ttm_tt *ttm)
        pgoff_t i;
        struct page **page = ttm->pages;
 
+       if (ttm->page_flags & TTM_PAGE_FLAG_SG)
+               return;
+
        for (i = 0; i < ttm->num_pages; ++i) {
                (*page)->mapping = NULL;
                (*page++)->index = 0;
index 8d67b943ac05ce2d1dd44597d00a1e5a07fd9bdb..0394811251bd7e8dd75159d9d01b045d089d2290 100644 (file)
@@ -177,8 +177,10 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj)
        if (obj->vmapping)
                udl_gem_vunmap(obj);
 
-       if (gem_obj->import_attach)
+       if (gem_obj->import_attach) {
                drm_prime_gem_destroy(gem_obj, obj->sg);
+               put_device(gem_obj->dev->dev);
+       }
 
        if (obj->pages)
                udl_gem_put_pages(obj);
@@ -256,9 +258,12 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
        int ret;
 
        /* need to attach */
+       get_device(dev->dev);
        attach = dma_buf_attach(dma_buf, dev->dev);
-       if (IS_ERR(attach))
+       if (IS_ERR(attach)) {
+               put_device(dev->dev);
                return ERR_CAST(attach);
+       }
 
        get_dma_buf(dma_buf);
 
@@ -282,6 +287,6 @@ fail_unmap:
 fail_detach:
        dma_buf_detach(dma_buf, attach);
        dma_buf_put(dma_buf);
-
+       put_device(dev->dev);
        return ERR_PTR(ret);
 }
index d95335cb90bd4f30f7b7cdcf601028611986d802..f58dc7dd15c576ad2e4e0a702ee6aea1bffb01ce 100644 (file)
@@ -261,12 +261,7 @@ typedef enum SVGA3dSurfaceFormat {
    /* Planar video formats. */
    SVGA3D_YV12                         = 121,
 
-   /* Shader constant formats. */
-   SVGA3D_SURFACE_SHADERCONST_FLOAT    = 122,
-   SVGA3D_SURFACE_SHADERCONST_INT      = 123,
-   SVGA3D_SURFACE_SHADERCONST_BOOL     = 124,
-
-   SVGA3D_FORMAT_MAX                   = 125,
+   SVGA3D_FORMAT_MAX                   = 122,
 } SVGA3dSurfaceFormat;
 
 typedef uint32 SVGA3dColor; /* a, r, g, b */
@@ -1223,9 +1218,19 @@ typedef enum {
 #define SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL 1129
 
 #define SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE  1130
-
+#define SVGA_3D_CMD_GB_SCREEN_DMA               1131
+#define SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH  1132
+#define SVGA_3D_CMD_GB_MOB_FENCE                1133
+#define SVGA_3D_CMD_DEFINE_GB_SURFACE_V2        1134
 #define SVGA_3D_CMD_DEFINE_GB_MOB64          1135
 #define SVGA_3D_CMD_REDEFINE_GB_MOB64        1136
+#define SVGA_3D_CMD_NOP_ERROR                1137
+
+#define SVGA_3D_CMD_RESERVED1                1138
+#define SVGA_3D_CMD_RESERVED2                1139
+#define SVGA_3D_CMD_RESERVED3                1140
+#define SVGA_3D_CMD_RESERVED4                1141
+#define SVGA_3D_CMD_RESERVED5                1142
 
 #define SVGA_3D_CMD_MAX                      1142
 #define SVGA_3D_CMD_FUTURE_MAX               3000
@@ -1973,8 +1978,7 @@ struct {
    uint32 sizeInBytes;
    uint32 validSizeInBytes;
    SVGAMobFormat ptDepth;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdSetOTableBase;  /* SVGA_3D_CMD_SET_OTABLE_BASE */
 
 typedef
@@ -1984,15 +1988,13 @@ struct {
    uint32 sizeInBytes;
    uint32 validSizeInBytes;
    SVGAMobFormat ptDepth;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdSetOTableBase64;  /* SVGA_3D_CMD_SET_OTABLE_BASE64 */
 
 typedef
 struct {
    SVGAOTableType type;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdReadbackOTable;  /* SVGA_3D_CMD_READBACK_OTABLE */
 
 /*
@@ -2005,8 +2007,7 @@ struct SVGA3dCmdDefineGBMob {
    SVGAMobFormat ptDepth;
    PPN base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
 
 
@@ -2017,8 +2018,7 @@ SVGA3dCmdDefineGBMob;   /* SVGA_3D_CMD_DEFINE_GB_MOB */
 typedef
 struct SVGA3dCmdDestroyGBMob {
    SVGAMobId mobid;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDestroyGBMob;   /* SVGA_3D_CMD_DESTROY_GB_MOB */
 
 /*
@@ -2031,8 +2031,7 @@ struct SVGA3dCmdRedefineGBMob {
    SVGAMobFormat ptDepth;
    PPN base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdRedefineGBMob;   /* SVGA_3D_CMD_REDEFINE_GB_MOB */
 
 /*
@@ -2045,8 +2044,7 @@ struct SVGA3dCmdDefineGBMob64 {
    SVGAMobFormat ptDepth;
    PPN64 base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdDefineGBMob64;   /* SVGA_3D_CMD_DEFINE_GB_MOB64 */
 
 /*
@@ -2059,8 +2057,7 @@ struct SVGA3dCmdRedefineGBMob64 {
    SVGAMobFormat ptDepth;
    PPN64 base;
    uint32 sizeInBytes;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
 
 /*
@@ -2070,8 +2067,7 @@ SVGA3dCmdRedefineGBMob64;   /* SVGA_3D_CMD_REDEFINE_GB_MOB64 */
 typedef
 struct SVGA3dCmdUpdateGBMobMapping {
    SVGAMobId mobid;
-}
-__attribute__((__packed__))
+} __packed
 SVGA3dCmdUpdateGBMobMapping;   /* SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING */
 
 /*
@@ -2087,7 +2083,8 @@ struct SVGA3dCmdDefineGBSurface {
    uint32 multisampleCount;
    SVGA3dTextureFilter autogenFilter;
    SVGA3dSize size;
-} SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
+} __packed
+SVGA3dCmdDefineGBSurface;   /* SVGA_3D_CMD_DEFINE_GB_SURFACE */
 
 /*
  * Destroy a guest-backed surface.
@@ -2096,7 +2093,8 @@ struct SVGA3dCmdDefineGBSurface {
 typedef
 struct SVGA3dCmdDestroyGBSurface {
    uint32 sid;
-} SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
+} __packed
+SVGA3dCmdDestroyGBSurface;   /* SVGA_3D_CMD_DESTROY_GB_SURFACE */
 
 /*
  * Bind a guest-backed surface to an object.
@@ -2106,7 +2104,8 @@ typedef
 struct SVGA3dCmdBindGBSurface {
    uint32 sid;
    SVGAMobId mobid;
-} SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
+} __packed
+SVGA3dCmdBindGBSurface;   /* SVGA_3D_CMD_BIND_GB_SURFACE */
 
 /*
  * Conditionally bind a mob to a guest backed surface if testMobid
@@ -2123,7 +2122,7 @@ struct{
    SVGAMobId testMobid;
    SVGAMobId mobid;
    uint32 flags;
-}
+} __packed
 SVGA3dCmdCondBindGBSurface;          /* SVGA_3D_CMD_COND_BIND_GB_SURFACE */
 
 /*
@@ -2135,7 +2134,8 @@ typedef
 struct SVGA3dCmdUpdateGBImage {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
-} SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
+} __packed
+SVGA3dCmdUpdateGBImage;   /* SVGA_3D_CMD_UPDATE_GB_IMAGE */
 
 /*
  * Update an entire guest-backed surface.
@@ -2145,7 +2145,8 @@ struct SVGA3dCmdUpdateGBImage {
 typedef
 struct SVGA3dCmdUpdateGBSurface {
    uint32 sid;
-} SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
+} __packed
+SVGA3dCmdUpdateGBSurface;   /* SVGA_3D_CMD_UPDATE_GB_SURFACE */
 
 /*
  * Readback an image in a guest-backed surface.
@@ -2155,7 +2156,8 @@ struct SVGA3dCmdUpdateGBSurface {
 typedef
 struct SVGA3dCmdReadbackGBImage {
    SVGA3dSurfaceImageId image;
-} SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
+} __packed
+SVGA3dCmdReadbackGBImage;   /* SVGA_3D_CMD_READBACK_GB_IMAGE*/
 
 /*
  * Readback an entire guest-backed surface.
@@ -2165,7 +2167,8 @@ struct SVGA3dCmdReadbackGBImage {
 typedef
 struct SVGA3dCmdReadbackGBSurface {
    uint32 sid;
-} SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
+} __packed
+SVGA3dCmdReadbackGBSurface;   /* SVGA_3D_CMD_READBACK_GB_SURFACE */
 
 /*
  * Readback a sub rect of an image in a guest-backed surface.  After
@@ -2179,7 +2182,7 @@ struct SVGA3dCmdReadbackGBImagePartial {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
    uint32 invertBox;
-}
+} __packed
 SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
 
 /*
@@ -2190,7 +2193,8 @@ SVGA3dCmdReadbackGBImagePartial; /* SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL */
 typedef
 struct SVGA3dCmdInvalidateGBImage {
    SVGA3dSurfaceImageId image;
-} SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
+} __packed
+SVGA3dCmdInvalidateGBImage;   /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE */
 
 /*
  * Invalidate an entire guest-backed surface.
@@ -2200,7 +2204,8 @@ struct SVGA3dCmdInvalidateGBImage {
 typedef
 struct SVGA3dCmdInvalidateGBSurface {
    uint32 sid;
-} SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
+} __packed
+SVGA3dCmdInvalidateGBSurface; /* SVGA_3D_CMD_INVALIDATE_GB_SURFACE */
 
 /*
  * Invalidate a sub rect of an image in a guest-backed surface.  After
@@ -2214,7 +2219,7 @@ struct SVGA3dCmdInvalidateGBImagePartial {
    SVGA3dSurfaceImageId image;
    SVGA3dBox box;
    uint32 invertBox;
-}
+} __packed
 SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
 
 /*
@@ -2224,7 +2229,8 @@ SVGA3dCmdInvalidateGBImagePartial; /* SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL */
 typedef
 struct SVGA3dCmdDefineGBContext {
    uint32 cid;
-} SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
+} __packed
+SVGA3dCmdDefineGBContext;   /* SVGA_3D_CMD_DEFINE_GB_CONTEXT */
 
 /*
  * Destroy a guest-backed context.
@@ -2233,7 +2239,8 @@ struct SVGA3dCmdDefineGBContext {
 typedef
 struct SVGA3dCmdDestroyGBContext {
    uint32 cid;
-} SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
+} __packed
+SVGA3dCmdDestroyGBContext;   /* SVGA_3D_CMD_DESTROY_GB_CONTEXT */
 
 /*
  * Bind a guest-backed context.
@@ -2252,7 +2259,8 @@ struct SVGA3dCmdBindGBContext {
    uint32 cid;
    SVGAMobId mobid;
    uint32 validContents;
-} SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
+} __packed
+SVGA3dCmdBindGBContext;   /* SVGA_3D_CMD_BIND_GB_CONTEXT */
 
 /*
  * Readback a guest-backed context.
@@ -2262,7 +2270,8 @@ struct SVGA3dCmdBindGBContext {
 typedef
 struct SVGA3dCmdReadbackGBContext {
    uint32 cid;
-} SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
+} __packed
+SVGA3dCmdReadbackGBContext;   /* SVGA_3D_CMD_READBACK_GB_CONTEXT */
 
 /*
  * Invalidate a guest-backed context.
@@ -2270,7 +2279,8 @@ struct SVGA3dCmdReadbackGBContext {
 typedef
 struct SVGA3dCmdInvalidateGBContext {
    uint32 cid;
-} SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
+} __packed
+SVGA3dCmdInvalidateGBContext;   /* SVGA_3D_CMD_INVALIDATE_GB_CONTEXT */
 
 /*
  * Define a guest-backed shader.
@@ -2281,7 +2291,8 @@ struct SVGA3dCmdDefineGBShader {
    uint32 shid;
    SVGA3dShaderType type;
    uint32 sizeInBytes;
-} SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
+} __packed
+SVGA3dCmdDefineGBShader;   /* SVGA_3D_CMD_DEFINE_GB_SHADER */
 
 /*
  * Bind a guest-backed shader.
@@ -2291,7 +2302,8 @@ typedef struct SVGA3dCmdBindGBShader {
    uint32 shid;
    SVGAMobId mobid;
    uint32 offsetInBytes;
-} SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
+} __packed
+SVGA3dCmdBindGBShader;   /* SVGA_3D_CMD_BIND_GB_SHADER */
 
 /*
  * Destroy a guest-backed shader.
@@ -2299,7 +2311,8 @@ typedef struct SVGA3dCmdBindGBShader {
 
 typedef struct SVGA3dCmdDestroyGBShader {
    uint32 shid;
-} SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
+} __packed
+SVGA3dCmdDestroyGBShader;   /* SVGA_3D_CMD_DESTROY_GB_SHADER */
 
 typedef
 struct {
@@ -2314,14 +2327,16 @@ struct {
     * Note that FLOAT and INT constants are 4-dwords in length, while
     * BOOL constants are 1-dword in length.
     */
-} SVGA3dCmdSetGBShaderConstInline;
+} __packed
+SVGA3dCmdSetGBShaderConstInline;
 /* SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE */
 
 typedef
 struct {
    uint32               cid;
    SVGA3dQueryType      type;
-} SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
+} __packed
+SVGA3dCmdBeginGBQuery;           /* SVGA_3D_CMD_BEGIN_GB_QUERY */
 
 typedef
 struct {
@@ -2329,7 +2344,8 @@ struct {
    SVGA3dQueryType      type;
    SVGAMobId mobid;
    uint32 offset;
-} SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
+} __packed
+SVGA3dCmdEndGBQuery;                  /* SVGA_3D_CMD_END_GB_QUERY */
 
 
 /*
@@ -2346,21 +2362,22 @@ struct {
    SVGA3dQueryType      type;
    SVGAMobId mobid;
    uint32 offset;
-} SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
+} __packed
+SVGA3dCmdWaitForGBQuery;          /* SVGA_3D_CMD_WAIT_FOR_GB_QUERY */
 
 typedef
 struct {
    SVGAMobId mobid;
    uint32 fbOffset;
    uint32 initalized;
-}
+} __packed
 SVGA3dCmdEnableGart;              /* SVGA_3D_CMD_ENABLE_GART */
 
 typedef
 struct {
    SVGAMobId mobid;
    uint32 gartOffset;
-}
+} __packed
 SVGA3dCmdMapMobIntoGart;          /* SVGA_3D_CMD_MAP_MOB_INTO_GART */
 
 
@@ -2368,7 +2385,7 @@ typedef
 struct {
    uint32 gartOffset;
    uint32 numPages;
-}
+} __packed
 SVGA3dCmdUnmapGartRange;          /* SVGA_3D_CMD_UNMAP_GART_RANGE */
 
 
@@ -2385,27 +2402,27 @@ struct {
    int32 xRoot;
    int32 yRoot;
    uint32 flags;
-}
+} __packed
 SVGA3dCmdDefineGBScreenTarget;    /* SVGA_3D_CMD_DEFINE_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
-}
+} __packed
 SVGA3dCmdDestroyGBScreenTarget;  /* SVGA_3D_CMD_DESTROY_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
    SVGA3dSurfaceImageId image;
-}
+} __packed
 SVGA3dCmdBindGBScreenTarget;  /* SVGA_3D_CMD_BIND_GB_SCREENTARGET */
 
 typedef
 struct {
    uint32 stid;
    SVGA3dBox box;
-}
+} __packed
 SVGA3dCmdUpdateGBScreenTarget;  /* SVGA_3D_CMD_UPDATE_GB_SCREENTARGET */
 
 /*
@@ -2583,4 +2600,28 @@ typedef union {
    float  f;
 } SVGA3dDevCapResult;
 
+typedef enum {
+   SVGA3DCAPS_RECORD_UNKNOWN        = 0,
+   SVGA3DCAPS_RECORD_DEVCAPS_MIN    = 0x100,
+   SVGA3DCAPS_RECORD_DEVCAPS        = 0x100,
+   SVGA3DCAPS_RECORD_DEVCAPS_MAX    = 0x1ff,
+} SVGA3dCapsRecordType;
+
+typedef
+struct SVGA3dCapsRecordHeader {
+   uint32 length;
+   SVGA3dCapsRecordType type;
+}
+SVGA3dCapsRecordHeader;
+
+typedef
+struct SVGA3dCapsRecord {
+   SVGA3dCapsRecordHeader header;
+   uint32 data[1];
+}
+SVGA3dCapsRecord;
+
+
+typedef uint32 SVGA3dCapPair[2];
+
 #endif /* _SVGA3D_REG_H_ */
index 8369c3ba10fe5119ea09ba713f6bd1e5cb81f9cf..ef3385096145586fa7f148944b518b93e61d2974 100644 (file)
 
 #define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
 #define max_t(type, x, y)  ((x) > (y) ? (x) : (y))
+#define min_t(type, x, y)  ((x) < (y) ? (x) : (y))
 #define surf_size_struct SVGA3dSize
 #define u32 uint32
+#define u64 uint64_t
+#define U32_MAX ((u32)~0U)
 
 #endif /* __KERNEL__ */
 
@@ -704,8 +707,8 @@ static const struct svga3d_surface_desc svga3d_surface_descs[] = {
 
 static inline u32 clamped_umul32(u32 a, u32 b)
 {
-       uint64_t tmp = (uint64_t) a*b;
-       return (tmp > (uint64_t) ((u32) -1)) ? (u32) -1 : tmp;
+       u64 tmp = (u64) a*b;
+       return (tmp > (u64) U32_MAX) ? U32_MAX : tmp;
 }
 
 static inline const struct svga3d_surface_desc *
@@ -834,7 +837,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
                                  bool cubemap)
 {
        const struct svga3d_surface_desc *desc = svga3dsurface_get_desc(format);
-       u32 total_size = 0;
+       u64 total_size = 0;
        u32 mip;
 
        for (mip = 0; mip < num_mip_levels; mip++) {
@@ -847,7 +850,7 @@ svga3dsurface_get_serialized_size(SVGA3dSurfaceFormat format,
        if (cubemap)
                total_size *= SVGA3D_MAX_SURFACE_FACES;
 
-       return total_size;
+       return (u32) min_t(u64, total_size, (u64) U32_MAX);
 }
 
 
index 71defa4d2d7528a247b8e985a7b14cd1197e2a58..11323dd5196f495e5f2dd24b388c1720f3b6c1ce 100644 (file)
@@ -169,10 +169,17 @@ enum {
    SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
    SVGA_REG_GMRS_MAX_PAGES = 46,    /* Maximum number of 4KB pages for all GMRs */
    SVGA_REG_MEMORY_SIZE = 47,       /* Total dedicated device memory excluding FIFO */
+   SVGA_REG_COMMAND_LOW = 48,       /* Lower 32 bits and submits commands */
+   SVGA_REG_COMMAND_HIGH = 49,      /* Upper 32 bits of command buffer PA */
    SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM = 50,   /* Max primary memory */
    SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB = 51, /* Suggested limit on mob mem */
    SVGA_REG_DEV_CAP = 52,           /* Write dev cap index, read value */
-   SVGA_REG_TOP = 53,               /* Must be 1 more than the last register */
+   SVGA_REG_CMD_PREPEND_LOW = 53,
+   SVGA_REG_CMD_PREPEND_HIGH = 54,
+   SVGA_REG_SCREENTARGET_MAX_WIDTH = 55,
+   SVGA_REG_SCREENTARGET_MAX_HEIGHT = 56,
+   SVGA_REG_MOB_MAX_SIZE = 57,
+   SVGA_REG_TOP = 58,               /* Must be 1 more than the last register */
 
    SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
    /* Next 768 (== 256*3) registers exist for colormap */
index 82c41daebc0e35be6fb3629b602a083a6520f6a3..1e80152674b50ed62a73e3544c19855de29af070 100644 (file)
@@ -37,7 +37,7 @@ struct vmw_user_context {
 
 
 
-typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *);
+typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
 
 static void vmw_user_context_free(struct vmw_resource *res);
 static struct vmw_resource *
@@ -50,9 +50,11 @@ static int vmw_gb_context_unbind(struct vmw_resource *res,
                                 bool readback,
                                 struct ttm_validate_buffer *val_buf);
 static int vmw_gb_context_destroy(struct vmw_resource *res);
-static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi);
-static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi);
-static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi);
+static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind);
+static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
+                                          bool rebind);
+static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind);
+static void vmw_context_binding_state_scrub(struct vmw_ctx_binding_state *cbs);
 static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs);
 static uint64_t vmw_user_context_size;
 
@@ -111,10 +113,14 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
 
        if (res->func->destroy == vmw_gb_context_destroy) {
                mutex_lock(&dev_priv->cmdbuf_mutex);
+               mutex_lock(&dev_priv->binding_mutex);
+               (void) vmw_context_binding_state_kill
+                       (&container_of(res, struct vmw_user_context, res)->cbs);
                (void) vmw_gb_context_destroy(res);
                if (dev_priv->pinned_bo != NULL &&
                    !dev_priv->query_cid_valid)
                        __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
+               mutex_unlock(&dev_priv->binding_mutex);
                mutex_unlock(&dev_priv->cmdbuf_mutex);
                return;
        }
@@ -328,7 +334,7 @@ static int vmw_gb_context_unbind(struct vmw_resource *res,
        BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
 
        mutex_lock(&dev_priv->binding_mutex);
-       vmw_context_binding_state_kill(&uctx->cbs);
+       vmw_context_binding_state_scrub(&uctx->cbs);
 
        submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
 
@@ -378,10 +384,6 @@ static int vmw_gb_context_destroy(struct vmw_resource *res)
                SVGA3dCmdHeader header;
                SVGA3dCmdDestroyGBContext body;
        } *cmd;
-       struct vmw_user_context *uctx =
-               container_of(res, struct vmw_user_context, res);
-
-       BUG_ON(!list_empty(&uctx->cbs.list));
 
        if (likely(res->id == -1))
                return 0;
@@ -528,8 +530,9 @@ out_unlock:
  * vmw_context_scrub_shader - scrub a shader binding from a context.
  *
  * @bi: single binding information.
+ * @rebind: Whether to issue a bind instead of scrub command.
  */
-static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
+static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
 {
        struct vmw_private *dev_priv = bi->ctx->dev_priv;
        struct {
@@ -548,7 +551,7 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
        cmd->header.size = sizeof(cmd->body);
        cmd->body.cid = bi->ctx->id;
        cmd->body.type = bi->i1.shader_type;
-       cmd->body.shid = SVGA3D_INVALID_ID;
+       cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
        return 0;
@@ -559,8 +562,10 @@ static int vmw_context_scrub_shader(struct vmw_ctx_bindinfo *bi)
  * from a context.
  *
  * @bi: single binding information.
+ * @rebind: Whether to issue a bind instead of scrub command.
  */
-static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
+static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi,
+                                          bool rebind)
 {
        struct vmw_private *dev_priv = bi->ctx->dev_priv;
        struct {
@@ -579,7 +584,7 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
        cmd->header.size = sizeof(cmd->body);
        cmd->body.cid = bi->ctx->id;
        cmd->body.type = bi->i1.rt_type;
-       cmd->body.target.sid = SVGA3D_INVALID_ID;
+       cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
        cmd->body.target.face = 0;
        cmd->body.target.mipmap = 0;
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
@@ -591,11 +596,13 @@ static int vmw_context_scrub_render_target(struct vmw_ctx_bindinfo *bi)
  * vmw_context_scrub_texture - scrub a texture binding from a context.
  *
  * @bi: single binding information.
+ * @rebind: Whether to issue a bind instead of scrub command.
  *
  * TODO: Possibly complement this function with a function that takes
  * a list of texture bindings and combines them to a single command.
  */
-static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi)
+static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi,
+                                    bool rebind)
 {
        struct vmw_private *dev_priv = bi->ctx->dev_priv;
        struct {
@@ -619,7 +626,7 @@ static int vmw_context_scrub_texture(struct vmw_ctx_bindinfo *bi)
        cmd->body.c.cid = bi->ctx->id;
        cmd->body.s1.stage = bi->i1.texture_stage;
        cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
-       cmd->body.s1.value = (uint32) SVGA3D_INVALID_ID;
+       cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
        vmw_fifo_commit(dev_priv, sizeof(*cmd));
 
        return 0;
@@ -692,6 +699,7 @@ int vmw_context_binding_add(struct vmw_ctx_binding_state *cbs,
                vmw_context_binding_drop(loc);
 
        loc->bi = *bi;
+       loc->bi.scrubbed = false;
        list_add_tail(&loc->ctx_list, &cbs->list);
        INIT_LIST_HEAD(&loc->res_list);
 
@@ -727,12 +735,11 @@ static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
        if (loc->bi.ctx != NULL)
                vmw_context_binding_drop(loc);
 
-       loc->bi = *bi;
-       list_add_tail(&loc->ctx_list, &cbs->list);
-       if (bi->res != NULL)
+       if (bi->res != NULL) {
+               loc->bi = *bi;
+               list_add_tail(&loc->ctx_list, &cbs->list);
                list_add_tail(&loc->res_list, &bi->res->binding_head);
-       else
-               INIT_LIST_HEAD(&loc->res_list);
+       }
 }
 
 /**
@@ -746,7 +753,10 @@ static void vmw_context_binding_transfer(struct vmw_ctx_binding_state *cbs,
  */
 static void vmw_context_binding_kill(struct vmw_ctx_binding *cb)
 {
-       (void) vmw_scrub_funcs[cb->bi.bt](&cb->bi);
+       if (!cb->bi.scrubbed) {
+               (void) vmw_scrub_funcs[cb->bi.bt](&cb->bi, false);
+               cb->bi.scrubbed = true;
+       }
        vmw_context_binding_drop(cb);
 }
 
@@ -767,6 +777,27 @@ static void vmw_context_binding_state_kill(struct vmw_ctx_binding_state *cbs)
                vmw_context_binding_kill(entry);
 }
 
+/**
+ * vmw_context_binding_state_scrub - Scrub all bindings associated with a
+ * struct vmw_ctx_binding state structure.
+ *
+ * @cbs: Pointer to the context binding state tracker.
+ *
+ * Emits commands to scrub all bindings associated with the
+ * context binding state tracker.
+ */
+static void vmw_context_binding_state_scrub(struct vmw_ctx_binding_state *cbs)
+{
+       struct vmw_ctx_binding *entry;
+
+       list_for_each_entry(entry, &cbs->list, ctx_list) {
+               if (!entry->bi.scrubbed) {
+                       (void) vmw_scrub_funcs[entry->bi.bt](&entry->bi, false);
+                       entry->bi.scrubbed = true;
+               }
+       }
+}
+
 /**
  * vmw_context_binding_res_list_kill - Kill all bindings on a
  * resource binding list
@@ -784,6 +815,27 @@ void vmw_context_binding_res_list_kill(struct list_head *head)
                vmw_context_binding_kill(entry);
 }
 
+/**
+ * vmw_context_binding_res_list_scrub - Scrub all bindings on a
+ * resource binding list
+ *
+ * @head: list head of resource binding list
+ *
+ * Scrub all bindings associated with a specific resource. Typically
+ * called before the resource is evicted.
+ */
+void vmw_context_binding_res_list_scrub(struct list_head *head)
+{
+       struct vmw_ctx_binding *entry;
+
+       list_for_each_entry(entry, head, res_list) {
+               if (!entry->bi.scrubbed) {
+                       (void) vmw_scrub_funcs[entry->bi.bt](&entry->bi, false);
+                       entry->bi.scrubbed = true;
+               }
+       }
+}
+
 /**
  * vmw_context_binding_state_transfer - Commit staged binding info
  *
@@ -803,3 +855,50 @@ void vmw_context_binding_state_transfer(struct vmw_resource *ctx,
        list_for_each_entry_safe(entry, next, &from->list, ctx_list)
                vmw_context_binding_transfer(&uctx->cbs, &entry->bi);
 }
+
+/**
+ * vmw_context_rebind_all - Rebind all scrubbed bindings of a context
+ *
+ * @ctx: The context resource
+ *
+ * Walks through the context binding list and rebinds all scrubbed
+ * resources.
+ */
+int vmw_context_rebind_all(struct vmw_resource *ctx)
+{
+       struct vmw_ctx_binding *entry;
+       struct vmw_user_context *uctx =
+               container_of(ctx, struct vmw_user_context, res);
+       struct vmw_ctx_binding_state *cbs = &uctx->cbs;
+       int ret;
+
+       list_for_each_entry(entry, &cbs->list, ctx_list) {
+               if (likely(!entry->bi.scrubbed))
+                       continue;
+
+               if (WARN_ON(entry->bi.res == NULL || entry->bi.res->id ==
+                           SVGA3D_INVALID_ID))
+                       continue;
+
+               ret = vmw_scrub_funcs[entry->bi.bt](&entry->bi, true);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               entry->bi.scrubbed = false;
+       }
+
+       return 0;
+}
+
+/**
+ * vmw_context_binding_list - Return a list of context bindings
+ *
+ * @ctx: The context resource
+ *
+ * Returns the current list of bindings of the given context. Note that
+ * this list becomes stale as soon as the dev_priv::binding_mutex is unlocked.
+ */
+struct list_head *vmw_context_binding_list(struct vmw_resource *ctx)
+{
+       return &(container_of(ctx, struct vmw_user_context, res)->cbs.list);
+}
index 9893328f8fdc04750ec78538c4cdb2ba89ddae30..0083cbf99edfd33bdfac9ad819ff4b12b1e7b5d8 100644 (file)
@@ -667,6 +667,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                dev_priv->memory_size = 512*1024*1024;
        }
        dev_priv->max_mob_pages = 0;
+       dev_priv->max_mob_size = 0;
        if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) {
                uint64_t mem_size =
                        vmw_read(dev_priv,
@@ -676,6 +677,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                dev_priv->prim_bb_mem =
                        vmw_read(dev_priv,
                                 SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+               dev_priv->max_mob_size =
+                       vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
        } else
                dev_priv->prim_bb_mem = dev_priv->vram_size;
 
@@ -941,6 +944,7 @@ static void vmw_postclose(struct drm_device *dev,
                drm_master_put(&vmw_fp->locked_master);
        }
 
+       vmw_compat_shader_man_destroy(vmw_fp->shman);
        ttm_object_file_release(&vmw_fp->tfile);
        kfree(vmw_fp);
 }
@@ -960,11 +964,17 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
        if (unlikely(vmw_fp->tfile == NULL))
                goto out_no_tfile;
 
+       vmw_fp->shman = vmw_compat_shader_man_create(dev_priv);
+       if (IS_ERR(vmw_fp->shman))
+               goto out_no_shman;
+
        file_priv->driver_priv = vmw_fp;
        dev_priv->bdev.dev_mapping = dev->dev_mapping;
 
        return 0;
 
+out_no_shman:
+       ttm_object_file_release(&vmw_fp->tfile);
 out_no_tfile:
        kfree(vmw_fp);
        return ret;
index 554e7fa330824cc7a2f1d728f4299c19c8ab8fb5..07831554dad7acc3dae34f36e3a96e7b7f5299af 100644 (file)
@@ -40,7 +40,7 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20121114"
+#define VMWGFX_DRIVER_DATE "20140228"
 #define VMWGFX_DRIVER_MAJOR 2
 #define VMWGFX_DRIVER_MINOR 5
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMW_RES_FENCE ttm_driver_type3
 #define VMW_RES_SHADER ttm_driver_type4
 
+struct vmw_compat_shader_manager;
+
 struct vmw_fpriv {
        struct drm_master *locked_master;
        struct ttm_object_file *tfile;
        struct list_head fence_events;
+       bool gb_aware;
+       struct vmw_compat_shader_manager *shman;
 };
 
 struct vmw_dma_buffer {
@@ -272,6 +276,7 @@ struct vmw_ctx_bindinfo {
        struct vmw_resource *ctx;
        struct vmw_resource *res;
        enum vmw_ctx_binding_type bt;
+       bool scrubbed;
        union {
                SVGA3dShaderType shader_type;
                SVGA3dRenderTargetType rt_type;
@@ -318,7 +323,7 @@ struct vmw_sw_context{
        struct drm_open_hash res_ht;
        bool res_ht_initialized;
        bool kernel; /**< is the called made from the kernel */
-       struct ttm_object_file *tfile;
+       struct vmw_fpriv *fp;
        struct list_head validate_nodes;
        struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
        uint32_t cur_reloc;
@@ -336,6 +341,7 @@ struct vmw_sw_context{
        bool needs_post_query_barrier;
        struct vmw_resource *error_resource;
        struct vmw_ctx_binding_state staged_bindings;
+       struct list_head staged_shaders;
 };
 
 struct vmw_legacy_display;
@@ -380,6 +386,7 @@ struct vmw_private {
        uint32_t max_gmr_ids;
        uint32_t max_gmr_pages;
        uint32_t max_mob_pages;
+       uint32_t max_mob_size;
        uint32_t memory_size;
        bool has_gmr;
        bool has_mob;
@@ -569,6 +576,8 @@ struct vmw_user_resource_conv;
 
 extern void vmw_resource_unreference(struct vmw_resource **p_res);
 extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
+extern struct vmw_resource *
+vmw_resource_reference_unless_doomed(struct vmw_resource *res);
 extern int vmw_resource_validate(struct vmw_resource *res);
 extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup);
 extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
@@ -957,6 +966,9 @@ extern void
 vmw_context_binding_state_transfer(struct vmw_resource *res,
                                   struct vmw_ctx_binding_state *cbs);
 extern void vmw_context_binding_res_list_kill(struct list_head *head);
+extern void vmw_context_binding_res_list_scrub(struct list_head *head);
+extern int vmw_context_rebind_all(struct vmw_resource *ctx);
+extern struct list_head *vmw_context_binding_list(struct vmw_resource *ctx);
 
 /*
  * Surface management - vmwgfx_surface.c
@@ -991,6 +1003,28 @@ extern int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
                                   struct drm_file *file_priv);
 extern int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
                                    struct drm_file *file_priv);
+extern int vmw_compat_shader_lookup(struct vmw_compat_shader_manager *man,
+                                   SVGA3dShaderType shader_type,
+                                   u32 *user_key);
+extern void vmw_compat_shaders_commit(struct vmw_compat_shader_manager *man,
+                                     struct list_head *list);
+extern void vmw_compat_shaders_revert(struct vmw_compat_shader_manager *man,
+                                     struct list_head *list);
+extern int vmw_compat_shader_remove(struct vmw_compat_shader_manager *man,
+                                   u32 user_key,
+                                   SVGA3dShaderType shader_type,
+                                   struct list_head *list);
+extern int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
+                                u32 user_key, const void *bytecode,
+                                SVGA3dShaderType shader_type,
+                                size_t size,
+                                struct ttm_object_file *tfile,
+                                struct list_head *list);
+extern struct vmw_compat_shader_manager *
+vmw_compat_shader_man_create(struct vmw_private *dev_priv);
+extern void
+vmw_compat_shader_man_destroy(struct vmw_compat_shader_manager *man);
+
 
 /**
  * Inline helper functions
index 7a5f1eb55c5a0ad09adf8aa02c92367908c49c24..efb575a7996c2aed35e7046a47fd61acdbc167a0 100644 (file)
@@ -114,8 +114,10 @@ static void vmw_resource_list_unreserve(struct list_head *list,
                 * persistent context binding tracker.
                 */
                if (unlikely(val->staged_bindings)) {
-                       vmw_context_binding_state_transfer
-                               (val->res, val->staged_bindings);
+                       if (!backoff) {
+                               vmw_context_binding_state_transfer
+                                       (val->res, val->staged_bindings);
+                       }
                        kfree(val->staged_bindings);
                        val->staged_bindings = NULL;
                }
@@ -177,6 +179,44 @@ static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
        return 0;
 }
 
+/**
+ * vmw_resource_context_res_add - Put resources previously bound to a context on
+ * the validation list
+ *
+ * @dev_priv: Pointer to a device private structure
+ * @sw_context: Pointer to a software context used for this command submission
+ * @ctx: Pointer to the context resource
+ *
+ * This function puts all resources that were previously bound to @ctx on
+ * the resource validation list. This is part of the context state reemission
+ */
+static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
+                                       struct vmw_sw_context *sw_context,
+                                       struct vmw_resource *ctx)
+{
+       struct list_head *binding_list;
+       struct vmw_ctx_binding *entry;
+       int ret = 0;
+       struct vmw_resource *res;
+
+       mutex_lock(&dev_priv->binding_mutex);
+       binding_list = vmw_context_binding_list(ctx);
+
+       list_for_each_entry(entry, binding_list, ctx_list) {
+               res = vmw_resource_reference_unless_doomed(entry->bi.res);
+               if (unlikely(res == NULL))
+                       continue;
+
+               ret = vmw_resource_val_add(sw_context, entry->bi.res, NULL);
+               vmw_resource_unreference(&res);
+               if (unlikely(ret != 0))
+                       break;
+       }
+
+       mutex_unlock(&dev_priv->binding_mutex);
+       return ret;
+}
+
 /**
  * vmw_resource_relocation_add - Add a relocation to the relocation list
  *
@@ -233,8 +273,12 @@ static void vmw_resource_relocations_apply(uint32_t *cb,
 {
        struct vmw_resource_relocation *rel;
 
-       list_for_each_entry(rel, list, head)
-               cb[rel->offset] = rel->res->id;
+       list_for_each_entry(rel, list, head) {
+               if (likely(rel->res != NULL))
+                       cb[rel->offset] = rel->res->id;
+               else
+                       cb[rel->offset] = SVGA_3D_CMD_NOP;
+       }
 }
 
 static int vmw_cmd_invalid(struct vmw_private *dev_priv,
@@ -379,22 +423,27 @@ static int vmw_resources_validate(struct vmw_sw_context *sw_context)
 }
 
 /**
- * vmw_cmd_res_check - Check that a resource is present and if so, put it
+ * vmw_cmd_compat_res_check - Check that a resource is present and if so, put it
  * on the resource validate list unless it's already there.
  *
  * @dev_priv: Pointer to a device private structure.
  * @sw_context: Pointer to the software context.
  * @res_type: Resource type.
  * @converter: User-space visisble type specific information.
- * @id: Pointer to the location in the command buffer currently being
+ * @id: user-space resource id handle.
+ * @id_loc: Pointer to the location in the command buffer currently being
  * parsed from where the user-space resource id handle is located.
+ * @p_val: Pointer to pointer to resource validalidation node. Populated
+ * on exit.
  */
-static int vmw_cmd_res_check(struct vmw_private *dev_priv,
-                            struct vmw_sw_context *sw_context,
-                            enum vmw_res_type res_type,
-                            const struct vmw_user_resource_conv *converter,
-                            uint32_t *id,
-                            struct vmw_resource_val_node **p_val)
+static int
+vmw_cmd_compat_res_check(struct vmw_private *dev_priv,
+                        struct vmw_sw_context *sw_context,
+                        enum vmw_res_type res_type,
+                        const struct vmw_user_resource_conv *converter,
+                        uint32_t id,
+                        uint32_t *id_loc,
+                        struct vmw_resource_val_node **p_val)
 {
        struct vmw_res_cache_entry *rcache =
                &sw_context->res_cache[res_type];
@@ -402,7 +451,7 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
        struct vmw_resource_val_node *node;
        int ret;
 
-       if (*id == SVGA3D_INVALID_ID) {
+       if (id == SVGA3D_INVALID_ID) {
                if (p_val)
                        *p_val = NULL;
                if (res_type == vmw_res_context) {
@@ -417,7 +466,7 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
         * resource
         */
 
-       if (likely(rcache->valid && *id == rcache->handle)) {
+       if (likely(rcache->valid && id == rcache->handle)) {
                const struct vmw_resource *res = rcache->res;
 
                rcache->node->first_usage = false;
@@ -426,28 +475,28 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
 
                return vmw_resource_relocation_add
                        (&sw_context->res_relocations, res,
-                        id - sw_context->buf_start);
+                        id_loc - sw_context->buf_start);
        }
 
        ret = vmw_user_resource_lookup_handle(dev_priv,
-                                             sw_context->tfile,
-                                             *id,
+                                             sw_context->fp->tfile,
+                                             id,
                                              converter,
                                              &res);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not find or use resource 0x%08x.\n",
-                         (unsigned) *id);
+                         (unsigned) id);
                dump_stack();
                return ret;
        }
 
        rcache->valid = true;
        rcache->res = res;
-       rcache->handle = *id;
+       rcache->handle = id;
 
        ret = vmw_resource_relocation_add(&sw_context->res_relocations,
                                          res,
-                                         id - sw_context->buf_start);
+                                         id_loc - sw_context->buf_start);
        if (unlikely(ret != 0))
                goto out_no_reloc;
 
@@ -459,7 +508,11 @@ static int vmw_cmd_res_check(struct vmw_private *dev_priv,
        if (p_val)
                *p_val = node;
 
-       if (node->first_usage && res_type == vmw_res_context) {
+       if (dev_priv->has_mob && node->first_usage &&
+           res_type == vmw_res_context) {
+               ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
+               if (unlikely(ret != 0))
+                       goto out_no_reloc;
                node->staged_bindings =
                        kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
                if (node->staged_bindings == NULL) {
@@ -480,6 +533,59 @@ out_no_reloc:
        return ret;
 }
 
+/**
+ * vmw_cmd_res_check - Check that a resource is present and if so, put it
+ * on the resource validate list unless it's already there.
+ *
+ * @dev_priv: Pointer to a device private structure.
+ * @sw_context: Pointer to the software context.
+ * @res_type: Resource type.
+ * @converter: User-space visisble type specific information.
+ * @id_loc: Pointer to the location in the command buffer currently being
+ * parsed from where the user-space resource id handle is located.
+ * @p_val: Pointer to pointer to resource validalidation node. Populated
+ * on exit.
+ */
+static int
+vmw_cmd_res_check(struct vmw_private *dev_priv,
+                 struct vmw_sw_context *sw_context,
+                 enum vmw_res_type res_type,
+                 const struct vmw_user_resource_conv *converter,
+                 uint32_t *id_loc,
+                 struct vmw_resource_val_node **p_val)
+{
+       return vmw_cmd_compat_res_check(dev_priv, sw_context, res_type,
+                                       converter, *id_loc, id_loc, p_val);
+}
+
+/**
+ * vmw_rebind_contexts - Rebind all resources previously bound to
+ * referenced contexts.
+ *
+ * @sw_context: Pointer to the software context.
+ *
+ * Rebind context binding points that have been scrubbed because of eviction.
+ */
+static int vmw_rebind_contexts(struct vmw_sw_context *sw_context)
+{
+       struct vmw_resource_val_node *val;
+       int ret;
+
+       list_for_each_entry(val, &sw_context->resource_list, head) {
+               if (likely(!val->staged_bindings))
+                       continue;
+
+               ret = vmw_context_rebind_all(val->res);
+               if (unlikely(ret != 0)) {
+                       if (ret != -ERESTARTSYS)
+                               DRM_ERROR("Failed to rebind context.\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * vmw_cmd_cid_check - Check a command header for valid context information.
  *
@@ -496,7 +602,7 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
 {
        struct vmw_cid_cmd {
                SVGA3dCmdHeader header;
-               __le32 cid;
+               uint32_t cid;
        } *cmd;
 
        cmd = container_of(header, struct vmw_cid_cmd, header);
@@ -767,7 +873,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
        struct vmw_relocation *reloc;
        int ret;
 
-       ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
+       ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not find or use MOB buffer.\n");
                return -EINVAL;
@@ -828,7 +934,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
        struct vmw_relocation *reloc;
        int ret;
 
-       ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
+       ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not find or use GMR region.\n");
                return -EINVAL;
@@ -1127,7 +1233,8 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
 
        srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
 
-       vmw_kms_cursor_snoop(srf, sw_context->tfile, &vmw_bo->base, header);
+       vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base,
+                            header);
 
 out_no_surface:
        vmw_dmabuf_unreference(&vmw_bo);
@@ -1478,6 +1585,98 @@ static int vmw_cmd_invalidate_gb_surface(struct vmw_private *dev_priv,
                                 &cmd->body.sid, NULL);
 }
 
+
+/**
+ * vmw_cmd_shader_define - Validate an SVGA_3D_CMD_SHADER_DEFINE
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
+                                struct vmw_sw_context *sw_context,
+                                SVGA3dCmdHeader *header)
+{
+       struct vmw_shader_define_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDefineShader body;
+       } *cmd;
+       int ret;
+       size_t size;
+
+       cmd = container_of(header, struct vmw_shader_define_cmd,
+                          header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               NULL);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (unlikely(!dev_priv->has_mob))
+               return 0;
+
+       size = cmd->header.size - sizeof(cmd->body);
+       ret = vmw_compat_shader_add(sw_context->fp->shman,
+                                   cmd->body.shid, cmd + 1,
+                                   cmd->body.type, size,
+                                   sw_context->fp->tfile,
+                                   &sw_context->staged_shaders);
+       if (unlikely(ret != 0))
+               return ret;
+
+       return vmw_resource_relocation_add(&sw_context->res_relocations,
+                                          NULL, &cmd->header.id -
+                                          sw_context->buf_start);
+
+       return 0;
+}
+
+/**
+ * vmw_cmd_shader_destroy - Validate an SVGA_3D_CMD_SHADER_DESTROY
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,
+                                 struct vmw_sw_context *sw_context,
+                                 SVGA3dCmdHeader *header)
+{
+       struct vmw_shader_destroy_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDestroyShader body;
+       } *cmd;
+       int ret;
+
+       cmd = container_of(header, struct vmw_shader_destroy_cmd,
+                          header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               NULL);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (unlikely(!dev_priv->has_mob))
+               return 0;
+
+       ret = vmw_compat_shader_remove(sw_context->fp->shman,
+                                      cmd->body.shid,
+                                      cmd->body.type,
+                                      &sw_context->staged_shaders);
+       if (unlikely(ret != 0))
+               return ret;
+
+       return vmw_resource_relocation_add(&sw_context->res_relocations,
+                                          NULL, &cmd->header.id -
+                                          sw_context->buf_start);
+
+       return 0;
+}
+
 /**
  * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER
  * command
@@ -1509,10 +1708,18 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
        if (dev_priv->has_mob) {
                struct vmw_ctx_bindinfo bi;
                struct vmw_resource_val_node *res_node;
-
-               ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader,
-                                       user_shader_converter,
-                                       &cmd->body.shid, &res_node);
+               u32 shid = cmd->body.shid;
+
+               if (shid != SVGA3D_INVALID_ID)
+                       (void) vmw_compat_shader_lookup(sw_context->fp->shman,
+                                                       cmd->body.type,
+                                                       &shid);
+
+               ret = vmw_cmd_compat_res_check(dev_priv, sw_context,
+                                              vmw_res_shader,
+                                              user_shader_converter,
+                                              shid,
+                                              &cmd->body.shid, &res_node);
                if (unlikely(ret != 0))
                        return ret;
 
@@ -1526,6 +1733,39 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
        return 0;
 }
 
+/**
+ * vmw_cmd_set_shader_const - Validate an SVGA_3D_CMD_SET_SHADER_CONST
+ * command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_set_shader_const(struct vmw_private *dev_priv,
+                                   struct vmw_sw_context *sw_context,
+                                   SVGA3dCmdHeader *header)
+{
+       struct vmw_set_shader_const_cmd {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdSetShaderConst body;
+       } *cmd;
+       int ret;
+
+       cmd = container_of(header, struct vmw_set_shader_const_cmd,
+                          header);
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
+                               user_context_converter, &cmd->body.cid,
+                               NULL);
+       if (unlikely(ret != 0))
+               return ret;
+
+       if (dev_priv->has_mob)
+               header->id = SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE;
+
+       return 0;
+}
+
 /**
  * vmw_cmd_bind_gb_shader - Validate an SVGA_3D_CMD_BIND_GB_SHADER
  * command
@@ -1595,7 +1835,7 @@ static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
        return 0;
 }
 
-static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
+static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
        VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid,
                    false, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid,
@@ -1634,14 +1874,14 @@ static const struct vmw_cmd_entry const vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
                    true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check,
                    false, false, false),
-       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check,
-                   true, true, false),
-       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check,
-                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_shader_define,
+                   true, false, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_shader_destroy,
+                   true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader,
                    true, false, false),
-       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check,
-                   true, true, false),
+       VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_set_shader_const,
+                   true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw,
                    true, false, false),
        VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check,
@@ -1792,6 +2032,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
                goto out_invalid;
 
        entry = &vmw_cmd_entries[cmd_id];
+       if (unlikely(!entry->func))
+               goto out_invalid;
+
        if (unlikely(!entry->user_allow && !sw_context->kernel))
                goto out_privileged;
 
@@ -2171,7 +2414,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        } else
                sw_context->kernel = true;
 
-       sw_context->tfile = vmw_fpriv(file_priv)->tfile;
+       sw_context->fp = vmw_fpriv(file_priv);
        sw_context->cur_reloc = 0;
        sw_context->cur_val_buf = 0;
        sw_context->fence_flags = 0;
@@ -2188,16 +2431,17 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                        goto out_unlock;
                sw_context->res_ht_initialized = true;
        }
+       INIT_LIST_HEAD(&sw_context->staged_shaders);
 
        INIT_LIST_HEAD(&resource_list);
        ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
                                command_size);
        if (unlikely(ret != 0))
-               goto out_err;
+               goto out_err_nores;
 
        ret = vmw_resources_reserve(sw_context);
        if (unlikely(ret != 0))
-               goto out_err;
+               goto out_err_nores;
 
        ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes);
        if (unlikely(ret != 0))
@@ -2225,6 +2469,12 @@ int vmw_execbuf_process(struct drm_file *file_priv,
                goto out_err;
        }
 
+       if (dev_priv->has_mob) {
+               ret = vmw_rebind_contexts(sw_context);
+               if (unlikely(ret != 0))
+                       goto out_unlock_binding;
+       }
+
        cmd = vmw_fifo_reserve(dev_priv, command_size);
        if (unlikely(cmd == NULL)) {
                DRM_ERROR("Failed reserving fifo space for commands.\n");
@@ -2276,6 +2526,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
        }
 
        list_splice_init(&sw_context->resource_list, &resource_list);
+       vmw_compat_shaders_commit(sw_context->fp->shman,
+                                 &sw_context->staged_shaders);
        mutex_unlock(&dev_priv->cmdbuf_mutex);
 
        /*
@@ -2289,10 +2541,11 @@ int vmw_execbuf_process(struct drm_file *file_priv,
 out_unlock_binding:
        mutex_unlock(&dev_priv->binding_mutex);
 out_err:
-       vmw_resource_relocations_free(&sw_context->res_relocations);
-       vmw_free_relocations(sw_context);
        ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes);
+out_err_nores:
        vmw_resource_list_unreserve(&sw_context->resource_list, true);
+       vmw_resource_relocations_free(&sw_context->res_relocations);
+       vmw_free_relocations(sw_context);
        vmw_clear_validations(sw_context);
        if (unlikely(dev_priv->pinned_bo != NULL &&
                     !dev_priv->query_cid_valid))
@@ -2301,6 +2554,8 @@ out_unlock:
        list_splice_init(&sw_context->resource_list, &resource_list);
        error_resource = sw_context->error_resource;
        sw_context->error_resource = NULL;
+       vmw_compat_shaders_revert(sw_context->fp->shman,
+                                 &sw_context->staged_shaders);
        mutex_unlock(&dev_priv->cmdbuf_mutex);
 
        /*
index 116c49736763ee81a4b4d664bfba2ab0a5e3d5cd..47b70949bf3af6683bb74552c0b91fa7b06d7a82 100644 (file)
 #include <drm/vmwgfx_drm.h>
 #include "vmwgfx_kms.h"
 
+struct svga_3d_compat_cap {
+       SVGA3dCapsRecordHeader header;
+       SVGA3dCapPair pairs[SVGA3D_DEVCAP_MAX];
+};
+
 int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct drm_vmw_getparam_arg *param =
            (struct drm_vmw_getparam_arg *)data;
+       struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
 
        switch (param->param) {
        case DRM_VMW_PARAM_NUM_STREAMS:
@@ -60,6 +66,11 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
                const struct vmw_fifo_state *fifo = &dev_priv->fifo;
 
+               if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) {
+                       param->value = SVGA3D_HWVERSION_WS8_B1;
+                       break;
+               }
+
                param->value =
                        ioread32(fifo_mem +
                                 ((fifo->capabilities &
@@ -69,19 +80,31 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                break;
        }
        case DRM_VMW_PARAM_MAX_SURF_MEMORY:
-               param->value = dev_priv->memory_size;
+               if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
+                   !vmw_fp->gb_aware)
+                       param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;
+               else
+                       param->value = dev_priv->memory_size;
                break;
        case DRM_VMW_PARAM_3D_CAPS_SIZE:
-               if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
-                       param->value = SVGA3D_DEVCAP_MAX;
+               if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
+                   vmw_fp->gb_aware)
+                       param->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
+               else if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
+                       param->value = sizeof(struct svga_3d_compat_cap) +
+                               sizeof(uint32_t);
                else
                        param->value = (SVGA_FIFO_3D_CAPS_LAST -
-                                       SVGA_FIFO_3D_CAPS + 1);
-               param->value *= sizeof(uint32_t);
+                                       SVGA_FIFO_3D_CAPS + 1) *
+                               sizeof(uint32_t);
                break;
        case DRM_VMW_PARAM_MAX_MOB_MEMORY:
+               vmw_fp->gb_aware = true;
                param->value = dev_priv->max_mob_pages * PAGE_SIZE;
                break;
+       case DRM_VMW_PARAM_MAX_MOB_SIZE:
+               param->value = dev_priv->max_mob_size;
+               break;
        default:
                DRM_ERROR("Illegal vmwgfx get param request: %d\n",
                          param->param);
@@ -91,6 +114,38 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
+                              size_t size)
+{
+       struct svga_3d_compat_cap *compat_cap =
+               (struct svga_3d_compat_cap *) bounce;
+       unsigned int i;
+       size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs);
+       unsigned int max_size;
+
+       if (size < pair_offset)
+               return -EINVAL;
+
+       max_size = (size - pair_offset) / sizeof(SVGA3dCapPair);
+
+       if (max_size > SVGA3D_DEVCAP_MAX)
+               max_size = SVGA3D_DEVCAP_MAX;
+
+       compat_cap->header.length =
+               (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32);
+       compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
+
+       mutex_lock(&dev_priv->hw_mutex);
+       for (i = 0; i < max_size; ++i) {
+               vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
+               compat_cap->pairs[i][0] = i;
+               compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+       }
+       mutex_unlock(&dev_priv->hw_mutex);
+
+       return 0;
+}
+
 
 int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
                         struct drm_file *file_priv)
@@ -104,41 +159,49 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        void *bounce;
        int ret;
        bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
+       struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
 
        if (unlikely(arg->pad64 != 0)) {
                DRM_ERROR("Illegal GET_3D_CAP argument.\n");
                return -EINVAL;
        }
 
-       if (gb_objects)
-               size = SVGA3D_DEVCAP_MAX;
+       if (gb_objects && vmw_fp->gb_aware)
+               size = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
+       else if (gb_objects)
+               size = sizeof(struct svga_3d_compat_cap) + sizeof(uint32_t);
        else
-               size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1);
-
-       size *= sizeof(uint32_t);
+               size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) *
+                       sizeof(uint32_t);
 
        if (arg->max_size < size)
                size = arg->max_size;
 
-       bounce = vmalloc(size);
+       bounce = vzalloc(size);
        if (unlikely(bounce == NULL)) {
                DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
                return -ENOMEM;
        }
 
-       if (gb_objects) {
-               int i;
+       if (gb_objects && vmw_fp->gb_aware) {
+               int i, num;
                uint32_t *bounce32 = (uint32_t *) bounce;
 
+               num = size / sizeof(uint32_t);
+               if (num > SVGA3D_DEVCAP_MAX)
+                       num = SVGA3D_DEVCAP_MAX;
+
                mutex_lock(&dev_priv->hw_mutex);
-               for (i = 0; i < SVGA3D_DEVCAP_MAX; ++i) {
+               for (i = 0; i < num; ++i) {
                        vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
                        *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
                }
                mutex_unlock(&dev_priv->hw_mutex);
-
+       } else if (gb_objects) {
+               ret = vmw_fill_compat_cap(dev_priv, bounce, size);
+               if (unlikely(ret != 0))
+                       goto out_err;
        } else {
-
                fifo_mem = dev_priv->mmio_virt;
                memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
        }
@@ -146,6 +209,7 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        ret = copy_to_user(buffer, bounce, size);
        if (ret)
                ret = -EFAULT;
+out_err:
        vfree(bounce);
 
        if (unlikely(ret != 0))
index 4910e7b8181111c63f0ceb586249b1f740409d95..04a64b8cd3cd4f17e00765efe2769e502c4b8240 100644 (file)
@@ -134,6 +134,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
        if (unlikely(cmd == NULL)) {
                DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
+               ret = -ENOMEM;
                goto out_no_fifo;
        }
 
@@ -187,18 +188,20 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv,
 
        bo = otable->page_table->pt_bo;
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-       if (unlikely(cmd == NULL))
-               DRM_ERROR("Failed reserving FIFO space for OTable setup.\n");
-
-       memset(cmd, 0, sizeof(*cmd));
-       cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
-       cmd->header.size = sizeof(cmd->body);
-       cmd->body.type = type;
-       cmd->body.baseAddress = 0;
-       cmd->body.sizeInBytes = 0;
-       cmd->body.validSizeInBytes = 0;
-       cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
-       vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       if (unlikely(cmd == NULL)) {
+               DRM_ERROR("Failed reserving FIFO space for OTable "
+                         "takedown.\n");
+       } else {
+               memset(cmd, 0, sizeof(*cmd));
+               cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
+               cmd->header.size = sizeof(cmd->body);
+               cmd->body.type = type;
+               cmd->body.baseAddress = 0;
+               cmd->body.sizeInBytes = 0;
+               cmd->body.validSizeInBytes = 0;
+               cmd->body.ptDepth = SVGA3D_MOBFMT_INVALID;
+               vmw_fifo_commit(dev_priv, sizeof(*cmd));
+       }
 
        if (bo) {
                int ret;
@@ -561,11 +564,12 @@ void vmw_mob_unbind(struct vmw_private *dev_priv,
        if (unlikely(cmd == NULL)) {
                DRM_ERROR("Failed reserving FIFO space for Memory "
                          "Object unbinding.\n");
+       } else {
+               cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
+               cmd->header.size = sizeof(cmd->body);
+               cmd->body.mobid = mob->id;
+               vmw_fifo_commit(dev_priv, sizeof(*cmd));
        }
-       cmd->header.id = SVGA_3D_CMD_DESTROY_GB_MOB;
-       cmd->header.size = sizeof(cmd->body);
-       cmd->body.mobid = mob->id;
-       vmw_fifo_commit(dev_priv, sizeof(*cmd));
        if (bo) {
                vmw_fence_single_bo(bo, NULL);
                ttm_bo_unreserve(bo);
index 6fdd82d42f6549d2af208516ad22b26d45785e28..9757b57f8388d7a29fa51d04f61f5076fd149793 100644 (file)
@@ -88,6 +88,11 @@ struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
        return res;
 }
 
+struct vmw_resource *
+vmw_resource_reference_unless_doomed(struct vmw_resource *res)
+{
+       return kref_get_unless_zero(&res->kref) ? res : NULL;
+}
 
 /**
  * vmw_resource_release_id - release a resource id to the id manager.
@@ -136,8 +141,12 @@ static void vmw_resource_release(struct kref *kref)
                vmw_dmabuf_unreference(&res->backup);
        }
 
-       if (likely(res->hw_destroy != NULL))
+       if (likely(res->hw_destroy != NULL)) {
                res->hw_destroy(res);
+               mutex_lock(&dev_priv->binding_mutex);
+               vmw_context_binding_res_list_kill(&res->binding_head);
+               mutex_unlock(&dev_priv->binding_mutex);
+       }
 
        id = res->id;
        if (res->res_free != NULL)
@@ -418,8 +427,7 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
        INIT_LIST_HEAD(&vmw_bo->res_list);
 
        ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-                         (user) ? ttm_bo_type_device :
-                         ttm_bo_type_kernel, placement,
+                         ttm_bo_type_device, placement,
                          0, interruptible,
                          NULL, acc_size, NULL, bo_free);
        return ret;
index 1457ec4b7125471d99aeac6da26009ee5009bc6a..ee3856578a12589d8b12e4133666d04134ad729a 100644 (file)
@@ -29,6 +29,8 @@
 #include "vmwgfx_resource_priv.h"
 #include "ttm/ttm_placement.h"
 
+#define VMW_COMPAT_SHADER_HT_ORDER 12
+
 struct vmw_shader {
        struct vmw_resource res;
        SVGA3dShaderType type;
@@ -40,6 +42,50 @@ struct vmw_user_shader {
        struct vmw_shader shader;
 };
 
+/**
+ * enum vmw_compat_shader_state - Staging state for compat shaders
+ */
+enum vmw_compat_shader_state {
+       VMW_COMPAT_COMMITED,
+       VMW_COMPAT_ADD,
+       VMW_COMPAT_DEL
+};
+
+/**
+ * struct vmw_compat_shader - Metadata for compat shaders.
+ *
+ * @handle: The TTM handle of the guest backed shader.
+ * @tfile: The struct ttm_object_file the guest backed shader is registered
+ * with.
+ * @hash: Hash item for lookup.
+ * @head: List head for staging lists or the compat shader manager list.
+ * @state: Staging state.
+ *
+ * The structure is protected by the cmdbuf lock.
+ */
+struct vmw_compat_shader {
+       u32 handle;
+       struct ttm_object_file *tfile;
+       struct drm_hash_item hash;
+       struct list_head head;
+       enum vmw_compat_shader_state state;
+};
+
+/**
+ * struct vmw_compat_shader_manager - Compat shader manager.
+ *
+ * @shaders: Hash table containing staged and commited compat shaders
+ * @list: List of commited shaders.
+ * @dev_priv: Pointer to a device private structure.
+ *
+ * @shaders and @list are protected by the cmdbuf mutex for now.
+ */
+struct vmw_compat_shader_manager {
+       struct drm_open_hash shaders;
+       struct list_head list;
+       struct vmw_private *dev_priv;
+};
+
 static void vmw_user_shader_free(struct vmw_resource *res);
 static struct vmw_resource *
 vmw_user_shader_base_to_res(struct ttm_base_object *base);
@@ -258,7 +304,7 @@ static int vmw_gb_shader_destroy(struct vmw_resource *res)
                return 0;
 
        mutex_lock(&dev_priv->binding_mutex);
-       vmw_context_binding_res_list_kill(&res->binding_head);
+       vmw_context_binding_res_list_scrub(&res->binding_head);
 
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
        if (unlikely(cmd == NULL)) {
@@ -325,13 +371,81 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
                                         TTM_REF_USAGE);
 }
 
+static int vmw_shader_alloc(struct vmw_private *dev_priv,
+                           struct vmw_dma_buffer *buffer,
+                           size_t shader_size,
+                           size_t offset,
+                           SVGA3dShaderType shader_type,
+                           struct ttm_object_file *tfile,
+                           u32 *handle)
+{
+       struct vmw_user_shader *ushader;
+       struct vmw_resource *res, *tmp;
+       int ret;
+
+       /*
+        * Approximate idr memory usage with 128 bytes. It will be limited
+        * by maximum number_of shaders anyway.
+        */
+       if (unlikely(vmw_user_shader_size == 0))
+               vmw_user_shader_size =
+                       ttm_round_pot(sizeof(struct vmw_user_shader)) + 128;
+
+       ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
+                                  vmw_user_shader_size,
+                                  false, true);
+       if (unlikely(ret != 0)) {
+               if (ret != -ERESTARTSYS)
+                       DRM_ERROR("Out of graphics memory for shader "
+                                 "creation.\n");
+               goto out;
+       }
+
+       ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
+       if (unlikely(ushader == NULL)) {
+               ttm_mem_global_free(vmw_mem_glob(dev_priv),
+                                   vmw_user_shader_size);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       res = &ushader->shader.res;
+       ushader->base.shareable = false;
+       ushader->base.tfile = NULL;
+
+       /*
+        * From here on, the destructor takes over resource freeing.
+        */
+
+       ret = vmw_gb_shader_init(dev_priv, res, shader_size,
+                                offset, shader_type, buffer,
+                                vmw_user_shader_free);
+       if (unlikely(ret != 0))
+               goto out;
+
+       tmp = vmw_resource_reference(res);
+       ret = ttm_base_object_init(tfile, &ushader->base, false,
+                                  VMW_RES_SHADER,
+                                  &vmw_user_shader_base_release, NULL);
+
+       if (unlikely(ret != 0)) {
+               vmw_resource_unreference(&tmp);
+               goto out_err;
+       }
+
+       if (handle)
+               *handle = ushader->base.hash.key;
+out_err:
+       vmw_resource_unreference(&res);
+out:
+       return ret;
+}
+
+
 int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_priv)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
-       struct vmw_user_shader *ushader;
-       struct vmw_resource *res;
-       struct vmw_resource *tmp;
        struct drm_vmw_shader_create_arg *arg =
                (struct drm_vmw_shader_create_arg *)data;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
@@ -373,69 +487,326 @@ int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
                goto out_bad_arg;
        }
 
-       /*
-        * Approximate idr memory usage with 128 bytes. It will be limited
-        * by maximum number_of shaders anyway.
-        */
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (unlikely(ret != 0))
+               goto out_bad_arg;
 
-       if (unlikely(vmw_user_shader_size == 0))
-               vmw_user_shader_size = ttm_round_pot(sizeof(*ushader))
-                       + 128;
+       ret = vmw_shader_alloc(dev_priv, buffer, arg->size, arg->offset,
+                              shader_type, tfile, &arg->shader_handle);
 
-       ret = ttm_read_lock(&vmaster->lock, true);
+       ttm_read_unlock(&vmaster->lock);
+out_bad_arg:
+       vmw_dmabuf_unreference(&buffer);
+       return ret;
+}
+
+/**
+ * vmw_compat_shader_lookup - Look up a compat shader
+ *
+ * @man: Pointer to the compat shader manager.
+ * @shader_type: The shader type, that combined with the user_key identifies
+ * the shader.
+ * @user_key: On entry, this should be a pointer to the user_key.
+ * On successful exit, it will contain the guest-backed shader's TTM handle.
+ *
+ * Returns 0 on success. Non-zero on failure, in which case the value pointed
+ * to by @user_key is unmodified.
+ */
+int vmw_compat_shader_lookup(struct vmw_compat_shader_manager *man,
+                            SVGA3dShaderType shader_type,
+                            u32 *user_key)
+{
+       struct drm_hash_item *hash;
+       int ret;
+       unsigned long key = *user_key | (shader_type << 24);
+
+       ret = drm_ht_find_item(&man->shaders, key, &hash);
        if (unlikely(ret != 0))
                return ret;
 
-       ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
-                                  vmw_user_shader_size,
-                                  false, true);
-       if (unlikely(ret != 0)) {
-               if (ret != -ERESTARTSYS)
-                       DRM_ERROR("Out of graphics memory for shader"
-                                 " creation.\n");
-               goto out_unlock;
+       *user_key = drm_hash_entry(hash, struct vmw_compat_shader,
+                                  hash)->handle;
+
+       return 0;
+}
+
+/**
+ * vmw_compat_shader_free - Free a compat shader.
+ *
+ * @man: Pointer to the compat shader manager.
+ * @entry: Pointer to a struct vmw_compat_shader.
+ *
+ * Frees a struct vmw_compat_shder entry and drops its reference to the
+ * guest backed shader.
+ */
+static void vmw_compat_shader_free(struct vmw_compat_shader_manager *man,
+                                  struct vmw_compat_shader *entry)
+{
+       list_del(&entry->head);
+       WARN_ON(drm_ht_remove_item(&man->shaders, &entry->hash));
+       WARN_ON(ttm_ref_object_base_unref(entry->tfile, entry->handle,
+                                         TTM_REF_USAGE));
+       kfree(entry);
+}
+
+/**
+ * vmw_compat_shaders_commit - Commit a list of compat shader actions.
+ *
+ * @man: Pointer to the compat shader manager.
+ * @list: Caller's list of compat shader actions.
+ *
+ * This function commits a list of compat shader additions or removals.
+ * It is typically called when the execbuf ioctl call triggering these
+ * actions has commited the fifo contents to the device.
+ */
+void vmw_compat_shaders_commit(struct vmw_compat_shader_manager *man,
+                              struct list_head *list)
+{
+       struct vmw_compat_shader *entry, *next;
+
+       list_for_each_entry_safe(entry, next, list, head) {
+               list_del(&entry->head);
+               switch (entry->state) {
+               case VMW_COMPAT_ADD:
+                       entry->state = VMW_COMPAT_COMMITED;
+                       list_add_tail(&entry->head, &man->list);
+                       break;
+               case VMW_COMPAT_DEL:
+                       ttm_ref_object_base_unref(entry->tfile, entry->handle,
+                                                 TTM_REF_USAGE);
+                       kfree(entry);
+                       break;
+               default:
+                       BUG();
+                       break;
+               }
        }
+}
 
-       ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
-       if (unlikely(ushader == NULL)) {
-               ttm_mem_global_free(vmw_mem_glob(dev_priv),
-                                   vmw_user_shader_size);
-               ret = -ENOMEM;
-               goto out_unlock;
+/**
+ * vmw_compat_shaders_revert - Revert a list of compat shader actions
+ *
+ * @man: Pointer to the compat shader manager.
+ * @list: Caller's list of compat shader actions.
+ *
+ * This function reverts a list of compat shader additions or removals.
+ * It is typically called when the execbuf ioctl call triggering these
+ * actions failed for some reason, and the command stream was never
+ * submitted.
+ */
+void vmw_compat_shaders_revert(struct vmw_compat_shader_manager *man,
+                              struct list_head *list)
+{
+       struct vmw_compat_shader *entry, *next;
+       int ret;
+
+       list_for_each_entry_safe(entry, next, list, head) {
+               switch (entry->state) {
+               case VMW_COMPAT_ADD:
+                       vmw_compat_shader_free(man, entry);
+                       break;
+               case VMW_COMPAT_DEL:
+                       ret = drm_ht_insert_item(&man->shaders, &entry->hash);
+                       list_del(&entry->head);
+                       list_add_tail(&entry->head, &man->list);
+                       entry->state = VMW_COMPAT_COMMITED;
+                       break;
+               default:
+                       BUG();
+                       break;
+               }
        }
+}
 
-       res = &ushader->shader.res;
-       ushader->base.shareable = false;
-       ushader->base.tfile = NULL;
+/**
+ * vmw_compat_shader_remove - Stage a compat shader for removal.
+ *
+ * @man: Pointer to the compat shader manager
+ * @user_key: The key that is used to identify the shader. The key is
+ * unique to the shader type.
+ * @shader_type: Shader type.
+ * @list: Caller's list of staged shader actions.
+ *
+ * This function stages a compat shader for removal and removes the key from
+ * the shader manager's hash table. If the shader was previously only staged
+ * for addition it is completely removed (But the execbuf code may keep a
+ * reference if it was bound to a context between addition and removal). If
+ * it was previously commited to the manager, it is staged for removal.
+ */
+int vmw_compat_shader_remove(struct vmw_compat_shader_manager *man,
+                            u32 user_key, SVGA3dShaderType shader_type,
+                            struct list_head *list)
+{
+       struct vmw_compat_shader *entry;
+       struct drm_hash_item *hash;
+       int ret;
 
-       /*
-        * From here on, the destructor takes over resource freeing.
-        */
+       ret = drm_ht_find_item(&man->shaders, user_key | (shader_type << 24),
+                              &hash);
+       if (likely(ret != 0))
+               return -EINVAL;
 
-       ret = vmw_gb_shader_init(dev_priv, res, arg->size,
-                                arg->offset, shader_type, buffer,
-                                vmw_user_shader_free);
+       entry = drm_hash_entry(hash, struct vmw_compat_shader, hash);
+
+       switch (entry->state) {
+       case VMW_COMPAT_ADD:
+               vmw_compat_shader_free(man, entry);
+               break;
+       case VMW_COMPAT_COMMITED:
+               (void) drm_ht_remove_item(&man->shaders, &entry->hash);
+               list_del(&entry->head);
+               entry->state = VMW_COMPAT_DEL;
+               list_add_tail(&entry->head, list);
+               break;
+       default:
+               BUG();
+               break;
+       }
+
+       return 0;
+}
+
+/**
+ * vmw_compat_shader_add - Create a compat shader and add the
+ * key to the manager
+ *
+ * @man: Pointer to the compat shader manager
+ * @user_key: The key that is used to identify the shader. The key is
+ * unique to the shader type.
+ * @bytecode: Pointer to the bytecode of the shader.
+ * @shader_type: Shader type.
+ * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is
+ * to be created with.
+ * @list: Caller's list of staged shader actions.
+ *
+ * Note that only the key is added to the shader manager's hash table.
+ * The shader is not yet added to the shader manager's list of shaders.
+ */
+int vmw_compat_shader_add(struct vmw_compat_shader_manager *man,
+                         u32 user_key, const void *bytecode,
+                         SVGA3dShaderType shader_type,
+                         size_t size,
+                         struct ttm_object_file *tfile,
+                         struct list_head *list)
+{
+       struct vmw_dma_buffer *buf;
+       struct ttm_bo_kmap_obj map;
+       bool is_iomem;
+       struct vmw_compat_shader *compat;
+       u32 handle;
+       int ret;
+
+       if (user_key > ((1 << 24) - 1) || (unsigned) shader_type > 16)
+               return -EINVAL;
+
+       /* Allocate and pin a DMA buffer */
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (unlikely(buf == NULL))
+               return -ENOMEM;
+
+       ret = vmw_dmabuf_init(man->dev_priv, buf, size, &vmw_sys_ne_placement,
+                             true, vmw_dmabuf_bo_free);
        if (unlikely(ret != 0))
-               goto out_unlock;
+               goto out;
 
-       tmp = vmw_resource_reference(res);
-       ret = ttm_base_object_init(tfile, &ushader->base, false,
-                                  VMW_RES_SHADER,
-                                  &vmw_user_shader_base_release, NULL);
+       ret = ttm_bo_reserve(&buf->base, false, true, false, NULL);
+       if (unlikely(ret != 0))
+               goto no_reserve;
 
+       /* Map and copy shader bytecode. */
+       ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT,
+                         &map);
        if (unlikely(ret != 0)) {
-               vmw_resource_unreference(&tmp);
-               goto out_err;
+               ttm_bo_unreserve(&buf->base);
+               goto no_reserve;
        }
 
-       arg->shader_handle = ushader->base.hash.key;
-out_err:
-       vmw_resource_unreference(&res);
-out_unlock:
-       ttm_read_unlock(&vmaster->lock);
-out_bad_arg:
-       vmw_dmabuf_unreference(&buffer);
+       memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size);
+       WARN_ON(is_iomem);
+
+       ttm_bo_kunmap(&map);
+       ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true);
+       WARN_ON(ret != 0);
+       ttm_bo_unreserve(&buf->base);
+
+       /* Create a guest-backed shader container backed by the dma buffer */
+       ret = vmw_shader_alloc(man->dev_priv, buf, size, 0, shader_type,
+                              tfile, &handle);
+       vmw_dmabuf_unreference(&buf);
+       if (unlikely(ret != 0))
+               goto no_reserve;
+       /*
+        * Create a compat shader structure and stage it for insertion
+        * in the manager
+        */
+       compat = kzalloc(sizeof(*compat), GFP_KERNEL);
+       if (compat == NULL)
+               goto no_compat;
+
+       compat->hash.key = user_key |  (shader_type << 24);
+       ret = drm_ht_insert_item(&man->shaders, &compat->hash);
+       if (unlikely(ret != 0))
+               goto out_invalid_key;
+
+       compat->state = VMW_COMPAT_ADD;
+       compat->handle = handle;
+       compat->tfile = tfile;
+       list_add_tail(&compat->head, list);
 
+       return 0;
+
+out_invalid_key:
+       kfree(compat);
+no_compat:
+       ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
+no_reserve:
+out:
        return ret;
+}
+
+/**
+ * vmw_compat_shader_man_create - Create a compat shader manager
+ *
+ * @dev_priv: Pointer to a device private structure.
+ *
+ * Typically done at file open time. If successful returns a pointer to a
+ * compat shader manager. Otherwise returns an error pointer.
+ */
+struct vmw_compat_shader_manager *
+vmw_compat_shader_man_create(struct vmw_private *dev_priv)
+{
+       struct vmw_compat_shader_manager *man;
+       int ret;
+
+       man = kzalloc(sizeof(*man), GFP_KERNEL);
+       if (man == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       man->dev_priv = dev_priv;
+       INIT_LIST_HEAD(&man->list);
+       ret = drm_ht_create(&man->shaders, VMW_COMPAT_SHADER_HT_ORDER);
+       if (ret == 0)
+               return man;
+
+       kfree(man);
+       return ERR_PTR(ret);
+}
+
+/**
+ * vmw_compat_shader_man_destroy - Destroy a compat shader manager
+ *
+ * @man: Pointer to the shader manager to destroy.
+ *
+ * Typically done at file close time.
+ */
+void vmw_compat_shader_man_destroy(struct vmw_compat_shader_manager *man)
+{
+       struct vmw_compat_shader *entry, *next;
+
+       mutex_lock(&man->dev_priv->cmdbuf_mutex);
+       list_for_each_entry_safe(entry, next, &man->list, head)
+               vmw_compat_shader_free(man, entry);
 
+       mutex_unlock(&man->dev_priv->cmdbuf_mutex);
+       kfree(man);
 }
index 979da1c246a543a445257daee03787e794b266a1..e7af580ab977f5932629b8d45e5d5e68a52942a5 100644 (file)
@@ -830,6 +830,24 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        if (unlikely(ret != 0))
                goto out_unlock;
 
+       /*
+        * A gb-aware client referencing a shared surface will
+        * expect a backup buffer to be present.
+        */
+       if (dev_priv->has_mob && req->shareable) {
+               uint32_t backup_handle;
+
+               ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
+                                           res->backup_size,
+                                           true,
+                                           &backup_handle,
+                                           &res->backup);
+               if (unlikely(ret != 0)) {
+                       vmw_resource_unreference(&res);
+                       goto out_unlock;
+               }
+       }
+
        tmp = vmw_resource_reference(&srf->res);
        ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
                                    req->shareable, VMW_RES_SURFACE,
@@ -908,8 +926,8 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
            rep->size_addr;
 
        if (user_sizes)
-               ret = copy_to_user(user_sizes, srf->sizes,
-                                  srf->num_sizes * sizeof(*srf->sizes));
+               ret = copy_to_user(user_sizes, &srf->base_size,
+                                  sizeof(srf->base_size));
        if (unlikely(ret != 0)) {
                DRM_ERROR("copy_to_user failed %p %u\n",
                          user_sizes, srf->num_sizes);
@@ -1111,7 +1129,7 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res)
                return 0;
 
        mutex_lock(&dev_priv->binding_mutex);
-       vmw_context_binding_res_list_kill(&res->binding_head);
+       vmw_context_binding_res_list_scrub(&res->binding_head);
 
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
        if (unlikely(cmd == NULL)) {
index 1146e3bba6e19bb69cd7f866c149b4aa7202ae46..112f27e51bc7df81b45efcb58f7c11fc46f097e0 100644 (file)
@@ -538,7 +538,7 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
 
                g->base = job->gather_addr_phys[i];
 
-               for (j = 0; j < job->num_gathers; j++)
+               for (j = i + 1; j < job->num_gathers; j++)
                        if (job->gathers[j].bo == g->bo)
                                job->gathers[j].handled = true;
 
index 497558127bb3e63609af2b5e1f75265f9e7b1423..f822fd2a1adabc4b3e53d86155c2d9e50d3d241e 100644 (file)
@@ -469,6 +469,9 @@ static const struct hid_device_id apple_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
                                USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
+                               USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
index 3bfac3accd22fa6dc8a9be7a31cf9fd2814d2443..cc32a6f96c64804d8a1fc936f0fd22244eb51e83 100644 (file)
@@ -1679,6 +1679,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_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) },
        { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
@@ -1779,6 +1780,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
index 8fae6d1414cca83bc7af2386b7db5dc4cbd3f27b..c24908f14934f4d788263d3a768ae69797913769 100644 (file)
@@ -157,6 +157,7 @@ struct mousevsc_dev {
        u32                     report_desc_size;
        struct hv_input_dev_info hid_dev_info;
        struct hid_device       *hid_device;
+       u8                      input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 
@@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device *device,
        struct synthhid_msg *hid_msg;
        struct mousevsc_dev *input_dev = hv_get_drvdata(device);
        struct synthhid_input_report *input_report;
+       size_t len;
 
        pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
                                                (packet->offset8 << 3));
@@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device *device,
                        (struct synthhid_input_report *)pipe_msg->data;
                if (!input_dev->init_complete)
                        break;
-               hid_input_report(input_dev->hid_device,
-                               HID_INPUT_REPORT, input_report->buffer,
-                               input_report->header.size, 1);
+
+               len = min(input_report->header.size,
+                         (u32)sizeof(input_dev->input_buf));
+               memcpy(input_dev->input_buf, input_report->buffer, len);
+               hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
+                                input_dev->input_buf, len, 1);
                break;
        default:
                pr_err("unsupported hid msg type - type %d len %d",
index 5a5248f2cc075b73ca68250866bddbc2b46f9bb1..22f28d6b33a845f0c728b3d4423b6c6fd848ff78 100644 (file)
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI  0x0255
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS   0x0257
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI   0x0290
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO    0x0291
 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS    0x0292
 
 #define USB_VENDOR_ID_CYGNAL           0x10c4
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X      0x818a
+#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH      0x81b9
 
 #define USB_DEVICE_ID_CYGNAL_RADIO_SI4713       0x8244
 
 #define USB_VENDOR_ID_INTEL_1          0x8087
 #define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa
 
+#define USB_VENDOR_ID_STM_0             0x0483
+#define USB_DEVICE_ID_STM_HID_SENSOR    0x91d1
+
 #define USB_VENDOR_ID_ION              0x15e4
 #define USB_DEVICE_ID_ICADE            0x0132
 
 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB      0x0713
 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K      0x0730
 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500    0x076c
+#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7
+#define USB_DEVICE_ID_MS_TYPE_COVER_2  0x07a9
 
 #define USB_VENDOR_ID_MOJO             0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER    0x3201
 
 #define USB_VENDOR_ID_NEXIO            0x1870
 #define USB_DEVICE_ID_NEXIO_MULTITOUCH_420     0x010d
+#define USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750 0x0110
 
 #define USB_VENDOR_ID_NEXTWINDOW       0x1926
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN   0x0003
index d50e7313b171e4e9bd732cbee40a1a5cd5e501b5..a713e6211419c880ddd0a39597b78f16ad84919a 100644 (file)
@@ -1178,7 +1178,7 @@ static void hidinput_led_worker(struct work_struct *work)
 
        /* fall back to generic raw-output-report */
        len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       buf = kmalloc(len, GFP_KERNEL);
+       buf = hid_alloc_report_buf(report, GFP_KERNEL);
        if (!buf)
                return;
 
index befe0e336471b0f36e34473ee97c3ba72759ddf9..24883b4d1a49d40a2bb3462ee36ed094f474b3cd 100644 (file)
@@ -43,6 +43,7 @@
 #define G25_REV_MIN 0x22
 #define G27_REV_MAJ 0x12
 #define G27_REV_MIN 0x38
+#define G27_2_REV_MIN 0x39
 
 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
 
@@ -130,6 +131,7 @@ static const struct lg4ff_usb_revision lg4ff_revs[] = {
        {DFP_REV_MAJ,  DFP_REV_MIN,  &native_dfp},      /* Driving Force Pro */
        {G25_REV_MAJ,  G25_REV_MIN,  &native_g25},      /* G25 */
        {G27_REV_MAJ,  G27_REV_MIN,  &native_g27},      /* G27 */
+       {G27_REV_MAJ,  G27_2_REV_MIN,  &native_g27},    /* G27 v2 */
 };
 
 /* Recalculates X axis value accordingly to currently selected range */
index c6ef6eed30915e272edf7249001d3005b9e1b667..404a3a8a82f123c40bca4c38ee84a0505aa404f6 100644 (file)
@@ -208,6 +208,10 @@ static const struct hid_device_id ms_devices[] = {
                .driver_data = MS_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
                .driver_data = MS_DUPLICATE_USAGES },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2),
+               .driver_data = 0 },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2),
+               .driver_data = 0 },
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
                .driver_data = MS_PRESENTER },
index f134d73beca16b72ddce5716d36e4d7ca949e61d..221d503f1c24fa7b1bbbc0c5871c3cbe742d1a5b 100644 (file)
@@ -1166,6 +1166,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
                        USB_DEVICE_ID_MULTITOUCH_3200) },
 
+       /* FocalTech Panels */
+       { .driver_data = MT_CLS_SERIAL,
+               MT_USB_DEVICE(USB_VENDOR_ID_CYGNAL,
+                       USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH) },
+
        /* GeneralTouch panel */
        { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
                MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
index 46f4480035bca14642c43618eb17bfd6729dfb0f..9c22e14c57f079622f297f6d5287919b8c5e2e31 100644 (file)
@@ -665,6 +665,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1,
                        USB_DEVICE_ID_INTEL_HID_SENSOR),
                        .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
+                       USB_DEVICE_ID_STM_HID_SENSOR),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
                     HID_ANY_ID) },
        { }
index 12354055d4745a4a50e783f624ec8b24bee46dc4..2f19b15f47f2ffca68de731ef0e0ba3ae53c972b 100644 (file)
@@ -42,6 +42,7 @@
 #define DUALSHOCK4_CONTROLLER_BT  BIT(6)
 
 #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB)
+#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER_USB | DUALSHOCK4_CONTROLLER_USB)
 
 #define MAX_LEDS 4
 
@@ -499,6 +500,7 @@ struct sony_sc {
        __u8 right;
 #endif
 
+       __u8 worker_initialized;
        __u8 led_state[MAX_LEDS];
        __u8 led_count;
 };
@@ -993,22 +995,11 @@ static int sony_init_ff(struct hid_device *hdev)
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
 }
 
-static void sony_destroy_ff(struct hid_device *hdev)
-{
-       struct sony_sc *sc = hid_get_drvdata(hdev);
-
-       cancel_work_sync(&sc->state_worker);
-}
-
 #else
 static int sony_init_ff(struct hid_device *hdev)
 {
        return 0;
 }
-
-static void sony_destroy_ff(struct hid_device *hdev)
-{
-}
 #endif
 
 static int sony_set_output_report(struct sony_sc *sc, int req_id, int req_size)
@@ -1077,6 +1068,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
                hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
                ret = sixaxis_set_operational_usb(hdev);
+
+               sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, sixaxis_state_worker);
        }
        else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
@@ -1087,6 +1080,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
                if (ret < 0)
                        goto err_stop;
 
+               sc->worker_initialized = 1;
                INIT_WORK(&sc->state_worker, dualshock4_state_worker);
        } else {
                ret = 0;
@@ -1101,9 +1095,11 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
                        goto err_stop;
        }
 
-       ret = sony_init_ff(hdev);
-       if (ret < 0)
-               goto err_stop;
+       if (sc->quirks & SONY_FF_SUPPORT) {
+               ret = sony_init_ff(hdev);
+               if (ret < 0)
+                       goto err_stop;
+       }
 
        return 0;
 err_stop:
@@ -1120,7 +1116,8 @@ static void sony_remove(struct hid_device *hdev)
        if (sc->quirks & SONY_LED_SUPPORT)
                sony_leds_remove(hdev);
 
-       sony_destroy_ff(hdev);
+       if (sc->worker_initialized)
+               cancel_work_sync(&sc->state_worker);
 
        hid_hw_stop(hdev);
 }
index cb0137b3718d8cd0a42d6483a9817a26733452c6..ab24ce2eb28f484e30fa0994cd2781994ff7d22d 100644 (file)
@@ -320,13 +320,13 @@ static void drop_ref(struct hidraw *hidraw, int exists_bit)
                        hid_hw_close(hidraw->hid);
                        wake_up_interruptible(&hidraw->wait);
                }
+               device_destroy(hidraw_class,
+                              MKDEV(hidraw_major, hidraw->minor));
        } else {
                --hidraw->open;
        }
        if (!hidraw->open) {
                if (!hidraw->exist) {
-                       device_destroy(hidraw_class,
-                                       MKDEV(hidraw_major, hidraw->minor));
                        hidraw_table[hidraw->minor] = NULL;
                        kfree(hidraw);
                } else {
index d1f81f52481a40bf7a0521eca0033da057d15641..42eebd14de1f2e41ed932335e729bfb448b7f3f1 100644 (file)
@@ -582,7 +582,7 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
        int ret;
        int len = i2c_hid_get_report_length(rep) - 2;
 
-       buf = kzalloc(len, GFP_KERNEL);
+       buf = hid_alloc_report_buf(rep, GFP_KERNEL);
        if (!buf)
                return;
 
index 175ec0afb70cff7770fe4460e18e3d1480546cec..dbd83878ff99ec029a1cda07b265ddcd27418710 100644 (file)
@@ -74,6 +74,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
index af6edf9b19365a4938ca16f6a913a08cc6a35fa7..f2d7bf90c9fe5b319d85bf1372a1c0cec36aa91c 100644 (file)
@@ -67,7 +67,6 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
        int ret = 0;
        struct vmbus_channel_initiate_contact *msg;
        unsigned long flags;
-       int t;
 
        init_completion(&msginfo->waitevent);
 
@@ -78,6 +77,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
        msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
        msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
        msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
+       if (version == VERSION_WIN8)
+               msg->target_vcpu = hv_context.vp_index[smp_processor_id()];
 
        /*
         * Add to list before we send the request since we may
@@ -100,15 +101,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
        }
 
        /* Wait for the connection response */
-       t =  wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
-       if (t == 0) {
-               spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
-                               flags);
-               list_del(&msginfo->msglistentry);
-               spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
-                                       flags);
-               return -ETIMEDOUT;
-       }
+       wait_for_completion(&msginfo->waitevent);
 
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&msginfo->msglistentry);
index 029ecabc4380dddae08fc62fb15d67c111caaaf2..73b3865f1207ada0b74949dba3d5e4636086c21b 100644 (file)
@@ -278,10 +278,6 @@ static int da9055_hwmon_probe(struct platform_device *pdev)
        if (hwmon_irq < 0)
                return hwmon_irq;
 
-       hwmon_irq = regmap_irq_get_virq(hwmon->da9055->irq_data, hwmon_irq);
-       if (hwmon_irq < 0)
-               return hwmon_irq;
-
        ret = devm_request_threaded_irq(&pdev->dev, hwmon_irq,
                                        NULL, da9055_auxadc_irq,
                                        IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
index a7626358c95df29c2ccb62fa89ed23251acfb979..029b65e6c58914d36061914e35738bda0c1e385c 100644 (file)
@@ -243,7 +243,7 @@ static ssize_t set_temp_min(struct device *dev,
        data->temp_min[index] = clamp_val(temp/1000, -128, 127);
        if (i2c_smbus_write_byte_data(client,
                                        MAX1668_REG_LIML_WR(index),
-                                       data->temp_max[index]))
+                                       data->temp_min[index]))
                count = -EIO;
        mutex_unlock(&data->update_lock);
 
index 8c23203915af3644cd138b13ec99faef572b49b5..8a17f01e8672065d7099e4c3ae156f93705eade4 100644 (file)
@@ -145,7 +145,7 @@ struct ntc_data {
 static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
 {
        struct iio_channel *channel = pdata->chan;
-       unsigned int result;
+       s64 result;
        int val, ret;
 
        ret = iio_read_channel_raw(channel, &val);
@@ -155,10 +155,10 @@ static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
        }
 
        /* unit: mV */
-       result = pdata->pullup_uv * val;
+       result = pdata->pullup_uv * (s64) val;
        result >>= 12;
 
-       return result;
+       return (int)result;
 }
 
 static const struct of_device_id ntc_match[] = {
index 3cbf66e9d861968863e01062902bdd699ca648e9..291d11fe93e792f50eab32bff2ce0783d97a75d8 100644 (file)
@@ -90,7 +90,8 @@ struct pmbus_data {
 
        u32 flags;              /* from platform data */
 
-       int exponent;           /* linear mode: exponent for output voltages */
+       int exponent[PMBUS_PAGES];
+                               /* linear mode: exponent for output voltages */
 
        const struct pmbus_driver_info *info;
 
@@ -410,7 +411,7 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
        long val;
 
        if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */
-               exponent = data->exponent;
+               exponent = data->exponent[sensor->page];
                mantissa = (u16) sensor->data;
        } else {                                /* LINEAR11 */
                exponent = ((s16)sensor->data) >> 11;
@@ -516,7 +517,7 @@ static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
 #define MIN_MANTISSA   (511 * 1000)
 
 static u16 pmbus_data2reg_linear(struct pmbus_data *data,
-                                enum pmbus_sensor_classes class, long val)
+                                struct pmbus_sensor *sensor, long val)
 {
        s16 exponent = 0, mantissa;
        bool negative = false;
@@ -525,7 +526,7 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
        if (val == 0)
                return 0;
 
-       if (class == PSC_VOLTAGE_OUT) {
+       if (sensor->class == PSC_VOLTAGE_OUT) {
                /* LINEAR16 does not support negative voltages */
                if (val < 0)
                        return 0;
@@ -534,10 +535,10 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
                 * For a static exponents, we don't have a choice
                 * but to adjust the value to it.
                 */
-               if (data->exponent < 0)
-                       val <<= -data->exponent;
+               if (data->exponent[sensor->page] < 0)
+                       val <<= -data->exponent[sensor->page];
                else
-                       val >>= data->exponent;
+                       val >>= data->exponent[sensor->page];
                val = DIV_ROUND_CLOSEST(val, 1000);
                return val & 0xffff;
        }
@@ -548,14 +549,14 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
        }
 
        /* Power is in uW. Convert to mW before converting. */
-       if (class == PSC_POWER)
+       if (sensor->class == PSC_POWER)
                val = DIV_ROUND_CLOSEST(val, 1000L);
 
        /*
         * For simplicity, convert fan data to milli-units
         * before calculating the exponent.
         */
-       if (class == PSC_FAN)
+       if (sensor->class == PSC_FAN)
                val = val * 1000;
 
        /* Reduce large mantissa until it fits into 10 bit */
@@ -585,22 +586,22 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
 }
 
 static u16 pmbus_data2reg_direct(struct pmbus_data *data,
-                                enum pmbus_sensor_classes class, long val)
+                                struct pmbus_sensor *sensor, long val)
 {
        long m, b, R;
 
-       m = data->info->m[class];
-       b = data->info->b[class];
-       R = data->info->R[class];
+       m = data->info->m[sensor->class];
+       b = data->info->b[sensor->class];
+       R = data->info->R[sensor->class];
 
        /* Power is in uW. Adjust R and b. */
-       if (class == PSC_POWER) {
+       if (sensor->class == PSC_POWER) {
                R -= 3;
                b *= 1000;
        }
 
        /* Calculate Y = (m * X + b) * 10^R */
-       if (class != PSC_FAN) {
+       if (sensor->class != PSC_FAN) {
                R -= 3;         /* Adjust R and b for data in milli-units */
                b *= 1000;
        }
@@ -619,7 +620,7 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
 }
 
 static u16 pmbus_data2reg_vid(struct pmbus_data *data,
-                             enum pmbus_sensor_classes class, long val)
+                             struct pmbus_sensor *sensor, long val)
 {
        val = clamp_val(val, 500, 1600);
 
@@ -627,20 +628,20 @@ static u16 pmbus_data2reg_vid(struct pmbus_data *data,
 }
 
 static u16 pmbus_data2reg(struct pmbus_data *data,
-                         enum pmbus_sensor_classes class, long val)
+                         struct pmbus_sensor *sensor, long val)
 {
        u16 regval;
 
-       switch (data->info->format[class]) {
+       switch (data->info->format[sensor->class]) {
        case direct:
-               regval = pmbus_data2reg_direct(data, class, val);
+               regval = pmbus_data2reg_direct(data, sensor, val);
                break;
        case vid:
-               regval = pmbus_data2reg_vid(data, class, val);
+               regval = pmbus_data2reg_vid(data, sensor, val);
                break;
        case linear:
        default:
-               regval = pmbus_data2reg_linear(data, class, val);
+               regval = pmbus_data2reg_linear(data, sensor, val);
                break;
        }
        return regval;
@@ -746,7 +747,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
-       regval = pmbus_data2reg(data, sensor->class, val);
+       regval = pmbus_data2reg(data, sensor, val);
        ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
        if (ret < 0)
                rv = ret;
@@ -1643,12 +1644,13 @@ static int pmbus_find_attributes(struct i2c_client *client,
  * This function is called for all chips.
  */
 static int pmbus_identify_common(struct i2c_client *client,
-                                struct pmbus_data *data)
+                                struct pmbus_data *data, int page)
 {
        int vout_mode = -1;
 
-       if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
-               vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+       if (pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE))
+               vout_mode = _pmbus_read_byte_data(client, page,
+                                                 PMBUS_VOUT_MODE);
        if (vout_mode >= 0 && vout_mode != 0xff) {
                /*
                 * Not all chips support the VOUT_MODE command,
@@ -1659,7 +1661,7 @@ static int pmbus_identify_common(struct i2c_client *client,
                        if (data->info->format[PSC_VOLTAGE_OUT] != linear)
                                return -ENODEV;
 
-                       data->exponent = ((s8)(vout_mode << 3)) >> 3;
+                       data->exponent[page] = ((s8)(vout_mode << 3)) >> 3;
                        break;
                case 1: /* VID mode         */
                        if (data->info->format[PSC_VOLTAGE_OUT] != vid)
@@ -1674,7 +1676,7 @@ static int pmbus_identify_common(struct i2c_client *client,
                }
        }
 
-       pmbus_clear_fault_page(client, 0);
+       pmbus_clear_fault_page(client, page);
        return 0;
 }
 
@@ -1682,7 +1684,7 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
                             struct pmbus_driver_info *info)
 {
        struct device *dev = &client->dev;
-       int ret;
+       int page, ret;
 
        /*
         * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try
@@ -1715,10 +1717,12 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
                return -ENODEV;
        }
 
-       ret = pmbus_identify_common(client, data);
-       if (ret < 0) {
-               dev_err(dev, "Failed to identify chip capabilities\n");
-               return ret;
+       for (page = 0; page < info->pages; page++) {
+               ret = pmbus_identify_common(client, data, page);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to identify chip capabilities\n");
+                       return ret;
+               }
        }
        return 0;
 }
index f5ed03164d86c314942453d244f103d6e9276070..de17c5593d97c1d702563217f0932aa0a0aee6bd 100644 (file)
@@ -387,7 +387,7 @@ config I2C_CBUS_GPIO
 
 config I2C_CPM
        tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
-       depends on (CPM1 || CPM2) && OF_I2C
+       depends on CPM1 || CPM2
        help
          This supports the use of the I2C interface on Freescale
          processors with CPM1 or CPM2.
index be7f0a20d634d1107a7bb3147b32edf0256546ed..f3b89a4698b6192a24d031bab358796e51fbb767 100644 (file)
@@ -39,7 +39,9 @@
 #include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <sysdev/fsl_soc.h>
 #include <asm/cpm.h>
index b8c5187b9ee0da912b3a872b828705891a0146a4..d52d84937ad39fee5f81f5a5ec832995cf6d956d 100644 (file)
@@ -97,7 +97,6 @@ enum {
 enum {
        MV64XXX_I2C_ACTION_INVALID,
        MV64XXX_I2C_ACTION_CONTINUE,
-       MV64XXX_I2C_ACTION_OFFLOAD_SEND_START,
        MV64XXX_I2C_ACTION_SEND_START,
        MV64XXX_I2C_ACTION_SEND_RESTART,
        MV64XXX_I2C_ACTION_OFFLOAD_RESTART,
@@ -204,6 +203,9 @@ static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data)
        unsigned long ctrl_reg;
        struct i2c_msg *msg = drv_data->msgs;
 
+       if (!drv_data->offload_enabled)
+               return -EOPNOTSUPP;
+
        drv_data->msg = msg;
        drv_data->byte_posn = 0;
        drv_data->bytes_left = msg->len;
@@ -433,8 +435,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
 
                drv_data->msgs++;
                drv_data->num_msgs--;
-               if (!(drv_data->offload_enabled &&
-                               mv64xxx_i2c_offload_msg(drv_data))) {
+               if (mv64xxx_i2c_offload_msg(drv_data) < 0) {
                        drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
                        writel(drv_data->cntl_bits,
                        drv_data->reg_base + drv_data->reg_offsets.control);
@@ -458,15 +459,14 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
                        drv_data->reg_base + drv_data->reg_offsets.control);
                break;
 
-       case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START:
-               if (!mv64xxx_i2c_offload_msg(drv_data))
-                       break;
-               else
-                       drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
-               /* FALLTHRU */
        case MV64XXX_I2C_ACTION_SEND_START:
-               writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
-                       drv_data->reg_base + drv_data->reg_offsets.control);
+               /* Can we offload this msg ? */
+               if (mv64xxx_i2c_offload_msg(drv_data) < 0) {
+                       /* No, switch to standard path */
+                       mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
+                       writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
+                               drv_data->reg_base + drv_data->reg_offsets.control);
+               }
                break;
 
        case MV64XXX_I2C_ACTION_SEND_ADDR_1:
@@ -625,15 +625,10 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
        unsigned long   flags;
 
        spin_lock_irqsave(&drv_data->lock, flags);
-       if (drv_data->offload_enabled) {
-               drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START;
-               drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
-       } else {
-               mv64xxx_i2c_prepare_for_io(drv_data, msg);
 
-               drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
-               drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
-       }
+       drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
+       drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
+
        drv_data->send_stop = is_last;
        drv_data->block = 1;
        mv64xxx_i2c_do_action(drv_data);
index 3bec9220df04e2a16ade76727dee9851ab1dee7e..bfec313492b3f0de16c8aa26bfb5b77ba9160473 100644 (file)
@@ -447,14 +447,14 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
        { },
 };
 
-#define BMA180_CHANNEL(_index) {                                       \
+#define BMA180_CHANNEL(_axis) {                                        \
        .type = IIO_ACCEL,                                              \
-       .indexed = 1,                                                   \
-       .channel = (_index),                                            \
+       .modified = 1,                                                  \
+       .channel2 = IIO_MOD_##_axis,                                    \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
                BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),       \
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
-       .scan_index = (_index),                                         \
+       .scan_index = AXIS_##_axis,                                     \
        .scan_type = {                                                  \
                .sign = 's',                                            \
                .realbits = 14,                                         \
@@ -465,10 +465,10 @@ static const struct iio_chan_spec_ext_info bma180_ext_info[] = {
 }
 
 static const struct iio_chan_spec bma180_channels[] = {
-       BMA180_CHANNEL(AXIS_X),
-       BMA180_CHANNEL(AXIS_Y),
-       BMA180_CHANNEL(AXIS_Z),
-       IIO_CHAN_SOFT_TIMESTAMP(4),
+       BMA180_CHANNEL(X),
+       BMA180_CHANNEL(Y),
+       BMA180_CHANNEL(Z),
+       IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
 static irqreturn_t bma180_trigger_handler(int irq, void *p)
index e283f2f2ee2fb89eadef04aebd198e1e0bc0ea7e..360259266d4f47a70702638c5a08d3d7779dca68 100644 (file)
@@ -1560,7 +1560,7 @@ static int max1363_probe(struct i2c_client *client,
        st->client = client;
 
        st->vref_uv = st->chip_info->int_vref_mv * 1000;
-       vref = devm_regulator_get(&client->dev, "vref");
+       vref = devm_regulator_get_optional(&client->dev, "vref");
        if (!IS_ERR(vref)) {
                int vref_uv;
 
index 41c64a43bcab163a1b08d70ce1433ee1e941b86a..ac2d69e34c8ceb60661c5f3b433d415939e607f9 100644 (file)
@@ -70,7 +70,7 @@ config IIO_ST_GYRO_3AXIS
        select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
        help
          Say yes here to build support for STMicroelectronics gyroscopes:
-         L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
+         L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330.
 
          This driver can also be built as a module. If so, these modules
          will be created:
index f8f2bf84a5a281f9d9cff04eeb4af3d81de6c5be..c197360c450bd8549a980a24941b322df4fca88f 100644 (file)
@@ -19,7 +19,6 @@
 #define LSM330DL_GYRO_DEV_NAME         "lsm330dl_gyro"
 #define LSM330DLC_GYRO_DEV_NAME                "lsm330dlc_gyro"
 #define L3GD20_GYRO_DEV_NAME           "l3gd20"
-#define L3GD20H_GYRO_DEV_NAME          "l3gd20h"
 #define L3G4IS_GYRO_DEV_NAME           "l3g4is_ui"
 #define LSM330_GYRO_DEV_NAME           "lsm330_gyro"
 
index d53d91adfb557b0e575a17030221c6e01b2b7d38..a8e174a47bc409cc22ece45c5a971ca3fe14f37d 100644 (file)
@@ -167,11 +167,10 @@ static const struct st_sensors st_gyro_sensors[] = {
                .wai = ST_GYRO_2_WAI_EXP,
                .sensors_supported = {
                        [0] = L3GD20_GYRO_DEV_NAME,
-                       [1] = L3GD20H_GYRO_DEV_NAME,
-                       [2] = LSM330D_GYRO_DEV_NAME,
-                       [3] = LSM330DLC_GYRO_DEV_NAME,
-                       [4] = L3G4IS_GYRO_DEV_NAME,
-                       [5] = LSM330_GYRO_DEV_NAME,
+                       [1] = LSM330D_GYRO_DEV_NAME,
+                       [2] = LSM330DLC_GYRO_DEV_NAME,
+                       [3] = L3G4IS_GYRO_DEV_NAME,
+                       [4] = LSM330_GYRO_DEV_NAME,
                },
                .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
                .odr = {
index 16b8b8d70bf127973b43f819999c3876f7a8683d..23c12f361b05b13f37430df0958f02a406b8812d 100644 (file)
@@ -55,7 +55,6 @@ static const struct i2c_device_id st_gyro_id_table[] = {
        { LSM330DL_GYRO_DEV_NAME },
        { LSM330DLC_GYRO_DEV_NAME },
        { L3GD20_GYRO_DEV_NAME },
-       { L3GD20H_GYRO_DEV_NAME },
        { L3G4IS_GYRO_DEV_NAME },
        { LSM330_GYRO_DEV_NAME },
        {},
index 94763e25caf999c22f2237fa3a5783d063512173..b4ad3be2668768e7a4ef35979478ed033933007f 100644 (file)
@@ -54,7 +54,6 @@ static const struct spi_device_id st_gyro_id_table[] = {
        { LSM330DL_GYRO_DEV_NAME },
        { LSM330DLC_GYRO_DEV_NAME },
        { L3GD20_GYRO_DEV_NAME },
-       { L3GD20H_GYRO_DEV_NAME },
        { L3G4IS_GYRO_DEV_NAME },
        { LSM330_GYRO_DEV_NAME },
        {},
index 2f8f9d632386b34b2ad6f6a776277fc65fc3acf4..0916bf6b6c311c503931f26387712c6677b17645 100644 (file)
@@ -189,6 +189,7 @@ enum {
        ADIS16300_SCAN_INCLI_X,
        ADIS16300_SCAN_INCLI_Y,
        ADIS16400_SCAN_ADC,
+       ADIS16400_SCAN_TIMESTAMP,
 };
 
 #ifdef CONFIG_IIO_BUFFER
index 368660dfe135a51c3cac05dd90d7dcb75dacb7c2..7c582f7ae34e15885dc075515de60a2a81be30b3 100644 (file)
@@ -632,7 +632,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
        ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
        ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12),
        ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12),
-       IIO_CHAN_SOFT_TIMESTAMP(12)
+       IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
 static const struct iio_chan_spec adis16448_channels[] = {
@@ -659,7 +659,7 @@ static const struct iio_chan_spec adis16448_channels[] = {
                },
        },
        ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
-       IIO_CHAN_SOFT_TIMESTAMP(11)
+       IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
 static const struct iio_chan_spec adis16350_channels[] = {
@@ -677,7 +677,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
        ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12),
        ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12),
        ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12),
-       IIO_CHAN_SOFT_TIMESTAMP(11)
+       IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
 static const struct iio_chan_spec adis16300_channels[] = {
@@ -690,7 +690,7 @@ static const struct iio_chan_spec adis16300_channels[] = {
        ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
        ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13),
        ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13),
-       IIO_CHAN_SOFT_TIMESTAMP(14)
+       IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
 static const struct iio_chan_spec adis16334_channels[] = {
@@ -701,7 +701,7 @@ static const struct iio_chan_spec adis16334_channels[] = {
        ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
        ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
        ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
-       IIO_CHAN_SOFT_TIMESTAMP(8)
+       IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 
 static struct attribute *adis16400_attributes[] = {
index f17b4e6183c6bae6f36ee8acfaac897f76dfd8d9..47a6dbac2d0ca8b23dcea31158b43d3c3df3d2f0 100644 (file)
@@ -103,13 +103,13 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
 /**
  *  cm32181_read_als_it() - Get sensor integration time (ms)
  *  @cm32181:  pointer of struct cm32181
- *  @val     pointer of int to load the als_it value.
+ *  @val2:     pointer of int to load the als_it value.
  *
  *  Report the current integartion time by millisecond.
  *
- *  Return: IIO_VAL_INT for success, otherwise -EINVAL.
+ *  Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL.
  */
-static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val)
+static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
 {
        u16 als_it;
        int i;
@@ -119,8 +119,8 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val)
        als_it >>= CM32181_CMD_ALS_IT_SHIFT;
        for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
                if (als_it == als_it_bits[i]) {
-                       *val = als_it_value[i];
-                       return IIO_VAL_INT;
+                       *val2 = als_it_value[i];
+                       return IIO_VAL_INT_PLUS_MICRO;
                }
        }
 
@@ -221,7 +221,7 @@ static int cm32181_read_raw(struct iio_dev *indio_dev,
                *val = cm32181->calibscale;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = cm32181_read_als_it(cm32181, val);
+               ret = cm32181_read_als_it(cm32181, val2);
                return ret;
        }
 
@@ -240,7 +240,7 @@ static int cm32181_write_raw(struct iio_dev *indio_dev,
                cm32181->calibscale = val;
                return val;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = cm32181_write_als_it(cm32181, val);
+               ret = cm32181_write_als_it(cm32181, val2);
                return ret;
        }
 
@@ -264,7 +264,7 @@ static ssize_t cm32181_get_it_available(struct device *dev,
 
        n = ARRAY_SIZE(als_it_value);
        for (i = 0, len = 0; i < n; i++)
-               len += sprintf(buf + len, "%d ", als_it_value[i]);
+               len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
        return len + sprintf(buf + len, "\n");
 }
 
index 0a142af83e25dbb112809f04a048fd581f9a7d96..a45e07492db318a22171546291d2b590e0d0668f 100644 (file)
 #define CM36651_CS_CONF2_DEFAULT_BIT   0x08
 
 /* CS_CONF3 channel integration time */
-#define CM36651_CS_IT1                 0x00 /* Integration time 80000 usec */
-#define CM36651_CS_IT2                 0x40 /* Integration time 160000 usec */
-#define CM36651_CS_IT3                 0x80 /* Integration time 320000 usec */
-#define CM36651_CS_IT4                 0xC0 /* Integration time 640000 usec */
+#define CM36651_CS_IT1                 0x00 /* Integration time 80 msec */
+#define CM36651_CS_IT2                 0x40 /* Integration time 160 msec */
+#define CM36651_CS_IT3                 0x80 /* Integration time 320 msec */
+#define CM36651_CS_IT4                 0xC0 /* Integration time 640 msec */
 
 /* PS_CONF1 command code */
 #define CM36651_PS_ENABLE              0x00
 #define CM36651_PS_PERS4               0x0C
 
 /* PS_CONF1 command code: integration time */
-#define CM36651_PS_IT1                 0x00 /* Integration time 320 usec */
-#define CM36651_PS_IT2                 0x10 /* Integration time 420 usec */
-#define CM36651_PS_IT3                 0x20 /* Integration time 520 usec */
-#define CM36651_PS_IT4                 0x30 /* Integration time 640 usec */
+#define CM36651_PS_IT1                 0x00 /* Integration time 0.32 msec */
+#define CM36651_PS_IT2                 0x10 /* Integration time 0.42 msec */
+#define CM36651_PS_IT3                 0x20 /* Integration time 0.52 msec */
+#define CM36651_PS_IT4                 0x30 /* Integration time 0.64 msec */
 
 /* PS_CONF1 command code: duty ratio */
 #define CM36651_PS_DR1                 0x00 /* Duty ratio 1/80 */
@@ -93,8 +93,8 @@
 #define CM36651_CLOSE_PROXIMITY                0x32
 #define CM36651_FAR_PROXIMITY                  0x33
 
-#define CM36651_CS_INT_TIME_AVAIL      "80000 160000 320000 640000"
-#define CM36651_PS_INT_TIME_AVAIL      "320 420 520 640"
+#define CM36651_CS_INT_TIME_AVAIL      "0.08 0.16 0.32 0.64"
+#define CM36651_PS_INT_TIME_AVAIL      "0.000320 0.000420 0.000520 0.000640"
 
 enum cm36651_operation_mode {
        CM36651_LIGHT_EN,
@@ -356,30 +356,30 @@ static int cm36651_read_channel(struct cm36651_data *cm36651,
 }
 
 static int cm36651_read_int_time(struct cm36651_data *cm36651,
-                               struct iio_chan_spec const *chan, int *val)
+                               struct iio_chan_spec const *chan, int *val2)
 {
        switch (chan->type) {
        case IIO_LIGHT:
                if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT1)
-                       *val = 80000;
+                       *val2 = 80000;
                else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT2)
-                       *val = 160000;
+                       *val2 = 160000;
                else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT3)
-                       *val = 320000;
+                       *val2 = 320000;
                else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT4)
-                       *val = 640000;
+                       *val2 = 640000;
                else
                        return -EINVAL;
                break;
        case IIO_PROXIMITY:
                if (cm36651->ps_int_time == CM36651_PS_IT1)
-                       *val = 320;
+                       *val2 = 320;
                else if (cm36651->ps_int_time == CM36651_PS_IT2)
-                       *val = 420;
+                       *val2 = 420;
                else if (cm36651->ps_int_time == CM36651_PS_IT3)
-                       *val = 520;
+                       *val2 = 520;
                else if (cm36651->ps_int_time == CM36651_PS_IT4)
-                       *val = 640;
+                       *val2 = 640;
                else
                        return -EINVAL;
                break;
@@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651,
                return -EINVAL;
        }
 
-       return IIO_VAL_INT;
+       return IIO_VAL_INT_PLUS_MICRO;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
@@ -459,7 +459,8 @@ static int cm36651_read_raw(struct iio_dev *indio_dev,
                ret = cm36651_read_channel(cm36651, chan, val);
                break;
        case IIO_CHAN_INFO_INT_TIME:
-               ret = cm36651_read_int_time(cm36651, chan, val);
+               *val = 0;
+               ret = cm36651_read_int_time(cm36651, chan, val2);
                break;
        default:
                ret = -EINVAL;
@@ -479,7 +480,7 @@ static int cm36651_write_raw(struct iio_dev *indio_dev,
        int ret = -EINVAL;
 
        if (mask == IIO_CHAN_INFO_INT_TIME) {
-               ret = cm36651_write_int_time(cm36651, chan, val);
+               ret = cm36651_write_int_time(cm36651, chan, val2);
                if (ret < 0)
                        dev_err(&client->dev, "Integration time write failed\n");
        }
index 3d8110157f2d4b33557be5415504ca81b992cf4d..94daa9fc12478b868dbe73a5cdce7a767bdc34a3 100644 (file)
@@ -460,10 +460,14 @@ static int tsl2563_write_raw(struct iio_dev *indio_dev,
 {
        struct tsl2563_chip *chip = iio_priv(indio_dev);
 
-       if (chan->channel == IIO_MOD_LIGHT_BOTH)
+       if (mask != IIO_CHAN_INFO_CALIBSCALE)
+               return -EINVAL;
+       if (chan->channel2 == IIO_MOD_LIGHT_BOTH)
                chip->calib0 = calib_from_sysfs(val);
-       else
+       else if (chan->channel2 == IIO_MOD_LIGHT_IR)
                chip->calib1 = calib_from_sysfs(val);
+       else
+               return -EINVAL;
 
        return 0;
 }
@@ -472,14 +476,14 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
                            struct iio_chan_spec const *chan,
                            int *val,
                            int *val2,
-                           long m)
+                           long mask)
 {
        int ret = -EINVAL;
        u32 calib0, calib1;
        struct tsl2563_chip *chip = iio_priv(indio_dev);
 
        mutex_lock(&chip->lock);
-       switch (m) {
+       switch (mask) {
        case IIO_CHAN_INFO_RAW:
        case IIO_CHAN_INFO_PROCESSED:
                switch (chan->type) {
@@ -498,7 +502,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
                        ret = tsl2563_get_adc(chip);
                        if (ret)
                                goto error_ret;
-                       if (chan->channel == 0)
+                       if (chan->channel2 == IIO_MOD_LIGHT_BOTH)
                                *val = chip->data0;
                        else
                                *val = chip->data1;
@@ -510,7 +514,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev,
                break;
 
        case IIO_CHAN_INFO_CALIBSCALE:
-               if (chan->channel == 0)
+               if (chan->channel2 == IIO_MOD_LIGHT_BOTH)
                        *val = calib_to_sysfs(chip->calib0);
                else
                        *val = calib_to_sysfs(chip->calib1);
index ff284e5afd9587c4e8a14bc9633b018098ce983c..05423543f89d7896ba1a6f086b409955c35417fa 100644 (file)
@@ -85,6 +85,7 @@
 #define AK8975_MAX_CONVERSION_TIMEOUT  500
 #define AK8975_CONVERSION_DONE_POLL_TIME 10
 #define AK8975_DATA_READY_TIMEOUT      ((100*HZ)/1000)
+#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256)
 
 /*
  * Per-instance context data for the device.
@@ -265,15 +266,15 @@ static int ak8975_setup(struct i2c_client *client)
  *
  * Since 1uT = 0.01 gauss, our final scale factor becomes:
  *
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
+ * Hadj = H * ((ASA + 128) * 0.003) / 256
  *
  * Since ASA doesn't change, we cache the resultant scale factor into the
  * device context in ak8975_setup().
  */
-       data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
-       data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
-       data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
+       data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]);
+       data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]);
+       data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]);
 
        return 0;
 }
@@ -428,8 +429,9 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_RAW:
                return ak8975_read_axis(indio_dev, chan->address, val);
        case IIO_CHAN_INFO_SCALE:
-               *val = data->raw_to_gauss[chan->address];
-               return IIO_VAL_INT;
+               *val = 0;
+               *val2 = data->raw_to_gauss[chan->address];
+               return IIO_VAL_INT_PLUS_MICRO;
        }
        return -EINVAL;
 }
index 4b65b6d3bdb17696027f58c34887befaaa209671..f66955fb3509e261f3a0d0cf7028f6178b3cb1a2 100644 (file)
@@ -106,7 +106,7 @@ static ssize_t mag3110_show_int_plus_micros(char *buf,
 
        while (n-- > 0)
                len += scnprintf(buf + len, PAGE_SIZE - len,
-                       "%d.%d ", vals[n][0], vals[n][1]);
+                       "%d.%06d ", vals[n][0], vals[n][1]);
 
        /* replace trailing space by newline */
        buf[len - 1] = '\n';
@@ -154,6 +154,9 @@ static int mag3110_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
+               if (iio_buffer_enabled(indio_dev))
+                       return -EBUSY;
+
                switch (chan->type) {
                case IIO_MAGN: /* in 0.1 uT / LSB */
                        ret = mag3110_read(data, buffer);
@@ -199,6 +202,9 @@ static int mag3110_write_raw(struct iio_dev *indio_dev,
        struct mag3110_data *data = iio_priv(indio_dev);
        int rate;
 
+       if (iio_buffer_enabled(indio_dev))
+               return -EBUSY;
+
        switch (mask) {
        case IIO_CHAN_INFO_SAMP_FREQ:
                rate = mag3110_get_samp_freq_index(data, val, val2);
index d53cf519f42a4267bcfecf487343150eed1cc7f9..00400c352c1a9ec33e7c291bcb997049686816c5 100644 (file)
@@ -1082,6 +1082,7 @@ static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
 
        /* Initialize network device */
        if ((netdev = c2_devinit(c2dev, mmio_regs)) == NULL) {
+               ret = -ENOMEM;
                iounmap(mmio_regs);
                goto bail4;
        }
@@ -1151,7 +1152,8 @@ static int c2_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
                goto bail10;
        }
 
-       if (c2_register_device(c2dev))
+       ret = c2_register_device(c2dev);
+       if (ret)
                goto bail10;
 
        return 0;
index b7c986990053da3f379bd013e7ed9a3bf1d893db..d2a6d961344b7e6f32855fad7b176149964bd43e 100644 (file)
@@ -576,7 +576,8 @@ int c2_rnic_init(struct c2_dev *c2dev)
                goto bail4;
 
        /* Initialize cached the adapter limits */
-       if (c2_rnic_query(c2dev, &c2dev->props))
+       err = c2_rnic_query(c2dev, &c2dev->props);
+       if (err)
                goto bail5;
 
        /* Initialize the PD pool */
index 45126879ad28a2149351232a1f9c4a2551f06c09..d286bdebe2ab90fc613c7696d41690909247da52 100644 (file)
@@ -3352,6 +3352,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
                goto free_dst;
        }
 
+       neigh_release(neigh);
        step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
        rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step];
        window = (__force u16) htons((__force u16)tcph->window);
index c2702f549f10aae4f7ef115fc25a238fb65c25bd..f9c12e92fdd661a4e639790c9b2b2dd19ba7eb36 100644 (file)
@@ -53,8 +53,8 @@
 #include "user.h"
 
 #define DRV_NAME       MLX4_IB_DRV_NAME
-#define DRV_VERSION    "1.0"
-#define DRV_RELDATE    "April 4, 2008"
+#define DRV_VERSION    "2.2-1"
+#define DRV_RELDATE    "Feb 2014"
 
 #define MLX4_IB_FLOW_MAX_PRIO 0xFFF
 #define MLX4_IB_FLOW_QPN_MASK 0xFFFFFF
@@ -347,7 +347,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
        props->active_width     =  (((u8 *)mailbox->buf)[5] == 0x40) ?
                                                IB_WIDTH_4X : IB_WIDTH_1X;
        props->active_speed     = IB_SPEED_QDR;
-       props->port_cap_flags   = IB_PORT_CM_SUP;
+       props->port_cap_flags   = IB_PORT_CM_SUP | IB_PORT_IP_BASED_GIDS;
        props->gid_tbl_len      = mdev->dev->caps.gid_table_len[port];
        props->max_msg_sz       = mdev->dev->caps.max_msg_sz;
        props->pkey_tbl_len     = 1;
@@ -1357,6 +1357,21 @@ static struct device_attribute *mlx4_class_attributes[] = {
        &dev_attr_board_id
 };
 
+static void mlx4_addrconf_ifid_eui48(u8 *eui, u16 vlan_id,
+                                    struct net_device *dev)
+{
+       memcpy(eui, dev->dev_addr, 3);
+       memcpy(eui + 5, dev->dev_addr + 3, 3);
+       if (vlan_id < 0x1000) {
+               eui[3] = vlan_id >> 8;
+               eui[4] = vlan_id & 0xff;
+       } else {
+               eui[3] = 0xff;
+               eui[4] = 0xfe;
+       }
+       eui[0] ^= 2;
+}
+
 static void update_gids_task(struct work_struct *work)
 {
        struct update_gid_work *gw = container_of(work, struct update_gid_work, work);
@@ -1393,7 +1408,6 @@ static void reset_gids_task(struct work_struct *work)
        struct mlx4_cmd_mailbox *mailbox;
        union ib_gid *gids;
        int err;
-       int i;
        struct mlx4_dev *dev = gw->dev->dev;
 
        mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -1405,18 +1419,16 @@ static void reset_gids_task(struct work_struct *work)
        gids = mailbox->buf;
        memcpy(gids, gw->gids, sizeof(gw->gids));
 
-       for (i = 1; i < gw->dev->num_ports + 1; i++) {
-               if (mlx4_ib_port_link_layer(&gw->dev->ib_dev, i) ==
-                                           IB_LINK_LAYER_ETHERNET) {
-                       err = mlx4_cmd(dev, mailbox->dma,
-                                      MLX4_SET_PORT_GID_TABLE << 8 | i,
-                                      1, MLX4_CMD_SET_PORT,
-                                      MLX4_CMD_TIME_CLASS_B,
-                                      MLX4_CMD_WRAPPED);
-                       if (err)
-                               pr_warn(KERN_WARNING
-                                       "set port %d command failed\n", i);
-               }
+       if (mlx4_ib_port_link_layer(&gw->dev->ib_dev, gw->port) ==
+                                   IB_LINK_LAYER_ETHERNET) {
+               err = mlx4_cmd(dev, mailbox->dma,
+                              MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
+                              1, MLX4_CMD_SET_PORT,
+                              MLX4_CMD_TIME_CLASS_B,
+                              MLX4_CMD_WRAPPED);
+               if (err)
+                       pr_warn(KERN_WARNING
+                               "set port %d command failed\n", gw->port);
        }
 
        mlx4_free_cmd_mailbox(dev, mailbox);
@@ -1425,7 +1437,8 @@ free:
 }
 
 static int update_gid_table(struct mlx4_ib_dev *dev, int port,
-                           union ib_gid *gid, int clear)
+                           union ib_gid *gid, int clear,
+                           int default_gid)
 {
        struct update_gid_work *work;
        int i;
@@ -1434,26 +1447,31 @@ static int update_gid_table(struct mlx4_ib_dev *dev, int port,
        int found = -1;
        int max_gids;
 
-       max_gids = dev->dev->caps.gid_table_len[port];
-       for (i = 0; i < max_gids; ++i) {
-               if (!memcmp(&dev->iboe.gid_table[port - 1][i], gid,
-                           sizeof(*gid)))
-                       found = i;
-
-               if (clear) {
-                       if (found >= 0) {
-                               need_update = 1;
-                               dev->iboe.gid_table[port - 1][found] = zgid;
-                               break;
-                       }
-               } else {
-                       if (found >= 0)
-                               break;
-
-                       if (free < 0 &&
-                           !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid,
+       if (default_gid) {
+               free = 0;
+       } else {
+               max_gids = dev->dev->caps.gid_table_len[port];
+               for (i = 1; i < max_gids; ++i) {
+                       if (!memcmp(&dev->iboe.gid_table[port - 1][i], gid,
                                    sizeof(*gid)))
-                               free = i;
+                               found = i;
+
+                       if (clear) {
+                               if (found >= 0) {
+                                       need_update = 1;
+                                       dev->iboe.gid_table[port - 1][found] =
+                                               zgid;
+                                       break;
+                               }
+                       } else {
+                               if (found >= 0)
+                                       break;
+
+                               if (free < 0 &&
+                                   !memcmp(&dev->iboe.gid_table[port - 1][i],
+                                           &zgid, sizeof(*gid)))
+                                       free = i;
+                       }
                }
        }
 
@@ -1478,18 +1496,26 @@ static int update_gid_table(struct mlx4_ib_dev *dev, int port,
        return 0;
 }
 
-static int reset_gid_table(struct mlx4_ib_dev *dev)
+static void mlx4_make_default_gid(struct  net_device *dev, union ib_gid *gid)
 {
-       struct update_gid_work *work;
+       gid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
+       mlx4_addrconf_ifid_eui48(&gid->raw[8], 0xffff, dev);
+}
+
 
+static int reset_gid_table(struct mlx4_ib_dev *dev, u8 port)
+{
+       struct update_gid_work *work;
 
        work = kzalloc(sizeof(*work), GFP_ATOMIC);
        if (!work)
                return -ENOMEM;
-       memset(dev->iboe.gid_table, 0, sizeof(dev->iboe.gid_table));
+
+       memset(dev->iboe.gid_table[port - 1], 0, sizeof(work->gids));
        memset(work->gids, 0, sizeof(work->gids));
        INIT_WORK(&work->work, reset_gids_task);
        work->dev = dev;
+       work->port = port;
        queue_work(wq, &work->work);
        return 0;
 }
@@ -1502,6 +1528,12 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev,
        struct net_device *real_dev = rdma_vlan_dev_real_dev(event_netdev) ?
                                rdma_vlan_dev_real_dev(event_netdev) :
                                event_netdev;
+       union ib_gid default_gid;
+
+       mlx4_make_default_gid(real_dev, &default_gid);
+
+       if (!memcmp(gid, &default_gid, sizeof(*gid)))
+               return 0;
 
        if (event != NETDEV_DOWN && event != NETDEV_UP)
                return 0;
@@ -1520,7 +1552,7 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev,
                     (!netif_is_bond_master(real_dev) &&
                     (real_dev == iboe->netdevs[port - 1])))
                        update_gid_table(ibdev, port, gid,
-                                        event == NETDEV_DOWN);
+                                        event == NETDEV_DOWN, 0);
 
        spin_unlock(&iboe->lock);
        return 0;
@@ -1536,7 +1568,6 @@ static u8 mlx4_ib_get_dev_port(struct net_device *dev,
                                rdma_vlan_dev_real_dev(dev) : dev;
 
        iboe = &ibdev->iboe;
-       spin_lock(&iboe->lock);
 
        for (port = 1; port <= MLX4_MAX_PORTS; ++port)
                if ((netif_is_bond_master(real_dev) &&
@@ -1545,8 +1576,6 @@ static u8 mlx4_ib_get_dev_port(struct net_device *dev,
                     (real_dev == iboe->netdevs[port - 1])))
                        break;
 
-       spin_unlock(&iboe->lock);
-
        if ((port == 0) || (port > MLX4_MAX_PORTS))
                return 0;
        else
@@ -1607,7 +1636,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev,
                        /*ifa->ifa_address;*/
                        ipv6_addr_set_v4mapped(ifa->ifa_address,
                                               (struct in6_addr *)&gid);
-                       update_gid_table(ibdev, port, &gid, 0);
+                       update_gid_table(ibdev, port, &gid, 0, 0);
                }
                endfor_ifa(in_dev);
                in_dev_put(in_dev);
@@ -1619,7 +1648,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev,
                read_lock_bh(&in6_dev->lock);
                list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
                        pgid = (union ib_gid *)&ifp->addr;
-                       update_gid_table(ibdev, port, pgid, 0);
+                       update_gid_table(ibdev, port, pgid, 0, 0);
                }
                read_unlock_bh(&in6_dev->lock);
                in6_dev_put(in6_dev);
@@ -1627,14 +1656,26 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev,
 #endif
 }
 
+static void mlx4_ib_set_default_gid(struct mlx4_ib_dev *ibdev,
+                                struct  net_device *dev, u8 port)
+{
+       union ib_gid gid;
+       mlx4_make_default_gid(dev, &gid);
+       update_gid_table(ibdev, port, &gid, 0, 1);
+}
+
 static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev)
 {
        struct  net_device *dev;
+       struct mlx4_ib_iboe *iboe = &ibdev->iboe;
+       int i;
 
-       if (reset_gid_table(ibdev))
-               return -1;
+       for (i = 1; i <= ibdev->num_ports; ++i)
+               if (reset_gid_table(ibdev, i))
+                       return -1;
 
        read_lock(&dev_base_lock);
+       spin_lock(&iboe->lock);
 
        for_each_netdev(&init_net, dev) {
                u8 port = mlx4_ib_get_dev_port(dev, ibdev);
@@ -1642,6 +1683,7 @@ static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev)
                        mlx4_ib_get_dev_addr(dev, ibdev, port);
        }
 
+       spin_unlock(&iboe->lock);
        read_unlock(&dev_base_lock);
 
        return 0;
@@ -1656,25 +1698,57 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev)
 
        spin_lock(&iboe->lock);
        mlx4_foreach_ib_transport_port(port, ibdev->dev) {
+               enum ib_port_state      port_state = IB_PORT_NOP;
                struct net_device *old_master = iboe->masters[port - 1];
+               struct net_device *curr_netdev;
                struct net_device *curr_master;
+
                iboe->netdevs[port - 1] =
                        mlx4_get_protocol_dev(ibdev->dev, MLX4_PROT_ETH, port);
+               if (iboe->netdevs[port - 1])
+                       mlx4_ib_set_default_gid(ibdev,
+                                               iboe->netdevs[port - 1], port);
+               curr_netdev = iboe->netdevs[port - 1];
 
                if (iboe->netdevs[port - 1] &&
                    netif_is_bond_slave(iboe->netdevs[port - 1])) {
-                       rtnl_lock();
                        iboe->masters[port - 1] = netdev_master_upper_dev_get(
                                iboe->netdevs[port - 1]);
-                       rtnl_unlock();
+               } else {
+                       iboe->masters[port - 1] = NULL;
                }
                curr_master = iboe->masters[port - 1];
 
+               if (curr_netdev) {
+                       port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ?
+                                               IB_PORT_ACTIVE : IB_PORT_DOWN;
+                       mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
+               } else {
+                       reset_gid_table(ibdev, port);
+               }
+               /* if using bonding/team and a slave port is down, we don't the bond IP
+                * based gids in the table since flows that select port by gid may get
+                * the down port.
+                */
+               if (curr_master && (port_state == IB_PORT_DOWN)) {
+                       reset_gid_table(ibdev, port);
+                       mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
+               }
                /* if bonding is used it is possible that we add it to masters
-                   only after IP address is assigned to the net bonding
-                   interface */
-               if (curr_master && (old_master != curr_master))
+                * only after IP address is assigned to the net bonding
+                * interface.
+               */
+               if (curr_master && (old_master != curr_master)) {
+                       reset_gid_table(ibdev, port);
+                       mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
                        mlx4_ib_get_dev_addr(curr_master, ibdev, port);
+               }
+
+               if (!curr_master && (old_master != curr_master)) {
+                       reset_gid_table(ibdev, port);
+                       mlx4_ib_set_default_gid(ibdev, curr_netdev, port);
+                       mlx4_ib_get_dev_addr(curr_netdev, ibdev, port);
+               }
        }
 
        spin_unlock(&iboe->lock);
@@ -1810,6 +1884,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        int i, j;
        int err;
        struct mlx4_ib_iboe *iboe;
+       int ib_num_ports = 0;
 
        pr_info_once("%s", mlx4_ib_version);
 
@@ -1985,10 +2060,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                                ibdev->counters[i] = -1;
        }
 
+       mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+               ib_num_ports++;
+
        spin_lock_init(&ibdev->sm_lock);
        mutex_init(&ibdev->cap_mask_mutex);
 
-       if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED) {
+       if (ibdev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED &&
+           ib_num_ports) {
                ibdev->steer_qpn_count = MLX4_IB_UC_MAX_NUM_QPS;
                err = mlx4_qp_reserve_range(dev, ibdev->steer_qpn_count,
                                            MLX4_IB_UC_STEER_QPN_ALIGN,
@@ -2051,7 +2130,11 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                        }
                }
 #endif
+               for (i = 1 ; i <= ibdev->num_ports ; ++i)
+                       reset_gid_table(ibdev, i);
+               rtnl_lock();
                mlx4_ib_scan_netdevs(ibdev);
+               rtnl_unlock();
                mlx4_ib_init_gid_table(ibdev);
        }
 
index 8e6aebfaf8a4cdb5c8cc503c24ac1701e1731c3c..10df386c63447c9757fa22bfc97c433b59ea3895 100644 (file)
@@ -1,6 +1,6 @@
 config MLX5_INFINIBAND
        tristate "Mellanox Connect-IB HCA support"
-       depends on NETDEVICES && ETHERNET && PCI && X86
+       depends on NETDEVICES && ETHERNET && PCI
        select NET_VENDOR_MELLANOX
        select MLX5_CORE
        ---help---
index 9660d093f8cf14cdb686f2b432f6eca96519fb8b..bf900579ac08b4cae5ac09320b5189727b292485 100644 (file)
@@ -46,8 +46,8 @@
 #include "mlx5_ib.h"
 
 #define DRIVER_NAME "mlx5_ib"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_RELDATE "June 2013"
+#define DRIVER_VERSION "2.2-1"
+#define DRIVER_RELDATE "Feb 2014"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox Connect-IB HCA IB driver");
@@ -261,8 +261,7 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
        props->device_cap_flags    = IB_DEVICE_CHANGE_PHY_PORT |
                IB_DEVICE_PORT_ACTIVE_EVENT             |
                IB_DEVICE_SYS_IMAGE_GUID                |
-               IB_DEVICE_RC_RNR_NAK_GEN                |
-               IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
+               IB_DEVICE_RC_RNR_NAK_GEN;
        flags = dev->mdev.caps.flags;
        if (flags & MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR)
                props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
@@ -536,24 +535,38 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
                                                  struct ib_udata *udata)
 {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
-       struct mlx5_ib_alloc_ucontext_req req;
+       struct mlx5_ib_alloc_ucontext_req_v2 req;
        struct mlx5_ib_alloc_ucontext_resp resp;
        struct mlx5_ib_ucontext *context;
        struct mlx5_uuar_info *uuari;
        struct mlx5_uar *uars;
        int gross_uuars;
        int num_uars;
+       int ver;
        int uuarn;
        int err;
        int i;
+       int reqlen;
 
        if (!dev->ib_active)
                return ERR_PTR(-EAGAIN);
 
-       err = ib_copy_from_udata(&req, udata, sizeof(req));
+       memset(&req, 0, sizeof(req));
+       reqlen = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr);
+       if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req))
+               ver = 0;
+       else if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req_v2))
+               ver = 2;
+       else
+               return ERR_PTR(-EINVAL);
+
+       err = ib_copy_from_udata(&req, udata, reqlen);
        if (err)
                return ERR_PTR(err);
 
+       if (req.flags || req.reserved)
+               return ERR_PTR(-EINVAL);
+
        if (req.total_num_uuars > MLX5_MAX_UUARS)
                return ERR_PTR(-ENOMEM);
 
@@ -626,6 +639,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        if (err)
                goto out_uars;
 
+       uuari->ver = ver;
        uuari->num_low_latency_uuars = req.num_low_latency_uuars;
        uuari->uars = uars;
        uuari->num_uars = num_uars;
index ae37fb9bf2627c7507dfb7b6a75e369e5b5fe29f..7dfe8a1c84cff141a2bee714e6367f5500334390 100644 (file)
@@ -216,7 +216,9 @@ static int sq_overhead(enum ib_qp_type qp_type)
 
        case IB_QPT_UC:
                size += sizeof(struct mlx5_wqe_ctrl_seg) +
-                       sizeof(struct mlx5_wqe_raddr_seg);
+                       sizeof(struct mlx5_wqe_raddr_seg) +
+                       sizeof(struct mlx5_wqe_umr_ctrl_seg) +
+                       sizeof(struct mlx5_mkey_seg);
                break;
 
        case IB_QPT_UD:
@@ -428,11 +430,17 @@ static int alloc_uuar(struct mlx5_uuar_info *uuari,
                break;
 
        case MLX5_IB_LATENCY_CLASS_MEDIUM:
-               uuarn = alloc_med_class_uuar(uuari);
+               if (uuari->ver < 2)
+                       uuarn = -ENOMEM;
+               else
+                       uuarn = alloc_med_class_uuar(uuari);
                break;
 
        case MLX5_IB_LATENCY_CLASS_HIGH:
-               uuarn = alloc_high_class_uuar(uuari);
+               if (uuari->ver < 2)
+                       uuarn = -ENOMEM;
+               else
+                       uuarn = alloc_high_class_uuar(uuari);
                break;
 
        case MLX5_IB_LATENCY_CLASS_FAST_PATH:
@@ -657,8 +665,8 @@ static int create_kernel_qp(struct mlx5_ib_dev *dev,
        int err;
 
        uuari = &dev->mdev.priv.uuari;
-       if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
-               qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK;
+       if (init_attr->create_flags)
+               return -EINVAL;
 
        if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR)
                lc = MLX5_IB_LATENCY_CLASS_FAST_PATH;
index 32a2a5dfc52308549b8e9457da44041936c38d70..0f4f8e42a17fe5f067d68782f21598980451c48f 100644 (file)
@@ -62,6 +62,13 @@ struct mlx5_ib_alloc_ucontext_req {
        __u32   num_low_latency_uuars;
 };
 
+struct mlx5_ib_alloc_ucontext_req_v2 {
+       __u32   total_num_uuars;
+       __u32   num_low_latency_uuars;
+       __u32   flags;
+       __u32   reserved;
+};
+
 struct mlx5_ib_alloc_ucontext_resp {
        __u32   qp_tab_size;
        __u32   bf_reg_size;
index 429141078eec632d2409b75f267193f4fb242f96..353c7b05a90a102db8fc22be79187918004334cc 100644 (file)
@@ -675,8 +675,11 @@ static int nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
        INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status);
 
        /* Initialize network devices */
-       if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL)
+       netdev = nes_netdev_init(nesdev, mmio_regs);
+       if (netdev == NULL) {
+               ret = -ENOMEM;
                goto bail7;
+       }
 
        /* Register network device */
        ret = register_netdev(netdev);
index 2ca86ca818bdf04d68a3f21c0cd74fa092c36504..1a8a945efa60e8fdb6683572d0d39e77f7dba36f 100644 (file)
@@ -127,7 +127,7 @@ static int ocrdma_addr_event(unsigned long event, struct net_device *netdev,
 
        is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN;
        if (is_vlan)
-               netdev = vlan_dev_real_dev(netdev);
+               netdev = rdma_vlan_dev_real_dev(netdev);
 
        rcu_read_lock();
        list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) {
index aa92f40c9d50e739a14b0f19fd5e183f63ab964a..e0cc201be41a96df4c177ffa9517fec12988ac7d 100644 (file)
@@ -176,7 +176,7 @@ int ocrdma_query_port(struct ib_device *ibdev,
        props->port_cap_flags =
            IB_PORT_CM_SUP |
            IB_PORT_REINIT_SUP |
-           IB_PORT_DEVICE_MGMT_SUP | IB_PORT_VENDOR_CLASS_SUP;
+           IB_PORT_DEVICE_MGMT_SUP | IB_PORT_VENDOR_CLASS_SUP | IB_PORT_IP_BASED_GIDS;
        props->gid_tbl_len = OCRDMA_MAX_SGID;
        props->pkey_tbl_len = 1;
        props->bad_pkey_cntr = 0;
@@ -1416,7 +1416,7 @@ int ocrdma_query_qp(struct ib_qp *ibqp,
                                          OCRDMA_QP_PARAMS_HOP_LMT_MASK) >>
                                                OCRDMA_QP_PARAMS_HOP_LMT_SHIFT;
        qp_attr->ah_attr.grh.traffic_class = (params.tclass_sq_psn &
-                                             OCRDMA_QP_PARAMS_SQ_PSN_MASK) >>
+                                             OCRDMA_QP_PARAMS_TCLASS_MASK) >>
                                                OCRDMA_QP_PARAMS_TCLASS_SHIFT;
 
        qp_attr->ah_attr.ah_flags = IB_AH_GRH;
index 5bfc02f450e6a69251632db17fb6ff699dfe8c10..d1bd21319d7d2ec128442042448ce101111938a3 100644 (file)
@@ -2395,6 +2395,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
        qib_write_kreg_port(ppd, krp_ibcctrl_a, ppd->cpspec->ibcctrl_a);
        qib_write_kreg(dd, kr_scratch, 0ULL);
 
+       /* ensure previous Tx parameters are not still forced */
+       qib_write_kreg_port(ppd, krp_tx_deemph_override,
+               SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+               reset_tx_deemphasis_override));
+
        if (qib_compat_ddr_negotiate) {
                ppd->cpspec->ibdeltainprog = 1;
                ppd->cpspec->ibsymsnap = read_7322_creg32_port(ppd,
index 7ecc6061f1f4d5f915edb0e3994b2dcdc327de83..f8dfd76be89fbfdcb94559ed58cda9a3d8c591b2 100644 (file)
@@ -629,6 +629,7 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow,
 {
        enum usnic_transport_type trans_type = qp_flow->trans_type;
        int err;
+       uint16_t port_num = 0;
 
        switch (trans_type) {
        case USNIC_TRANSPORT_ROCE_CUSTOM:
@@ -637,9 +638,15 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow,
        case USNIC_TRANSPORT_IPV4_UDP:
                err = usnic_transport_sock_get_addr(qp_flow->udp.sock,
                                                        NULL, NULL,
-                                                       (uint16_t *) id);
+                                                       &port_num);
                if (err)
                        return err;
+               /*
+                * Copy port_num to stack first and then to *id,
+                * so that the short to int cast works for little
+                * and big endian systems.
+                */
+               *id = port_num;
                break;
        default:
                usnic_err("Unsupported transport %u\n", trans_type);
index 538822684d5ba537ce2f11e9366fae0766fd4a6f..334f34b1cd46533b0b1dc6cdec9c9f0f30c2af76 100644 (file)
@@ -610,11 +610,12 @@ void iser_snd_completion(struct iser_tx_desc *tx_desc,
                ib_dma_unmap_single(device->ib_device, tx_desc->dma_addr,
                                        ISER_HEADERS_LEN, DMA_TO_DEVICE);
                kmem_cache_free(ig.desc_cache, tx_desc);
+               tx_desc = NULL;
        }
 
        atomic_dec(&ib_conn->post_send_buf_count);
 
-       if (tx_desc->type == ISCSI_TX_CONTROL) {
+       if (tx_desc && tx_desc->type == ISCSI_TX_CONTROL) {
                /* this arithmetic is legal by libiscsi dd_data allocation */
                task = (void *) ((long)(void *)tx_desc -
                                  sizeof(struct iscsi_task));
index afe95674008be88104d384923129d40fda9f75e8..ca37edef27910cc188ab89a6e626ce29d6d5a344 100644 (file)
@@ -652,9 +652,13 @@ static int iser_disconnected_handler(struct rdma_cm_id *cma_id)
        /* getting here when the state is UP means that the conn is being *
         * terminated asynchronously from the iSCSI layer's perspective.  */
        if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
-                                     ISER_CONN_TERMINATING))
-               iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
-                                  ISCSI_ERR_CONN_FAILED);
+                                       ISER_CONN_TERMINATING)){
+               if (ib_conn->iser_conn)
+                       iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+                                          ISCSI_ERR_CONN_FAILED);
+               else
+                       iser_err("iscsi_iser connection isn't bound\n");
+       }
 
        /* Complete the termination process if no posts are pending */
        if (ib_conn->post_recv_buf_count == 0 &&
index 2b161be3c1a346e3a7203a7f88a624dac4df1cee..8ee228e9ab5aa28b85ee2893a92b3ab243c35388 100644 (file)
@@ -453,6 +453,7 @@ isert_conn_create_fastreg_pool(struct isert_conn *isert_conn)
                if (ret) {
                        pr_err("Failed to create fastreg descriptor err=%d\n",
                               ret);
+                       kfree(fr_desc);
                        goto err;
                }
 
@@ -491,12 +492,11 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        isert_conn->state = ISER_CONN_INIT;
        INIT_LIST_HEAD(&isert_conn->conn_accept_node);
        init_completion(&isert_conn->conn_login_comp);
-       init_waitqueue_head(&isert_conn->conn_wait);
-       init_waitqueue_head(&isert_conn->conn_wait_comp_err);
+       init_completion(&isert_conn->conn_wait);
+       init_completion(&isert_conn->conn_wait_comp_err);
        kref_init(&isert_conn->conn_kref);
        kref_get(&isert_conn->conn_kref);
        mutex_init(&isert_conn->conn_mutex);
-       mutex_init(&isert_conn->conn_comp_mutex);
        spin_lock_init(&isert_conn->conn_lock);
 
        cma_id->context = isert_conn;
@@ -687,11 +687,11 @@ isert_disconnect_work(struct work_struct *work)
 
        pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
        mutex_lock(&isert_conn->conn_mutex);
-       isert_conn->state = ISER_CONN_DOWN;
+       if (isert_conn->state == ISER_CONN_UP)
+               isert_conn->state = ISER_CONN_TERMINATING;
 
        if (isert_conn->post_recv_buf_count == 0 &&
            atomic_read(&isert_conn->post_send_buf_count) == 0) {
-               pr_debug("Calling wake_up(&isert_conn->conn_wait);\n");
                mutex_unlock(&isert_conn->conn_mutex);
                goto wake_up;
        }
@@ -711,7 +711,7 @@ isert_disconnect_work(struct work_struct *work)
        mutex_unlock(&isert_conn->conn_mutex);
 
 wake_up:
-       wake_up(&isert_conn->conn_wait);
+       complete(&isert_conn->conn_wait);
        isert_put_conn(isert_conn);
 }
 
@@ -887,16 +887,17 @@ isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
         * Coalesce send completion interrupts by only setting IB_SEND_SIGNALED
         * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls.
         */
-       mutex_lock(&isert_conn->conn_comp_mutex);
-       if (coalesce &&
+       mutex_lock(&isert_conn->conn_mutex);
+       if (coalesce && isert_conn->state == ISER_CONN_UP &&
            ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) {
+               tx_desc->llnode_active = true;
                llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist);
-               mutex_unlock(&isert_conn->conn_comp_mutex);
+               mutex_unlock(&isert_conn->conn_mutex);
                return;
        }
        isert_conn->conn_comp_batch = 0;
        tx_desc->comp_llnode_batch = llist_del_all(&isert_conn->conn_comp_llist);
-       mutex_unlock(&isert_conn->conn_comp_mutex);
+       mutex_unlock(&isert_conn->conn_mutex);
 
        send_wr->send_flags = IB_SEND_SIGNALED;
 }
@@ -1463,7 +1464,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
        case ISCSI_OP_SCSI_CMD:
                spin_lock_bh(&conn->cmd_lock);
                if (!list_empty(&cmd->i_conn_node))
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
                if (cmd->data_direction == DMA_TO_DEVICE)
@@ -1475,7 +1476,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
        case ISCSI_OP_SCSI_TMFUNC:
                spin_lock_bh(&conn->cmd_lock);
                if (!list_empty(&cmd->i_conn_node))
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
                transport_generic_free_cmd(&cmd->se_cmd, 0);
@@ -1485,7 +1486,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
        case ISCSI_OP_TEXT:
                spin_lock_bh(&conn->cmd_lock);
                if (!list_empty(&cmd->i_conn_node))
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
                /*
@@ -1548,6 +1549,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
        iscsit_stop_dataout_timer(cmd);
        device->unreg_rdma_mem(isert_cmd, isert_conn);
        cmd->write_data_done = wr->cur_rdma_length;
+       wr->send_wr_num = 0;
 
        pr_debug("Cmd: %p RDMA_READ comp calling execute_cmd\n", isert_cmd);
        spin_lock_bh(&cmd->istate_lock);
@@ -1588,7 +1590,7 @@ isert_do_control_comp(struct work_struct *work)
                pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n");
                /*
                 * Call atomic_dec(&isert_conn->post_send_buf_count)
-                * from isert_free_conn()
+                * from isert_wait_conn()
                 */
                isert_conn->logout_posted = true;
                iscsit_logout_post_handler(cmd, cmd->conn);
@@ -1612,6 +1614,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
                          struct ib_device *ib_dev)
 {
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
+       struct isert_rdma_wr *wr = &isert_cmd->rdma_wr;
 
        if (cmd->i_state == ISTATE_SEND_TASKMGTRSP ||
            cmd->i_state == ISTATE_SEND_LOGOUTRSP ||
@@ -1623,7 +1626,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
                queue_work(isert_comp_wq, &isert_cmd->comp_work);
                return;
        }
-       atomic_dec(&isert_conn->post_send_buf_count);
+       atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
 
        cmd->i_state = ISTATE_SENT_STATUS;
        isert_completion_put(tx_desc, isert_cmd, ib_dev);
@@ -1661,7 +1664,7 @@ __isert_send_completion(struct iser_tx_desc *tx_desc,
        case ISER_IB_RDMA_READ:
                pr_debug("isert_send_completion: Got ISER_IB_RDMA_READ:\n");
 
-               atomic_dec(&isert_conn->post_send_buf_count);
+               atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count);
                isert_completion_rdma_read(tx_desc, isert_cmd);
                break;
        default:
@@ -1690,31 +1693,76 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
 }
 
 static void
-isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
+isert_cq_drain_comp_llist(struct isert_conn *isert_conn, struct ib_device *ib_dev)
+{
+       struct llist_node *llnode;
+       struct isert_rdma_wr *wr;
+       struct iser_tx_desc *t;
+
+       mutex_lock(&isert_conn->conn_mutex);
+       llnode = llist_del_all(&isert_conn->conn_comp_llist);
+       isert_conn->conn_comp_batch = 0;
+       mutex_unlock(&isert_conn->conn_mutex);
+
+       while (llnode) {
+               t = llist_entry(llnode, struct iser_tx_desc, comp_llnode);
+               llnode = llist_next(llnode);
+               wr = &t->isert_cmd->rdma_wr;
+
+               atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
+               isert_completion_put(t, t->isert_cmd, ib_dev);
+       }
+}
+
+static void
+isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn)
 {
        struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
+       struct llist_node *llnode = tx_desc->comp_llnode_batch;
+       struct isert_rdma_wr *wr;
+       struct iser_tx_desc *t;
 
-       if (tx_desc) {
-               struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
+       while (llnode) {
+               t = llist_entry(llnode, struct iser_tx_desc, comp_llnode);
+               llnode = llist_next(llnode);
+               wr = &t->isert_cmd->rdma_wr;
 
-               if (!isert_cmd)
-                       isert_unmap_tx_desc(tx_desc, ib_dev);
-               else
-                       isert_completion_put(tx_desc, isert_cmd, ib_dev);
+               atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
+               isert_completion_put(t, t->isert_cmd, ib_dev);
        }
+       tx_desc->comp_llnode_batch = NULL;
 
-       if (isert_conn->post_recv_buf_count == 0 &&
-           atomic_read(&isert_conn->post_send_buf_count) == 0) {
-               pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
-               pr_debug("Calling wake_up from isert_cq_comp_err\n");
+       if (!isert_cmd)
+               isert_unmap_tx_desc(tx_desc, ib_dev);
+       else
+               isert_completion_put(tx_desc, isert_cmd, ib_dev);
+}
 
-               mutex_lock(&isert_conn->conn_mutex);
-               if (isert_conn->state != ISER_CONN_DOWN)
-                       isert_conn->state = ISER_CONN_TERMINATING;
-               mutex_unlock(&isert_conn->conn_mutex);
+static void
+isert_cq_rx_comp_err(struct isert_conn *isert_conn)
+{
+       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct iscsi_conn *conn = isert_conn->conn;
 
-               wake_up(&isert_conn->conn_wait_comp_err);
+       if (isert_conn->post_recv_buf_count)
+               return;
+
+       isert_cq_drain_comp_llist(isert_conn, ib_dev);
+
+       if (conn->sess) {
+               target_sess_cmd_list_set_waiting(conn->sess->se_sess);
+               target_wait_for_sess_cmds(conn->sess->se_sess);
        }
+
+       while (atomic_read(&isert_conn->post_send_buf_count))
+               msleep(3000);
+
+       mutex_lock(&isert_conn->conn_mutex);
+       isert_conn->state = ISER_CONN_DOWN;
+       mutex_unlock(&isert_conn->conn_mutex);
+
+       complete(&isert_conn->conn_wait_comp_err);
 }
 
 static void
@@ -1739,8 +1787,14 @@ isert_cq_tx_work(struct work_struct *work)
                        pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n");
                        pr_debug("TX wc.status: 0x%08x\n", wc.status);
                        pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err);
-                       atomic_dec(&isert_conn->post_send_buf_count);
-                       isert_cq_comp_err(tx_desc, isert_conn);
+
+                       if (wc.wr_id != ISER_FASTREG_LI_WRID) {
+                               if (tx_desc->llnode_active)
+                                       continue;
+
+                               atomic_dec(&isert_conn->post_send_buf_count);
+                               isert_cq_tx_comp_err(tx_desc, isert_conn);
+                       }
                }
        }
 
@@ -1783,7 +1837,7 @@ isert_cq_rx_work(struct work_struct *work)
                                         wc.vendor_err);
                        }
                        isert_conn->post_recv_buf_count--;
-                       isert_cq_comp_err(NULL, isert_conn);
+                       isert_cq_rx_comp_err(isert_conn);
                }
        }
 
@@ -2201,6 +2255,7 @@ isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc,
 
        if (!fr_desc->valid) {
                memset(&inv_wr, 0, sizeof(inv_wr));
+               inv_wr.wr_id = ISER_FASTREG_LI_WRID;
                inv_wr.opcode = IB_WR_LOCAL_INV;
                inv_wr.ex.invalidate_rkey = fr_desc->data_mr->rkey;
                wr = &inv_wr;
@@ -2211,6 +2266,7 @@ isert_fast_reg_mr(struct fast_reg_descriptor *fr_desc,
 
        /* Prepare FASTREG WR */
        memset(&fr_wr, 0, sizeof(fr_wr));
+       fr_wr.wr_id = ISER_FASTREG_LI_WRID;
        fr_wr.opcode = IB_WR_FAST_REG_MR;
        fr_wr.wr.fast_reg.iova_start =
                fr_desc->data_frpl->page_list[0] + page_off;
@@ -2376,12 +2432,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
        isert_init_send_wr(isert_conn, isert_cmd,
                           &isert_cmd->tx_desc.send_wr, true);
 
-       atomic_inc(&isert_conn->post_send_buf_count);
+       atomic_add(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
 
        rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed);
        if (rc) {
                pr_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n");
-               atomic_dec(&isert_conn->post_send_buf_count);
+               atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count);
        }
        pr_debug("Cmd: %p posted RDMA_WRITE + Response for iSER Data READ\n",
                 isert_cmd);
@@ -2409,12 +2465,12 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
                return rc;
        }
 
-       atomic_inc(&isert_conn->post_send_buf_count);
+       atomic_add(wr->send_wr_num, &isert_conn->post_send_buf_count);
 
        rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed);
        if (rc) {
                pr_warn("ib_post_send() failed for IB_WR_RDMA_READ\n");
-               atomic_dec(&isert_conn->post_send_buf_count);
+               atomic_sub(wr->send_wr_num, &isert_conn->post_send_buf_count);
        }
        pr_debug("Cmd: %p posted RDMA_READ memory for ISER Data WRITE\n",
                 isert_cmd);
@@ -2701,22 +2757,11 @@ isert_free_np(struct iscsi_np *np)
        kfree(isert_np);
 }
 
-static int isert_check_state(struct isert_conn *isert_conn, int state)
-{
-       int ret;
-
-       mutex_lock(&isert_conn->conn_mutex);
-       ret = (isert_conn->state == state);
-       mutex_unlock(&isert_conn->conn_mutex);
-
-       return ret;
-}
-
-static void isert_free_conn(struct iscsi_conn *conn)
+static void isert_wait_conn(struct iscsi_conn *conn)
 {
        struct isert_conn *isert_conn = conn->context;
 
-       pr_debug("isert_free_conn: Starting \n");
+       pr_debug("isert_wait_conn: Starting \n");
        /*
         * Decrement post_send_buf_count for special case when called
         * from isert_do_control_comp() -> iscsit_logout_post_handler()
@@ -2726,38 +2771,29 @@ static void isert_free_conn(struct iscsi_conn *conn)
                atomic_dec(&isert_conn->post_send_buf_count);
 
        if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) {
-               pr_debug("Calling rdma_disconnect from isert_free_conn\n");
+               pr_debug("Calling rdma_disconnect from isert_wait_conn\n");
                rdma_disconnect(isert_conn->conn_cm_id);
        }
        /*
         * Only wait for conn_wait_comp_err if the isert_conn made it
         * into full feature phase..
         */
-       if (isert_conn->state == ISER_CONN_UP) {
-               pr_debug("isert_free_conn: Before wait_event comp_err %d\n",
-                        isert_conn->state);
-               mutex_unlock(&isert_conn->conn_mutex);
-
-               wait_event(isert_conn->conn_wait_comp_err,
-                         (isert_check_state(isert_conn, ISER_CONN_TERMINATING)));
-
-               wait_event(isert_conn->conn_wait,
-                         (isert_check_state(isert_conn, ISER_CONN_DOWN)));
-
-               isert_put_conn(isert_conn);
-               return;
-       }
        if (isert_conn->state == ISER_CONN_INIT) {
                mutex_unlock(&isert_conn->conn_mutex);
-               isert_put_conn(isert_conn);
                return;
        }
-       pr_debug("isert_free_conn: wait_event conn_wait %d\n",
-                isert_conn->state);
+       if (isert_conn->state == ISER_CONN_UP)
+               isert_conn->state = ISER_CONN_TERMINATING;
        mutex_unlock(&isert_conn->conn_mutex);
 
-       wait_event(isert_conn->conn_wait,
-                 (isert_check_state(isert_conn, ISER_CONN_DOWN)));
+       wait_for_completion(&isert_conn->conn_wait_comp_err);
+
+       wait_for_completion(&isert_conn->conn_wait);
+}
+
+static void isert_free_conn(struct iscsi_conn *conn)
+{
+       struct isert_conn *isert_conn = conn->context;
 
        isert_put_conn(isert_conn);
 }
@@ -2770,6 +2806,7 @@ static struct iscsit_transport iser_target_transport = {
        .iscsit_setup_np        = isert_setup_np,
        .iscsit_accept_np       = isert_accept_np,
        .iscsit_free_np         = isert_free_np,
+       .iscsit_wait_conn       = isert_wait_conn,
        .iscsit_free_conn       = isert_free_conn,
        .iscsit_get_login_rx    = isert_get_login_rx,
        .iscsit_put_login_tx    = isert_put_login_tx,
index 708a069002f3530e00002c5d1e454c1823119bb4..f6ae7f5dd4082768f3b6f0dfb36c1d45506b5eb6 100644 (file)
@@ -6,6 +6,7 @@
 
 #define ISERT_RDMA_LISTEN_BACKLOG      10
 #define ISCSI_ISER_SG_TABLESIZE                256
+#define ISER_FASTREG_LI_WRID           0xffffffffffffffffULL
 
 enum isert_desc_type {
        ISCSI_TX_CONTROL,
@@ -45,6 +46,7 @@ struct iser_tx_desc {
        struct isert_cmd *isert_cmd;
        struct llist_node *comp_llnode_batch;
        struct llist_node comp_llnode;
+       bool            llnode_active;
        struct ib_send_wr send_wr;
 } __packed;
 
@@ -116,8 +118,8 @@ struct isert_conn {
        struct isert_device     *conn_device;
        struct work_struct      conn_logout_work;
        struct mutex            conn_mutex;
-       wait_queue_head_t       conn_wait;
-       wait_queue_head_t       conn_wait_comp_err;
+       struct completion       conn_wait;
+       struct completion       conn_wait_comp_err;
        struct kref             conn_kref;
        struct list_head        conn_fr_pool;
        int                     conn_fr_pool_size;
@@ -126,7 +128,6 @@ struct isert_conn {
 #define ISERT_COMP_BATCH_COUNT 8
        int                     conn_comp_batch;
        struct llist_head       conn_comp_llist;
-       struct mutex            conn_comp_mutex;
 };
 
 #define ISERT_MAX_CQ 64
index 520a7e5a490b1b61042cad7acead955bbed2b759..0e537d8d0e4774312d632f68f0cedd0aaa406b7d 100644 (file)
@@ -3666,9 +3666,9 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(page, 0, &val);
+       ret = kstrtoul(page, 0, &val);
        if (ret < 0) {
-               pr_err("strict_strtoul() failed with ret: %d\n", ret);
+               pr_err("kstrtoul() failed with ret: %d\n", ret);
                return -EINVAL;
        }
        if (val > MAX_SRPT_RDMA_SIZE) {
@@ -3706,9 +3706,9 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(page, 0, &val);
+       ret = kstrtoul(page, 0, &val);
        if (ret < 0) {
-               pr_err("strict_strtoul() failed with ret: %d\n", ret);
+               pr_err("kstrtoul() failed with ret: %d\n", ret);
                return -EINVAL;
        }
        if (val > MAX_SRPT_RSP_SIZE) {
@@ -3746,9 +3746,9 @@ static ssize_t srpt_tpg_attrib_store_srp_sq_size(
        unsigned long val;
        int ret;
 
-       ret = strict_strtoul(page, 0, &val);
+       ret = kstrtoul(page, 0, &val);
        if (ret < 0) {
-               pr_err("strict_strtoul() failed with ret: %d\n", ret);
+               pr_err("kstrtoul() failed with ret: %d\n", ret);
                return -EINVAL;
        }
        if (val > MAX_SRPT_SRQ_SIZE) {
@@ -3793,7 +3793,7 @@ static ssize_t srpt_tpg_store_enable(
        unsigned long tmp;
         int ret;
 
-       ret = strict_strtoul(page, 0, &tmp);
+       ret = kstrtoul(page, 0, &tmp);
        if (ret < 0) {
                printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n");
                return -EINVAL;
index a06e12552886fa57ffbe1731eb744762666cd787..ce953d895f5b2b92d3bbb0d1a19be8a86d563d6b 100644 (file)
@@ -954,11 +954,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                error = input_ff_upload(dev, &effect, file);
+               if (error)
+                       return error;
 
                if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
                        return -EFAULT;
 
-               return error;
+               return 0;
        }
 
        /* Multi-number variable-length handlers */
index bb3b57bea8ba4578df5d29c72230882ac29bd62a..5ef7fcf0e2509b8196cf69a993247febae4c20b7 100644 (file)
@@ -76,8 +76,18 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
        struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
        unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
        unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
+       int val;
 
-       return !!(adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank) & bit);
+       mutex_lock(&kpad->gpio_lock);
+
+       if (kpad->dir[bank] & bit)
+               val = kpad->dat_out[bank];
+       else
+               val = adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank);
+
+       mutex_unlock(&kpad->gpio_lock);
+
+       return !!(val & bit);
 }
 
 static void adp5588_gpio_set_value(struct gpio_chip *chip,
index 7a04f54ef961fda20385251413fdee4490669ef6..ef2e281b0a43b641a1dbc6f5dd7fcb9190477d24 100644 (file)
@@ -37,7 +37,6 @@ static void arizona_haptics_work(struct work_struct *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) {
@@ -67,13 +66,10 @@ static void arizona_haptics_work(struct work_struct *work)
                        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;
                }
 
@@ -81,21 +77,14 @@ static void arizona_haptics_work(struct work_struct *work)
                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;
                }
 
@@ -103,12 +92,9 @@ static void arizona_haptics_work(struct work_struct *work)
                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,
@@ -155,16 +141,11 @@ static int arizona_haptics_play(struct input_dev *input, void *data,
 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)
index 1f695f229ea8988001da801bb60db7b6d939f293..184c8f21ab59a9736feb262f79331cae878af1ff 100644 (file)
@@ -27,29 +27,32 @@ struct da9052_onkey {
 
 static void da9052_onkey_query(struct da9052_onkey *onkey)
 {
-       int key_stat;
+       int ret;
 
-       key_stat = da9052_reg_read(onkey->da9052, DA9052_EVENT_B_REG);
-       if (key_stat < 0) {
+       ret = da9052_reg_read(onkey->da9052, DA9052_STATUS_A_REG);
+       if (ret < 0) {
                dev_err(onkey->da9052->dev,
-                       "Failed to read onkey event %d\n", key_stat);
+                       "Failed to read onkey event err=%d\n", ret);
        } else {
                /*
                 * Since interrupt for deassertion of ONKEY pin is not
                 * generated, onkey event state determines the onkey
                 * button state.
                 */
-               key_stat &= DA9052_EVENTB_ENONKEY;
-               input_report_key(onkey->input, KEY_POWER, key_stat);
+               bool pressed = !(ret & DA9052_STATUSA_NONKEY);
+
+               input_report_key(onkey->input, KEY_POWER, pressed);
                input_sync(onkey->input);
-       }
 
-       /*
-        * Interrupt is generated only when the ONKEY pin is asserted.
-        * Hence the deassertion of the pin is simulated through work queue.
-        */
-       if (key_stat)
-               schedule_delayed_work(&onkey->work, msecs_to_jiffies(50));
+               /*
+                * Interrupt is generated only when the ONKEY pin
+                * is asserted.  Hence the deassertion of the pin
+                * is simulated through work queue.
+                */
+               if (pressed)
+                       schedule_delayed_work(&onkey->work,
+                                               msecs_to_jiffies(50));
+       }
 }
 
 static void da9052_onkey_work(struct work_struct *work)
index 87095e2f5153c7dedeae38a18cd10efaa62a9e0c..8af34ffe208b16eff1ab240de45967fb84b6610f 100644 (file)
@@ -409,7 +409,6 @@ static int cypress_set_input_params(struct input_dev *input,
        __clear_bit(REL_X, input->relbit);
        __clear_bit(REL_Y, input->relbit);
 
-       __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
        __set_bit(EV_KEY, input->evbit);
        __set_bit(BTN_LEFT, input->keybit);
        __set_bit(BTN_RIGHT, input->keybit);
index 26386f9d25696841584f4b7f698a3cc8727fdc54..d8d49d10f9bb60d477124bba603fb9f61be1efdb 100644 (file)
@@ -265,11 +265,22 @@ static int synaptics_identify(struct psmouse *psmouse)
  * Read touchpad resolution and maximum reported coordinates
  * Resolution is left zero if touchpad does not support the query
  */
+
+static const int *quirk_min_max;
+
 static int synaptics_resolution(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
        unsigned char resp[3];
 
+       if (quirk_min_max) {
+               priv->x_min = quirk_min_max[0];
+               priv->x_max = quirk_min_max[1];
+               priv->y_min = quirk_min_max[2];
+               priv->y_max = quirk_min_max[3];
+               return 0;
+       }
+
        if (SYN_ID_MAJOR(priv->identity) < 4)
                return 0;
 
@@ -1485,10 +1496,54 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
        { }
 };
 
+static const struct dmi_system_id min_max_dmi_table[] __initconst = {
+#if defined(CONFIG_DMI)
+       {
+               /* Lenovo ThinkPad Helix */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
+               },
+               .driver_data = (int []){1024, 5052, 2258, 4832},
+       },
+       {
+               /* Lenovo ThinkPad X240 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"),
+               },
+               .driver_data = (int []){1232, 5710, 1156, 4696},
+       },
+       {
+               /* Lenovo ThinkPad T440s */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
+               },
+               .driver_data = (int []){1024, 5112, 2024, 4832},
+       },
+       {
+               /* Lenovo ThinkPad T540p */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
+               },
+               .driver_data = (int []){1024, 5056, 2058, 4832},
+       },
+#endif
+       { }
+};
+
 void __init synaptics_module_init(void)
 {
+       const struct dmi_system_id *min_max_dmi;
+
        impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
        broken_olpc_ec = dmi_check_system(olpc_dmi_table);
+
+       min_max_dmi = dmi_first_match(min_max_dmi_table);
+       if (min_max_dmi)
+               quirk_min_max = min_max_dmi->driver_data;
 }
 
 static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
index 4c842c320c2ede9f2bf42d507ee5c91f00eef7e3..b604564dec5c9a5d8d154ac18a61c02341f77e5d 100644 (file)
@@ -67,7 +67,6 @@ struct mousedev {
        struct device dev;
        struct cdev cdev;
        bool exist;
-       bool is_mixdev;
 
        struct list_head mixdev_node;
        bool opened_by_mixdev;
@@ -77,6 +76,9 @@ struct mousedev {
        int old_x[4], old_y[4];
        int frac_dx, frac_dy;
        unsigned long touch;
+
+       int (*open_device)(struct mousedev *mousedev);
+       void (*close_device)(struct mousedev *mousedev);
 };
 
 enum mousedev_emul {
@@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
 static struct mousedev *mousedev_mix;
 static LIST_HEAD(mousedev_mix_list);
 
-static void mixdev_open_devices(void);
-static void mixdev_close_devices(void);
-
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
 #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
 
@@ -428,9 +427,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
        if (retval)
                return retval;
 
-       if (mousedev->is_mixdev)
-               mixdev_open_devices();
-       else if (!mousedev->exist)
+       if (!mousedev->exist)
                retval = -ENODEV;
        else if (!mousedev->open++) {
                retval = input_open_device(&mousedev->handle);
@@ -446,9 +443,7 @@ static void mousedev_close_device(struct mousedev *mousedev)
 {
        mutex_lock(&mousedev->mutex);
 
-       if (mousedev->is_mixdev)
-               mixdev_close_devices();
-       else if (mousedev->exist && !--mousedev->open)
+       if (mousedev->exist && !--mousedev->open)
                input_close_device(&mousedev->handle);
 
        mutex_unlock(&mousedev->mutex);
@@ -459,21 +454,29 @@ static void mousedev_close_device(struct mousedev *mousedev)
  * stream. Note that this function is called with mousedev_mix->mutex
  * held.
  */
-static void mixdev_open_devices(void)
+static int mixdev_open_devices(struct mousedev *mixdev)
 {
-       struct mousedev *mousedev;
+       int error;
+
+       error = mutex_lock_interruptible(&mixdev->mutex);
+       if (error)
+               return error;
 
-       if (mousedev_mix->open++)
-               return;
+       if (!mixdev->open++) {
+               struct mousedev *mousedev;
 
-       list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-               if (!mousedev->opened_by_mixdev) {
-                       if (mousedev_open_device(mousedev))
-                               continue;
+               list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+                       if (!mousedev->opened_by_mixdev) {
+                               if (mousedev_open_device(mousedev))
+                                       continue;
 
-                       mousedev->opened_by_mixdev = true;
+                               mousedev->opened_by_mixdev = true;
+                       }
                }
        }
+
+       mutex_unlock(&mixdev->mutex);
+       return 0;
 }
 
 /*
@@ -481,19 +484,22 @@ static void mixdev_open_devices(void)
  * device. Note that this function is called with mousedev_mix->mutex
  * held.
  */
-static void mixdev_close_devices(void)
+static void mixdev_close_devices(struct mousedev *mixdev)
 {
-       struct mousedev *mousedev;
+       mutex_lock(&mixdev->mutex);
 
-       if (--mousedev_mix->open)
-               return;
+       if (!--mixdev->open) {
+               struct mousedev *mousedev;
 
-       list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-               if (mousedev->opened_by_mixdev) {
-                       mousedev->opened_by_mixdev = false;
-                       mousedev_close_device(mousedev);
+               list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+                       if (mousedev->opened_by_mixdev) {
+                               mousedev->opened_by_mixdev = false;
+                               mousedev_close_device(mousedev);
+                       }
                }
        }
+
+       mutex_unlock(&mixdev->mutex);
 }
 
 
@@ -522,7 +528,7 @@ static int mousedev_release(struct inode *inode, struct file *file)
        mousedev_detach_client(mousedev, client);
        kfree(client);
 
-       mousedev_close_device(mousedev);
+       mousedev->close_device(mousedev);
 
        return 0;
 }
@@ -550,7 +556,7 @@ static int mousedev_open(struct inode *inode, struct file *file)
        client->mousedev = mousedev;
        mousedev_attach_client(mousedev, client);
 
-       error = mousedev_open_device(mousedev);
+       error = mousedev->open_device(mousedev);
        if (error)
                goto err_free_client;
 
@@ -861,16 +867,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
 
        if (mixdev) {
                dev_set_name(&mousedev->dev, "mice");
+
+               mousedev->open_device = mixdev_open_devices;
+               mousedev->close_device = mixdev_close_devices;
        } else {
                int dev_no = minor;
                /* Normalize device number if it falls into legacy range */
                if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
                        dev_no -= MOUSEDEV_MINOR_BASE;
                dev_set_name(&mousedev->dev, "mouse%d", dev_no);
+
+               mousedev->open_device = mousedev_open_device;
+               mousedev->close_device = mousedev_close_device;
        }
 
        mousedev->exist = true;
-       mousedev->is_mixdev = mixdev;
        mousedev->handle.dev = input_get_device(dev);
        mousedev->handle.name = dev_name(&mousedev->dev);
        mousedev->handle.handler = handler;
@@ -919,7 +930,7 @@ static void mousedev_destroy(struct mousedev *mousedev)
        device_del(&mousedev->dev);
        mousedev_cleanup(mousedev);
        input_free_minor(MINOR(mousedev->dev.devt));
-       if (!mousedev->is_mixdev)
+       if (mousedev != mousedev_mix)
                input_unregister_handle(&mousedev->handle);
        put_device(&mousedev->dev);
 }
index 8911850c94445fa5adf3b41de168293e5adf7721..1d9ab39af29f7c5d6ab2504fd2403ff725358a5d 100644 (file)
@@ -79,7 +79,6 @@
 
 #define ARM_SMMU_PTE_CONT_SIZE         (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES)
 #define ARM_SMMU_PTE_CONT_MASK         (~(ARM_SMMU_PTE_CONT_SIZE - 1))
-#define ARM_SMMU_PTE_HWTABLE_SIZE      (PTRS_PER_PTE * sizeof(pte_t))
 
 /* Stage-1 PTE */
 #define ARM_SMMU_PTE_AP_UNPRIV         (((pteval_t)1) << 6)
 #define ARM_SMMU_GR1_CBAR(n)           (0x0 + ((n) << 2))
 #define CBAR_VMID_SHIFT                        0
 #define CBAR_VMID_MASK                 0xff
+#define CBAR_S1_BPSHCFG_SHIFT          8
+#define CBAR_S1_BPSHCFG_MASK           3
+#define CBAR_S1_BPSHCFG_NSH            3
 #define CBAR_S1_MEMATTR_SHIFT          12
 #define CBAR_S1_MEMATTR_MASK           0xf
 #define CBAR_S1_MEMATTR_WB             0xf
@@ -393,7 +395,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             root_cfg;
        phys_addr_t                     output_mask;
 
-       struct mutex                    lock;
+       spinlock_t                      lock;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -632,6 +634,28 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
+                                  size_t size)
+{
+       unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+
+       /* Ensure new page tables are visible to the hardware walker */
+       if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) {
+               dsb();
+       } else {
+               /*
+                * If the SMMU can't walk tables in the CPU caches, treat them
+                * like non-coherent DMA since we need to flush the new entries
+                * all the way out to memory. There's no possibility of
+                * recursion here as the SMMU table walker will not be wired
+                * through another SMMU.
+                */
+               dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
+                               DMA_TO_DEVICE);
+       }
+}
+
 static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
 {
        u32 reg;
@@ -650,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
        if (smmu->version == 1)
              reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
 
-       /* Use the weakest memory type, so it is overridden by the pte */
-       if (stage1)
-               reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
-       else
+       /*
+        * Use the weakest shareability/memory types, so they are
+        * overridden by the ttbcr/pte.
+        */
+       if (stage1) {
+               reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+                       (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+       } else {
                reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
+       }
        writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
 
        if (smmu->version > 1) {
@@ -715,6 +744,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
        }
 
        /* TTBR0 */
+       arm_smmu_flush_pgtable(smmu, root_cfg->pgd,
+                              PTRS_PER_PGD * sizeof(pgd_t));
        reg = __pa(root_cfg->pgd);
        writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
        reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32;
@@ -901,7 +932,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
                goto out_free_domain;
        smmu_domain->root_cfg.pgd = pgd;
 
-       mutex_init(&smmu_domain->lock);
+       spin_lock_init(&smmu_domain->lock);
        domain->priv = smmu_domain;
        return 0;
 
@@ -1128,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        struct arm_smmu_domain *smmu_domain = domain->priv;
        struct arm_smmu_device *device_smmu = dev->archdata.iommu;
        struct arm_smmu_master *master;
+       unsigned long flags;
 
        if (!device_smmu) {
                dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
@@ -1138,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
         * Sanity check the domain. We don't currently support domains
         * that cross between different SMMU chains.
         */
-       mutex_lock(&smmu_domain->lock);
+       spin_lock_irqsave(&smmu_domain->lock, flags);
        if (!smmu_domain->leaf_smmu) {
                /* Now that we have a master, we can finalise the domain */
                ret = arm_smmu_init_domain_context(domain, dev);
@@ -1153,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                        dev_name(device_smmu->dev));
                goto err_unlock;
        }
-       mutex_unlock(&smmu_domain->lock);
+       spin_unlock_irqrestore(&smmu_domain->lock, flags);
 
        /* Looks ok, so add the device to the domain */
        master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1163,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        return arm_smmu_domain_add_master(smmu_domain, master);
 
 err_unlock:
-       mutex_unlock(&smmu_domain->lock);
+       spin_unlock_irqrestore(&smmu_domain->lock, flags);
        return ret;
 }
 
@@ -1177,23 +1209,6 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
                arm_smmu_domain_remove_master(smmu_domain, master);
 }
 
-static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
-                                  size_t size)
-{
-       unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
-
-       /*
-        * If the SMMU can't walk tables in the CPU caches, treat them
-        * like non-coherent DMA since we need to flush the new entries
-        * all the way out to memory. There's no possibility of recursion
-        * here as the SMMU table walker will not be wired through another
-        * SMMU.
-        */
-       if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK))
-               dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
-                            DMA_TO_DEVICE);
-}
-
 static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
                                             unsigned long end)
 {
@@ -1210,12 +1225,11 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
 
        if (pmd_none(*pmd)) {
                /* Allocate a new set of tables */
-               pgtable_t table = alloc_page(PGALLOC_GFP);
+               pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
                if (!table)
                        return -ENOMEM;
 
-               arm_smmu_flush_pgtable(smmu, page_address(table),
-                                      ARM_SMMU_PTE_HWTABLE_SIZE);
+               arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
                if (!pgtable_page_ctor(table)) {
                        __free_page(table);
                        return -ENOMEM;
@@ -1317,9 +1331,15 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
 
 #ifndef __PAGETABLE_PMD_FOLDED
        if (pud_none(*pud)) {
-               pmd = pmd_alloc_one(NULL, addr);
+               pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
                if (!pmd)
                        return -ENOMEM;
+
+               arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE);
+               pud_populate(NULL, pud, pmd);
+               arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
+
+               pmd += pmd_index(addr);
        } else
 #endif
                pmd = pmd_offset(pud, addr);
@@ -1328,8 +1348,6 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
                next = pmd_addr_end(addr, end);
                ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn,
                                              flags, stage);
-               pud_populate(NULL, pud, pmd);
-               arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
                phys += next - addr;
        } while (pmd++, addr = next, addr < end);
 
@@ -1346,9 +1364,15 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
 
 #ifndef __PAGETABLE_PUD_FOLDED
        if (pgd_none(*pgd)) {
-               pud = pud_alloc_one(NULL, addr);
+               pud = (pud_t *)get_zeroed_page(GFP_ATOMIC);
                if (!pud)
                        return -ENOMEM;
+
+               arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE);
+               pgd_populate(NULL, pgd, pud);
+               arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
+
+               pud += pud_index(addr);
        } else
 #endif
                pud = pud_offset(pgd, addr);
@@ -1357,8 +1381,6 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
                next = pud_addr_end(addr, end);
                ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys,
                                              flags, stage);
-               pgd_populate(NULL, pud, pgd);
-               arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
                phys += next - addr;
        } while (pud++, addr = next, addr < end);
 
@@ -1375,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
        pgd_t *pgd = root_cfg->pgd;
        struct arm_smmu_device *smmu = root_cfg->smmu;
+       unsigned long irqflags;
 
        if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) {
                stage = 2;
@@ -1397,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        if (paddr & ~output_mask)
                return -ERANGE;
 
-       mutex_lock(&smmu_domain->lock);
+       spin_lock_irqsave(&smmu_domain->lock, irqflags);
        pgd += pgd_index(iova);
        end = iova + size;
        do {
@@ -1413,11 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        } while (pgd++, iova != end);
 
 out_unlock:
-       mutex_unlock(&smmu_domain->lock);
-
-       /* Ensure new page tables are visible to the hardware walker */
-       if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
-               dsb();
+       spin_unlock_irqrestore(&smmu_domain->lock, irqflags);
 
        return ret;
 }
@@ -1987,8 +2006,10 @@ static int __init arm_smmu_init(void)
        if (!iommu_present(&platform_bus_type))
                bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
 
+#ifdef CONFIG_ARM_AMBA
        if (!iommu_present(&amba_bustype))
                bus_set_iommu(&amba_bustype, &arm_smmu_ops);
+#endif
 
        return 0;
 }
index d97fbe4fb9b1358f0f7bea574edd6c8cd73502df..80fffba7f12dfd77dcff90d06a9783613d131827 100644 (file)
@@ -354,8 +354,8 @@ DEBUG_FOPS(mem);
                        return -ENOMEM;                                 \
        }
 
-#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 600)
-#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 400)
+#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 0600)
+#define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 0400)
 
 static int iommu_debug_register(struct device *dev, void *data)
 {
index 86b484cb3ec2d1f99b4c708c2a35abb60a315a91..5194afb39e781062bc6e82d55163174494fbb751 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_SIRF_IRQ)                        += irq-sirfsoc.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)      += irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)             += irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
+obj-$(CONFIG_ARCH_NSPIRE)              += irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)              += irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)               += irq-tb10x.o
 obj-$(CONFIG_XTENSA)                   += irq-xtensa-pic.o
index 9300bc32784eb689d3021130a7330cbd4d106308..540956465ed2db759ca72eae11a26b16a4c17047 100644 (file)
@@ -381,7 +381,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
                                                ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
                                & PCI_MSI_DOORBELL_MASK;
 
-                       writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
+                       writel(~msimask, per_cpu_int_base +
                               ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
 
                        for (msinr = PCI_MSI_DOORBELL_START;
@@ -407,7 +407,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
                                                ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
                                & IPI_DOORBELL_MASK;
 
-                       writel(~IPI_DOORBELL_MASK, per_cpu_int_base +
+                       writel(~ipimask, per_cpu_int_base +
                                ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
 
                        /* Handle all pending doorbells */
index 92c41ab4dbfd619b5458338c3e6b6563019b150c..2cb474ad8809faa2fadaf5b08a7b06b087e73794 100644 (file)
@@ -515,7 +515,7 @@ static int meta_intc_set_affinity(struct irq_data *data,
         * one cpu (the interrupt code doesn't support it), so we just
         * pick the first cpu we find in 'cpumask'.
         */
-       cpu = cpumask_any(cpumask);
+       cpu = cpumask_any_and(cpumask, cpu_online_mask);
        thread = cpu_2_hwthread_id[cpu];
 
        metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr);
index 8e94d7a3b20d277d127adf15441ea0b53879c606..c16c186d97d35f4246fa2acbd17942789922d6d7 100644 (file)
@@ -201,7 +201,7 @@ static int metag_internal_irq_set_affinity(struct irq_data *data,
         * one cpu (the interrupt code doesn't support it), so we just
         * pick the first cpu we find in 'cpumask'.
         */
-       cpu = cpumask_any(cpumask);
+       cpu = cpumask_any_and(cpumask, cpu_online_mask);
        thread = cpu_2_hwthread_id[cpu];
 
        metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)),
index e51d40031884b1d75f12d659e2f040f391a7ad73..8e41be62812e1663df05b58f75c52ecfdc7b844f 100644 (file)
@@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init);
 static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_domain *d = irq_get_handler_data(irq);
-       struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq);
+
+       struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
        u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
                   gc->mask_cache;
 
@@ -123,6 +124,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
        }
 }
 
+/*
+ * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register.
+ * To avoid interrupt events on stale irqs, we clear them before unmask.
+ */
+static unsigned int orion_bridge_irq_startup(struct irq_data *d)
+{
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+
+       ct->chip.irq_ack(d);
+       ct->chip.irq_unmask(d);
+       return 0;
+}
+
 static int __init orion_bridge_irq_init(struct device_node *np,
                                        struct device_node *parent)
 {
@@ -143,7 +157,7 @@ static int __init orion_bridge_irq_init(struct device_node *np,
        }
 
        ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
-                            handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
+                            handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
        if (ret) {
                pr_err("%s: unable to alloc irq domain gc\n", np->name);
                return ret;
@@ -176,12 +190,14 @@ static int __init orion_bridge_irq_init(struct device_node *np,
 
        gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
        gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
+       gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup;
        gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit;
        gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
        gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
 
-       /* mask all interrupts */
+       /* mask and clear all interrupts */
        writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
+       writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
 
        irq_set_handler_data(irq, domain);
        irq_set_chained_handler(irq, orion_bridge_irq_handler);
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c
new file mode 100644 (file)
index 0000000..8ed04c4
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  linux/drivers/irqchip/irq-zevio.c
+ *
+ *  Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
+ *
+ * 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/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+
+#include "irqchip.h"
+
+#define IO_STATUS      0x000
+#define IO_RAW_STATUS  0x004
+#define IO_ENABLE      0x008
+#define IO_DISABLE     0x00C
+#define IO_CURRENT     0x020
+#define IO_RESET       0x028
+#define IO_MAX_PRIOTY  0x02C
+
+#define IO_IRQ_BASE    0x000
+#define IO_FIQ_BASE    0x100
+
+#define IO_INVERT_SEL  0x200
+#define IO_STICKY_SEL  0x204
+#define IO_PRIORITY_SEL        0x300
+
+#define MAX_INTRS      32
+#define FIQ_START      MAX_INTRS
+
+static struct irq_domain *zevio_irq_domain;
+static void __iomem *zevio_irq_io;
+
+static void zevio_irq_ack(struct irq_data *irqd)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd);
+       struct irq_chip_regs *regs =
+               &container_of(irqd->chip, struct irq_chip_type, chip)->regs;
+
+       readl(gc->reg_base + regs->ack);
+}
+
+static asmlinkage void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
+{
+       int irqnr;
+
+       while (readl(zevio_irq_io + IO_STATUS)) {
+               irqnr = readl(zevio_irq_io + IO_CURRENT);
+               irqnr = irq_find_mapping(zevio_irq_domain, irqnr);
+               handle_IRQ(irqnr, regs);
+       };
+}
+
+static void __init zevio_init_irq_base(void __iomem *base)
+{
+       /* Disable all interrupts */
+       writel(~0, base + IO_DISABLE);
+
+       /* Accept interrupts of all priorities */
+       writel(0xF, base + IO_MAX_PRIOTY);
+
+       /* Reset existing interrupts */
+       readl(base + IO_RESET);
+}
+
+static int __init zevio_of_init(struct device_node *node,
+                               struct device_node *parent)
+{
+       unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+       struct irq_chip_generic *gc;
+       int ret;
+
+       if (WARN_ON(zevio_irq_io || zevio_irq_domain))
+               return -EBUSY;
+
+       zevio_irq_io = of_iomap(node, 0);
+       BUG_ON(!zevio_irq_io);
+
+       /* Do not invert interrupt status bits */
+       writel(~0, zevio_irq_io + IO_INVERT_SEL);
+
+       /* Disable sticky interrupts */
+       writel(0, zevio_irq_io + IO_STICKY_SEL);
+
+       /* We don't use IRQ priorities. Set each IRQ to highest priority. */
+       memset_io(zevio_irq_io + IO_PRIORITY_SEL, 0, MAX_INTRS * sizeof(u32));
+
+       /* Init IRQ and FIQ */
+       zevio_init_irq_base(zevio_irq_io + IO_IRQ_BASE);
+       zevio_init_irq_base(zevio_irq_io + IO_FIQ_BASE);
+
+       zevio_irq_domain = irq_domain_add_linear(node, MAX_INTRS,
+                                                &irq_generic_chip_ops, NULL);
+       BUG_ON(!zevio_irq_domain);
+
+       ret = irq_alloc_domain_generic_chips(zevio_irq_domain, MAX_INTRS, 1,
+                                            "zevio_intc", handle_level_irq,
+                                            clr, 0, IRQ_GC_INIT_MASK_CACHE);
+       BUG_ON(ret);
+
+       gc = irq_get_domain_generic_chip(zevio_irq_domain, 0);
+       gc->reg_base                            = zevio_irq_io;
+       gc->chip_types[0].chip.irq_ack          = zevio_irq_ack;
+       gc->chip_types[0].chip.irq_mask         = irq_gc_mask_disable_reg;
+       gc->chip_types[0].chip.irq_unmask       = irq_gc_unmask_enable_reg;
+       gc->chip_types[0].regs.mask             = IO_IRQ_BASE + IO_ENABLE;
+       gc->chip_types[0].regs.enable           = IO_IRQ_BASE + IO_ENABLE;
+       gc->chip_types[0].regs.disable          = IO_IRQ_BASE + IO_DISABLE;
+       gc->chip_types[0].regs.ack              = IO_IRQ_BASE + IO_RESET;
+
+       set_handle_irq(zevio_handle_irq);
+
+       pr_info("TI-NSPIRE classic IRQ controller\n");
+       return 0;
+}
+
+IRQCHIP_DECLARE(zevio_irq, "lsi,zevio-intc", zevio_of_init);
index f046865800405664ae73ec6dc761635327b7b55a..9816c51eb5c240be8c19b9c26bbd25d50fbca652 100644 (file)
@@ -16,9 +16,17 @@ config CAPI_TRACE
          This will increase the size of the kernelcapi module by 20 KB.
          If unsure, say Y.
 
+config ISDN_CAPI_CAPI20
+       tristate "CAPI2.0 /dev/capi support"
+       help
+         This option will provide the CAPI 2.0 interface to userspace
+         applications via /dev/capi20. Applications should use the
+         standardized libcapi20 to access this functionality.  You should say
+         Y/M here.
+
 config ISDN_CAPI_MIDDLEWARE
        bool "CAPI2.0 Middleware support"
-       depends on TTY
+       depends on ISDN_CAPI_CAPI20 && TTY
        help
          This option will enhance the capabilities of the /dev/capi20
          interface.  It will provide a means of moving a data connection,
@@ -26,14 +34,6 @@ config ISDN_CAPI_MIDDLEWARE
          device.  If you want to use pppd with pppdcapiplugin to dial up to
          your ISP, say Y here.
 
-config ISDN_CAPI_CAPI20
-       tristate "CAPI2.0 /dev/capi support"
-       help
-         This option will provide the CAPI 2.0 interface to userspace
-         applications via /dev/capi20. Applications should use the
-         standardized libcapi20 to access this functionality.  You should say
-         Y/M here.
-
 config ISDN_CAPI_CAPIDRV
        tristate "CAPI2.0 capidrv interface support"
        depends on ISDN_I4L
index af1b020a81f1814eb28b8fea83fca30b3b4332fc..b420f8bd862e454df2cc08f4da84b8bc7ef76e57 100644 (file)
@@ -810,7 +810,7 @@ prfeatureind(char *dest, u_char *p)
        dp += sprintf(dp, "    octet 3  ");
        dp += prbits(dp, *p, 8, 8);
        *dp++ = '\n';
-       if (!(*p++ & 80)) {
+       if (!(*p++ & 0x80)) {
                dp += sprintf(dp, "    octet 4  ");
                dp += prbits(dp, *p++, 8, 8);
                *dp++ = '\n';
index 9a06fe8837666036fe04afbde6d5e2adf8de6256..95ad936e60482477c1f87c0aa654fded90d06ba5 100644 (file)
@@ -254,16 +254,6 @@ config DM_THIN_PROVISIONING
        ---help---
          Provides thin provisioning and snapshots that share a data store.
 
-config DM_DEBUG_BLOCK_STACK_TRACING
-       boolean "Keep stack trace of persistent data block lock holders"
-       depends on STACKTRACE_SUPPORT && DM_PERSISTENT_DATA
-       select STACKTRACE
-       ---help---
-         Enable this for messages that may help debug problems with the
-         block manager locking used by thin provisioning and caching.
-
-         If unsure, say N.
-
 config DM_CACHE
        tristate "Cache target (EXPERIMENTAL)"
        depends on BLK_DEV_DM
index 0c707e4f4eafc32adcdb3fec5539b2dbe0998a7a..a4c7306ff43de4f1a928962251ffaea384dcb287 100644 (file)
@@ -210,7 +210,9 @@ BITMASK(GC_MARK,     struct bucket, gc_mark, 0, 2);
 #define GC_MARK_RECLAIMABLE    0
 #define GC_MARK_DIRTY          1
 #define GC_MARK_METADATA       2
-BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13);
+#define GC_SECTORS_USED_SIZE   13
+#define MAX_GC_SECTORS_USED    (~(~0ULL << GC_SECTORS_USED_SIZE))
+BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, GC_SECTORS_USED_SIZE);
 BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1);
 
 #include "journal.h"
index 4f6b5940e609b4f53c248bf65762ef8f99c7258c..3f74b4b0747b9fec3fcb7ad02cfed9ff1baa2f63 100644 (file)
@@ -23,7 +23,7 @@ void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned set)
        for (k = i->start; k < bset_bkey_last(i); k = next) {
                next = bkey_next(k);
 
-               printk(KERN_ERR "block %u key %zi/%u: ", set,
+               printk(KERN_ERR "block %u key %li/%u: ", set,
                       (uint64_t *) k - i->d, i->keys);
 
                if (b->ops->key_dump)
@@ -1185,9 +1185,12 @@ static void __btree_sort(struct btree_keys *b, struct btree_iter *iter,
        struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOIO,
                                                     order);
        if (!out) {
+               struct page *outp;
+
                BUG_ON(order > state->page_order);
 
-               out = page_address(mempool_alloc(state->pool, GFP_NOIO));
+               outp = mempool_alloc(state->pool, GFP_NOIO);
+               out = page_address(outp);
                used_mempool = true;
                order = state->page_order;
        }
index 98cc0a810a366a466253d250baba5c2564e9fab7..5f9c2a665ca5079bd372646f70de2117a77b995a 100644 (file)
@@ -1167,7 +1167,7 @@ uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k)
                /* guard against overflow */
                SET_GC_SECTORS_USED(g, min_t(unsigned,
                                             GC_SECTORS_USED(g) + KEY_SIZE(k),
-                                            (1 << 14) - 1));
+                                            MAX_GC_SECTORS_USED));
 
                BUG_ON(!GC_SECTORS_USED(g));
        }
@@ -1805,7 +1805,7 @@ static bool btree_insert_key(struct btree *b, struct bkey *k,
 
 static size_t insert_u64s_remaining(struct btree *b)
 {
-       ssize_t ret = bch_btree_keys_u64s_remaining(&b->keys);
+       long ret = bch_btree_keys_u64s_remaining(&b->keys);
 
        /*
         * Might land in the middle of an existing extent and have to split it
index c3ead586dc274d35124689b03572b4f740719a57..416d1a3e028e03a34a9d03e31b9e6fa583c9b357 100644 (file)
@@ -194,7 +194,7 @@ err:
        mutex_unlock(&b->c->bucket_lock);
        bch_extent_to_text(buf, sizeof(buf), k);
        btree_bug(b,
-"inconsistent btree pointer %s: bucket %li pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
+"inconsistent btree pointer %s: bucket %zi pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
                  buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin),
                  g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen);
        return true;
index 72cd213f213f9e806dc9a0360000ffffe6466896..5d5d031cf3813247adb89653f2fe5fcd227ce764 100644 (file)
@@ -353,14 +353,14 @@ static void bch_data_insert_start(struct closure *cl)
        struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
        struct bio *bio = op->bio, *n;
 
-       if (op->bypass)
-               return bch_data_invalidate(cl);
-
        if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) {
                set_gc_sectors(op->c);
                wake_up_gc(op->c);
        }
 
+       if (op->bypass)
+               return bch_data_invalidate(cl);
+
        /*
         * Journal writes are marked REQ_FLUSH; if the original write was a
         * flush, it'll wait on the journal write.
index c6ab69333a6dfde7761e9e2b05c16574f5c52480..d8458d477a1282110a8c685859ecc66dcf947057 100644 (file)
@@ -416,7 +416,7 @@ static int btree_bset_stats(struct btree_op *b_op, struct btree *b)
        return MAP_CONTINUE;
 }
 
-int bch_bset_print_stats(struct cache_set *c, char *buf)
+static int bch_bset_print_stats(struct cache_set *c, char *buf)
 {
        struct bset_stats_op op;
        int ret;
index 1e018e986610a57ef9f82a818aa1f70a8c364e30..0e385e40909e74fcde4da4ee5d785149101ad9cb 100644 (file)
@@ -872,7 +872,7 @@ static void mq_destroy(struct dm_cache_policy *p)
 {
        struct mq_policy *mq = to_mq_policy(p);
 
-       kfree(mq->table);
+       vfree(mq->table);
        epool_exit(&mq->cache_pool);
        epool_exit(&mq->pre_cache_pool);
        kfree(mq);
@@ -1245,7 +1245,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
 
        mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16);
        mq->hash_bits = ffs(mq->nr_buckets) - 1;
-       mq->table = kzalloc(sizeof(*mq->table) * mq->nr_buckets, GFP_KERNEL);
+       mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets);
        if (!mq->table)
                goto bad_alloc_table;
 
index ffd472e015caa918facaed4f65a621c0f61e58a9..074b9c8e4cf0840dd0d64014776dc297c2d82da6 100644 (file)
@@ -289,6 +289,7 @@ struct per_bio_data {
        bool tick:1;
        unsigned req_nr:2;
        struct dm_deferred_entry *all_io_entry;
+       struct dm_hook_info hook_info;
 
        /*
         * writethrough fields.  These MUST remain at the end of this
@@ -297,7 +298,6 @@ struct per_bio_data {
         */
        struct cache *cache;
        dm_cblock_t cblock;
-       struct dm_hook_info hook_info;
        struct dm_bio_details bio_details;
 };
 
@@ -671,15 +671,16 @@ static void remap_to_cache(struct cache *cache, struct bio *bio,
                           dm_cblock_t cblock)
 {
        sector_t bi_sector = bio->bi_iter.bi_sector;
+       sector_t block = from_cblock(cblock);
 
        bio->bi_bdev = cache->cache_dev->bdev;
        if (!block_size_is_power_of_two(cache))
                bio->bi_iter.bi_sector =
-                       (from_cblock(cblock) * cache->sectors_per_block) +
+                       (block * cache->sectors_per_block) +
                        sector_div(bi_sector, cache->sectors_per_block);
        else
                bio->bi_iter.bi_sector =
-                       (from_cblock(cblock) << cache->sectors_per_block_shift) |
+                       (block << cache->sectors_per_block_shift) |
                        (bi_sector & (cache->sectors_per_block - 1));
 }
 
@@ -978,12 +979,13 @@ static void issue_copy_real(struct dm_cache_migration *mg)
        int r;
        struct dm_io_region o_region, c_region;
        struct cache *cache = mg->cache;
+       sector_t cblock = from_cblock(mg->cblock);
 
        o_region.bdev = cache->origin_dev->bdev;
        o_region.count = cache->sectors_per_block;
 
        c_region.bdev = cache->cache_dev->bdev;
-       c_region.sector = from_cblock(mg->cblock) * cache->sectors_per_block;
+       c_region.sector = cblock * cache->sectors_per_block;
        c_region.count = cache->sectors_per_block;
 
        if (mg->writeback || mg->demote) {
@@ -1010,13 +1012,15 @@ static void overwrite_endio(struct bio *bio, int err)
        struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
        unsigned long flags;
 
+       dm_unhook_bio(&pb->hook_info, bio);
+
        if (err)
                mg->err = true;
 
+       mg->requeue_holder = false;
+
        spin_lock_irqsave(&cache->lock, flags);
        list_add_tail(&mg->list, &cache->completed_migrations);
-       dm_unhook_bio(&pb->hook_info, bio);
-       mg->requeue_holder = false;
        spin_unlock_irqrestore(&cache->lock, flags);
 
        wake_worker(cache);
@@ -2461,20 +2465,18 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
        bool discarded_block;
        struct dm_bio_prison_cell *cell;
        struct policy_result lookup_result;
-       struct per_bio_data *pb;
+       struct per_bio_data *pb = init_per_bio_data(bio, pb_data_size);
 
-       if (from_oblock(block) > from_oblock(cache->origin_blocks)) {
+       if (unlikely(from_oblock(block) >= from_oblock(cache->origin_blocks))) {
                /*
                 * This can only occur if the io goes to a partial block at
                 * the end of the origin device.  We don't cache these.
                 * Just remap to the origin and carry on.
                 */
-               remap_to_origin_clear_discard(cache, bio, block);
+               remap_to_origin(cache, bio);
                return DM_MAPIO_REMAPPED;
        }
 
-       pb = init_per_bio_data(bio, pb_data_size);
-
        if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) {
                defer_bio(cache, bio);
                return DM_MAPIO_SUBMITTED;
index b2b8a10e842784de5454e2639474f1a208b4b3f1..3842ac738f98ff324f5e1152f08fb546a5bb47fa 100644 (file)
@@ -201,29 +201,28 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse
 /*
  * Functions for getting the pages from a bvec.
  */
-static void bio_get_page(struct dpages *dp,
-                 struct page **p, unsigned long *len, unsigned *offset)
+static void bio_get_page(struct dpages *dp, struct page **p,
+                        unsigned long *len, unsigned *offset)
 {
-       struct bio *bio = dp->context_ptr;
-       struct bio_vec bvec = bio_iovec(bio);
-       *p = bvec.bv_page;
-       *len = bvec.bv_len;
-       *offset = bvec.bv_offset;
+       struct bio_vec *bvec = dp->context_ptr;
+       *p = bvec->bv_page;
+       *len = bvec->bv_len - dp->context_u;
+       *offset = bvec->bv_offset + dp->context_u;
 }
 
 static void bio_next_page(struct dpages *dp)
 {
-       struct bio *bio = dp->context_ptr;
-       struct bio_vec bvec = bio_iovec(bio);
-
-       bio_advance(bio, bvec.bv_len);
+       struct bio_vec *bvec = dp->context_ptr;
+       dp->context_ptr = bvec + 1;
+       dp->context_u = 0;
 }
 
 static void bio_dp_init(struct dpages *dp, struct bio *bio)
 {
        dp->get_page = bio_get_page;
        dp->next_page = bio_next_page;
-       dp->context_ptr = bio;
+       dp->context_ptr = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
+       dp->context_u = bio->bi_iter.bi_bvec_done;
 }
 
 /*
index 6eb9dc9ef8f36c4b709df6f3b46170598964e88d..422a9fdeb53e641d97acec4793ab00747dde9b1d 100644 (file)
@@ -1626,8 +1626,11 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
        /*
         * Only pass ioctls through if the device sizes match exactly.
         */
-       if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
-               r = scsi_verify_blk_ioctl(NULL, cmd);
+       if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) {
+               int err = scsi_verify_blk_ioctl(NULL, cmd);
+               if (err)
+                       r = err;
+       }
 
        if (r == -ENOTCONN && !fatal_signal_pending(current))
                queue_work(kmultipathd, &m->process_queued_ios);
index f284e0bfb25fca869855f390f2d8d7a5519a0864..7dfdb5c746d6f31960902350c33b7457485caadb 100644 (file)
@@ -1244,6 +1244,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
 
                        dm_bio_restore(bd, bio);
                        bio_record->details.bi_bdev = NULL;
+
+                       atomic_inc(&bio->bi_remaining);
+
                        queue_bio(ms, bio, rw);
                        return DM_ENDIO_INCOMPLETE;
                }
index afc3d017de4c6a479f418df9197a62677539752d..d6e88178d22cff0e88fb8b21cb20558f51e8d6a1 100644 (file)
@@ -546,6 +546,9 @@ static int read_exceptions(struct pstore *ps,
                r = insert_exceptions(ps, area, callback, callback_context,
                                      &full);
 
+               if (!full)
+                       memcpy(ps->area, area, ps->store->chunk_size << SECTOR_SHIFT);
+
                dm_bufio_release(bp);
 
                dm_bufio_forget(client, chunk);
index 7da34766555284486e39a08306f88a876deeefc3..fb9efc829182d4cce55c9c8cfac1e850e65abe79 100644 (file)
@@ -76,7 +76,7 @@
 
 #define THIN_SUPERBLOCK_MAGIC 27022010
 #define THIN_SUPERBLOCK_LOCATION 0
-#define THIN_VERSION 1
+#define THIN_VERSION 2
 #define THIN_METADATA_CACHE_SIZE 64
 #define SECTOR_TO_BLOCK_SHIFT 3
 
@@ -483,7 +483,7 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
 
        disk_super->data_mapping_root = cpu_to_le64(pmd->root);
        disk_super->device_details_root = cpu_to_le64(pmd->details_root);
-       disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+       disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE);
        disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT);
        disk_super->data_block_size = cpu_to_le32(pmd->data_block_size);
 
@@ -651,7 +651,7 @@ static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool f
 {
        int r;
 
-       pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE,
+       pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
                                          THIN_METADATA_CACHE_SIZE,
                                          THIN_MAX_CONCURRENT_LOCKS);
        if (IS_ERR(pmd->bm)) {
@@ -1489,6 +1489,23 @@ bool dm_thin_changed_this_transaction(struct dm_thin_device *td)
        return r;
 }
 
+bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd)
+{
+       bool r = false;
+       struct dm_thin_device *td, *tmp;
+
+       down_read(&pmd->root_lock);
+       list_for_each_entry_safe(td, tmp, &pmd->thin_devices, list) {
+               if (td->changed) {
+                       r = td->changed;
+                       break;
+               }
+       }
+       up_read(&pmd->root_lock);
+
+       return r;
+}
+
 bool dm_thin_aborted_changes(struct dm_thin_device *td)
 {
        bool r;
@@ -1738,3 +1755,38 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
 
        return r;
 }
+
+int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
+{
+       int r;
+       struct dm_block *sblock;
+       struct thin_disk_superblock *disk_super;
+
+       down_write(&pmd->root_lock);
+       pmd->flags |= THIN_METADATA_NEEDS_CHECK_FLAG;
+
+       r = superblock_lock(pmd, &sblock);
+       if (r) {
+               DMERR("couldn't read superblock");
+               goto out;
+       }
+
+       disk_super = dm_block_data(sblock);
+       disk_super->flags = cpu_to_le32(pmd->flags);
+
+       dm_bm_unlock(sblock);
+out:
+       up_write(&pmd->root_lock);
+       return r;
+}
+
+bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd)
+{
+       bool needs_check;
+
+       down_read(&pmd->root_lock);
+       needs_check = pmd->flags & THIN_METADATA_NEEDS_CHECK_FLAG;
+       up_read(&pmd->root_lock);
+
+       return needs_check;
+}
index 9a368567632f9733f04bc0a1aebfbc3d871f13df..e3c857db195a7453d192f5f55cfb766a046a789a 100644 (file)
@@ -9,16 +9,14 @@
 
 #include "persistent-data/dm-block-manager.h"
 #include "persistent-data/dm-space-map.h"
+#include "persistent-data/dm-space-map-metadata.h"
 
-#define THIN_METADATA_BLOCK_SIZE 4096
+#define THIN_METADATA_BLOCK_SIZE DM_SM_METADATA_BLOCK_SIZE
 
 /*
  * The metadata device is currently limited in size.
- *
- * We have one block of index, which can hold 255 index entries.  Each
- * index entry contains allocation info about 16k metadata blocks.
  */
-#define THIN_METADATA_MAX_SECTORS (255 * (1 << 14) * (THIN_METADATA_BLOCK_SIZE / (1 << SECTOR_SHIFT)))
+#define THIN_METADATA_MAX_SECTORS DM_SM_METADATA_MAX_SECTORS
 
 /*
  * A metadata device larger than 16GB triggers a warning.
 
 /*----------------------------------------------------------------*/
 
+/*
+ * Thin metadata superblock flags.
+ */
+#define THIN_METADATA_NEEDS_CHECK_FLAG (1 << 0)
+
 struct dm_pool_metadata;
 struct dm_thin_device;
 
@@ -161,6 +164,8 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
  */
 bool dm_thin_changed_this_transaction(struct dm_thin_device *td);
 
+bool dm_pool_changed_this_transaction(struct dm_pool_metadata *pmd);
+
 bool dm_thin_aborted_changes(struct dm_thin_device *td);
 
 int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
@@ -202,6 +207,12 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_sm_threshold_fn fn,
                                        void *context);
 
+/*
+ * Updates the superblock immediately.
+ */
+int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd);
+bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd);
+
 /*----------------------------------------------------------------*/
 
 #endif
index faaf944597ab7669b90f3ecb85152fbcd16cbe33..be70d38745f7a7f5da51bd4ba83a29afe851b238 100644 (file)
@@ -130,10 +130,11 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
 struct dm_thin_new_mapping;
 
 /*
- * The pool runs in 3 modes.  Ordered in degraded order for comparisons.
+ * The pool runs in 4 modes.  Ordered in degraded order for comparisons.
  */
 enum pool_mode {
        PM_WRITE,               /* metadata may be changed */
+       PM_OUT_OF_DATA_SPACE,   /* metadata may be changed, though data may not be allocated */
        PM_READ_ONLY,           /* metadata may not be changed */
        PM_FAIL,                /* all I/O fails */
 };
@@ -198,7 +199,6 @@ struct pool {
 };
 
 static enum pool_mode get_pool_mode(struct pool *pool);
-static void out_of_data_space(struct pool *pool);
 static void metadata_operation_failed(struct pool *pool, const char *op, int r);
 
 /*
@@ -226,6 +226,7 @@ struct thin_c {
 
        struct pool *pool;
        struct dm_thin_device *td;
+       bool requeue_mode:1;
 };
 
 /*----------------------------------------------------------------*/
@@ -369,14 +370,18 @@ struct dm_thin_endio_hook {
        struct dm_thin_new_mapping *overwrite_mapping;
 };
 
-static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
+static void requeue_bio_list(struct thin_c *tc, struct bio_list *master)
 {
        struct bio *bio;
        struct bio_list bios;
+       unsigned long flags;
 
        bio_list_init(&bios);
+
+       spin_lock_irqsave(&tc->pool->lock, flags);
        bio_list_merge(&bios, master);
        bio_list_init(master);
+       spin_unlock_irqrestore(&tc->pool->lock, flags);
 
        while ((bio = bio_list_pop(&bios))) {
                struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
@@ -391,12 +396,26 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master)
 static void requeue_io(struct thin_c *tc)
 {
        struct pool *pool = tc->pool;
+
+       requeue_bio_list(tc, &pool->deferred_bios);
+       requeue_bio_list(tc, &pool->retry_on_resume_list);
+}
+
+static void error_retry_list(struct pool *pool)
+{
+       struct bio *bio;
        unsigned long flags;
+       struct bio_list bios;
+
+       bio_list_init(&bios);
 
        spin_lock_irqsave(&pool->lock, flags);
-       __requeue_bio_list(tc, &pool->deferred_bios);
-       __requeue_bio_list(tc, &pool->retry_on_resume_list);
+       bio_list_merge(&bios, &pool->retry_on_resume_list);
+       bio_list_init(&pool->retry_on_resume_list);
        spin_unlock_irqrestore(&pool->lock, flags);
+
+       while ((bio = bio_list_pop(&bios)))
+               bio_io_error(bio);
 }
 
 /*
@@ -925,13 +944,15 @@ static void check_low_water_mark(struct pool *pool, dm_block_t free_blocks)
        }
 }
 
+static void set_pool_mode(struct pool *pool, enum pool_mode new_mode);
+
 static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
 {
        int r;
        dm_block_t free_blocks;
        struct pool *pool = tc->pool;
 
-       if (get_pool_mode(pool) != PM_WRITE)
+       if (WARN_ON(get_pool_mode(pool) != PM_WRITE))
                return -EINVAL;
 
        r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
@@ -958,7 +979,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                }
 
                if (!free_blocks) {
-                       out_of_data_space(pool);
+                       set_pool_mode(pool, PM_OUT_OF_DATA_SPACE);
                        return -ENOSPC;
                }
        }
@@ -988,15 +1009,32 @@ static void retry_on_resume(struct bio *bio)
        spin_unlock_irqrestore(&pool->lock, flags);
 }
 
-static void handle_unserviceable_bio(struct pool *pool, struct bio *bio)
+static bool should_error_unserviceable_bio(struct pool *pool)
 {
-       /*
-        * When pool is read-only, no cell locking is needed because
-        * nothing is changing.
-        */
-       WARN_ON_ONCE(get_pool_mode(pool) != PM_READ_ONLY);
+       enum pool_mode m = get_pool_mode(pool);
 
-       if (pool->pf.error_if_no_space)
+       switch (m) {
+       case PM_WRITE:
+               /* Shouldn't get here */
+               DMERR_LIMIT("bio unserviceable, yet pool is in PM_WRITE mode");
+               return true;
+
+       case PM_OUT_OF_DATA_SPACE:
+               return pool->pf.error_if_no_space;
+
+       case PM_READ_ONLY:
+       case PM_FAIL:
+               return true;
+       default:
+               /* Shouldn't get here */
+               DMERR_LIMIT("bio unserviceable, yet pool has an unknown mode");
+               return true;
+       }
+}
+
+static void handle_unserviceable_bio(struct pool *pool, struct bio *bio)
+{
+       if (should_error_unserviceable_bio(pool))
                bio_io_error(bio);
        else
                retry_on_resume(bio);
@@ -1007,11 +1045,20 @@ static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *c
        struct bio *bio;
        struct bio_list bios;
 
+       if (should_error_unserviceable_bio(pool)) {
+               cell_error(pool, cell);
+               return;
+       }
+
        bio_list_init(&bios);
        cell_release(pool, cell, &bios);
 
-       while ((bio = bio_list_pop(&bios)))
-               handle_unserviceable_bio(pool, bio);
+       if (should_error_unserviceable_bio(pool))
+               while ((bio = bio_list_pop(&bios)))
+                       bio_io_error(bio);
+       else
+               while ((bio = bio_list_pop(&bios)))
+                       retry_on_resume(bio);
 }
 
 static void process_discard(struct thin_c *tc, struct bio *bio)
@@ -1296,6 +1343,11 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
        }
 }
 
+static void process_bio_success(struct thin_c *tc, struct bio *bio)
+{
+       bio_endio(bio, 0);
+}
+
 static void process_bio_fail(struct thin_c *tc, struct bio *bio)
 {
        bio_io_error(bio);
@@ -1328,6 +1380,11 @@ static void process_deferred_bios(struct pool *pool)
                struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
                struct thin_c *tc = h->tc;
 
+               if (tc->requeue_mode) {
+                       bio_endio(bio, DM_ENDIO_REQUEUE);
+                       continue;
+               }
+
                /*
                 * If we've got no free new_mapping structs, and processing
                 * this bio might require one, we pause until there are some
@@ -1357,7 +1414,8 @@ static void process_deferred_bios(struct pool *pool)
        bio_list_init(&pool->deferred_flush_bios);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
+       if (bio_list_empty(&bios) &&
+           !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
                return;
 
        if (commit(pool)) {
@@ -1393,51 +1451,134 @@ static void do_waker(struct work_struct *ws)
 
 /*----------------------------------------------------------------*/
 
+struct noflush_work {
+       struct work_struct worker;
+       struct thin_c *tc;
+
+       atomic_t complete;
+       wait_queue_head_t wait;
+};
+
+static void complete_noflush_work(struct noflush_work *w)
+{
+       atomic_set(&w->complete, 1);
+       wake_up(&w->wait);
+}
+
+static void do_noflush_start(struct work_struct *ws)
+{
+       struct noflush_work *w = container_of(ws, struct noflush_work, worker);
+       w->tc->requeue_mode = true;
+       requeue_io(w->tc);
+       complete_noflush_work(w);
+}
+
+static void do_noflush_stop(struct work_struct *ws)
+{
+       struct noflush_work *w = container_of(ws, struct noflush_work, worker);
+       w->tc->requeue_mode = false;
+       complete_noflush_work(w);
+}
+
+static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *))
+{
+       struct noflush_work w;
+
+       INIT_WORK(&w.worker, fn);
+       w.tc = tc;
+       atomic_set(&w.complete, 0);
+       init_waitqueue_head(&w.wait);
+
+       queue_work(tc->pool->wq, &w.worker);
+
+       wait_event(w.wait, atomic_read(&w.complete));
+}
+
+/*----------------------------------------------------------------*/
+
 static enum pool_mode get_pool_mode(struct pool *pool)
 {
        return pool->pf.mode;
 }
 
+static void notify_of_pool_mode_change(struct pool *pool, const char *new_mode)
+{
+       dm_table_event(pool->ti->table);
+       DMINFO("%s: switching pool to %s mode",
+              dm_device_name(pool->pool_md), new_mode);
+}
+
 static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
 {
-       int r;
-       enum pool_mode old_mode = pool->pf.mode;
+       struct pool_c *pt = pool->ti->private;
+       bool needs_check = dm_pool_metadata_needs_check(pool->pmd);
+       enum pool_mode old_mode = get_pool_mode(pool);
+
+       /*
+        * Never allow the pool to transition to PM_WRITE mode if user
+        * intervention is required to verify metadata and data consistency.
+        */
+       if (new_mode == PM_WRITE && needs_check) {
+               DMERR("%s: unable to switch pool to write mode until repaired.",
+                     dm_device_name(pool->pool_md));
+               if (old_mode != new_mode)
+                       new_mode = old_mode;
+               else
+                       new_mode = PM_READ_ONLY;
+       }
+       /*
+        * If we were in PM_FAIL mode, rollback of metadata failed.  We're
+        * not going to recover without a thin_repair.  So we never let the
+        * pool move out of the old mode.
+        */
+       if (old_mode == PM_FAIL)
+               new_mode = old_mode;
 
        switch (new_mode) {
        case PM_FAIL:
                if (old_mode != new_mode)
-                       DMERR("%s: switching pool to failure mode",
-                             dm_device_name(pool->pool_md));
+                       notify_of_pool_mode_change(pool, "failure");
                dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_fail;
                pool->process_discard = process_bio_fail;
                pool->process_prepared_mapping = process_prepared_mapping_fail;
                pool->process_prepared_discard = process_prepared_discard_fail;
+
+               error_retry_list(pool);
                break;
 
        case PM_READ_ONLY:
                if (old_mode != new_mode)
-                       DMERR("%s: switching pool to read-only mode",
-                             dm_device_name(pool->pool_md));
-               r = dm_pool_abort_metadata(pool->pmd);
-               if (r) {
-                       DMERR("%s: aborting transaction failed",
-                             dm_device_name(pool->pool_md));
-                       new_mode = PM_FAIL;
-                       set_pool_mode(pool, new_mode);
-               } else {
-                       dm_pool_metadata_read_only(pool->pmd);
-                       pool->process_bio = process_bio_read_only;
-                       pool->process_discard = process_discard;
-                       pool->process_prepared_mapping = process_prepared_mapping_fail;
-                       pool->process_prepared_discard = process_prepared_discard_passdown;
-               }
+                       notify_of_pool_mode_change(pool, "read-only");
+               dm_pool_metadata_read_only(pool->pmd);
+               pool->process_bio = process_bio_read_only;
+               pool->process_discard = process_bio_success;
+               pool->process_prepared_mapping = process_prepared_mapping_fail;
+               pool->process_prepared_discard = process_prepared_discard_passdown;
+
+               error_retry_list(pool);
+               break;
+
+       case PM_OUT_OF_DATA_SPACE:
+               /*
+                * Ideally we'd never hit this state; the low water mark
+                * would trigger userland to extend the pool before we
+                * completely run out of data space.  However, many small
+                * IOs to unprovisioned space can consume data space at an
+                * alarming rate.  Adjust your low water mark if you're
+                * frequently seeing this mode.
+                */
+               if (old_mode != new_mode)
+                       notify_of_pool_mode_change(pool, "out-of-data-space");
+               pool->process_bio = process_bio_read_only;
+               pool->process_discard = process_discard;
+               pool->process_prepared_mapping = process_prepared_mapping;
+               pool->process_prepared_discard = process_prepared_discard_passdown;
                break;
 
        case PM_WRITE:
                if (old_mode != new_mode)
-                       DMINFO("%s: switching pool to write mode",
-                              dm_device_name(pool->pool_md));
+                       notify_of_pool_mode_change(pool, "write");
                dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
                pool->process_discard = process_discard;
@@ -1447,32 +1588,35 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
        }
 
        pool->pf.mode = new_mode;
+       /*
+        * The pool mode may have changed, sync it so bind_control_target()
+        * doesn't cause an unexpected mode transition on resume.
+        */
+       pt->adjusted_pf.mode = new_mode;
 }
 
-/*
- * Rather than calling set_pool_mode directly, use these which describe the
- * reason for mode degradation.
- */
-static void out_of_data_space(struct pool *pool)
+static void abort_transaction(struct pool *pool)
 {
-       DMERR_LIMIT("%s: no free data space available.",
-                   dm_device_name(pool->pool_md));
-       set_pool_mode(pool, PM_READ_ONLY);
+       const char *dev_name = dm_device_name(pool->pool_md);
+
+       DMERR_LIMIT("%s: aborting current metadata transaction", dev_name);
+       if (dm_pool_abort_metadata(pool->pmd)) {
+               DMERR("%s: failed to abort metadata transaction", dev_name);
+               set_pool_mode(pool, PM_FAIL);
+       }
+
+       if (dm_pool_metadata_set_needs_check(pool->pmd)) {
+               DMERR("%s: failed to set 'needs_check' flag in metadata", dev_name);
+               set_pool_mode(pool, PM_FAIL);
+       }
 }
 
 static void metadata_operation_failed(struct pool *pool, const char *op, int r)
 {
-       dm_block_t free_blocks;
-
        DMERR_LIMIT("%s: metadata operation '%s' failed: error = %d",
                    dm_device_name(pool->pool_md), op, r);
 
-       if (r == -ENOSPC &&
-           !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
-           !free_blocks)
-               DMERR_LIMIT("%s: no free metadata space available.",
-                           dm_device_name(pool->pool_md));
-
+       abort_transaction(pool);
        set_pool_mode(pool, PM_READ_ONLY);
 }
 
@@ -1523,6 +1667,11 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
 
        thin_hook_bio(tc, bio);
 
+       if (tc->requeue_mode) {
+               bio_endio(bio, DM_ENDIO_REQUEUE);
+               return DM_MAPIO_SUBMITTED;
+       }
+
        if (get_pool_mode(tc->pool) == PM_FAIL) {
                bio_io_error(bio);
                return DM_MAPIO_SUBMITTED;
@@ -1686,7 +1835,7 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
        /*
         * We want to make sure that a pool in PM_FAIL mode is never upgraded.
         */
-       enum pool_mode old_mode = pool->pf.mode;
+       enum pool_mode old_mode = get_pool_mode(pool);
        enum pool_mode new_mode = pt->adjusted_pf.mode;
 
        /*
@@ -1700,16 +1849,6 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
        pool->pf = pt->adjusted_pf;
        pool->low_water_blocks = pt->low_water_blocks;
 
-       /*
-        * If we were in PM_FAIL mode, rollback of metadata failed.  We're
-        * not going to recover without a thin_repair.  So we never let the
-        * pool move out of the old mode.  On the other hand a PM_READ_ONLY
-        * may have been due to a lack of metadata or data space, and may
-        * now work (ie. if the underlying devices have been resized).
-        */
-       if (old_mode == PM_FAIL)
-               new_mode = old_mode;
-
        set_pool_mode(pool, new_mode);
 
        return 0;
@@ -1999,16 +2138,27 @@ static void metadata_low_callback(void *context)
        dm_table_event(pool->ti->table);
 }
 
-static sector_t get_metadata_dev_size(struct block_device *bdev)
+static sector_t get_dev_size(struct block_device *bdev)
+{
+       return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+}
+
+static void warn_if_metadata_device_too_big(struct block_device *bdev)
 {
-       sector_t metadata_dev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+       sector_t metadata_dev_size = get_dev_size(bdev);
        char buffer[BDEVNAME_SIZE];
 
-       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING) {
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS_WARNING)
                DMWARN("Metadata device %s is larger than %u sectors: excess space will not be used.",
                       bdevname(bdev, buffer), THIN_METADATA_MAX_SECTORS);
-               metadata_dev_size = THIN_METADATA_MAX_SECTORS_WARNING;
-       }
+}
+
+static sector_t get_metadata_dev_size(struct block_device *bdev)
+{
+       sector_t metadata_dev_size = get_dev_size(bdev);
+
+       if (metadata_dev_size > THIN_METADATA_MAX_SECTORS)
+               metadata_dev_size = THIN_METADATA_MAX_SECTORS;
 
        return metadata_dev_size;
 }
@@ -2017,7 +2167,7 @@ static dm_block_t get_metadata_dev_size_in_blocks(struct block_device *bdev)
 {
        sector_t metadata_dev_size = get_metadata_dev_size(bdev);
 
-       sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
+       sector_div(metadata_dev_size, THIN_METADATA_BLOCK_SIZE);
 
        return metadata_dev_size;
 }
@@ -2095,12 +2245,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                ti->error = "Error opening metadata block device";
                goto out_unlock;
        }
-
-       /*
-        * Run for the side-effect of possibly issuing a warning if the
-        * device is too big.
-        */
-       (void) get_metadata_dev_size(metadata_dev->bdev);
+       warn_if_metadata_device_too_big(metadata_dev->bdev);
 
        r = dm_get_device(ti, argv[1], FMODE_READ | FMODE_WRITE, &data_dev);
        if (r) {
@@ -2246,6 +2391,12 @@ static int maybe_resize_data_dev(struct dm_target *ti, bool *need_commit)
                return -EINVAL;
 
        } else if (data_size > sb_data_size) {
+               if (dm_pool_metadata_needs_check(pool->pmd)) {
+                       DMERR("%s: unable to grow the data device until repaired.",
+                             dm_device_name(pool->pool_md));
+                       return 0;
+               }
+
                if (sb_data_size)
                        DMINFO("%s: growing the data device from %llu to %llu blocks",
                               dm_device_name(pool->pool_md),
@@ -2287,6 +2438,13 @@ static int maybe_resize_metadata_dev(struct dm_target *ti, bool *need_commit)
                return -EINVAL;
 
        } else if (metadata_dev_size > sb_metadata_dev_size) {
+               if (dm_pool_metadata_needs_check(pool->pmd)) {
+                       DMERR("%s: unable to grow the metadata device until repaired.",
+                             dm_device_name(pool->pool_md));
+                       return 0;
+               }
+
+               warn_if_metadata_device_too_big(pool->md_dev);
                DMINFO("%s: growing the metadata device from %llu to %llu blocks",
                       dm_device_name(pool->pool_md),
                       sb_metadata_dev_size, metadata_dev_size);
@@ -2673,7 +2831,9 @@ static void pool_status(struct dm_target *ti, status_type_t type,
                else
                        DMEMIT("- ");
 
-               if (pool->pf.mode == PM_READ_ONLY)
+               if (pool->pf.mode == PM_OUT_OF_DATA_SPACE)
+                       DMEMIT("out_of_data_space ");
+               else if (pool->pf.mode == PM_READ_ONLY)
                        DMEMIT("ro ");
                else
                        DMEMIT("rw ");
@@ -2787,7 +2947,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 10, 0},
+       .version = {1, 11, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2894,6 +3054,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        if (get_pool_mode(tc->pool) == PM_FAIL) {
                ti->error = "Couldn't open thin device, Pool is in fail mode";
+               r = -EINVAL;
                goto bad_thin_open;
        }
 
@@ -2905,7 +3066,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        r = dm_set_target_max_io_len(ti, tc->pool->sectors_per_block);
        if (r)
-               goto bad_thin_open;
+               goto bad_target_max_io_len;
 
        ti->num_flush_bios = 1;
        ti->flush_supported = true;
@@ -2926,6 +3087,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        return 0;
 
+bad_target_max_io_len:
+       dm_pool_close_thin_device(tc->td);
 bad_thin_open:
        __pool_dec(tc->pool);
 bad_pool_lookup:
@@ -2986,10 +3149,23 @@ static int thin_endio(struct dm_target *ti, struct bio *bio, int err)
        return 0;
 }
 
-static void thin_postsuspend(struct dm_target *ti)
+static void thin_presuspend(struct dm_target *ti)
 {
+       struct thin_c *tc = ti->private;
+
        if (dm_noflush_suspending(ti))
-               requeue_io((struct thin_c *)ti->private);
+               noflush_work(tc, do_noflush_start);
+}
+
+static void thin_postsuspend(struct dm_target *ti)
+{
+       struct thin_c *tc = ti->private;
+
+       /*
+        * The dm_noflush_suspending flag has been cleared by now, so
+        * unfortunately we must always run this.
+        */
+       noflush_work(tc, do_noflush_stop);
 }
 
 /*
@@ -3074,12 +3250,13 @@ static int thin_iterate_devices(struct dm_target *ti,
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 10, 0},
+       .version = {1, 11, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
        .map = thin_map,
        .end_io = thin_endio,
+       .presuspend = thin_presuspend,
        .postsuspend = thin_postsuspend,
        .status = thin_status,
        .iterate_devices = thin_iterate_devices,
index 19b268795415b4a1eaf519001511275774a7f96e..0c2dec7aec20fd798d45b24d92156b3f85f4aae0 100644 (file)
@@ -6,3 +6,13 @@ config DM_PERSISTENT_DATA
        ---help---
         Library providing immutable on-disk data structure support for
         device-mapper targets such as the thin provisioning target.
+
+config DM_DEBUG_BLOCK_STACK_TRACING
+       boolean "Keep stack trace of persistent data block lock holders"
+       depends on STACKTRACE_SUPPORT && DM_PERSISTENT_DATA
+       select STACKTRACE
+       ---help---
+        Enable this for messages that may help debug problems with the
+        block manager locking used by thin provisioning and caching.
+
+        If unsure, say N.
index 536782e3bcb757427763868fbf86fcb0bd92e273..786b689bdfc7fe0c42d9a651a2369ffadcdc2382 100644 (file)
@@ -91,6 +91,69 @@ struct block_op {
        dm_block_t block;
 };
 
+struct bop_ring_buffer {
+       unsigned begin;
+       unsigned end;
+       struct block_op bops[MAX_RECURSIVE_ALLOCATIONS + 1];
+};
+
+static void brb_init(struct bop_ring_buffer *brb)
+{
+       brb->begin = 0;
+       brb->end = 0;
+}
+
+static bool brb_empty(struct bop_ring_buffer *brb)
+{
+       return brb->begin == brb->end;
+}
+
+static unsigned brb_next(struct bop_ring_buffer *brb, unsigned old)
+{
+       unsigned r = old + 1;
+       return (r >= (sizeof(brb->bops) / sizeof(*brb->bops))) ? 0 : r;
+}
+
+static int brb_push(struct bop_ring_buffer *brb,
+                   enum block_op_type type, dm_block_t b)
+{
+       struct block_op *bop;
+       unsigned next = brb_next(brb, brb->end);
+
+       /*
+        * We don't allow the last bop to be filled, this way we can
+        * differentiate between full and empty.
+        */
+       if (next == brb->begin)
+               return -ENOMEM;
+
+       bop = brb->bops + brb->end;
+       bop->type = type;
+       bop->block = b;
+
+       brb->end = next;
+
+       return 0;
+}
+
+static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result)
+{
+       struct block_op *bop;
+
+       if (brb_empty(brb))
+               return -ENODATA;
+
+       bop = brb->bops + brb->begin;
+       result->type = bop->type;
+       result->block = bop->block;
+
+       brb->begin = brb_next(brb, brb->begin);
+
+       return 0;
+}
+
+/*----------------------------------------------------------------*/
+
 struct sm_metadata {
        struct dm_space_map sm;
 
@@ -101,25 +164,20 @@ struct sm_metadata {
 
        unsigned recursion_count;
        unsigned allocated_this_transaction;
-       unsigned nr_uncommitted;
-       struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];
+       struct bop_ring_buffer uncommitted;
 
        struct threshold threshold;
 };
 
 static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b)
 {
-       struct block_op *op;
+       int r = brb_push(&smm->uncommitted, type, b);
 
-       if (smm->nr_uncommitted == MAX_RECURSIVE_ALLOCATIONS) {
+       if (r) {
                DMERR("too many recursive allocations");
                return -ENOMEM;
        }
 
-       op = smm->uncommitted + smm->nr_uncommitted++;
-       op->type = type;
-       op->block = b;
-
        return 0;
 }
 
@@ -158,11 +216,17 @@ static int out(struct sm_metadata *smm)
                return -ENOMEM;
        }
 
-       if (smm->recursion_count == 1 && smm->nr_uncommitted) {
-               while (smm->nr_uncommitted && !r) {
-                       smm->nr_uncommitted--;
-                       r = commit_bop(smm, smm->uncommitted +
-                                      smm->nr_uncommitted);
+       if (smm->recursion_count == 1) {
+               while (!brb_empty(&smm->uncommitted)) {
+                       struct block_op bop;
+
+                       r = brb_pop(&smm->uncommitted, &bop);
+                       if (r) {
+                               DMERR("bug in bop ring buffer");
+                               break;
+                       }
+
+                       r = commit_bop(smm, &bop);
                        if (r)
                                break;
                }
@@ -217,7 +281,8 @@ static int sm_metadata_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
 static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
                                 uint32_t *result)
 {
-       int r, i;
+       int r;
+       unsigned i;
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
        unsigned adjustment = 0;
 
@@ -225,8 +290,10 @@ static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
         * We may have some uncommitted adjustments to add.  This list
         * should always be really short.
         */
-       for (i = 0; i < smm->nr_uncommitted; i++) {
-               struct block_op *op = smm->uncommitted + i;
+       for (i = smm->uncommitted.begin;
+            i != smm->uncommitted.end;
+            i = brb_next(&smm->uncommitted, i)) {
+               struct block_op *op = smm->uncommitted.bops + i;
 
                if (op->block != b)
                        continue;
@@ -254,7 +321,8 @@ static int sm_metadata_get_count(struct dm_space_map *sm, dm_block_t b,
 static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
                                              dm_block_t b, int *result)
 {
-       int r, i, adjustment = 0;
+       int r, adjustment = 0;
+       unsigned i;
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
        uint32_t rc;
 
@@ -262,8 +330,11 @@ static int sm_metadata_count_is_more_than_one(struct dm_space_map *sm,
         * We may have some uncommitted adjustments to add.  This list
         * should always be really short.
         */
-       for (i = 0; i < smm->nr_uncommitted; i++) {
-               struct block_op *op = smm->uncommitted + i;
+       for (i = smm->uncommitted.begin;
+            i != smm->uncommitted.end;
+            i = brb_next(&smm->uncommitted, i)) {
+
+               struct block_op *op = smm->uncommitted.bops + i;
 
                if (op->block != b)
                        continue;
@@ -671,7 +742,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
        smm->begin = superblock + 1;
        smm->recursion_count = 0;
        smm->allocated_this_transaction = 0;
-       smm->nr_uncommitted = 0;
+       brb_init(&smm->uncommitted);
        threshold_init(&smm->threshold);
 
        memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
@@ -680,6 +751,8 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
        if (r)
                return r;
 
+       if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
+               nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
        r = sm_ll_extend(&smm->ll, nr_blocks);
        if (r)
                return r;
@@ -713,7 +786,7 @@ int dm_sm_metadata_open(struct dm_space_map *sm,
        smm->begin = 0;
        smm->recursion_count = 0;
        smm->allocated_this_transaction = 0;
-       smm->nr_uncommitted = 0;
+       brb_init(&smm->uncommitted);
        threshold_init(&smm->threshold);
 
        memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
index 39bba0801cf2ff092a593e6ccb283f949918cc89..64df923974d86a0ad4d22d59ebdb7fd7f6ecee3f 100644 (file)
@@ -9,6 +9,17 @@
 
 #include "dm-transaction-manager.h"
 
+#define DM_SM_METADATA_BLOCK_SIZE (4096 >> SECTOR_SHIFT)
+
+/*
+ * The metadata device is currently limited in size.
+ *
+ * We have one block of index, which can hold 255 index entries.  Each
+ * index entry contains allocation info about ~16k metadata blocks.
+ */
+#define DM_SM_METADATA_MAX_BLOCKS (255 * ((1 << 14) - 64))
+#define DM_SM_METADATA_MAX_SECTORS (DM_SM_METADATA_MAX_BLOCKS * DM_SM_METADATA_BLOCK_SIZE)
+
 /*
  * Unfortunately we have to use two-phase construction due to the cycle
  * between the tm and sm.
index fd3a2a14b587da5e3bb5046b0017ed7bd46f67a1..4a6ca1cb2e78539679b96a00b89542f6f0eab8f0 100644 (file)
@@ -1953,11 +1953,15 @@ static int process_checks(struct r1bio *r1_bio)
        for (i = 0; i < conf->raid_disks * 2; i++) {
                int j;
                int size;
+               int uptodate;
                struct bio *b = r1_bio->bios[i];
                if (b->bi_end_io != end_sync_read)
                        continue;
-               /* fixup the bio for reuse */
+               /* fixup the bio for reuse, but preserve BIO_UPTODATE */
+               uptodate = test_bit(BIO_UPTODATE, &b->bi_flags);
                bio_reset(b);
+               if (!uptodate)
+                       clear_bit(BIO_UPTODATE, &b->bi_flags);
                b->bi_vcnt = vcnt;
                b->bi_iter.bi_size = r1_bio->sectors << 9;
                b->bi_iter.bi_sector = r1_bio->sector +
@@ -1990,11 +1994,14 @@ static int process_checks(struct r1bio *r1_bio)
                int j;
                struct bio *pbio = r1_bio->bios[primary];
                struct bio *sbio = r1_bio->bios[i];
+               int uptodate = test_bit(BIO_UPTODATE, &sbio->bi_flags);
 
                if (sbio->bi_end_io != end_sync_read)
                        continue;
+               /* Now we can 'fixup' the BIO_UPTODATE flag */
+               set_bit(BIO_UPTODATE, &sbio->bi_flags);
 
-               if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) {
+               if (uptodate) {
                        for (j = vcnt; j-- ; ) {
                                struct page *p, *s;
                                p = pbio->bi_io_vec[j].bv_page;
@@ -2009,7 +2016,7 @@ static int process_checks(struct r1bio *r1_bio)
                if (j >= 0)
                        atomic64_add(r1_bio->sectors, &mddev->resync_mismatches);
                if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)
-                             && test_bit(BIO_UPTODATE, &sbio->bi_flags))) {
+                             && uptodate)) {
                        /* No need to write to this device. */
                        sbio->bi_end_io = NULL;
                        rdev_dec_pending(conf->mirrors[i].rdev, mddev);
index f1feadeb7bb2d1b68a6592d946516e4036c7e939..16f5c21963db5391ed25fd1e185ab8399f353e74 100644 (file)
@@ -5514,23 +5514,43 @@ raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
        return sectors * (raid_disks - conf->max_degraded);
 }
 
+static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
+{
+       safe_put_page(percpu->spare_page);
+       kfree(percpu->scribble);
+       percpu->spare_page = NULL;
+       percpu->scribble = NULL;
+}
+
+static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
+{
+       if (conf->level == 6 && !percpu->spare_page)
+               percpu->spare_page = alloc_page(GFP_KERNEL);
+       if (!percpu->scribble)
+               percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
+
+       if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
+               free_scratch_buffer(conf, percpu);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 static void raid5_free_percpu(struct r5conf *conf)
 {
-       struct raid5_percpu *percpu;
        unsigned long cpu;
 
        if (!conf->percpu)
                return;
 
-       get_online_cpus();
-       for_each_possible_cpu(cpu) {
-               percpu = per_cpu_ptr(conf->percpu, cpu);
-               safe_put_page(percpu->spare_page);
-               kfree(percpu->scribble);
-       }
 #ifdef CONFIG_HOTPLUG_CPU
        unregister_cpu_notifier(&conf->cpu_notify);
 #endif
+
+       get_online_cpus();
+       for_each_possible_cpu(cpu)
+               free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
        put_online_cpus();
 
        free_percpu(conf->percpu);
@@ -5557,15 +5577,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
        switch (action) {
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
-               if (conf->level == 6 && !percpu->spare_page)
-                       percpu->spare_page = alloc_page(GFP_KERNEL);
-               if (!percpu->scribble)
-                       percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
-
-               if (!percpu->scribble ||
-                   (conf->level == 6 && !percpu->spare_page)) {
-                       safe_put_page(percpu->spare_page);
-                       kfree(percpu->scribble);
+               if (alloc_scratch_buffer(conf, percpu)) {
                        pr_err("%s: failed memory allocation for cpu%ld\n",
                               __func__, cpu);
                        return notifier_from_errno(-ENOMEM);
@@ -5573,10 +5585,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
                break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               safe_put_page(percpu->spare_page);
-               kfree(percpu->scribble);
-               percpu->spare_page = NULL;
-               percpu->scribble = NULL;
+               free_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
                break;
        default:
                break;
@@ -5588,40 +5597,29 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 static int raid5_alloc_percpu(struct r5conf *conf)
 {
        unsigned long cpu;
-       struct page *spare_page;
-       struct raid5_percpu __percpu *allcpus;
-       void *scribble;
-       int err;
+       int err = 0;
 
-       allcpus = alloc_percpu(struct raid5_percpu);
-       if (!allcpus)
+       conf->percpu = alloc_percpu(struct raid5_percpu);
+       if (!conf->percpu)
                return -ENOMEM;
-       conf->percpu = allcpus;
+
+#ifdef CONFIG_HOTPLUG_CPU
+       conf->cpu_notify.notifier_call = raid456_cpu_notify;
+       conf->cpu_notify.priority = 0;
+       err = register_cpu_notifier(&conf->cpu_notify);
+       if (err)
+               return err;
+#endif
 
        get_online_cpus();
-       err = 0;
        for_each_present_cpu(cpu) {
-               if (conf->level == 6) {
-                       spare_page = alloc_page(GFP_KERNEL);
-                       if (!spare_page) {
-                               err = -ENOMEM;
-                               break;
-                       }
-                       per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
-               }
-               scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
-               if (!scribble) {
-                       err = -ENOMEM;
+               err = alloc_scratch_buffer(conf, per_cpu_ptr(conf->percpu, cpu));
+               if (err) {
+                       pr_err("%s: failed memory allocation for cpu%ld\n",
+                              __func__, cpu);
                        break;
                }
-               per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
        }
-#ifdef CONFIG_HOTPLUG_CPU
-       conf->cpu_notify.notifier_call = raid456_cpu_notify;
-       conf->cpu_notify.priority = 0;
-       if (err == 0)
-               err = register_cpu_notifier(&conf->cpu_notify);
-#endif
        put_online_cpus();
 
        return err;
index 68f768a5422d063f69b4e33446364f5af699a7a1..a6c3c9e2e89772ffcee9d5ed3baaa1ae980b83e5 100644 (file)
@@ -1176,7 +1176,7 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
 
        switch (demod) {
        case 0:
-               dev_err(&state->priv->i2c->dev,
+               dev_err(&i2c->dev,
                        "%s: Error attaching frontend %d\n",
                        KBUILD_MODNAME, demod);
                goto error1;
@@ -1200,12 +1200,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
        state->demod = demod - 1;
        state->priv = priv;
 
-       /* test i2c bus for ack */
-       if (demod == 0) {
-               if (cx24117_readreg(state, 0x00) < 0)
-                       goto error3;
-       }
-
        dev_info(&state->priv->i2c->dev,
                "%s: Attaching frontend %d\n",
                KBUILD_MODNAME, state->demod);
@@ -1216,8 +1210,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
-error3:
-       kfree(state);
 error2:
        cx24117_release_priv(priv);
 error1:
index 4bf057544607e0762b13332e5da122561fcf4d36..8a8e1ecb762d8abe8e6ab7b8478b2ec65f3577f9 100644 (file)
@@ -2,7 +2,7 @@
  *    Support for NXT2002 and NXT2004 - VSB/QAM
  *
  *    Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
- *    Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
+ *    Copyright (C) 2006-2014 Michael Krufky <mkrufky@linuxtv.org>
  *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
  *    and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
  *
index 1effc21e1cdd1bf110d175627009cba22d55c171..9bbd6656fb8ff72fcb14e440bbecf633d353d6b1 100644 (file)
@@ -2554,7 +2554,7 @@ static int adv7842_core_init(struct v4l2_subdev *sd)
        sdp_write_and_or(sd, 0xdd, 0xf0, pdata->sdp_free_run_force |
                                         (pdata->sdp_free_run_cbar_en << 1) |
                                         (pdata->sdp_free_run_man_col_en << 2) |
-                                        (pdata->sdp_free_run_force << 3));
+                                        (pdata->sdp_free_run_auto << 3));
 
        /* TODO from platform data */
        cp_write(sd, 0x69, 0x14);   /* Enable CP CSC */
index 4b8381111cbd2e66ef2cccc4be64c1e45106d161..77e10e0fd8d623fa78a0ca8e4688c9e44ab2ae10 100644 (file)
@@ -478,25 +478,33 @@ static void s5k5baf_write_arr_seq(struct s5k5baf *state, u16 addr,
                                  u16 count, const u16 *seq)
 {
        struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
-       __be16 buf[count + 1];
-       int ret, n;
+       __be16 buf[65];
 
        s5k5baf_i2c_write(state, REG_CMDWR_ADDR, addr);
        if (state->error)
                return;
 
+       v4l2_dbg(3, debug, c, "i2c_write_seq(count=%d): %*ph\n", count,
+                min(2 * count, 64), seq);
+
        buf[0] = __constant_cpu_to_be16(REG_CMD_BUF);
-       for (n = 1; n <= count; ++n)
-               buf[n] = cpu_to_be16(*seq++);
 
-       n *= 2;
-       ret = i2c_master_send(c, (char *)buf, n);
-       v4l2_dbg(3, debug, c, "i2c_write_seq(count=%d): %*ph\n", count,
-                min(2 * count, 64), seq - count);
+       while (count > 0) {
+               int n = min_t(int, count, ARRAY_SIZE(buf) - 1);
+               int ret, i;
 
-       if (ret != n) {
-               v4l2_err(c, "i2c_write_seq: error during transfer (%d)\n", ret);
-               state->error = ret;
+               for (i = 1; i <= n; ++i)
+                       buf[i] = cpu_to_be16(*seq++);
+
+               i *= 2;
+               ret = i2c_master_send(c, (char *)buf, i);
+               if (ret != i) {
+                       v4l2_err(c, "i2c_write_seq: error during transfer (%d)\n", ret);
+                       state->error = ret;
+                       break;
+               }
+
+               count -= n;
        }
 }
 
index d85cb0ace4dc654b541017a38fde5e0e004f3b1e..6662b495b22c637c73ee2f6e50bf8571e5d2e948 100644 (file)
@@ -2426,7 +2426,7 @@ struct tvcard bttv_tvcards[] = {
        },
                /* ---- card 0x87---------------------------------- */
        [BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = {
-               /* Michael Krufky <mkrufky@m1k.net> */
+               /* Michael Krufky <mkrufky@linuxtv.org> */
                .name           = "DViCO FusionHDTV 5 Lite",
                .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
                .tuner_addr     = ADDR_UNSET,
index 922e8233fd0b88dbed55c284342edfa7c9b23cf0..3f364b7062b915445bf952b84dc1a64950b2ba02 100644 (file)
@@ -98,7 +98,7 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
 
        err = device_register(&sub->dev);
        if (0 != err) {
-               kfree(sub);
+               put_device(&sub->dev);
                return err;
        }
        pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
index d45e7f6ff332203785171a3aa6c915ac0e1a9950..c9b2350e92c863f87b329e8972d50fafa883dc90 100644 (file)
@@ -2590,7 +2590,7 @@ struct saa7134_board saa7134_boards[] = {
                }},
        },
        [SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
-               /* Michael Krufky <mkrufky@m1k.net>
+               /* Michael Krufky <mkrufky@linuxtv.org>
                 * Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
                 * AFAIK, there is no analog demod, thus,
                 * no support for analog television.
index a7dfd07e838954b6fb500cc6d1d7991ea5cf0dc5..da2fc86cc52433bd8f1c6b32a898baa87c2a1064 100644 (file)
@@ -1027,7 +1027,8 @@ static int fimc_probe(struct platform_device *pdev)
        return 0;
 
 err_gclk:
-       clk_disable(fimc->clock[CLK_GATE]);
+       if (!pm_runtime_enabled(dev))
+               clk_disable(fimc->clock[CLK_GATE]);
 err_sd:
        fimc_unregister_capture_subdev(fimc);
 err_sclk:
@@ -1036,6 +1037,7 @@ err_sclk:
        return ret;
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static int fimc_runtime_resume(struct device *dev)
 {
        struct fimc_dev *fimc = dev_get_drvdata(dev);
@@ -1068,6 +1070,7 @@ static int fimc_runtime_suspend(struct device *dev)
        dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
        return ret;
 }
+#endif
 
 #ifdef CONFIG_PM_SLEEP
 static int fimc_resume(struct device *dev)
index 1234734bccf4d3943d047e53a2f54347d73c58c0..779ec3cd259dad43bee5ec151bfcc51a6fde0c15 100644 (file)
@@ -1563,7 +1563,7 @@ static int fimc_lite_probe(struct platform_device *pdev)
        if (!pm_runtime_enabled(dev)) {
                ret = clk_enable(fimc->clock);
                if (ret < 0)
-                       goto err_clk_put;
+                       goto err_sd;
        }
 
        fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
@@ -1579,7 +1579,8 @@ static int fimc_lite_probe(struct platform_device *pdev)
        return 0;
 
 err_clk_dis:
-       clk_disable(fimc->clock);
+       if (!pm_runtime_enabled(dev))
+               clk_disable(fimc->clock);
 err_sd:
        fimc_lite_unregister_capture_subdev(fimc);
 err_clk_put:
@@ -1587,6 +1588,7 @@ err_clk_put:
        return ret;
 }
 
+#ifdef CONFIG_PM_RUNTIME
 static int fimc_lite_runtime_resume(struct device *dev)
 {
        struct fimc_lite *fimc = dev_get_drvdata(dev);
@@ -1602,6 +1604,7 @@ static int fimc_lite_runtime_suspend(struct device *dev)
        clk_disable(fimc->clock);
        return 0;
 }
+#endif
 
 #ifdef CONFIG_PM_SLEEP
 static int fimc_lite_resume(struct device *dev)
index a1c78c870b68b44f660d2b54844ca5a5b13b1c7a..7d68d0b9966aa7774edfa1ccce40100768632bab 100644 (file)
@@ -175,7 +175,7 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
        {
                .name           = "YUV 4:2:0 planar, Y/CbCr",
                .fourcc         = V4L2_PIX_FMT_NV12,
-               .depth          = 16,
+               .depth          = 12,
                .colplanes      = 2,
                .h_align        = 1,
                .v_align        = 1,
@@ -188,10 +188,10 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
        {
                .name           = "YUV 4:2:0 planar, Y/CbCr",
                .fourcc         = V4L2_PIX_FMT_NV12,
-               .depth          = 16,
-               .colplanes      = 4,
+               .depth          = 12,
+               .colplanes      = 2,
                .h_align        = 4,
-               .v_align        = 1,
+               .v_align        = 4,
                .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
                                  SJPEG_FMT_FLAG_DEC_CAPTURE |
                                  SJPEG_FMT_FLAG_S5P |
index 8f9b2cea88f009ec316fb1b97cbbfa67984fcda0..8ede8ea762e601a773dd49c1ae397f016d533338 100644 (file)
@@ -1539,6 +1539,8 @@ static const struct usb_device_id af9035_id_table[] = {
                &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) },
        { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05,
                &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900,
+               &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
index d83df4bb72d352308f8baff11e7fe6ad72a63026..0a98d04c53e484206aede5579638ed91dcaa0a7c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -601,7 +601,7 @@ struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
 EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
 
 MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.1");
 
index 3f3f8bfd190b9e9e3f415cf7f2a21fae25a473bf..2d4530f5be543a9c04029abefeb6def55c8eab31 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e4121cb8f5ef44716ed15ab07f96c6ad6fcbf2bd..a619410adde454076e90d0206b5b1056d5379d3a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0220f54299a5d0488b1ad3c7798151e56a34fbb9..b85a5772d771b063310c9790b46ec1aaeac5e772 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 34434557ef65934d0652d926df3459d8bbc30c1c..a101d06eb143f4729a76830df6940907ff7d3925 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index a57a45ffb9e401396cd8f69097453e3a86d98bc8..465762145ad229895c075d8fb5328240c5e8cf62 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index b741b3a7a325d423287512dce40440ad9556505a..f6b348024bec2f8c3968b3e3c4a8753d7a267b28 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-phy.c - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index f0756071d34711b423bae7601420bcd6ccb1d4bc..0643738de7dec76a4947d323099750e8c82dd204 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-phy.h - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 17831b0fb9db04cdcacfbb15006b00dbc5dbd16e..89bf115e927e0583b054834427ec3df5a9a26220 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-reg.h - driver for the MaxLinear MXL111SF
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 879c529640f7e20234ef3a40a9231223c110259a..a8d2c7053674aa674bd04e0943ee1cdf9057ad40 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -512,7 +512,7 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
 EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
 
 MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.1");
 
index 90f583e5d6a6bb458f82fe2c08578d8d44c303d8..2046db22519e5ba68f7fa4ba9fa1e659efec5a15 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
  *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
+ *  Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -68,7 +68,7 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
 #else
 static inline
 struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
-                                          struct mxl111sf_state *mxl_state
+                                          struct mxl111sf_state *mxl_state,
                                           struct mxl111sf_tuner_config *cfg)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
index 08240e498451a55810e4bd00a75df73d0c1a607e..c7304fa8ab737e46257545d0e30316de2c8cd539 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
+ * Copyright (C) 2010-2014 Michael Krufky (mkrufky@linuxtv.org)
  *
  *   This program is free software; you can redistribute it and/or modify it
  *   under the terms of the GNU General Public License as published by the Free
@@ -105,7 +105,7 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
                ret = -EINVAL;
        }
 
-       pr_debug("R: (0x%02x, 0x%02x)\n", addr, *data);
+       pr_debug("R: (0x%02x, 0x%02x)\n", addr, buf[1]);
 fail:
        return ret;
 }
@@ -1421,7 +1421,7 @@ static struct usb_driver mxl111sf_usb_driver = {
 
 module_usb_driver(mxl111sf_usb_driver);
 
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
index 9816de86e48cb4bd088c535b990d582db1e636db..8516c011b7cc71c11a84ad9bb8814a02f0a06ff3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
+ * Copyright (C) 2010-2014 Michael Krufky (mkrufky@linuxtv.org)
  *
  *   This program is free software; you can redistribute it and/or modify it
  *   under the terms of the GNU General Public License as published by the Free
index 2f0c89cbac763bfdb5d8434bc19768df8b8f977b..c5638964c3f286665e0cd57ae1e713be0506e881 100644 (file)
@@ -198,7 +198,6 @@ static int device_authorization(struct hdpvr_device *dev)
        hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
        v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
                 print_buf);
-       kfree(print_buf);
 #endif
 
        msleep(100);
@@ -214,6 +213,9 @@ static int device_authorization(struct hdpvr_device *dev)
        retval = ret != 8;
 unlock:
        mutex_unlock(&dev->usbc_mutex);
+#ifdef HDPVR_DEBUG
+       kfree(print_buf);
+#endif
        return retval;
 }
 
index ee52b9f4a9444137dd28be70c1d752c258911258..f7902fe8a5267972aa7d2e9daa0b66e81d6727e3 100644 (file)
@@ -515,6 +515,7 @@ bool v4l2_detect_gtf(unsigned frame_height,
                aspect.denominator = 9;
        }
        image_width = ((image_height * aspect.numerator) / aspect.denominator);
+       image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1);
 
        /* Horizontal */
        if (default_gtf)
index 65411adcd0ea958a3b4c7a5edd6f4f2d57cb32d9..7e6b209b7002da88979a46f0edff9c2f39a62738 100644 (file)
@@ -66,14 +66,11 @@ static void __videobuf_dc_free(struct device *dev,
 static void videobuf_vm_open(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
-       struct videobuf_queue *q = map->q;
 
-       dev_dbg(q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
+       dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
                map, map->count, vma->vm_start, vma->vm_end);
 
-       videobuf_queue_lock(q);
        map->count++;
-       videobuf_queue_unlock(q);
 }
 
 static void videobuf_vm_close(struct vm_area_struct *vma)
@@ -85,11 +82,12 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
        dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
                map, map->count, vma->vm_start, vma->vm_end);
 
-       videobuf_queue_lock(q);
-       if (!--map->count) {
+       map->count--;
+       if (0 == map->count) {
                struct videobuf_dma_contig_memory *mem;
 
                dev_dbg(q->dev, "munmap %p q=%p\n", map, q);
+               videobuf_queue_lock(q);
 
                /* We need first to cancel streams, before unmapping */
                if (q->streaming)
@@ -128,8 +126,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
 
                kfree(map);
 
+               videobuf_queue_unlock(q);
        }
-       videobuf_queue_unlock(q);
 }
 
 static const struct vm_operations_struct videobuf_vm_ops = {
index 9db674ccdc68c11b2751d290f786a6cf56d6a6d9..828e7c10bd701cc9b598f26721a413de7d378cde 100644 (file)
@@ -338,14 +338,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_free);
 static void videobuf_vm_open(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
-       struct videobuf_queue *q = map->q;
 
        dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map,
                map->count, vma->vm_start, vma->vm_end);
 
-       videobuf_queue_lock(q);
        map->count++;
-       videobuf_queue_unlock(q);
 }
 
 static void videobuf_vm_close(struct vm_area_struct *vma)
@@ -358,9 +355,10 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
        dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map,
                map->count, vma->vm_start, vma->vm_end);
 
-       videobuf_queue_lock(q);
-       if (!--map->count) {
+       map->count--;
+       if (0 == map->count) {
                dprintk(1, "munmap %p q=%p\n", map, q);
+               videobuf_queue_lock(q);
                for (i = 0; i < VIDEO_MAX_FRAME; i++) {
                        if (NULL == q->bufs[i])
                                continue;
@@ -376,9 +374,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
                        q->bufs[i]->baddr = 0;
                        q->ops->buf_release(q, q->bufs[i]);
                }
+               videobuf_queue_unlock(q);
                kfree(map);
        }
-       videobuf_queue_unlock(q);
        return;
 }
 
index 1365c651c1777bd5f7973281f26baccdad6c8995..2ff7fcc77b1104fe7d1ca1a2a9d5738ede27acb7 100644 (file)
@@ -54,14 +54,11 @@ MODULE_LICENSE("GPL");
 static void videobuf_vm_open(struct vm_area_struct *vma)
 {
        struct videobuf_mapping *map = vma->vm_private_data;
-       struct videobuf_queue *q = map->q;
 
        dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
                map->count, vma->vm_start, vma->vm_end);
 
-       videobuf_queue_lock(q);
        map->count++;
-       videobuf_queue_unlock(q);
 }
 
 static void videobuf_vm_close(struct vm_area_struct *vma)
@@ -73,11 +70,12 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
        dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
                map->count, vma->vm_start, vma->vm_end);
 
-       videobuf_queue_lock(q);
-       if (!--map->count) {
+       map->count--;
+       if (0 == map->count) {
                struct videobuf_vmalloc_memory *mem;
 
                dprintk(1, "munmap %p q=%p\n", map, q);
+               videobuf_queue_lock(q);
 
                /* We need first to cancel streams, before unmapping */
                if (q->streaming)
@@ -116,8 +114,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
 
                kfree(map);
 
+               videobuf_queue_unlock(q);
        }
-       videobuf_queue_unlock(q);
 
        return;
 }
index 5a5fb7f09b7bd1857bc7e660c24d7e1b95117dc6..a127925c9d61da6f92a93fb49d6e6f01f03e0e25 100644 (file)
@@ -1776,6 +1776,11 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
                return 0;
        }
 
+       if (!q->num_buffers) {
+               dprintk(1, "streamon: no buffers have been allocated\n");
+               return -EINVAL;
+       }
+
        /*
         * If any buffers were queued before streamon,
         * we can now pass them to driver for processing.
index a60c188c2bd937255f60f42920e4b9fbba68cb88..04bd3b6de40188bebf7f083750ed547c38265ec2 100644 (file)
@@ -754,19 +754,19 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
                                 unsigned long arg)
 {
        int ret;
-       mutex_lock(&i2o_cfg_mutex);
        switch (cmd) {
        case I2OGETIOPS:
                ret = i2o_cfg_ioctl(file, cmd, arg);
                break;
        case I2OPASSTHRU32:
+               mutex_lock(&i2o_cfg_mutex);
                ret = i2o_cfg_passthru32(file, cmd, arg);
+               mutex_unlock(&i2o_cfg_mutex);
                break;
        default:
                ret = -ENOIOCTLCMD;
                break;
        }
-       mutex_unlock(&i2o_cfg_mutex);
        return ret;
 }
 
index 13af7e50021eedd5767aa296cfe46118f55f49ac..8103e4362132a24486961bf3ac6fd80980210107 100644 (file)
@@ -53,17 +53,25 @@ static int da9055_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the PMIC and CODEC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 ids for PMIC
+ * and CODEC, which must be different to operate together.
+ */
 static struct i2c_device_id da9055_i2c_id[] = {
-       {"da9055", 0},
+       {"da9055-pmic", 0},
        { }
 };
+MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
 
 static struct i2c_driver da9055_i2c_driver = {
        .probe = da9055_i2c_probe,
        .remove = da9055_i2c_remove,
        .id_table = da9055_i2c_id,
        .driver = {
-               .name = "da9055",
+               .name = "da9055-pmic",
                .owner = THIS_MODULE,
        },
 };
index ac514fb2b8779ef6a1b7395bcd6c26cc45aefdc2..71aa14a6bfbbb4ffd061aeb91df739fc70684446 100644 (file)
@@ -173,6 +173,7 @@ static const struct i2c_device_id max14577_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
 
+#ifdef CONFIG_PM_SLEEP
 static int max14577_suspend(struct device *dev)
 {
        struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -208,6 +209,7 @@ static int max14577_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static struct of_device_id max14577_dt_match[] = {
        { .compatible = "maxim,max14577", },
index be88a3bf7b857a5b19f7e9d95b1be42c7e58b2d3..5adede0fb04c8c5a82f7804d3138ab1f7a74f334 100644 (file)
@@ -164,15 +164,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
        return pd;
 }
 
-static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+static inline unsigned long max8997_i2c_get_driver_data(struct i2c_client *i2c,
                                                const struct i2c_device_id *id)
 {
        if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
                const struct of_device_id *match;
                match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
-               return (int)match->data;
+               return (unsigned long)match->data;
        }
-       return (int)id->driver_data;
+       return id->driver_data;
 }
 
 static int max8997_i2c_probe(struct i2c_client *i2c,
index 612ca404e1502d6c736eaf239d9b721e522664f9..5d5e186b5d8bbbfed035725480fb85dc52a0fdb4 100644 (file)
@@ -169,16 +169,16 @@ static struct max8998_platform_data *max8998_i2c_parse_dt_pdata(
        return pd;
 }
 
-static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
+static inline unsigned long max8998_i2c_get_driver_data(struct i2c_client *i2c,
                                                const struct i2c_device_id *id)
 {
        if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
                const struct of_device_id *match;
                match = of_match_node(max8998_dt_match, i2c->dev.of_node);
-               return (int)(long)match->data;
+               return (unsigned long)match->data;
        }
 
-       return (int)id->driver_data;
+       return id->driver_data;
 }
 
 static int max8998_i2c_probe(struct i2c_client *i2c,
index a139798b806546b751b37f22e4d3e8044f3e2422..714e2135210ec2ddc989efcd44f3e800b80f5bcf 100644 (file)
@@ -315,6 +315,7 @@ static int sec_pmic_remove(struct i2c_client *i2c)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int sec_pmic_suspend(struct device *dev)
 {
        struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
@@ -349,6 +350,7 @@ static int sec_pmic_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
 
index 966cf65c5c363f63d907048fe4bb31b3d30bbbac..3cc4c7084b9244dcc18dd42a7ab77a3550e59ddb 100644 (file)
@@ -158,7 +158,7 @@ static int tps65217_probe(struct i2c_client *client,
 {
        struct tps65217 *tps;
        unsigned int version;
-       unsigned int chip_id = ids->driver_data;
+       unsigned long chip_id = ids->driver_data;
        const struct of_device_id *match;
        bool status_off = false;
        int ret;
@@ -170,7 +170,7 @@ static int tps65217_probe(struct i2c_client *client,
                                "Failed to find matching dt id\n");
                        return -EINVAL;
                }
-               chip_id = (unsigned int)(unsigned long)match->data;
+               chip_id = (unsigned long)match->data;
                status_off = of_property_read_bool(client->dev.of_node,
                                        "ti,pmic-shutdown-controller");
        }
index ba04f1bc70eb52988ce27b5f4e45195e8b216b82..e6fab94e2c8a0fb1eed8df339833e36f2dd7c38b 100644 (file)
@@ -636,7 +636,7 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
        if (i2c->dev.of_node) {
                of_id = of_match_device(wm8994_of_match, &i2c->dev);
                if (of_id)
-                       wm8994->type = (int)of_id->data;
+                       wm8994->type = (enum wm8994_type)of_id->data;
        } else {
                wm8994->type = id->driver_data;
        }
index 8f8a6b327cdb83dd494823a77a50c98078738b38..2c2c9cc75231d7c9182a47fa43d22c5d99d58627 100644 (file)
@@ -787,6 +787,7 @@ static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m)
        if (rc != 0) {
                dev_err(&pci_dev->dev,
                        "[%s] genwqe_user_vmap rc=%d\n", __func__, rc);
+               kfree(dma_map);
                return rc;
        }
 
index 1ee2b9492a82527d508b4396647f75823956e28c..89a557972d1b926abe915760366d6602c1efa0cf 100644 (file)
@@ -666,7 +666,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
                goto err;
 
        cb->fop_type = MEI_FOP_READ;
-       cl->read_cb = cb;
        if (dev->hbuf_is_ready) {
                dev->hbuf_is_ready = false;
                if (mei_hbm_cl_flow_control_req(dev, cl)) {
@@ -678,6 +677,9 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
        } else {
                list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
        }
+
+       cl->read_cb = cb;
+
        return rets;
 err:
        mei_io_cb_free(cb);
@@ -908,7 +910,6 @@ void mei_cl_all_disconnect(struct mei_device *dev)
        list_for_each_entry_safe(cl, next, &dev->file_list, link) {
                cl->state = MEI_FILE_DISCONNECTED;
                cl->mei_flow_ctrl_creds = 0;
-               cl->read_cb = NULL;
                cl->timer_count = 0;
        }
 }
@@ -942,8 +943,16 @@ void mei_cl_all_wakeup(struct mei_device *dev)
 void mei_cl_all_write_clear(struct mei_device *dev)
 {
        struct mei_cl_cb *cb, *next;
+       struct list_head *list;
+
+       list = &dev->write_list.list;
+       list_for_each_entry_safe(cb, next, list, list) {
+               list_del(&cb->list);
+               mei_io_cb_free(cb);
+       }
 
-       list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
+       list = &dev->write_waiting_list.list;
+       list_for_each_entry_safe(cb, next, list, list) {
                list_del(&cb->list);
                mei_io_cb_free(cb);
        }
index 752ff873f891bb3dc502305506f3f782ede28296..7e1ef0ebbb800bfcf00d7d07aaff02f7a5af7b4a 100644 (file)
@@ -156,7 +156,8 @@ static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
 static int _mic_virtio_copy(struct mic_vdev *mvdev,
        struct mic_copy_desc *copy)
 {
-       int ret = 0, iovcnt = copy->iovcnt;
+       int ret = 0;
+       u32 iovcnt = copy->iovcnt;
        struct iovec iov;
        struct iovec __user *u_iov = copy->iov;
        void __user *ubuf = NULL;
index 9b2062d173279438a92b6f1ba548404fe4c429b0..2bef3f76032aa117d8bc2fa06451e832118acce1 100644 (file)
@@ -139,8 +139,11 @@ static int gru_dump_context(struct gru_state *gru, int ctxnum,
 
        ubuf += sizeof(hdr);
        ubufcch = ubuf;
-       if (gru_user_copy_handle(&ubuf, cch))
-               goto fail;
+       if (gru_user_copy_handle(&ubuf, cch)) {
+               if (cch_locked)
+                       unlock_cch_handle(cch);
+               return -EFAULT;
+       }
        if (cch_locked)
                ubufcch->delresp = 0;
        bytes = sizeof(hdr) + GRU_CACHE_LINE_BYTES;
@@ -179,10 +182,6 @@ static int gru_dump_context(struct gru_state *gru, int ctxnum,
                ret = -EFAULT;
 
        return ret ? ret : bytes;
-
-fail:
-       unlock_cch_handle(cch);
-       return -EFAULT;
 }
 
 int gru_dump_chiplet_request(unsigned long arg)
index b9e2000969f025894be4bcae2c6950d699ded3a9..95c894482fddf443d4516ffad39c54adda5be754 100644 (file)
@@ -240,7 +240,7 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
 
        nid = cpu_to_node(cpu);
        page = alloc_pages_exact_node(nid,
-                                     GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+                                     GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
                                      pg_order);
        if (page == NULL) {
                dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
index 357bbc54fe4b6f423aa2dcc86ca3a23624748a6b..3e049c13429cfbe730179724053796cc65ba62de 100644 (file)
@@ -197,7 +197,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
 
        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-               limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
+               limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
        mq->card = card;
        mq->queue = blk_init_queue(mmc_request_fn, lock);
index 55cd110a49c4009451b0ca4b35144c8631b8c7d1..c204b7d1532c0f1c910b25a7435d3f12c8435732 100644 (file)
@@ -2607,7 +2607,7 @@ int dw_mci_probe(struct dw_mci *host)
 
        tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
        host->card_workqueue = alloc_workqueue("dw-mci-card",
-                       WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1);
+                       WQ_MEM_RECLAIM, 1);
        if (!host->card_workqueue) {
                ret = -ENOMEM;
                goto err_dmaunmap;
index 59eba5d2c68574fae787d36d2bd9e5ed29eb9f25..9715a7ba164a042abbba49fd842e9400a677d6fe 100644 (file)
@@ -1584,7 +1584,7 @@ read_retry:
                        }
 
                        if (mtd->ecc_stats.failed - ecc_failures) {
-                               if (retry_mode + 1 <= chip->read_retries) {
+                               if (retry_mode + 1 < chip->read_retries) {
                                        retry_mode++;
                                        ret = nand_setup_read_retry(mtd,
                                                        retry_mode);
index ef4190a02b7bd591af7c97be8ee1e3caecf6f83c..bf642ceef68172b4575d8e9d3263320e0fc7095a 100644 (file)
@@ -1633,6 +1633,7 @@ static int omap_nand_probe(struct platform_device *pdev)
        int                             i;
        dma_cap_mask_t                  mask;
        unsigned                        sig;
+       unsigned                        oob_index;
        struct resource                 *res;
        struct mtd_part_parser_data     ppdata = {};
 
@@ -1826,11 +1827,14 @@ static int omap_nand_probe(struct platform_device *pdev)
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
                if (nand_chip->options & NAND_BUSWIDTH_16)
-                       ecclayout->eccpos[0]    = BADBLOCK_MARKER_LENGTH;
+                       oob_index               = BADBLOCK_MARKER_LENGTH;
                else
-                       ecclayout->eccpos[0]    = 1;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+                       oob_index               = 1;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+                       ecclayout->eccpos[i]    = oob_index;
+               /* no reserved-marker in ecclayout for this ecc-scheme */
+               ecclayout->oobfree->offset      =
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                break;
 
        case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
@@ -1847,9 +1851,15 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+                       ecclayout->eccpos[i] = oob_index;
+                       if (((i + 1) % nand_chip->ecc.bytes) == 0)
+                               oob_index++;
+               }
+               /* include reserved-marker in ecclayout->oobfree calculation */
+               ecclayout->oobfree->offset      = 1 +
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                /* software bch library is used for locating errors */
                nand_chip->ecc.priv             = nand_bch_init(mtd,
                                                        nand_chip->ecc.size,
@@ -1883,9 +1893,12 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+                       ecclayout->eccpos[i]    = oob_index;
+               /* reserved marker already included in ecclayout->eccbytes */
+               ecclayout->oobfree->offset      =
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                /* This ECC scheme requires ELM H/W block */
                if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
                        pr_err("nand: error: could not initialize ELM\n");
@@ -1913,9 +1926,15 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+                       ecclayout->eccpos[i] = oob_index;
+                       if (((i + 1) % nand_chip->ecc.bytes) == 0)
+                               oob_index++;
+               }
+               /* include reserved-marker in ecclayout->oobfree calculation */
+               ecclayout->oobfree->offset      = 1 +
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                /* software bch library is used for locating errors */
                nand_chip->ecc.priv             = nand_bch_init(mtd,
                                                        nand_chip->ecc.size,
@@ -1956,9 +1975,12 @@ static int omap_nand_probe(struct platform_device *pdev)
                ecclayout->eccbytes             = nand_chip->ecc.bytes *
                                                        (mtd->writesize /
                                                        nand_chip->ecc.size);
-               ecclayout->eccpos[0]            = BADBLOCK_MARKER_LENGTH;
-               ecclayout->oobfree->offset      = ecclayout->eccpos[0] +
-                                                       ecclayout->eccbytes;
+               oob_index                       = BADBLOCK_MARKER_LENGTH;
+               for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+                       ecclayout->eccpos[i]    = oob_index;
+               /* reserved marker already included in ecclayout->eccbytes */
+               ecclayout->oobfree->offset      =
+                               ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
                break;
 #else
                pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
@@ -1972,11 +1994,8 @@ static int omap_nand_probe(struct platform_device *pdev)
                goto return_error;
        }
 
-       /* populate remaining ECC layout data */
-       ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
-                                                       ecclayout->eccbytes);
-       for (i = 1; i < ecclayout->eccbytes; i++)
-               ecclayout->eccpos[i] = ecclayout->eccpos[0] + i;
+       /* all OOB bytes from oobfree->offset till end off OOB are free */
+       ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
        /* check if NAND device's OOB is enough to store ECC signatures */
        if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
                pr_err("not enough OOB bytes required = %d, available=%d\n",
index ead861307b3c57aac13bbb187a958a8910062904..c5dad652614d747df33477dbd414c472572aefe5 100644 (file)
@@ -463,8 +463,8 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
                                }
                        }
                        if (found_orphan) {
-                               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                                list_del(&tmp_aeb->u.list);
+                               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                        }
 
                        new_aeb = kmem_cache_alloc(ai->aeb_slab_cache,
@@ -846,16 +846,16 @@ fail_bad:
        ret = UBI_BAD_FASTMAP;
 fail:
        list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
-               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                list_del(&tmp_aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
        }
        list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) {
-               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                list_del(&tmp_aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
        }
        list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
-               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
                list_del(&tmp_aeb->u.list);
+               kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
        }
 
        return ret;
index f342278539d50cfb58b0cfea45894bb1c63babd2..494b888a65681bde29911f13bea5ab02ed1c32d2 100644 (file)
@@ -139,7 +139,7 @@ config MACVTAP
          This adds a specialized tap character device driver that is based
          on the MAC-VLAN network interface, called macvtap. A macvtap device
          can be added in the same way as a macvlan device, using 'type
-         macvlan', and then be accessed through the tap user space interface.
+         macvtap', and then be accessed through the tap user space interface.
 
          To compile this driver as a module, choose M here: the module
          will be called macvtap.
index cce1f1bf90b4324e6e2f20e5da6ef53a307bd296..dcde56057fe14f7bb64a8221db03b2d72a22d842 100644 (file)
@@ -181,7 +181,7 @@ static inline int __agg_has_partner(struct aggregator *agg)
  */
 static inline void __disable_port(struct port *port)
 {
-       bond_set_slave_inactive_flags(port->slave);
+       bond_set_slave_inactive_flags(port->slave, BOND_SLAVE_NOTIFY_LATER);
 }
 
 /**
@@ -193,7 +193,7 @@ static inline void __enable_port(struct port *port)
        struct slave *slave = port->slave;
 
        if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev))
-               bond_set_slave_active_flags(slave);
+               bond_set_slave_active_flags(slave, BOND_SLAVE_NOTIFY_LATER);
 }
 
 /**
@@ -1796,8 +1796,6 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
        BOND_AD_INFO(bond).agg_select_timer = timeout;
 }
 
-static u16 aggregator_identifier;
-
 /**
  * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
  * @bond: bonding struct to work on
@@ -1811,7 +1809,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
        if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
                                bond->dev->dev_addr)) {
 
-               aggregator_identifier = 0;
+               BOND_AD_INFO(bond).aggregator_identifier = 0;
 
                BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
                BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@ -1880,7 +1878,7 @@ void bond_3ad_bind_slave(struct slave *slave)
                ad_initialize_agg(aggregator);
 
                aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
-               aggregator->aggregator_identifier = (++aggregator_identifier);
+               aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier;
                aggregator->slave = slave;
                aggregator->is_active = 0;
                aggregator->num_of_ports = 0;
@@ -2064,6 +2062,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
        struct list_head *iter;
        struct slave *slave;
        struct port *port;
+       bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
 
        read_lock(&bond->lock);
        rcu_read_lock();
@@ -2121,8 +2120,19 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
        }
 
 re_arm:
+       bond_for_each_slave_rcu(bond, slave, iter) {
+               if (slave->should_notify) {
+                       should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
+                       break;
+               }
+       }
        rcu_read_unlock();
        read_unlock(&bond->lock);
+
+       if (should_notify_rtnl && rtnl_trylock()) {
+               bond_slave_state_notify(bond);
+               rtnl_unlock();
+       }
        queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
 }
 
index 13dc9d3c5e3460e2e0e4f01e2ab1df2a962d60e2..f4dd9592ac62561fb8967843446d6a9c0463b7e7 100644 (file)
@@ -253,6 +253,7 @@ struct ad_system {
 struct ad_bond_info {
        struct ad_system system;            /* 802.3ad system structure */
        u32 agg_select_timer;       // Timer to select aggregator after all adapter's hand shakes
+       u16 aggregator_identifier;
 };
 
 struct ad_slave_info {
index a2c47476804dc388406e05b4c425c4be59089add..e8f133e926aae720d09d76117bd0c84dcc90d775 100644 (file)
@@ -730,7 +730,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
                        client_info->ntt = 0;
                }
 
-               if (!vlan_get_tag(skb, &client_info->vlan_id))
+               if (vlan_get_tag(skb, &client_info->vlan_id))
                        client_info->vlan_id = 0;
 
                if (!client_info->assigned) {
index 4c08018d7333138a95d0d6a3c72c67131f842ed5..e5628fc725c3fc3885b7deac79074caa41edbae4 100644 (file)
@@ -829,21 +829,25 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
        if (bond_is_lb(bond)) {
                bond_alb_handle_active_change(bond, new_active);
                if (old_active)
-                       bond_set_slave_inactive_flags(old_active);
+                       bond_set_slave_inactive_flags(old_active,
+                                                     BOND_SLAVE_NOTIFY_NOW);
                if (new_active)
-                       bond_set_slave_active_flags(new_active);
+                       bond_set_slave_active_flags(new_active,
+                                                   BOND_SLAVE_NOTIFY_NOW);
        } else {
                rcu_assign_pointer(bond->curr_active_slave, new_active);
        }
 
        if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
                if (old_active)
-                       bond_set_slave_inactive_flags(old_active);
+                       bond_set_slave_inactive_flags(old_active,
+                                                     BOND_SLAVE_NOTIFY_NOW);
 
                if (new_active) {
                        bool should_notify_peers = false;
 
-                       bond_set_slave_active_flags(new_active);
+                       bond_set_slave_active_flags(new_active,
+                                                   BOND_SLAVE_NOTIFY_NOW);
 
                        if (bond->params.fail_over_mac)
                                bond_do_fail_over_mac(bond, new_active,
@@ -1193,6 +1197,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
                return -EBUSY;
        }
 
+       if (bond_dev == slave_dev) {
+               pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name);
+               return -EPERM;
+       }
+
        /* vlan challenged mutual exclusion */
        /* no need to lock since we're protected by rtnl_lock */
        if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
@@ -1270,9 +1279,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        if (slave_ops->ndo_set_mac_address == NULL) {
                if (!bond_has_slaves(bond)) {
-                       pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.",
-                                  bond_dev->name);
-                       bond->params.fail_over_mac = BOND_FOM_ACTIVE;
+                       pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address.\n",
+                               bond_dev->name);
+                       if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+                               bond->params.fail_over_mac = BOND_FOM_ACTIVE;
+                               pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n",
+                                       bond_dev->name);
+                       }
                } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
                        pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n",
                               bond_dev->name);
@@ -1315,7 +1328,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
         */
        memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
 
-       if (!bond->params.fail_over_mac) {
+       if (!bond->params.fail_over_mac ||
+           bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
                /*
                 * Set slave to master's mac address.  The application already
                 * set the master's mac address to that of the first slave
@@ -1458,14 +1472,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        switch (bond->params.mode) {
        case BOND_MODE_ACTIVEBACKUP:
-               bond_set_slave_inactive_flags(new_slave);
+               bond_set_slave_inactive_flags(new_slave,
+                                             BOND_SLAVE_NOTIFY_NOW);
                break;
        case BOND_MODE_8023AD:
                /* in 802.3ad mode, the internal mechanism
                 * will activate the slaves in the selected
                 * aggregator
                 */
-               bond_set_slave_inactive_flags(new_slave);
+               bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
                /* if this is the first slave */
                if (!prev_slave) {
                        SLAVE_AD_INFO(new_slave).id = 1;
@@ -1483,7 +1498,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        case BOND_MODE_TLB:
        case BOND_MODE_ALB:
                bond_set_active_slave(new_slave);
-               bond_set_slave_inactive_flags(new_slave);
+               bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
                break;
        default:
                pr_debug("This slave is always active in trunk mode\n");
@@ -1505,7 +1520,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        slave_dev->npinfo = bond->dev->npinfo;
        if (slave_dev->npinfo) {
                if (slave_enable_netpoll(new_slave)) {
-                       read_unlock(&bond->lock);
                        pr_info("Error, %s: master_dev is using netpoll, "
                                 "but new slave device does not support netpoll.\n",
                                 bond_dev->name);
@@ -1539,9 +1553,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        bond_set_carrier(bond);
 
        if (USES_PRIMARY(bond->params.mode)) {
+               block_netpoll_tx();
                write_lock_bh(&bond->curr_slave_lock);
                bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
+               unblock_netpoll_tx();
        }
 
        pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
@@ -1567,10 +1583,12 @@ err_detach:
        if (bond->primary_slave == new_slave)
                bond->primary_slave = NULL;
        if (bond->curr_active_slave == new_slave) {
+               block_netpoll_tx();
                write_lock_bh(&bond->curr_slave_lock);
                bond_change_active_slave(bond, NULL);
                bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
+               unblock_netpoll_tx();
        }
        slave_disable_netpoll(new_slave);
 
@@ -1579,7 +1597,8 @@ err_close:
        dev_close(slave_dev);
 
 err_restore_mac:
-       if (!bond->params.fail_over_mac) {
+       if (!bond->params.fail_over_mac ||
+           bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
                /* XXX TODO - fom follow mode needs to change master's
                 * MAC if this slave's MAC is in use by the bond, or at
                 * least print a warning.
@@ -1645,9 +1664,6 @@ static int __bond_release_one(struct net_device *bond_dev,
                return -EINVAL;
        }
 
-       /* release the slave from its bond */
-       bond->slave_cnt--;
-
        bond_sysfs_slave_del(slave);
 
        bond_upper_dev_unlink(bond_dev, slave_dev);
@@ -1672,7 +1688,8 @@ static int __bond_release_one(struct net_device *bond_dev,
 
        bond->current_arp_slave = NULL;
 
-       if (!all && !bond->params.fail_over_mac) {
+       if (!all && (!bond->params.fail_over_mac ||
+                    bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
                if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
                    bond_has_slaves(bond))
                        pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
@@ -1728,6 +1745,7 @@ static int __bond_release_one(struct net_device *bond_dev,
 
        unblock_netpoll_tx();
        synchronize_rcu();
+       bond->slave_cnt--;
 
        if (!bond_has_slaves(bond)) {
                call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
@@ -1769,7 +1787,8 @@ static int __bond_release_one(struct net_device *bond_dev,
        /* close slave before restoring its mac address */
        dev_close(slave_dev);
 
-       if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
+       if (bond->params.fail_over_mac != BOND_FOM_ACTIVE ||
+           bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
                /* restore original ("permanent") mac address */
                memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
                addr.sa_family = slave_dev->type;
@@ -2004,7 +2023,8 @@ static void bond_miimon_commit(struct bonding *bond)
 
                        if (bond->params.mode == BOND_MODE_ACTIVEBACKUP ||
                            bond->params.mode == BOND_MODE_8023AD)
-                               bond_set_slave_inactive_flags(slave);
+                               bond_set_slave_inactive_flags(slave,
+                                                             BOND_SLAVE_NOTIFY_NOW);
 
                        pr_info("%s: link status definitely down for interface %s, disabling it\n",
                                bond->dev->name, slave->dev->name);
@@ -2551,7 +2571,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
                                slave->link = BOND_LINK_UP;
                                if (bond->current_arp_slave) {
                                        bond_set_slave_inactive_flags(
-                                               bond->current_arp_slave);
+                                               bond->current_arp_slave,
+                                               BOND_SLAVE_NOTIFY_NOW);
                                        bond->current_arp_slave = NULL;
                                }
 
@@ -2571,7 +2592,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
                                slave->link_failure_count++;
 
                        slave->link = BOND_LINK_DOWN;
-                       bond_set_slave_inactive_flags(slave);
+                       bond_set_slave_inactive_flags(slave,
+                                                     BOND_SLAVE_NOTIFY_NOW);
 
                        pr_info("%s: link status definitely down for interface %s, disabling it\n",
                                bond->dev->name, slave->dev->name);
@@ -2604,17 +2626,17 @@ do_failover:
 
 /*
  * Send ARP probes for active-backup mode ARP monitor.
+ *
+ * Called with rcu_read_lock hold.
  */
 static bool bond_ab_arp_probe(struct bonding *bond)
 {
        struct slave *slave, *before = NULL, *new_slave = NULL,
-                    *curr_arp_slave, *curr_active_slave;
+                    *curr_arp_slave = rcu_dereference(bond->current_arp_slave),
+                    *curr_active_slave = rcu_dereference(bond->curr_active_slave);
        struct list_head *iter;
        bool found = false;
-
-       rcu_read_lock();
-       curr_arp_slave = rcu_dereference(bond->current_arp_slave);
-       curr_active_slave = rcu_dereference(bond->curr_active_slave);
+       bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
 
        if (curr_arp_slave && curr_active_slave)
                pr_info("PROBE: c_arp %s && cas %s BAD\n",
@@ -2623,32 +2645,23 @@ static bool bond_ab_arp_probe(struct bonding *bond)
 
        if (curr_active_slave) {
                bond_arp_send_all(bond, curr_active_slave);
-               rcu_read_unlock();
-               return true;
+               return should_notify_rtnl;
        }
-       rcu_read_unlock();
 
        /* if we don't have a curr_active_slave, search for the next available
         * backup slave from the current_arp_slave and make it the candidate
         * for becoming the curr_active_slave
         */
 
-       if (!rtnl_trylock())
-               return false;
-       /* curr_arp_slave might have gone away */
-       curr_arp_slave = ACCESS_ONCE(bond->current_arp_slave);
-
        if (!curr_arp_slave) {
-               curr_arp_slave = bond_first_slave(bond);
-               if (!curr_arp_slave) {
-                       rtnl_unlock();
-                       return true;
-               }
+               curr_arp_slave = bond_first_slave_rcu(bond);
+               if (!curr_arp_slave)
+                       return should_notify_rtnl;
        }
 
-       bond_set_slave_inactive_flags(curr_arp_slave);
+       bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER);
 
-       bond_for_each_slave(bond, slave, iter) {
+       bond_for_each_slave_rcu(bond, slave, iter) {
                if (!found && !before && IS_UP(slave->dev))
                        before = slave;
 
@@ -2666,7 +2679,8 @@ static bool bond_ab_arp_probe(struct bonding *bond)
                        if (slave->link_failure_count < UINT_MAX)
                                slave->link_failure_count++;
 
-                       bond_set_slave_inactive_flags(slave);
+                       bond_set_slave_inactive_flags(slave,
+                                                     BOND_SLAVE_NOTIFY_LATER);
 
                        pr_info("%s: backup interface %s is now down.\n",
                                bond->dev->name, slave->dev->name);
@@ -2678,26 +2692,31 @@ static bool bond_ab_arp_probe(struct bonding *bond)
        if (!new_slave && before)
                new_slave = before;
 
-       if (!new_slave) {
-               rtnl_unlock();
-               return true;
-       }
+       if (!new_slave)
+               goto check_state;
 
        new_slave->link = BOND_LINK_BACK;
-       bond_set_slave_active_flags(new_slave);
+       bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
        bond_arp_send_all(bond, new_slave);
        new_slave->jiffies = jiffies;
        rcu_assign_pointer(bond->current_arp_slave, new_slave);
-       rtnl_unlock();
 
-       return true;
+check_state:
+       bond_for_each_slave_rcu(bond, slave, iter) {
+               if (slave->should_notify) {
+                       should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
+                       break;
+               }
+       }
+       return should_notify_rtnl;
 }
 
 static void bond_activebackup_arp_mon(struct work_struct *work)
 {
        struct bonding *bond = container_of(work, struct bonding,
                                            arp_work.work);
-       bool should_notify_peers = false, should_commit = false;
+       bool should_notify_peers = false;
+       bool should_notify_rtnl = false;
        int delta_in_ticks;
 
        delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
@@ -2706,11 +2725,12 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
                goto re_arm;
 
        rcu_read_lock();
+
        should_notify_peers = bond_should_notify_peers(bond);
-       should_commit = bond_ab_arp_inspect(bond);
-       rcu_read_unlock();
 
-       if (should_commit) {
+       if (bond_ab_arp_inspect(bond)) {
+               rcu_read_unlock();
+
                /* Race avoidance with bond_close flush of workqueue */
                if (!rtnl_trylock()) {
                        delta_in_ticks = 1;
@@ -2719,23 +2739,28 @@ static void bond_activebackup_arp_mon(struct work_struct *work)
                }
 
                bond_ab_arp_commit(bond);
+
                rtnl_unlock();
+               rcu_read_lock();
        }
 
-       if (!bond_ab_arp_probe(bond)) {
-               /* rtnl locking failed, re-arm */
-               delta_in_ticks = 1;
-               should_notify_peers = false;
-       }
+       should_notify_rtnl = bond_ab_arp_probe(bond);
+       rcu_read_unlock();
 
 re_arm:
        if (bond->params.arp_interval)
                queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
 
-       if (should_notify_peers) {
+       if (should_notify_peers || should_notify_rtnl) {
                if (!rtnl_trylock())
                        return;
-               call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);
+
+               if (should_notify_peers)
+                       call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
+                                                bond->dev);
+               if (should_notify_rtnl)
+                       bond_slave_state_notify(bond);
+
                rtnl_unlock();
        }
 }
@@ -2857,9 +2882,12 @@ static int bond_slave_netdev_event(unsigned long event,
                pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
                        bond->dev->name, bond->primary_slave ? slave_dev->name :
                                                               "none");
+
+               block_netpoll_tx();
                write_lock_bh(&bond->curr_slave_lock);
                bond_select_active_slave(bond);
                write_unlock_bh(&bond->curr_slave_lock);
+               unblock_netpoll_tx();
                break;
        case NETDEV_FEAT_CHANGE:
                bond_compute_features(bond);
@@ -3032,9 +3060,11 @@ static int bond_open(struct net_device *bond_dev)
                bond_for_each_slave(bond, slave, iter) {
                        if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
                                && (slave != bond->curr_active_slave)) {
-                               bond_set_slave_inactive_flags(slave);
+                               bond_set_slave_inactive_flags(slave,
+                                                             BOND_SLAVE_NOTIFY_NOW);
                        } else {
-                               bond_set_slave_active_flags(slave);
+                               bond_set_slave_active_flags(slave,
+                                                           BOND_SLAVE_NOTIFY_NOW);
                        }
                }
                read_unlock(&bond->curr_slave_lock);
@@ -3431,7 +3461,8 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
        /* If fail_over_mac is enabled, do nothing and return success.
         * Returning an error causes ifenslave to fail.
         */
-       if (bond->params.fail_over_mac)
+       if (bond->params.fail_over_mac &&
+           bond->params.mode == BOND_MODE_ACTIVEBACKUP)
                return 0;
 
        if (!is_valid_ether_addr(sa->sa_data))
@@ -3692,7 +3723,7 @@ static inline int bond_slave_override(struct bonding *bond,
 
 
 static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
-                            void *accel_priv)
+                            void *accel_priv, select_queue_fallback_t fallback)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 11cb943222d5c839ed363715db445351e6b3da56..298c26509095cdd6a6306aa954fe79b1ba46622b 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/if.h>
 #include <linux/netdevice.h>
-#include <linux/rwlock.h>
+#include <linux/spinlock.h>
 #include <linux/rcupdate.h>
 #include <linux/ctype.h>
 #include <linux/inet.h>
@@ -121,6 +121,7 @@ static struct bond_opt_value bond_resend_igmp_tbl[] = {
 static struct bond_opt_value bond_lp_interval_tbl[] = {
        { "minval",  1,       BOND_VALFLAG_MIN | BOND_VALFLAG_DEFAULT},
        { "maxval",  INT_MAX, BOND_VALFLAG_MAX},
+       { NULL,      -1,      0},
 };
 
 static struct bond_option bond_opts[] = {
index 86ccfb9f71cc4dd8c843f40f5eee38b7c0c033ab..2b0fdec695f78fbf77d9cb7c9cd43cb5b7adb30b 100644 (file)
@@ -195,7 +195,8 @@ struct slave {
        s8     new_link;
        u8     backup:1,   /* indicates backup slave. Value corresponds with
                              BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
-              inactive:1; /* indicates inactive slave */
+              inactive:1, /* indicates inactive slave */
+              should_notify:1; /* indicateds whether the state changed */
        u8     duplex;
        u32    original_mtu;
        u32    link_failure_count;
@@ -303,6 +304,24 @@ static inline void bond_set_backup_slave(struct slave *slave)
        }
 }
 
+static inline void bond_set_slave_state(struct slave *slave,
+                                       int slave_state, bool notify)
+{
+       if (slave->backup == slave_state)
+               return;
+
+       slave->backup = slave_state;
+       if (notify) {
+               rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_KERNEL);
+               slave->should_notify = 0;
+       } else {
+               if (slave->should_notify)
+                       slave->should_notify = 0;
+               else
+                       slave->should_notify = 1;
+       }
+}
+
 static inline void bond_slave_state_change(struct bonding *bond)
 {
        struct list_head *iter;
@@ -316,6 +335,19 @@ static inline void bond_slave_state_change(struct bonding *bond)
        }
 }
 
+static inline void bond_slave_state_notify(struct bonding *bond)
+{
+       struct list_head *iter;
+       struct slave *tmp;
+
+       bond_for_each_slave(bond, tmp, iter) {
+               if (tmp->should_notify) {
+                       rtmsg_ifinfo(RTM_NEWLINK, tmp->dev, 0, GFP_KERNEL);
+                       tmp->should_notify = 0;
+               }
+       }
+}
+
 static inline int bond_slave_state(struct slave *slave)
 {
        return slave->backup;
@@ -343,6 +375,9 @@ static inline bool bond_is_active_slave(struct slave *slave)
 #define BOND_ARP_VALIDATE_ALL          (BOND_ARP_VALIDATE_ACTIVE | \
                                         BOND_ARP_VALIDATE_BACKUP)
 
+#define BOND_SLAVE_NOTIFY_NOW          true
+#define BOND_SLAVE_NOTIFY_LATER                false
+
 static inline int slave_do_arp_validate(struct bonding *bond,
                                        struct slave *slave)
 {
@@ -394,17 +429,19 @@ static inline void bond_netpoll_send_skb(const struct slave *slave,
 }
 #endif
 
-static inline void bond_set_slave_inactive_flags(struct slave *slave)
+static inline void bond_set_slave_inactive_flags(struct slave *slave,
+                                                bool notify)
 {
        if (!bond_is_lb(slave->bond))
-               bond_set_backup_slave(slave);
+               bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);
        if (!slave->bond->params.all_slaves_active)
                slave->inactive = 1;
 }
 
-static inline void bond_set_slave_active_flags(struct slave *slave)
+static inline void bond_set_slave_active_flags(struct slave *slave,
+                                              bool notify)
 {
-       bond_set_active_slave(slave);
+       bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);
        slave->inactive = 0;
 }
 
index d447b881bbde1af6d25f6102b0f3efc639893d70..9e7d95dae2c7038478d6efadddba81e2778f47a9 100644 (file)
@@ -104,7 +104,7 @@ config CAN_JANZ_ICAN3
 
 config CAN_FLEXCAN
        tristate "Support for Freescale FLEXCAN based chips"
-       depends on (ARM && CPU_LITTLE_ENDIAN) || PPC
+       depends on ARM || PPC
        ---help---
          Say Y here if you want to support for Freescale FlexCAN.
 
index 13a909822e25bf54d455c251ab9655f9554f00e9..fc59bc6f040b623fcc57ceb4af0bccad3a38281e 100644 (file)
@@ -323,19 +323,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
        }
 
        if (!priv->echo_skb[idx]) {
-               struct sock *srcsk = skb->sk;
 
-               if (atomic_read(&skb->users) != 1) {
-                       struct sk_buff *old_skb = skb;
-
-                       skb = skb_clone(old_skb, GFP_ATOMIC);
-                       kfree_skb(old_skb);
-                       if (!skb)
-                               return;
-               } else
-                       skb_orphan(skb);
-
-               skb->sk = srcsk;
+               skb = can_create_echo_skb(skb);
+               if (!skb)
+                       return;
 
                /* make settings for echo to reduce code in irq context */
                skb->protocol = htons(ETH_P_CAN);
index aaed97bee4711d1cb2e8b1eb514fc3e343ad21e0..61376abdab395cd941f9a118c46e9912e17f4452 100644 (file)
 
 #define FLEXCAN_MB_CODE_MASK           (0xf0ffffff)
 
+#define FLEXCAN_TIMEOUT_US             (50)
+
 /*
  * FLEXCAN hardware feature flags
  *
@@ -235,9 +237,12 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
 };
 
 /*
- * Abstract off the read/write for arm versus ppc.
+ * Abstract off the read/write for arm versus ppc. This
+ * assumes that PPC uses big-endian registers and everything
+ * else uses little-endian registers, independent of CPU
+ * endianess.
  */
-#if defined(__BIG_ENDIAN)
+#if defined(CONFIG_PPC)
 static inline u32 flexcan_read(void __iomem *addr)
 {
        return in_be32(addr);
@@ -259,6 +264,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
 }
 #endif
 
+static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
+{
+       if (!priv->reg_xceiver)
+               return 0;
+
+       return regulator_enable(priv->reg_xceiver);
+}
+
+static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
+{
+       if (!priv->reg_xceiver)
+               return 0;
+
+       return regulator_disable(priv->reg_xceiver);
+}
+
 static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
                                              u32 reg_esr)
 {
@@ -266,26 +287,95 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
                (reg_esr & FLEXCAN_ESR_ERR_BUS);
 }
 
-static inline void flexcan_chip_enable(struct flexcan_priv *priv)
+static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->base;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
        u32 reg;
 
        reg = flexcan_read(&regs->mcr);
        reg &= ~FLEXCAN_MCR_MDIS;
        flexcan_write(reg, &regs->mcr);
 
-       udelay(10);
+       while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               usleep_range(10, 20);
+
+       if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
+               return -ETIMEDOUT;
+
+       return 0;
 }
 
-static inline void flexcan_chip_disable(struct flexcan_priv *priv)
+static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->base;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
        u32 reg;
 
        reg = flexcan_read(&regs->mcr);
        reg |= FLEXCAN_MCR_MDIS;
        flexcan_write(reg, &regs->mcr);
+
+       while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               usleep_range(10, 20);
+
+       if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int flexcan_chip_freeze(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->base;
+       unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
+       u32 reg;
+
+       reg = flexcan_read(&regs->mcr);
+       reg |= FLEXCAN_MCR_HALT;
+       flexcan_write(reg, &regs->mcr);
+
+       while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+               usleep_range(100, 200);
+
+       if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->base;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+       u32 reg;
+
+       reg = flexcan_read(&regs->mcr);
+       reg &= ~FLEXCAN_MCR_HALT;
+       flexcan_write(reg, &regs->mcr);
+
+       while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
+               usleep_range(10, 20);
+
+       if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int flexcan_chip_softreset(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->base;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+       flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
+       while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
+               usleep_range(10, 20);
+
+       if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
+               return -ETIMEDOUT;
+
+       return 0;
 }
 
 static int flexcan_get_berr_counter(const struct net_device *dev,
@@ -706,19 +796,14 @@ static int flexcan_chip_start(struct net_device *dev)
        u32 reg_mcr, reg_ctrl;
 
        /* enable module */
-       flexcan_chip_enable(priv);
+       err = flexcan_chip_enable(priv);
+       if (err)
+               return err;
 
        /* soft reset */
-       flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
-       udelay(10);
-
-       reg_mcr = flexcan_read(&regs->mcr);
-       if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
-               netdev_err(dev, "Failed to softreset can module (mcr=0x%08x)\n",
-                          reg_mcr);
-               err = -ENODEV;
-               goto out;
-       }
+       err = flexcan_chip_softreset(priv);
+       if (err)
+               goto out_chip_disable;
 
        flexcan_set_bittiming(dev);
 
@@ -785,16 +870,14 @@ static int flexcan_chip_start(struct net_device *dev)
        if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
                flexcan_write(0x0, &regs->rxfgmask);
 
-       if (priv->reg_xceiver)  {
-               err = regulator_enable(priv->reg_xceiver);
-               if (err)
-                       goto out;
-       }
+       err = flexcan_transceiver_enable(priv);
+       if (err)
+               goto out_chip_disable;
 
        /* synchronize with the can bus */
-       reg_mcr = flexcan_read(&regs->mcr);
-       reg_mcr &= ~FLEXCAN_MCR_HALT;
-       flexcan_write(reg_mcr, &regs->mcr);
+       err = flexcan_chip_unfreeze(priv);
+       if (err)
+               goto out_transceiver_disable;
 
        priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
@@ -807,7 +890,9 @@ static int flexcan_chip_start(struct net_device *dev)
 
        return 0;
 
- out:
+ out_transceiver_disable:
+       flexcan_transceiver_disable(priv);
+ out_chip_disable:
        flexcan_chip_disable(priv);
        return err;
 }
@@ -822,18 +907,17 @@ static void flexcan_chip_stop(struct net_device *dev)
 {
        struct flexcan_priv *priv = netdev_priv(dev);
        struct flexcan_regs __iomem *regs = priv->base;
-       u32 reg;
+
+       /* freeze + disable module */
+       flexcan_chip_freeze(priv);
+       flexcan_chip_disable(priv);
 
        /* Disable all interrupts */
        flexcan_write(0, &regs->imask1);
+       flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
+                     &regs->ctrl);
 
-       /* Disable + halt module */
-       reg = flexcan_read(&regs->mcr);
-       reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
-       flexcan_write(reg, &regs->mcr);
-
-       if (priv->reg_xceiver)
-               regulator_disable(priv->reg_xceiver);
+       flexcan_transceiver_disable(priv);
        priv->can.state = CAN_STATE_STOPPED;
 
        return;
@@ -863,7 +947,7 @@ static int flexcan_open(struct net_device *dev)
        /* start chip and queuing */
        err = flexcan_chip_start(dev);
        if (err)
-               goto out_close;
+               goto out_free_irq;
 
        can_led_event(dev, CAN_LED_EVENT_OPEN);
 
@@ -872,6 +956,8 @@ static int flexcan_open(struct net_device *dev)
 
        return 0;
 
+ out_free_irq:
+       free_irq(dev->irq, dev);
  out_close:
        close_candev(dev);
  out_disable_per:
@@ -942,12 +1028,16 @@ static int register_flexcandev(struct net_device *dev)
                goto out_disable_ipg;
 
        /* select "bus clock", chip must be disabled */
-       flexcan_chip_disable(priv);
+       err = flexcan_chip_disable(priv);
+       if (err)
+               goto out_disable_per;
        reg = flexcan_read(&regs->ctrl);
        reg |= FLEXCAN_CTRL_CLK_SRC;
        flexcan_write(reg, &regs->ctrl);
 
-       flexcan_chip_enable(priv);
+       err = flexcan_chip_enable(priv);
+       if (err)
+               goto out_chip_disable;
 
        /* set freeze, halt and activate FIFO, restrict register access */
        reg = flexcan_read(&regs->mcr);
@@ -964,14 +1054,15 @@ static int register_flexcandev(struct net_device *dev)
        if (!(reg & FLEXCAN_MCR_FEN)) {
                netdev_err(dev, "Could not enable RX FIFO, unsupported core\n");
                err = -ENODEV;
-               goto out_disable_per;
+               goto out_chip_disable;
        }
 
        err = register_candev(dev);
 
- out_disable_per:
        /* disable core and turn off clocks */
+ out_chip_disable:
        flexcan_chip_disable(priv);
+ out_disable_per:
        clk_disable_unprepare(priv->clk_per);
  out_disable_ipg:
        clk_disable_unprepare(priv->clk_ipg);
@@ -1101,9 +1192,10 @@ static int flexcan_probe(struct platform_device *pdev)
 static int flexcan_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
+       struct flexcan_priv *priv = netdev_priv(dev);
 
        unregister_flexcandev(dev);
-
+       netif_napi_del(&priv->napi);
        free_candev(dev);
 
        return 0;
@@ -1114,8 +1206,11 @@ static int flexcan_suspend(struct device *device)
 {
        struct net_device *dev = dev_get_drvdata(device);
        struct flexcan_priv *priv = netdev_priv(dev);
+       int err;
 
-       flexcan_chip_disable(priv);
+       err = flexcan_chip_disable(priv);
+       if (err)
+               return err;
 
        if (netif_running(dev)) {
                netif_stop_queue(dev);
@@ -1136,9 +1231,7 @@ static int flexcan_resume(struct device *device)
                netif_device_attach(dev);
                netif_start_queue(dev);
        }
-       flexcan_chip_enable(priv);
-
-       return 0;
+       return flexcan_chip_enable(priv);
 }
 #endif /* CONFIG_PM_SLEEP */
 
index e24e6690d672bfb9f5b2315d2927c1fd8e9b89bd..71594e5676fdc31fc422a542cb1786013a0f4ea4 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/netdevice.h>
 #include <linux/can.h>
 #include <linux/can/dev.h>
+#include <linux/can/skb.h>
 #include <linux/can/error.h>
 
 #include <linux/mfd/janz.h>
@@ -1133,20 +1134,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
  */
 static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb)
 {
-       struct sock *srcsk = skb->sk;
-
-       if (atomic_read(&skb->users) != 1) {
-               struct sk_buff *old_skb = skb;
-
-               skb = skb_clone(old_skb, GFP_ATOMIC);
-               kfree_skb(old_skb);
-               if (!skb)
-                       return;
-       } else {
-               skb_orphan(skb);
-       }
-
-       skb->sk = srcsk;
+       skb = can_create_echo_skb(skb);
+       if (!skb)
+               return;
 
        /* save this skb for tx interrupt echo handling */
        skb_queue_tail(&mod->echoq, skb);
@@ -1322,7 +1312,7 @@ static int ican3_napi(struct napi_struct *napi, int budget)
 
        /* process all communication messages */
        while (true) {
-               struct ican3_msg msg;
+               struct ican3_msg uninitialized_var(msg);
                ret = ican3_recv_msg(mod, &msg);
                if (ret)
                        break;
index 6c859bba8b650852663a6ac538a0744a44135296..e77d11049747047a3824d7e9a1dc32fc004f552d 100644 (file)
@@ -473,6 +473,8 @@ static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
                return err;
 
        dev->nchannels = msg.u.cardinfo.nchannels;
+       if (dev->nchannels > MAX_NET_DEVICES)
+               return -EINVAL;
 
        return 0;
 }
index 0a2a5ee79a177f1d78d9e4b3deb447f82be62757..4e94057ef5cf55df4600496d38b5fce433f851b4 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/if_ether.h>
 #include <linux/can.h>
 #include <linux/can/dev.h>
+#include <linux/can/skb.h>
 #include <linux/slab.h>
 #include <net/rtnetlink.h>
 
@@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
                        stats->rx_packets++;
                        stats->rx_bytes += cfd->len;
                }
-               kfree_skb(skb);
+               consume_skb(skb);
                return NETDEV_TX_OK;
        }
 
        /* perform standard echo handling for CAN network interfaces */
 
        if (loop) {
-               struct sock *srcsk = skb->sk;
 
-               skb = skb_share_check(skb, GFP_ATOMIC);
+               skb = can_create_echo_skb(skb);
                if (!skb)
                        return NETDEV_TX_OK;
 
                /* receive with packet counting */
-               skb->sk = srcsk;
                vcan_rx(skb, dev);
        } else {
                /* no looped packets => no counting */
-               kfree_skb(skb);
+               consume_skb(skb);
        }
        return NETDEV_TX_OK;
 }
index 0f4241c6e97e7545eed585f445d1f3e01e436277..238ccea965c8a1528c10d7477753fcc1ad068ca0 100644 (file)
@@ -3294,7 +3294,6 @@ static int __init vortex_init(void)
 
 static void __exit vortex_eisa_cleanup(void)
 {
-       struct vortex_private *vp;
        void __iomem *ioaddr;
 
 #ifdef CONFIG_EISA
@@ -3303,7 +3302,6 @@ static void __exit vortex_eisa_cleanup(void)
 #endif
 
        if (compaq_net_device) {
-               vp = netdev_priv(compaq_net_device);
                ioaddr = ioport_map(compaq_net_device->base_addr,
                                    VORTEX_TOTAL_SIZE);
 
index 0cc21437478c43a031fbeb09be434e2819797f52..511f6eecd58bc8153ef9cbf6a0ae021e91d8d889 100644 (file)
@@ -929,6 +929,9 @@ static int emac_resume(struct platform_device *dev)
 }
 
 static const struct of_device_id emac_of_match[] = {
+       {.compatible = "allwinner,sun4i-a10-emac",},
+
+       /* Deprecated */
        {.compatible = "allwinner,sun4i-emac",},
        {},
 };
index e92ffd6e1c15fdbd2aaaa21f9335fb25bc142d20..380d24922049d97beeedd523e04e9ba9f8033bc5 100644 (file)
@@ -1248,19 +1248,13 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * shared register for the high 32 bits, so only a single, aligned,
         * 4 GB physical address range can be used for descriptors.
         */
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
-           !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+       if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
                dev_dbg(&pdev->dev, "DMA to 64-BIT addresses\n");
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               dev_err(&pdev->dev,
-                                       "No usable DMA config, aborting\n");
-                               goto out_pci_disable;
-                       }
+                       dev_err(&pdev->dev, "No usable DMA config, aborting\n");
+                       goto out_pci_disable;
                }
        }
 
@@ -1292,6 +1286,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        alx = netdev_priv(netdev);
        spin_lock_init(&alx->hw.mdio_lock);
        spin_lock_init(&alx->irq_lock);
+       spin_lock_init(&alx->stats_lock);
        alx->dev = netdev;
        alx->hw.pdev = pdev;
        alx->msg_enable = NETIF_MSG_LINK | NETIF_MSG_HW | NETIF_MSG_IFUP |
index d5c2d3e912e57e1aae51b4bc265a95420f89822b..422aab27ea1bb7b3e9f52e7d44ba6d157a1c2647 100644 (file)
@@ -2436,7 +2436,7 @@ err_reset:
 err_register:
 err_sw_init:
 err_eeprom:
-       iounmap(adapter->hw.hw_addr);
+       pci_iounmap(pdev, adapter->hw.hw_addr);
 err_init_netdev:
 err_ioremap:
        free_netdev(netdev);
@@ -2474,7 +2474,7 @@ static void atl1e_remove(struct pci_dev *pdev)
        unregister_netdev(netdev);
        atl1e_free_ring_resources(adapter);
        atl1e_force_ps(&adapter->hw);
-       iounmap(adapter->hw.hw_addr);
+       pci_iounmap(pdev, adapter->hw.hw_addr);
        pci_release_regions(pdev);
        free_netdev(netdev);
        pci_disable_device(pdev);
index 1f7b5aa114fae3ee3adf589af58e5def31fc84d7..8a7bf7dad89823fadaa7b98f74ae08fe6a56838b 100644 (file)
@@ -1484,6 +1484,10 @@ static int b44_open(struct net_device *dev)
        add_timer(&bp->timer);
 
        b44_enable_ints(bp);
+
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+               phy_start(bp->phydev);
+
        netif_start_queue(dev);
 out:
        return err;
@@ -1646,6 +1650,9 @@ static int b44_close(struct net_device *dev)
 
        netif_stop_queue(dev);
 
+       if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+               phy_stop(bp->phydev);
+
        napi_disable(&bp->napi);
 
        del_timer_sync(&bp->timer);
@@ -2222,7 +2229,12 @@ static void b44_adjust_link(struct net_device *dev)
        }
 
        if (status_changed) {
-               b44_check_phy(bp);
+               u32 val = br32(bp, B44_TX_CTRL);
+               if (bp->flags & B44_FLAG_FULL_DUPLEX)
+                       val |= TX_CTRL_DUPLEX;
+               else
+                       val &= ~TX_CTRL_DUPLEX;
+               bw32(bp, B44_TX_CTRL, val);
                phy_print_status(phydev);
        }
 }
index 9d2dedadf2dfb7e0090be24064e46f63112bce3e..6c9e1c9bdeb8cbe06ae1788bd7ecb628e2ea4564 100644 (file)
@@ -85,7 +85,7 @@ MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax);
 
 static int disable_msi = 0;
 
-module_param(disable_msi, int, 0);
+module_param(disable_msi, int, S_IRUGO);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
 typedef enum {
@@ -2507,6 +2507,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
 
        bp->fw_wr_seq++;
        msg_data |= bp->fw_wr_seq;
+       bp->fw_last_msg = msg_data;
 
        bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
 
@@ -4000,8 +4001,23 @@ bnx2_setup_wol(struct bnx2 *bp)
                        wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
        }
 
-       if (!(bp->flags & BNX2_FLAG_NO_WOL))
-               bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 1, 0);
+       if (!(bp->flags & BNX2_FLAG_NO_WOL)) {
+               u32 val;
+
+               wol_msg |= BNX2_DRV_MSG_DATA_WAIT3;
+               if (bp->fw_last_msg || BNX2_CHIP(bp) != BNX2_CHIP_5709) {
+                       bnx2_fw_sync(bp, wol_msg, 1, 0);
+                       return;
+               }
+               /* Tell firmware not to power down the PHY yet, otherwise
+                * the chip will take a long time to respond to MMIO reads.
+                */
+               val = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE);
+               bnx2_shmem_wr(bp, BNX2_PORT_FEATURE,
+                             val | BNX2_PORT_FEATURE_ASF_ENABLED);
+               bnx2_fw_sync(bp, wol_msg, 1, 0);
+               bnx2_shmem_wr(bp, BNX2_PORT_FEATURE, val);
+       }
 
 }
 
@@ -4033,9 +4049,22 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
 
                        if (bp->wol)
                                pci_set_power_state(bp->pdev, PCI_D3hot);
-               } else {
-                       pci_set_power_state(bp->pdev, PCI_D3hot);
+                       break;
+
+               }
+               if (!bp->fw_last_msg && BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+                       u32 val;
+
+                       /* Tell firmware not to power down the PHY yet,
+                        * otherwise the other port may not respond to
+                        * MMIO reads.
+                        */
+                       val = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
+                       val &= ~BNX2_CONDITION_PM_STATE_MASK;
+                       val |= BNX2_CONDITION_PM_STATE_UNPREP;
+                       bnx2_shmem_wr(bp, BNX2_BC_STATE_CONDITION, val);
                }
+               pci_set_power_state(bp->pdev, PCI_D3hot);
 
                /* No more memory access after this point until
                 * device is brought back to D0.
index f1cf2c44e7ed549519fe2eaf860d0d01302b032d..e341bc366fa5f1d003a9355516a8ebdd81811ac8 100644 (file)
@@ -6900,6 +6900,7 @@ struct bnx2 {
 
        u16                     fw_wr_seq;
        u16                     fw_drv_pulse_wr_seq;
+       u32                     fw_last_msg;
 
        int                     rx_max_ring;
        int                     rx_ring_size;
@@ -7406,6 +7407,10 @@ struct bnx2_rv2p_fw_file {
 #define BNX2_CONDITION_MFW_RUN_NCSI             0x00006000
 #define BNX2_CONDITION_MFW_RUN_NONE             0x0000e000
 #define BNX2_CONDITION_MFW_RUN_MASK             0x0000e000
+#define BNX2_CONDITION_PM_STATE_MASK            0x00030000
+#define BNX2_CONDITION_PM_STATE_FULL            0x00030000
+#define BNX2_CONDITION_PM_STATE_PREP            0x00020000
+#define BNX2_CONDITION_PM_STATE_UNPREP          0x00010000
 
 #define BNX2_BC_STATE_DEBUG_CMD                        0x1dc
 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE      0x42440000
index 9d7419e0390bd526d52e850f0d54c3863c920ffd..dbcff509dc3f6d62cf48c729563196de8c4c7904 100644 (file)
@@ -1873,7 +1873,7 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
 }
 
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
-                      void *accel_priv)
+                      void *accel_priv, select_queue_fallback_t fallback)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
@@ -1895,7 +1895,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
        }
 
        /* select a non-FCoE queue */
-       return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+       return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -3875,7 +3875,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                                     xmit_type);
                }
 
-               /* Add the macs to the parsing BD this is a vf */
+               /* Add the macs to the parsing BD if this is a vf or if
+                * Tx Switching is enabled.
+                */
                if (IS_VF(bp)) {
                        /* override GRE parameters in BD */
                        bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.src_hi,
@@ -3883,6 +3885,11 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                              &pbd_e2->data.mac_addr.src_lo,
                                              eth->h_source);
 
+                       bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.dst_hi,
+                                             &pbd_e2->data.mac_addr.dst_mid,
+                                             &pbd_e2->data.mac_addr.dst_lo,
+                                             eth->h_dest);
+               } else if (bp->flags & TX_SWITCHING) {
                        bnx2x_set_fw_mac_addr(&pbd_e2->data.mac_addr.dst_hi,
                                              &pbd_e2->data.mac_addr.dst_mid,
                                              &pbd_e2->data.mac_addr.dst_lo,
index 17d1689aec6b83cd002bed8a62ad7b6d06cba1b6..a89a40f88c25779ded7f3e9357f765f191dbd55f 100644 (file)
@@ -496,7 +496,7 @@ int bnx2x_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos);
 
 /* select_queue callback */
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
-                      void *accel_priv);
+                      void *accel_priv, select_queue_fallback_t fallback);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
                                        struct bnx2x_fastpath *fp,
@@ -936,7 +936,7 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
        else /* CHIP_IS_E1X */
                start_params->network_cos_mode = FW_WRR;
 
-       start_params->gre_tunnel_mode = IPGRE_TUNNEL;
+       start_params->gre_tunnel_mode = L2GRE_TUNNEL;
        start_params->gre_tunnel_rss = GRE_INNER_HEADERS_RSS;
 
        return bnx2x_func_state_change(bp, &func_params);
index c9c445e7b4a5ab0d756880926fc529ed538a70a6..7d4382286457e6f0bf1b9ba87a981dd758fc874b 100644 (file)
@@ -95,29 +95,29 @@ MODULE_FIRMWARE(FW_FILE_NAME_E1H);
 MODULE_FIRMWARE(FW_FILE_NAME_E2);
 
 int bnx2x_num_queues;
-module_param_named(num_queues, bnx2x_num_queues, int, 0);
+module_param_named(num_queues, bnx2x_num_queues, int, S_IRUGO);
 MODULE_PARM_DESC(num_queues,
                 " Set number of queues (default is as a number of CPUs)");
 
 static int disable_tpa;
-module_param(disable_tpa, int, 0);
+module_param(disable_tpa, int, S_IRUGO);
 MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
 
 static int int_mode;
-module_param(int_mode, int, 0);
+module_param(int_mode, int, S_IRUGO);
 MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
                                "(1 INT#x; 2 MSI)");
 
 static int dropless_fc;
-module_param(dropless_fc, int, 0);
+module_param(dropless_fc, int, S_IRUGO);
 MODULE_PARM_DESC(dropless_fc, " Pause on exhausted host ring");
 
 static int mrrs = -1;
-module_param(mrrs, int, 0);
+module_param(mrrs, int, S_IRUGO);
 MODULE_PARM_DESC(mrrs, " Force Max Read Req Size (0..3) (for debug)");
 
 static int debug;
-module_param(debug, int, 0);
+module_param(debug, int, S_IRUGO);
 MODULE_PARM_DESC(debug, " Default debug msglevel");
 
 struct workqueue_struct *bnx2x_wq;
index aec5ef2ed7ce26329ff2638b48bda29979c360ee..e42f48df6e943e9ab21a34a5e3a7a49c43a726c8 100644 (file)
@@ -1446,12 +1446,12 @@ static void bnx2x_vf_igu_reset(struct bnx2x *bp, struct bnx2x_virtf *vf)
        if (vf->cfg_flags & VF_CFG_INT_SIMD)
                val |= IGU_VF_CONF_SINGLE_ISR_EN;
        val &= ~IGU_VF_CONF_PARENT_MASK;
-       val |= BP_FUNC(bp) << IGU_VF_CONF_PARENT_SHIFT; /* parent PF */
+       val |= (BP_ABS_FUNC(bp) >> 1) << IGU_VF_CONF_PARENT_SHIFT;
        REG_WR(bp, IGU_REG_VF_CONFIGURATION, val);
 
        DP(BNX2X_MSG_IOV,
-          "value in IGU_REG_VF_CONFIGURATION of vf %d after write %x\n",
-          vf->abs_vfid, REG_RD(bp, IGU_REG_VF_CONFIGURATION));
+          "value in IGU_REG_VF_CONFIGURATION of vf %d after write is 0x%08x\n",
+          vf->abs_vfid, val);
 
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
index fcf9105a5476123c0e5d4e7a4095f05d6c95774e..09f3fefcbf9ce405839e6f5893174a79dc91c5b8 100644 (file)
@@ -1,6 +1,6 @@
 /* cnic.c: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2013 Broadcom Corporation
+ * Copyright (c) 2006-2014 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -342,7 +342,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
        while (retry < 3) {
                rc = 0;
                rcu_read_lock();
-               ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
+               ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]);
                if (ulp_ops)
                        rc = ulp_ops->iscsi_nl_send_msg(
                                cp->ulp_handle[CNIC_ULP_ISCSI],
@@ -726,7 +726,7 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
 
        for (i = 0; i < dma->num_pages; i++) {
                if (dma->pg_arr[i]) {
-                       dma_free_coherent(&dev->pcidev->dev, BNX2_PAGE_SIZE,
+                       dma_free_coherent(&dev->pcidev->dev, CNIC_PAGE_SIZE,
                                          dma->pg_arr[i], dma->pg_map_arr[i]);
                        dma->pg_arr[i] = NULL;
                }
@@ -785,7 +785,7 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
 
        for (i = 0; i < pages; i++) {
                dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev,
-                                                   BNX2_PAGE_SIZE,
+                                                   CNIC_PAGE_SIZE,
                                                    &dma->pg_map_arr[i],
                                                    GFP_ATOMIC);
                if (dma->pg_arr[i] == NULL)
@@ -794,8 +794,8 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
        if (!use_pg_tbl)
                return 0;
 
-       dma->pgtbl_size = ((pages * 8) + BNX2_PAGE_SIZE - 1) &
-                         ~(BNX2_PAGE_SIZE - 1);
+       dma->pgtbl_size = ((pages * 8) + CNIC_PAGE_SIZE - 1) &
+                         ~(CNIC_PAGE_SIZE - 1);
        dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size,
                                        &dma->pgtbl_map, GFP_ATOMIC);
        if (dma->pgtbl == NULL)
@@ -900,8 +900,8 @@ static int cnic_alloc_context(struct cnic_dev *dev)
        if (BNX2_CHIP(cp) == BNX2_CHIP_5709) {
                int i, k, arr_size;
 
-               cp->ctx_blk_size = BNX2_PAGE_SIZE;
-               cp->cids_per_blk = BNX2_PAGE_SIZE / 128;
+               cp->ctx_blk_size = CNIC_PAGE_SIZE;
+               cp->cids_per_blk = CNIC_PAGE_SIZE / 128;
                arr_size = BNX2_MAX_CID / cp->cids_per_blk *
                           sizeof(struct cnic_ctx);
                cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL);
@@ -933,7 +933,7 @@ static int cnic_alloc_context(struct cnic_dev *dev)
                for (i = 0; i < cp->ctx_blks; i++) {
                        cp->ctx_arr[i].ctx =
                                dma_alloc_coherent(&dev->pcidev->dev,
-                                                  BNX2_PAGE_SIZE,
+                                                  CNIC_PAGE_SIZE,
                                                   &cp->ctx_arr[i].mapping,
                                                   GFP_KERNEL);
                        if (cp->ctx_arr[i].ctx == NULL)
@@ -1013,7 +1013,7 @@ static int __cnic_alloc_uio_rings(struct cnic_uio_dev *udev, int pages)
        if (udev->l2_ring)
                return 0;
 
-       udev->l2_ring_size = pages * BNX2_PAGE_SIZE;
+       udev->l2_ring_size = pages * CNIC_PAGE_SIZE;
        udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size,
                                           &udev->l2_ring_map,
                                           GFP_KERNEL | __GFP_COMP);
@@ -1021,7 +1021,7 @@ static int __cnic_alloc_uio_rings(struct cnic_uio_dev *udev, int pages)
                return -ENOMEM;
 
        udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
-       udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
+       udev->l2_buf_size = CNIC_PAGE_ALIGN(udev->l2_buf_size);
        udev->l2_buf = dma_alloc_coherent(&udev->pdev->dev, udev->l2_buf_size,
                                          &udev->l2_buf_map,
                                          GFP_KERNEL | __GFP_COMP);
@@ -1102,7 +1102,7 @@ static int cnic_init_uio(struct cnic_dev *dev)
                uinfo->mem[0].size = MB_GET_CID_ADDR(TX_TSS_CID +
                                                     TX_MAX_TSS_RINGS + 1);
                uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen &
-                                       PAGE_MASK;
+                                       CNIC_PAGE_MASK;
                if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX)
                        uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9;
                else
@@ -1113,7 +1113,7 @@ static int cnic_init_uio(struct cnic_dev *dev)
                uinfo->mem[0].size = pci_resource_len(dev->pcidev, 0);
 
                uinfo->mem[1].addr = (unsigned long) cp->bnx2x_def_status_blk &
-                       PAGE_MASK;
+                       CNIC_PAGE_MASK;
                uinfo->mem[1].size = sizeof(*cp->bnx2x_def_status_blk);
 
                uinfo->name = "bnx2x_cnic";
@@ -1267,14 +1267,14 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
        for (i = MAX_ISCSI_TBL_SZ; i < cp->max_cid_space; i++)
                cp->ctx_tbl[i].ulp_proto_id = CNIC_ULP_FCOE;
 
-       pages = PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) /
-               PAGE_SIZE;
+       pages = CNIC_PAGE_ALIGN(cp->max_cid_space * CNIC_KWQ16_DATA_SIZE) /
+               CNIC_PAGE_SIZE;
 
        ret = cnic_alloc_dma(dev, kwq_16_dma, pages, 0);
        if (ret)
                return -ENOMEM;
 
-       n = PAGE_SIZE / CNIC_KWQ16_DATA_SIZE;
+       n = CNIC_PAGE_SIZE / CNIC_KWQ16_DATA_SIZE;
        for (i = 0, j = 0; i < cp->max_cid_space; i++) {
                long off = CNIC_KWQ16_DATA_SIZE * (i % n);
 
@@ -1296,7 +1296,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
                        goto error;
        }
 
-       pages = PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / PAGE_SIZE;
+       pages = CNIC_PAGE_ALIGN(BNX2X_ISCSI_GLB_BUF_SIZE) / CNIC_PAGE_SIZE;
        ret = cnic_alloc_dma(dev, &cp->gbl_buf_info, pages, 0);
        if (ret)
                goto error;
@@ -1466,8 +1466,8 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
        cp->r2tq_size = cp->num_iscsi_tasks * BNX2X_ISCSI_MAX_PENDING_R2TS *
                        BNX2X_ISCSI_R2TQE_SIZE;
        cp->hq_size = cp->num_ccells * BNX2X_ISCSI_HQ_BD_SIZE;
-       pages = PAGE_ALIGN(cp->hq_size) / PAGE_SIZE;
-       hq_bds = pages * (PAGE_SIZE / BNX2X_ISCSI_HQ_BD_SIZE);
+       pages = CNIC_PAGE_ALIGN(cp->hq_size) / CNIC_PAGE_SIZE;
+       hq_bds = pages * (CNIC_PAGE_SIZE / BNX2X_ISCSI_HQ_BD_SIZE);
        cp->num_cqs = req1->num_cqs;
 
        if (!dev->max_iscsi_conn)
@@ -1477,9 +1477,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
        CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_RQ_SIZE_OFFSET(pfid),
                  req1->rq_num_wqes);
        CNIC_WR16(dev, BAR_TSTRORM_INTMEM + TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-                 PAGE_SIZE);
+                 CNIC_PAGE_SIZE);
        CNIC_WR8(dev, BAR_TSTRORM_INTMEM +
-                TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
+                TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS);
        CNIC_WR16(dev, BAR_TSTRORM_INTMEM +
                  TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
                  req1->num_tasks_per_conn);
@@ -1489,9 +1489,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
                  USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfid),
                  req1->rq_buffer_size);
        CNIC_WR16(dev, BAR_USTRORM_INTMEM + USTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-                 PAGE_SIZE);
+                 CNIC_PAGE_SIZE);
        CNIC_WR8(dev, BAR_USTRORM_INTMEM +
-                USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
+                USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS);
        CNIC_WR16(dev, BAR_USTRORM_INTMEM +
                  USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
                  req1->num_tasks_per_conn);
@@ -1504,9 +1504,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
 
        /* init Xstorm RAM */
        CNIC_WR16(dev, BAR_XSTRORM_INTMEM + XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-                 PAGE_SIZE);
+                 CNIC_PAGE_SIZE);
        CNIC_WR8(dev, BAR_XSTRORM_INTMEM +
-                XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
+                XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS);
        CNIC_WR16(dev, BAR_XSTRORM_INTMEM +
                  XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
                  req1->num_tasks_per_conn);
@@ -1519,9 +1519,9 @@ static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
 
        /* init Cstorm RAM */
        CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfid),
-                 PAGE_SIZE);
+                 CNIC_PAGE_SIZE);
        CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
-                CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), PAGE_SHIFT);
+                CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfid), CNIC_PAGE_BITS);
        CNIC_WR16(dev, BAR_CSTRORM_INTMEM +
                  CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfid),
                  req1->num_tasks_per_conn);
@@ -1623,18 +1623,18 @@ static int cnic_alloc_bnx2x_conn_resc(struct cnic_dev *dev, u32 l5_cid)
        }
 
        ctx->cid = cid;
-       pages = PAGE_ALIGN(cp->task_array_size) / PAGE_SIZE;
+       pages = CNIC_PAGE_ALIGN(cp->task_array_size) / CNIC_PAGE_SIZE;
 
        ret = cnic_alloc_dma(dev, &iscsi->task_array_info, pages, 1);
        if (ret)
                goto error;
 
-       pages = PAGE_ALIGN(cp->r2tq_size) / PAGE_SIZE;
+       pages = CNIC_PAGE_ALIGN(cp->r2tq_size) / CNIC_PAGE_SIZE;
        ret = cnic_alloc_dma(dev, &iscsi->r2tq_info, pages, 1);
        if (ret)
                goto error;
 
-       pages = PAGE_ALIGN(cp->hq_size) / PAGE_SIZE;
+       pages = CNIC_PAGE_ALIGN(cp->hq_size) / CNIC_PAGE_SIZE;
        ret = cnic_alloc_dma(dev, &iscsi->hq_info, pages, 1);
        if (ret)
                goto error;
@@ -1760,7 +1760,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
        ictx->tstorm_st_context.iscsi.hdr_bytes_2_fetch = ISCSI_HEADER_SIZE;
        /* TSTORM requires the base address of RQ DB & not PTE */
        ictx->tstorm_st_context.iscsi.rq_db_phy_addr.lo =
-               req2->rq_page_table_addr_lo & PAGE_MASK;
+               req2->rq_page_table_addr_lo & CNIC_PAGE_MASK;
        ictx->tstorm_st_context.iscsi.rq_db_phy_addr.hi =
                req2->rq_page_table_addr_hi;
        ictx->tstorm_st_context.iscsi.iscsi_conn_id = req1->iscsi_conn_id;
@@ -1842,7 +1842,7 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
        /* CSTORM and USTORM initialization is different, CSTORM requires
         * CQ DB base & not PTE addr */
        ictx->cstorm_st_context.cq_db_base.lo =
-               req1->cq_page_table_addr_lo & PAGE_MASK;
+               req1->cq_page_table_addr_lo & CNIC_PAGE_MASK;
        ictx->cstorm_st_context.cq_db_base.hi = req1->cq_page_table_addr_hi;
        ictx->cstorm_st_context.iscsi_conn_id = req1->iscsi_conn_id;
        ictx->cstorm_st_context.cq_proc_en_bit_map = (1 << cp->num_cqs) - 1;
@@ -2911,7 +2911,7 @@ static int cnic_l2_completion(struct cnic_local *cp)
        u16 hw_cons, sw_cons;
        struct cnic_uio_dev *udev = cp->udev;
        union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *)
-                                       (udev->l2_ring + (2 * BNX2_PAGE_SIZE));
+                                       (udev->l2_ring + (2 * CNIC_PAGE_SIZE));
        u32 cmd;
        int comp = 0;
 
@@ -3244,7 +3244,8 @@ static int cnic_copy_ulp_stats(struct cnic_dev *dev, int ulp_type)
        int rc;
 
        mutex_lock(&cnic_lock);
-       ulp_ops = cnic_ulp_tbl_prot(ulp_type);
+       ulp_ops = rcu_dereference_protected(cp->ulp_ops[ulp_type],
+                                           lockdep_is_held(&cnic_lock));
        if (ulp_ops && ulp_ops->cnic_get_stats)
                rc = ulp_ops->cnic_get_stats(cp->ulp_handle[ulp_type]);
        else
@@ -4384,7 +4385,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
                u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk;
                u32 val;
 
-               memset(cp->ctx_arr[i].ctx, 0, BNX2_PAGE_SIZE);
+               memset(cp->ctx_arr[i].ctx, 0, CNIC_PAGE_SIZE);
 
                CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0,
                        (cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit);
@@ -4628,7 +4629,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
                val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
 
-       rxbd = udev->l2_ring + BNX2_PAGE_SIZE;
+       rxbd = udev->l2_ring + CNIC_PAGE_SIZE;
        for (i = 0; i < BNX2_MAX_RX_DESC_CNT; i++, rxbd++) {
                dma_addr_t buf_map;
                int n = (i % cp->l2_rx_ring_size) + 1;
@@ -4639,11 +4640,11 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
                rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
                rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
        }
-       val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32;
+       val = (u64) (ring_map + CNIC_PAGE_SIZE) >> 32;
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
        rxbd->rx_bd_haddr_hi = val;
 
-       val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff;
+       val = (u64) (ring_map + CNIC_PAGE_SIZE) & 0xffffffff;
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
        rxbd->rx_bd_haddr_lo = val;
 
@@ -4709,10 +4710,10 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 
        val = CNIC_RD(dev, BNX2_MQ_CONFIG);
        val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
-       if (BNX2_PAGE_BITS > 12)
+       if (CNIC_PAGE_BITS > 12)
                val |= (12 - 8)  << 4;
        else
-               val |= (BNX2_PAGE_BITS - 8)  << 4;
+               val |= (CNIC_PAGE_BITS - 8)  << 4;
 
        CNIC_WR(dev, BNX2_MQ_CONFIG, val);
 
@@ -4742,13 +4743,13 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 
        /* Initialize the kernel work queue context. */
        val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
-             (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+             (CNIC_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
        cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val);
 
-       val = (BNX2_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
+       val = (CNIC_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
        cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
 
-       val = ((BNX2_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
+       val = ((CNIC_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
        cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
 
        val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32);
@@ -4768,13 +4769,13 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 
        /* Initialize the kernel complete queue context. */
        val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
-             (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+             (CNIC_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
        cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val);
 
-       val = (BNX2_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
+       val = (CNIC_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
        cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
 
-       val = ((BNX2_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
+       val = ((CNIC_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
        cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
 
        val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32);
@@ -4918,7 +4919,7 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
        u32 cli = cp->ethdev->iscsi_l2_client_id;
        u32 val;
 
-       memset(txbd, 0, BNX2_PAGE_SIZE);
+       memset(txbd, 0, CNIC_PAGE_SIZE);
 
        buf_map = udev->l2_buf_map;
        for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i += 3, txbd += 3) {
@@ -4978,9 +4979,9 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
        struct bnx2x *bp = netdev_priv(dev->netdev);
        struct cnic_uio_dev *udev = cp->udev;
        struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
-                               BNX2_PAGE_SIZE);
+                               CNIC_PAGE_SIZE);
        struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *)
-                               (udev->l2_ring + (2 * BNX2_PAGE_SIZE));
+                               (udev->l2_ring + (2 * CNIC_PAGE_SIZE));
        struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
        int i;
        u32 cli = cp->ethdev->iscsi_l2_client_id;
@@ -5004,20 +5005,20 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
                rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
        }
 
-       val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32;
+       val = (u64) (ring_map + CNIC_PAGE_SIZE) >> 32;
        rxbd->addr_hi = cpu_to_le32(val);
        data->rx.bd_page_base.hi = cpu_to_le32(val);
 
-       val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff;
+       val = (u64) (ring_map + CNIC_PAGE_SIZE) & 0xffffffff;
        rxbd->addr_lo = cpu_to_le32(val);
        data->rx.bd_page_base.lo = cpu_to_le32(val);
 
        rxcqe += BNX2X_MAX_RCQ_DESC_CNT;
-       val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) >> 32;
+       val = (u64) (ring_map + (2 * CNIC_PAGE_SIZE)) >> 32;
        rxcqe->addr_hi = cpu_to_le32(val);
        data->rx.cqe_page_base.hi = cpu_to_le32(val);
 
-       val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) & 0xffffffff;
+       val = (u64) (ring_map + (2 * CNIC_PAGE_SIZE)) & 0xffffffff;
        rxcqe->addr_lo = cpu_to_le32(val);
        data->rx.cqe_page_base.lo = cpu_to_le32(val);
 
@@ -5265,8 +5266,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
                msleep(10);
        }
        clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
-       rx_ring = udev->l2_ring + BNX2_PAGE_SIZE;
-       memset(rx_ring, 0, BNX2_PAGE_SIZE);
+       rx_ring = udev->l2_ring + CNIC_PAGE_SIZE;
+       memset(rx_ring, 0, CNIC_PAGE_SIZE);
 }
 
 static int cnic_register_netdev(struct cnic_dev *dev)
index 0d6b13f854d959ab0cdaf101192dfe2c4930c372..d535ae4228b4ccb12d9df6e24f7fed6911e9a6da 100644 (file)
@@ -1,6 +1,6 @@
 /* cnic.h: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2013 Broadcom Corporation
+ * Copyright (c) 2006-2014 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 95a8e4b11c9fcce45a0f24acea5bd1b86fa53ab9..dcbca6997e8fbcb9d4f38f12acbf8718846bdfbd 100644 (file)
@@ -1,7 +1,7 @@
 
 /* cnic.c: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2013 Broadcom Corporation
+ * Copyright (c) 2006-2014 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 8cf6b1926069d2c541b8b6888eced6463b887aa4..5f4d5573a73dbb8252d34ec6419750c3ec06eee1 100644 (file)
@@ -1,6 +1,6 @@
 /* cnic_if.h: Broadcom CNIC core network driver.
  *
- * Copyright (c) 2006-2013 Broadcom Corporation
+ * Copyright (c) 2006-2014 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
 
 #include "bnx2x/bnx2x_mfw_req.h"
 
-#define CNIC_MODULE_VERSION    "2.5.19"
-#define CNIC_MODULE_RELDATE    "December 19, 2013"
+#define CNIC_MODULE_VERSION    "2.5.20"
+#define CNIC_MODULE_RELDATE    "March 14, 2014"
 
 #define CNIC_ULP_RDMA          0
 #define CNIC_ULP_ISCSI         1
 #define MAX_CNIC_ULP_TYPE_EXT  3
 #define MAX_CNIC_ULP_TYPE      4
 
+/* Use CPU native page size up to 16K for cnic ring sizes.  */
+#if (PAGE_SHIFT > 14)
+#define CNIC_PAGE_BITS 14
+#else
+#define CNIC_PAGE_BITS PAGE_SHIFT
+#endif
+#define CNIC_PAGE_SIZE (1 << (CNIC_PAGE_BITS))
+#define CNIC_PAGE_ALIGN(addr) ALIGN(addr, CNIC_PAGE_SIZE)
+#define CNIC_PAGE_MASK (~((CNIC_PAGE_SIZE) - 1))
+
 struct kwqe {
        u32 kwqe_op_flag;
 
index e2ca03e23dc1f7542c43d9f82b1fdd6ba9d0a5fe..70a225c8df5c846a4d7045f2e7649925a5d8c50c 100644 (file)
@@ -2609,13 +2609,14 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
 
        tg3_writephy(tp, MII_CTRL1000, phy9_orig);
 
-       if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
-               reg32 &= ~0x3000;
-               tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
-       } else if (!err)
-               err = -EBUSY;
+       err = tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
+       if (err)
+               return err;
 
-       return err;
+       reg32 &= ~0x3000;
+       tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
+
+       return 0;
 }
 
 static void tg3_carrier_off(struct tg3 *tp)
@@ -6842,8 +6843,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 
                work_mask |= opaque_key;
 
-               if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
-                   (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
+               if (desc->err_vlan & RXD_ERR_MASK) {
                drop_it:
                        tg3_recycle_rx(tnapi, tpr, opaque_key,
                                       desc_idx, *post_ptr);
@@ -14113,12 +14113,12 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 
        tg3_netif_stop(tp);
 
+       tg3_set_mtu(dev, tp, new_mtu);
+
        tg3_full_lock(tp, 1);
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 
-       tg3_set_mtu(dev, tp, new_mtu);
-
        /* Reset PHY, otherwise the read DMA engine will be in a mode that
         * breaks all requests to 256 bytes.
         */
@@ -17649,8 +17649,6 @@ static int tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_bufmgr_config(tp);
 
-       features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
-
        /* 5700 B0 chips do not support checksumming correctly due
         * to hardware bugs.
         */
@@ -17682,7 +17680,8 @@ static int tg3_init_one(struct pci_dev *pdev,
                        features |= NETIF_F_TSO_ECN;
        }
 
-       dev->features |= features;
+       dev->features |= features | NETIF_F_HW_VLAN_CTAG_TX |
+                        NETIF_F_HW_VLAN_CTAG_RX;
        dev->vlan_features |= features;
 
        /*
index ef472385bce47dcea87f43e48f202ffabbddf16d..04321e5a356e45a0f7fc642f3817035d983dbd90 100644 (file)
@@ -2608,7 +2608,11 @@ struct tg3_rx_buffer_desc {
 #define RXD_ERR_TOO_SMALL              0x00400000
 #define RXD_ERR_NO_RESOURCES           0x00800000
 #define RXD_ERR_HUGE_FRAME             0x01000000
-#define RXD_ERR_MASK                   0xffff0000
+
+#define RXD_ERR_MASK   (RXD_ERR_BAD_CRC | RXD_ERR_COLLISION |          \
+                        RXD_ERR_LINK_LOST | RXD_ERR_PHY_DECODE |       \
+                        RXD_ERR_MAC_ABRT | RXD_ERR_TOO_SMALL |         \
+                        RXD_ERR_NO_RESOURCES | RXD_ERR_HUGE_FRAME)
 
        u32                             reserved;
        u32                             opaque;
index 1803c39590442d497d1cc7f543ef8148ac7e56ec..354ae9792badb329e89b0ab37f59ff78c73efd11 100644 (file)
@@ -1704,7 +1704,7 @@ bfa_flash_sem_get(void __iomem *bar)
        while (!bfa_raw_sem_get(bar)) {
                if (--n <= 0)
                        return BFA_STATUS_BADFLASH;
-               udelay(10000);
+               mdelay(10);
        }
        return BFA_STATUS_OK;
 }
index cf64f3d0b60d91a1de68836523c6304086dc9ece..4ad1187e82fb463e9642fd3e73b2850cf1137a01 100644 (file)
@@ -707,7 +707,8 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget)
                else
                        skb_checksum_none_assert(skb);
 
-               if (flags & BNA_CQ_EF_VLAN)
+               if ((flags & BNA_CQ_EF_VLAN) &&
+                   (bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
                        __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(cmpl->vlan_tag));
 
                if (BNAD_RXBUF_IS_SK_BUFF(unmap_q->type))
@@ -2094,7 +2095,9 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config)
                rx_config->q1_buf_size = BFI_SMALL_RXBUF_SIZE;
        }
 
-       rx_config->vlan_strip_status = BNA_STATUS_T_ENABLED;
+       rx_config->vlan_strip_status =
+               (bnad->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) ?
+               BNA_STATUS_T_ENABLED : BNA_STATUS_T_DISABLED;
 }
 
 static void
@@ -3245,11 +3248,6 @@ bnad_set_rx_mode(struct net_device *netdev)
                        BNA_RXMODE_ALLMULTI;
        bna_rx_mode_set(bnad->rx_info[0].rx, new_mode, mode_mask, NULL);
 
-       if (bnad->cfg_flags & BNAD_CF_PROMISC)
-               bna_rx_vlan_strip_disable(bnad->rx_info[0].rx);
-       else
-               bna_rx_vlan_strip_enable(bnad->rx_info[0].rx);
-
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 }
 
@@ -3374,6 +3372,27 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
        return 0;
 }
 
+static int bnad_set_features(struct net_device *dev, netdev_features_t features)
+{
+       struct bnad *bnad = netdev_priv(dev);
+       netdev_features_t changed = features ^ dev->features;
+
+       if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(dev)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&bnad->bna_lock, flags);
+
+               if (features & NETIF_F_HW_VLAN_CTAG_RX)
+                       bna_rx_vlan_strip_enable(bnad->rx_info[0].rx);
+               else
+                       bna_rx_vlan_strip_disable(bnad->rx_info[0].rx);
+
+               spin_unlock_irqrestore(&bnad->bna_lock, flags);
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void
 bnad_netpoll(struct net_device *netdev)
@@ -3421,6 +3440,7 @@ static const struct net_device_ops bnad_netdev_ops = {
        .ndo_change_mtu         = bnad_change_mtu,
        .ndo_vlan_rx_add_vid    = bnad_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = bnad_vlan_rx_kill_vid,
+       .ndo_set_features       = bnad_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = bnad_netpoll
 #endif
@@ -3433,14 +3453,14 @@ bnad_netdev_init(struct bnad *bnad, bool using_dac)
 
        netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-               NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX;
+               NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_VLAN_CTAG_TX |
+               NETIF_F_HW_VLAN_CTAG_RX;
 
        netdev->vlan_features = NETIF_F_SG | NETIF_F_HIGHDMA |
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_TSO | NETIF_F_TSO6;
 
-       netdev->features |= netdev->hw_features |
-               NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER;
+       netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
 
        if (using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
index 3190d38e16fbd5d59a8cbc0cca7378a500572402..d0c38e01e99fdc70e802b33dc977e081d1a72f5c 100644 (file)
@@ -632,11 +632,16 @@ static void gem_rx_refill(struct macb *bp)
                                           "Unable to allocate sk_buff\n");
                                break;
                        }
-                       bp->rx_skbuff[entry] = skb;
 
                        /* now fill corresponding descriptor entry */
                        paddr = dma_map_single(&bp->pdev->dev, skb->data,
                                               bp->rx_buffer_size, DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&bp->pdev->dev, paddr)) {
+                               dev_kfree_skb(skb);
+                               break;
+                       }
+
+                       bp->rx_skbuff[entry] = skb;
 
                        if (entry == RX_RING_SIZE - 1)
                                paddr |= MACB_BIT(RX_WRAP);
@@ -725,7 +730,7 @@ static int gem_rx(struct macb *bp, int budget)
                skb_put(skb, len);
                addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, addr));
                dma_unmap_single(&bp->pdev->dev, addr,
-                                len, DMA_FROM_DEVICE);
+                                bp->rx_buffer_size, DMA_FROM_DEVICE);
 
                skb->protocol = eth_type_trans(skb, bp->dev);
                skb_checksum_none_assert(skb);
@@ -1036,11 +1041,15 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        entry = macb_tx_ring_wrap(bp->tx_head);
-       bp->tx_head++;
        netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
        mapping = dma_map_single(&bp->pdev->dev, skb->data,
                                 len, DMA_TO_DEVICE);
+       if (dma_mapping_error(&bp->pdev->dev, mapping)) {
+               kfree_skb(skb);
+               goto unlock;
+       }
 
+       bp->tx_head++;
        tx_skb = &bp->tx_skb[entry];
        tx_skb->skb = skb;
        tx_skb->mapping = mapping;
@@ -1066,6 +1075,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1)
                netif_stop_queue(dev);
 
+unlock:
        spin_unlock_irqrestore(&bp->lock, flags);
 
        return NETDEV_TX_OK;
index 43ab35fea48d2be9fe6dfcd4d1e9dc10651724be..34e2488767d94d0c6eeaf677ffbfca493d871e54 100644 (file)
@@ -6179,6 +6179,7 @@ static struct pci_driver cxgb4_driver = {
        .id_table = cxgb4_pci_tbl,
        .probe    = init_one,
        .remove   = remove_one,
+       .shutdown = remove_one,
        .err_handler = &cxgb4_eeh,
 };
 
index add05f14b38be17311f3344bd23860064fac8ce1..1642de78aac84c86b51cbae27c16d9748d70fb19 100644 (file)
@@ -1939,6 +1939,7 @@ static void tulip_remove_one(struct pci_dev *pdev)
        pci_iounmap(pdev, tp->base_addr);
        free_netdev (dev);
        pci_release_regions (pdev);
+       pci_disable_device(pdev);
 
        /* pci_power_off (pdev, -1); */
 }
index 8d09615da585671a4d0fa9d00dc9cc6ba80f6517..05529e273050e3718c0ca1e105ce05174fdfe618 100644 (file)
@@ -350,11 +350,13 @@ struct be_drv_stats {
        u32 roce_drops_crc;
 };
 
+/* A vlan-id of 0xFFFF must be used to clear transparent vlan-tagging */
+#define BE_RESET_VLAN_TAG_ID   0xFFFF
+
 struct be_vf_cfg {
        unsigned char mac_addr[ETH_ALEN];
        int if_handle;
        int pmac_id;
-       u16 def_vid;
        u16 vlan_tag;
        u32 tx_rate;
 };
index 04ac9c6a0d3972d4e18ee91a8ce3a8bf2e141cd7..36c80612e21a3ebe6ee52447e9075dc4022f005e 100644 (file)
@@ -913,24 +913,14 @@ static int be_ipv6_tx_stall_chk(struct be_adapter *adapter,
        return BE3_chip(adapter) && be_ipv6_exthdr_check(skb);
 }
 
-static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
-                                          struct sk_buff *skb,
-                                          bool *skip_hw_vlan)
+static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
+                                                 struct sk_buff *skb,
+                                                 bool *skip_hw_vlan)
 {
        struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
        unsigned int eth_hdr_len;
        struct iphdr *ip;
 
-       /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or less
-        * may cause a transmit stall on that port. So the work-around is to
-        * pad short packets (<= 32 bytes) to a 36-byte length.
-        */
-       if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
-               if (skb_padto(skb, 36))
-                       goto tx_drop;
-               skb->len = 36;
-       }
-
        /* For padded packets, BE HW modifies tot_len field in IP header
         * incorrecly when VLAN tag is inserted by HW.
         * For padded packets, Lancer computes incorrect checksum.
@@ -959,7 +949,7 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
            vlan_tx_tag_present(skb)) {
                skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
                if (unlikely(!skb))
-                       goto tx_drop;
+                       goto err;
        }
 
        /* HW may lockup when VLAN HW tagging is requested on
@@ -981,15 +971,39 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
            be_vlan_tag_tx_chk(adapter, skb)) {
                skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
                if (unlikely(!skb))
-                       goto tx_drop;
+                       goto err;
        }
 
        return skb;
 tx_drop:
        dev_kfree_skb_any(skb);
+err:
        return NULL;
 }
 
+static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
+                                          struct sk_buff *skb,
+                                          bool *skip_hw_vlan)
+{
+       /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
+        * less may cause a transmit stall on that port. So the work-around is
+        * to pad short packets (<= 32 bytes) to a 36-byte length.
+        */
+       if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
+               if (skb_padto(skb, 36))
+                       return NULL;
+               skb->len = 36;
+       }
+
+       if (BEx_chip(adapter) || lancer_chip(adapter)) {
+               skb = be_lancer_xmit_workarounds(adapter, skb, skip_hw_vlan);
+               if (!skb)
+                       return NULL;
+       }
+
+       return skb;
+}
+
 static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
@@ -1157,6 +1171,14 @@ ret:
        return status;
 }
 
+static void be_clear_promisc(struct be_adapter *adapter)
+{
+       adapter->promiscuous = false;
+       adapter->flags &= ~BE_FLAGS_VLAN_PROMISC;
+
+       be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
+}
+
 static void be_set_rx_mode(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
@@ -1170,9 +1192,7 @@ static void be_set_rx_mode(struct net_device *netdev)
 
        /* BE was previously in promiscuous mode; disable it */
        if (adapter->promiscuous) {
-               adapter->promiscuous = false;
-               be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
-
+               be_clear_promisc(adapter);
                if (adapter->vlans_added)
                        be_vid_config(adapter);
        }
@@ -1287,24 +1307,20 @@ static int be_set_vf_vlan(struct net_device *netdev,
 
        if (vlan || qos) {
                vlan |= qos << VLAN_PRIO_SHIFT;
-               if (vf_cfg->vlan_tag != vlan) {
-                       /* If this is new value, program it. Else skip. */
-                       vf_cfg->vlan_tag = vlan;
+               if (vf_cfg->vlan_tag != vlan)
                        status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
                                                       vf_cfg->if_handle, 0);
-               }
        } else {
                /* Reset Transparent Vlan Tagging. */
-               vf_cfg->vlan_tag = 0;
-               vlan = vf_cfg->def_vid;
-               status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
-                                              vf_cfg->if_handle, 0);
+               status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID,
+                                              vf + 1, vf_cfg->if_handle, 0);
        }
 
-
-       if (status)
+       if (!status)
+               vf_cfg->vlan_tag = vlan;
+       else
                dev_info(&adapter->pdev->dev,
-                               "VLAN %d config on VF %d failed\n", vlan, vf);
+                        "VLAN %d config on VF %d failed\n", vlan, vf);
        return status;
 }
 
@@ -3013,11 +3029,11 @@ static int be_vf_setup_init(struct be_adapter *adapter)
 
 static int be_vf_setup(struct be_adapter *adapter)
 {
+       struct device *dev = &adapter->pdev->dev;
        struct be_vf_cfg *vf_cfg;
-       u16 def_vlan, lnk_speed;
        int status, old_vfs, vf;
-       struct device *dev = &adapter->pdev->dev;
        u32 privileges;
+       u16 lnk_speed;
 
        old_vfs = pci_num_vf(adapter->pdev);
        if (old_vfs) {
@@ -3084,12 +3100,6 @@ static int be_vf_setup(struct be_adapter *adapter)
                if (!status)
                        vf_cfg->tx_rate = lnk_speed;
 
-               status = be_cmd_get_hsw_config(adapter, &def_vlan,
-                                              vf + 1, vf_cfg->if_handle, NULL);
-               if (status)
-                       goto err;
-               vf_cfg->def_vid = def_vlan;
-
                if (!old_vfs)
                        be_cmd_enable_vf(adapter, vf + 1);
        }
index 4de8cfd149cfbd0fb6ed0c2782852c1eee599fa9..55e0fa03dc90d1323bacaf129f00e745c5a52c58 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
+#include <linux/clk.h>
 #include <linux/crc32.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -51,6 +52,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
 #define        ETH_HASH0       0x48
 #define        ETH_HASH1       0x4c
 #define        ETH_TXCTRL      0x50
+#define        ETH_END         0x54
 
 /* mode register */
 #define        MODER_RXEN      (1 <<  0) /* receive enable */
@@ -179,6 +181,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
  * @membase:   pointer to buffer memory region
  * @dma_alloc: dma allocated buffer size
  * @io_region_size:    I/O memory region size
+ * @num_bd:    number of buffer descriptors
  * @num_tx:    number of send buffers
  * @cur_tx:    last send buffer written
  * @dty_tx:    last buffer actually sent
@@ -199,6 +202,7 @@ struct ethoc {
        int dma_alloc;
        resource_size_t io_region_size;
 
+       unsigned int num_bd;
        unsigned int num_tx;
        unsigned int cur_tx;
        unsigned int dty_tx;
@@ -216,6 +220,7 @@ struct ethoc {
 
        struct phy_device *phy;
        struct mii_bus *mdio;
+       struct clk *clk;
        s8 phy_id;
 };
 
@@ -688,6 +693,11 @@ static int ethoc_mdio_probe(struct net_device *dev)
        }
 
        priv->phy = phy;
+       phy->advertising &= ~(ADVERTISED_1000baseT_Full |
+                             ADVERTISED_1000baseT_Half);
+       phy->supported &= ~(SUPPORTED_1000baseT_Full |
+                           SUPPORTED_1000baseT_Half);
+
        return 0;
 }
 
@@ -890,6 +900,102 @@ out:
        return NETDEV_TX_OK;
 }
 
+static int ethoc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ethoc *priv = netdev_priv(dev);
+       struct phy_device *phydev = priv->phy;
+
+       if (!phydev)
+               return -EOPNOTSUPP;
+
+       return phy_ethtool_gset(phydev, cmd);
+}
+
+static int ethoc_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ethoc *priv = netdev_priv(dev);
+       struct phy_device *phydev = priv->phy;
+
+       if (!phydev)
+               return -EOPNOTSUPP;
+
+       return phy_ethtool_sset(phydev, cmd);
+}
+
+static int ethoc_get_regs_len(struct net_device *netdev)
+{
+       return ETH_END;
+}
+
+static void ethoc_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+                          void *p)
+{
+       struct ethoc *priv = netdev_priv(dev);
+       u32 *regs_buff = p;
+       unsigned i;
+
+       regs->version = 0;
+       for (i = 0; i < ETH_END / sizeof(u32); ++i)
+               regs_buff[i] = ethoc_read(priv, i * sizeof(u32));
+}
+
+static void ethoc_get_ringparam(struct net_device *dev,
+                               struct ethtool_ringparam *ring)
+{
+       struct ethoc *priv = netdev_priv(dev);
+
+       ring->rx_max_pending = priv->num_bd - 1;
+       ring->rx_mini_max_pending = 0;
+       ring->rx_jumbo_max_pending = 0;
+       ring->tx_max_pending = priv->num_bd - 1;
+
+       ring->rx_pending = priv->num_rx;
+       ring->rx_mini_pending = 0;
+       ring->rx_jumbo_pending = 0;
+       ring->tx_pending = priv->num_tx;
+}
+
+static int ethoc_set_ringparam(struct net_device *dev,
+                              struct ethtool_ringparam *ring)
+{
+       struct ethoc *priv = netdev_priv(dev);
+
+       if (ring->tx_pending < 1 || ring->rx_pending < 1 ||
+           ring->tx_pending + ring->rx_pending > priv->num_bd)
+               return -EINVAL;
+       if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+               return -EINVAL;
+
+       if (netif_running(dev)) {
+               netif_tx_disable(dev);
+               ethoc_disable_rx_and_tx(priv);
+               ethoc_disable_irq(priv, INT_MASK_TX | INT_MASK_RX);
+               synchronize_irq(dev->irq);
+       }
+
+       priv->num_tx = rounddown_pow_of_two(ring->tx_pending);
+       priv->num_rx = ring->rx_pending;
+       ethoc_init_ring(priv, dev->mem_start);
+
+       if (netif_running(dev)) {
+               ethoc_enable_irq(priv, INT_MASK_TX | INT_MASK_RX);
+               ethoc_enable_rx_and_tx(priv);
+               netif_wake_queue(dev);
+       }
+       return 0;
+}
+
+const struct ethtool_ops ethoc_ethtool_ops = {
+       .get_settings = ethoc_get_settings,
+       .set_settings = ethoc_set_settings,
+       .get_regs_len = ethoc_get_regs_len,
+       .get_regs = ethoc_get_regs,
+       .get_link = ethtool_op_get_link,
+       .get_ringparam = ethoc_get_ringparam,
+       .set_ringparam = ethoc_set_ringparam,
+       .get_ts_info = ethtool_op_get_ts_info,
+};
+
 static const struct net_device_ops ethoc_netdev_ops = {
        .ndo_open = ethoc_open,
        .ndo_stop = ethoc_stop,
@@ -917,6 +1023,8 @@ static int ethoc_probe(struct platform_device *pdev)
        int num_bd;
        int ret = 0;
        bool random_mac = false;
+       struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       u32 eth_clkfreq = pdata ? pdata->eth_clkfreq : 0;
 
        /* allocate networking device */
        netdev = alloc_etherdev(sizeof(struct ethoc));
@@ -1016,6 +1124,7 @@ static int ethoc_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto error;
        }
+       priv->num_bd = num_bd;
        /* num_tx must be a power of two */
        priv->num_tx = rounddown_pow_of_two(num_bd >> 1);
        priv->num_rx = num_bd - priv->num_tx;
@@ -1030,8 +1139,7 @@ static int ethoc_probe(struct platform_device *pdev)
        }
 
        /* Allow the platform setup code to pass in a MAC address. */
-       if (dev_get_platdata(&pdev->dev)) {
-               struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       if (pdata) {
                memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
                priv->phy_id = pdata->phy_id;
        } else {
@@ -1069,6 +1177,27 @@ static int ethoc_probe(struct platform_device *pdev)
        if (random_mac)
                netdev->addr_assign_type = NET_ADDR_RANDOM;
 
+       /* Allow the platform setup code to adjust MII management bus clock. */
+       if (!eth_clkfreq) {
+               struct clk *clk = devm_clk_get(&pdev->dev, NULL);
+
+               if (!IS_ERR(clk)) {
+                       priv->clk = clk;
+                       clk_prepare_enable(clk);
+                       eth_clkfreq = clk_get_rate(clk);
+               }
+       }
+       if (eth_clkfreq) {
+               u32 clkdiv = MIIMODER_CLKDIV(eth_clkfreq / 2500000 + 1);
+
+               if (!clkdiv)
+                       clkdiv = 2;
+               dev_dbg(&pdev->dev, "setting MII clkdiv to %u\n", clkdiv);
+               ethoc_write(priv, MIIMODER,
+                           (ethoc_read(priv, MIIMODER) & MIIMODER_NOPRE) |
+                           clkdiv);
+       }
+
        /* register MII bus */
        priv->mdio = mdiobus_alloc();
        if (!priv->mdio) {
@@ -1111,6 +1240,7 @@ static int ethoc_probe(struct platform_device *pdev)
        netdev->netdev_ops = &ethoc_netdev_ops;
        netdev->watchdog_timeo = ETHOC_TIMEOUT;
        netdev->features |= 0;
+       netdev->ethtool_ops = &ethoc_ethtool_ops;
 
        /* setup NAPI */
        netif_napi_add(netdev, &priv->napi, ethoc_poll, 64);
@@ -1133,6 +1263,8 @@ free_mdio:
        kfree(priv->mdio->irq);
        mdiobus_free(priv->mdio);
 free:
+       if (priv->clk)
+               clk_disable_unprepare(priv->clk);
        free_netdev(netdev);
 out:
        return ret;
@@ -1157,6 +1289,8 @@ static int ethoc_remove(struct platform_device *pdev)
                        kfree(priv->mdio->irq);
                        mdiobus_free(priv->mdio);
                }
+               if (priv->clk)
+                       clk_disable_unprepare(priv->clk);
                unregister_netdev(netdev);
                free_netdev(netdev);
        }
index d4782b42401b0159b6375891db99bfc9999b0ecd..03a351300013c82999474fb411731f1487755550 100644 (file)
@@ -389,12 +389,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                        netdev_err(ndev, "Tx DMA memory map failed\n");
                return NETDEV_TX_OK;
        }
-       /* Send it on its way.  Tell FEC it's ready, interrupt when done,
-        * it's the last BD of the frame, and to put the CRC on the end.
-        */
-       status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
-                       | BD_ENET_TX_LAST | BD_ENET_TX_TC);
-       bdp->cbd_sc = status;
 
        if (fep->bufdesc_ex) {
 
@@ -416,6 +410,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                }
        }
 
+       /* Send it on its way.  Tell FEC it's ready, interrupt when done,
+        * it's the last BD of the frame, and to put the CRC on the end.
+        */
+       status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
+                       | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+       bdp->cbd_sc = status;
+
        bdp_pre = fec_enet_get_prevdesc(bdp, fep);
        if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
            !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
@@ -527,13 +528,6 @@ fec_restart(struct net_device *ndev, int duplex)
        /* Clear any outstanding interrupt. */
        writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
-       /* Setup multicast filter. */
-       set_multicast_list(ndev);
-#ifndef CONFIG_M5272
-       writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
-       writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
-#endif
-
        /* Set maximum receive buffer size. */
        writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
@@ -654,6 +648,13 @@ fec_restart(struct net_device *ndev, int duplex)
 
        writel(rcntl, fep->hwp + FEC_R_CNTRL);
 
+       /* Setup multicast filter. */
+       set_multicast_list(ndev);
+#ifndef CONFIG_M5272
+       writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+       writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+#endif
+
        if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
                /* enable ENET endian swap */
                ecntl |= (1 << 8);
@@ -1778,8 +1779,6 @@ fec_enet_open(struct net_device *ndev)
        struct fec_enet_private *fep = netdev_priv(ndev);
        int ret;
 
-       napi_enable(&fep->napi);
-
        /* I should reset the ring buffers here, but I don't yet know
         * a simple way to do that.
         */
@@ -1794,6 +1793,8 @@ fec_enet_open(struct net_device *ndev)
                fec_enet_free_buffers(ndev);
                return ret;
        }
+
+       napi_enable(&fep->napi);
        phy_start(fep->phy_dev);
        netif_start_queue(ndev);
        fep->opened = 1;
index 4be9715904616b3f9c1ff2a3bc38d55b58135e58..1fc8334fc181ad6d949ecffa2a289eb899c2a160 100644 (file)
@@ -522,10 +522,21 @@ retry:
        return rc;
 }
 
+static u64 ibmveth_encode_mac_addr(u8 *mac)
+{
+       int i;
+       u64 encoded = 0;
+
+       for (i = 0; i < ETH_ALEN; i++)
+               encoded = (encoded << 8) | mac[i];
+
+       return encoded;
+}
+
 static int ibmveth_open(struct net_device *netdev)
 {
        struct ibmveth_adapter *adapter = netdev_priv(netdev);
-       u64 mac_address = 0;
+       u64 mac_address;
        int rxq_entries = 1;
        unsigned long lpar_rc;
        int rc;
@@ -579,8 +590,7 @@ static int ibmveth_open(struct net_device *netdev)
        adapter->rx_queue.num_slots = rxq_entries;
        adapter->rx_queue.toggle = 1;
 
-       memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
-       mac_address = mac_address >> 16;
+       mac_address = ibmveth_encode_mac_addr(netdev->dev_addr);
 
        rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
                                        adapter->rx_queue.queue_len;
@@ -1183,8 +1193,8 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                /* add the addresses to the filter table */
                netdev_for_each_mc_addr(ha, netdev) {
                        /* add the multicast address to the filter table */
-                       unsigned long mcast_addr = 0;
-                       memcpy(((char *)&mcast_addr)+2, ha->addr, ETH_ALEN);
+                       u64 mcast_addr;
+                       mcast_addr = ibmveth_encode_mac_addr(ha->addr);
                        lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
                                                   IbmVethMcastAddFilter,
                                                   mcast_addr);
@@ -1372,9 +1382,6 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
 
-       adapter->mac_addr = 0;
-       memcpy(&adapter->mac_addr, mac_addr_p, ETH_ALEN);
-
        netdev->irq = dev->irq;
        netdev->netdev_ops = &ibmveth_netdev_ops;
        netdev->ethtool_ops = &netdev_ethtool_ops;
@@ -1383,7 +1390,7 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
        netdev->features |= netdev->hw_features;
 
-       memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
+       memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
 
        for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
                struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
index 451ba7949e152a66ee87e661e90722496792dfb8..1f37499d43981d260c61cdc1c089d7328a7942c9 100644 (file)
@@ -138,7 +138,6 @@ struct ibmveth_adapter {
     struct napi_struct napi;
     struct net_device_stats stats;
     unsigned int mcastFilterSize;
-    unsigned long mac_addr;
     void * buffer_list_addr;
     void * filter_list_addr;
     dma_addr_t buffer_list_dma;
index cbaba4442d4b226d18691059a4e122029040ff0a..bf7a01ef9a57fd532e3b8433733a22f0bfcefc27 100644 (file)
@@ -3034,7 +3034,7 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
                *enable_wake = false;
        }
 
-       pci_disable_device(pdev);
+       pci_clear_master(pdev);
 }
 
 static int __e100_power_off(struct pci_dev *pdev, bool wake)
index 6d4ada72dfd0a79f1111ff5c48f91ba3e2c862f1..18076c4178b4ff7762a117ef00595ab71173a10d 100644 (file)
@@ -6881,7 +6881,7 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
 }
 
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
-                             void *accel_priv)
+                             void *accel_priv, select_queue_fallback_t fallback)
 {
        struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
 #ifdef IXGBE_FCOE
@@ -6907,7 +6907,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
                if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
                        break;
        default:
-               return __netdev_pick_tx(dev, skb);
+               return fallback(dev, skb);
        }
 
        f = &adapter->ring_feature[RING_F_FCOE];
@@ -6920,7 +6920,7 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
 
        return txq + f->offset;
 #else
-       return __netdev_pick_tx(dev, skb);
+       return fallback(dev, skb);
 #endif
 }
 
index 8f9266c64c7589902c62443f79cc65a00895785f..fd4b6aecf6ee85d8f135cd6491582b417e1f3f1a 100644 (file)
@@ -619,7 +619,7 @@ ltq_etop_set_multicast_list(struct net_device *dev)
 
 static u16
 ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
-                     void *accel_priv)
+                     void *accel_priv, select_queue_fallback_t fallback)
 {
        /* we are currently only using the first queue */
        return 0;
index 6300fd27f2dbcc51157e362db65510c501b3ca6a..68e6a6613e9a1ccfd6a45f10d0ca0fb53c4c3dd6 100644 (file)
@@ -43,12 +43,12 @@ config MVMDIO
          This driver is used by the MV643XX_ETH and MVNETA drivers.
 
 config MVNETA
-       tristate "Marvell Armada 370/XP network interface support"
-       depends on MACH_ARMADA_370_XP
+       tristate "Marvell Armada 370/38x/XP network interface support"
+       depends on PLAT_ORION
        select MVMDIO
        ---help---
          This driver supports the network interface units in the
-         Marvell ARMADA XP and ARMADA 370 SoC family.
+         Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.
 
          Note that this driver is distinct from the mv643xx_eth
          driver, which should be used for the older Marvell SoCs
index f418f4f20f94a0f22524a6d5c1c878c2a40f7146..8d76fca7fde75085da8364a621e97e332f1e23bc 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
+#include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_mdio.h>
@@ -88,8 +89,9 @@
 #define      MVNETA_TX_IN_PRGRS                  BIT(1)
 #define      MVNETA_TX_FIFO_EMPTY                BIT(8)
 #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
-#define MVNETA_SGMII_SERDES_CFG                         0x24A0
+#define MVNETA_SERDES_CFG                       0x24A0
 #define      MVNETA_SGMII_SERDES_PROTO          0x0cc7
+#define      MVNETA_RGMII_SERDES_PROTO          0x0667
 #define MVNETA_TYPE_PRIO                         0x24bc
 #define      MVNETA_FORCE_UNI                    BIT(21)
 #define MVNETA_TXQ_CMD_1                         0x24e4
 #define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc
 #define      MVNETA_GMAC0_PORT_ENABLE            BIT(0)
 #define MVNETA_GMAC_CTRL_2                       0x2c08
-#define      MVNETA_GMAC2_PSC_ENABLE             BIT(3)
+#define      MVNETA_GMAC2_PCS_ENABLE             BIT(3)
 #define      MVNETA_GMAC2_PORT_RGMII             BIT(4)
 #define      MVNETA_GMAC2_PORT_RESET             BIT(6)
 #define MVNETA_GMAC_STATUS                       0x2c10
@@ -710,35 +712,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp,
        mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
 }
 
-
-
-/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */
-static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
-{
-       u32  val;
-
-       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
-
-       if (enable)
-               val |= MVNETA_GMAC2_PORT_RGMII;
-       else
-               val &= ~MVNETA_GMAC2_PORT_RGMII;
-
-       mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
-}
-
-/* Config SGMII port */
-static void mvneta_port_sgmii_config(struct mvneta_port *pp)
-{
-       u32 val;
-
-       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
-       val |= MVNETA_GMAC2_PSC_ENABLE;
-       mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
-
-       mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
-}
-
 /* Start the Ethernet port RX and TX activity */
 static void mvneta_port_up(struct mvneta_port *pp)
 {
@@ -2756,12 +2729,15 @@ static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
        mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
 
        if (phy_mode == PHY_INTERFACE_MODE_SGMII)
-               mvneta_port_sgmii_config(pp);
+               mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
+       else
+               mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_RGMII_SERDES_PROTO);
+
+       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
 
-       mvneta_gmac_rgmii_set(pp, 1);
+       val |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
 
        /* Cancel Port Reset */
-       val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
        val &= ~MVNETA_GMAC2_PORT_RESET;
        mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
 
@@ -2774,6 +2750,7 @@ static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 static int mvneta_probe(struct platform_device *pdev)
 {
        const struct mbus_dram_target_info *dram_target_info;
+       struct resource *res;
        struct device_node *dn = pdev->dev.of_node;
        struct device_node *phy_node;
        u32 phy_addr;
@@ -2838,9 +2815,15 @@ static int mvneta_probe(struct platform_device *pdev)
 
        clk_prepare_enable(pp->clk);
 
-       pp->base = of_iomap(dn, 0);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               err = -ENODEV;
+               goto err_clk;
+       }
+
+       pp->base = devm_ioremap_resource(&pdev->dev, res);
        if (pp->base == NULL) {
-               err = -ENOMEM;
+               err = PTR_ERR(pp->base);
                goto err_clk;
        }
 
@@ -2848,7 +2831,7 @@ static int mvneta_probe(struct platform_device *pdev)
        pp->stats = alloc_percpu(struct mvneta_pcpu_stats);
        if (!pp->stats) {
                err = -ENOMEM;
-               goto err_unmap;
+               goto err_clk;
        }
 
        for_each_possible_cpu(cpu) {
@@ -2913,8 +2896,6 @@ err_deinit:
        mvneta_deinit(pp);
 err_free_stats:
        free_percpu(pp->stats);
-err_unmap:
-       iounmap(pp->base);
 err_clk:
        clk_disable_unprepare(pp->clk);
 err_free_irq:
@@ -2934,7 +2915,6 @@ static int mvneta_remove(struct platform_device *pdev)
        mvneta_deinit(pp);
        clk_disable_unprepare(pp->clk);
        free_percpu(pp->stats);
-       iounmap(pp->base);
        irq_dispose_mapping(dev->irq);
        free_netdev(dev);
 
index fad45316200aa0fbcb115e3f6b4ec56a24ca29cd..84a96f70dfb51ea7cecf3c5f0e03daa90f52a880 100644 (file)
@@ -742,6 +742,14 @@ static int mlx4_en_replace_mac(struct mlx4_en_priv *priv, int qpn,
                                err = mlx4_en_uc_steer_add(priv, new_mac,
                                                           &qpn,
                                                           &entry->reg_id);
+                               if (err)
+                                       return err;
+                               if (priv->tunnel_reg_id) {
+                                       mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id);
+                                       priv->tunnel_reg_id = 0;
+                               }
+                               err = mlx4_en_tunnel_steer_add(priv, new_mac, qpn,
+                                                              &priv->tunnel_reg_id);
                                return err;
                        }
                }
@@ -1792,6 +1800,8 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
                mc_list[5] = priv->port;
                mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
                                      mc_list, MLX4_PROT_ETH, mclist->reg_id);
+               if (mclist->tunnel_reg_id)
+                       mlx4_flow_detach(mdev->dev, mclist->tunnel_reg_id);
        }
        mlx4_en_clear_list(dev);
        list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
index 8e8a7eb43a2ce861249d678e1f1053be9b7b0ac5..13457032d15ff09489cff354b3322f06011e1c2b 100644 (file)
@@ -629,7 +629,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
 }
 
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
-                        void *accel_priv)
+                        void *accel_priv, select_queue_fallback_t fallback)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        u16 rings_p_up = priv->num_tx_rings_p_up;
@@ -641,7 +641,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
        if (vlan_tx_tag_present(skb))
                up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT;
 
-       return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up;
+       return fallback(dev, skb) % rings_p_up + up * rings_p_up;
 }
 
 static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
index 91b69ff4b4a20f8f2bd2f6c9405cf6ab60af7f6a..7e2995ecea6f4b3e6d4a2fbadbdfb6876a73e5c8 100644 (file)
@@ -129,13 +129,14 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
                [0] = "RSS support",
                [1] = "RSS Toeplitz Hash Function support",
                [2] = "RSS XOR Hash Function support",
-               [3] = "Device manage flow steering support",
+               [3] = "Device managed flow steering support",
                [4] = "Automatic MAC reassignment support",
                [5] = "Time stamping support",
                [6] = "VST (control vlan insertion/stripping) support",
                [7] = "FSM (MAC anti-spoofing) support",
                [8] = "Dynamic QP updates support",
-               [9] = "TCP/IP offloads/flow-steering for VXLAN support"
+               [9] = "Device managed flow steering IPoIB support",
+               [10] = "TCP/IP offloads/flow-steering for VXLAN support"
        };
        int i;
 
@@ -859,7 +860,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
 
        /* For guests, disable vxlan tunneling */
-       MLX4_GET(field, outbox, QUERY_DEV_CAP_VXLAN);
+       MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VXLAN);
        field &= 0xf7;
        MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VXLAN);
 
@@ -869,7 +870,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
 
        /* For guests, disable mw type 2 */
-       MLX4_GET(bmme_flags, outbox, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
+       MLX4_GET(bmme_flags, outbox->buf, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
        bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
        MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
 
@@ -883,7 +884,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        }
 
        /* turn off ipoib managed steering for guests */
-       MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
+       MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
        field &= ~0x80;
        MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
 
index d711158b0d4b1ab59bb3d1cf8973e8d4936ce853..d413e60071d47cd7e74d86652f5a0fb813cd5eb0 100644 (file)
@@ -150,6 +150,8 @@ struct mlx4_port_config {
        struct pci_dev *pdev;
 };
 
+static atomic_t pf_loading = ATOMIC_INIT(0);
+
 int mlx4_check_port_params(struct mlx4_dev *dev,
                           enum mlx4_port_type *port_type)
 {
@@ -749,7 +751,7 @@ static void mlx4_request_modules(struct mlx4_dev *dev)
                        has_eth_port = true;
        }
 
-       if (has_ib_port)
+       if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE))
                request_module_nowait(IB_DRV_NAME);
        if (has_eth_port)
                request_module_nowait(EN_DRV_NAME);
@@ -1407,6 +1409,11 @@ static int mlx4_init_slave(struct mlx4_dev *dev)
        u32 slave_read;
        u32 cmd_channel_ver;
 
+       if (atomic_read(&pf_loading)) {
+               mlx4_warn(dev, "PF is not ready. Deferring probe\n");
+               return -EPROBE_DEFER;
+       }
+
        mutex_lock(&priv->cmd.slave_cmd_mutex);
        priv->cmd.max_cmds = 1;
        mlx4_warn(dev, "Sending reset\n");
@@ -2319,7 +2326,11 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
 
                if (num_vfs) {
                        mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", num_vfs);
+
+                       atomic_inc(&pf_loading);
                        err = pci_enable_sriov(pdev, num_vfs);
+                       atomic_dec(&pf_loading);
+
                        if (err) {
                                mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",
                                         err);
@@ -2670,7 +2681,11 @@ static pci_ers_result_t mlx4_pci_err_detected(struct pci_dev *pdev,
 
 static pci_ers_result_t mlx4_pci_slot_reset(struct pci_dev *pdev)
 {
-       int ret = __mlx4_init_one(pdev, 0);
+       const struct pci_device_id *id;
+       int ret;
+
+       id = pci_match_id(mlx4_pci_table, pdev);
+       ret = __mlx4_init_one(pdev, id->driver_data);
 
        return ret ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
 }
@@ -2684,6 +2699,7 @@ static struct pci_driver mlx4_driver = {
        .name           = DRV_NAME,
        .id_table       = mlx4_pci_table,
        .probe          = mlx4_init_one,
+       .shutdown       = mlx4_remove_one,
        .remove         = mlx4_remove_one,
        .err_handler    = &mlx4_err_handler,
 };
index 6b65f77952153f5dd1ceab2d074e456b2a9567c4..7aec6c833973c3c84c13bc3d02ca34c5a6dfef4e 100644 (file)
@@ -51,8 +51,8 @@
 
 #define DRV_NAME       "mlx4_core"
 #define PFX            DRV_NAME ": "
-#define DRV_VERSION    "1.1"
-#define DRV_RELDATE    "Dec, 2011"
+#define DRV_VERSION    "2.2-1"
+#define DRV_RELDATE    "Feb, 2014"
 
 #define MLX4_FS_UDP_UC_EN              (1 << 1)
 #define MLX4_FS_TCP_UC_EN              (1 << 2)
index 3af04c3f42ea96ddfa013ee874791c2db9dd6d94..b57e8c87a34ea8723ae9316747a69a32386429ea 100644 (file)
@@ -57,8 +57,8 @@
 #include "en_port.h"
 
 #define DRV_NAME       "mlx4_en"
-#define DRV_VERSION    "2.0"
-#define DRV_RELDATE    "Dec 2011"
+#define DRV_VERSION    "2.2-1"
+#define DRV_RELDATE    "Feb 2014"
 
 #define MLX4_EN_MSG_LEVEL      (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
 
@@ -723,7 +723,7 @@ int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 
 void mlx4_en_tx_irq(struct mlx4_cq *mcq);
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
-                        void *accel_priv);
+                        void *accel_priv, select_queue_fallback_t fallback);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
index 157fe8df2c3ed5c105a5301219b281670ed70efd..8ff57e8e3e91601bc503e5f501ac2ef1da956296 100644 (file)
@@ -4,5 +4,5 @@
 
 config MLX5_CORE
        tristate
-       depends on PCI && X86
+       depends on PCI
        default n
index a064f06e0cb8a244d183c3c48acb1754349115dd..23b7e2d35a93bb0598ac76b71d75cfc3ea7afff8 100644 (file)
@@ -46,8 +46,8 @@
 #include "mlx5_core.h"
 
 #define DRIVER_NAME "mlx5_core"
-#define DRIVER_VERSION "1.0"
-#define DRIVER_RELDATE "June 2013"
+#define DRIVER_VERSION "2.2-1"
+#define DRIVER_RELDATE "Feb 2014"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox ConnectX-IB HCA core library");
index 727b546a9eb844c909dd8cd145aacfab014c9f99..e0c92e0e5e1d463f0242088d184394608b243cb6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/eeprom_93cx6.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/spi/spi.h>
 
@@ -83,6 +84,7 @@ union ks8851_tx_hdr {
  * @rc_rxqcr: Cached copy of KS_RXQCR.
  * @eeprom_size: Companion eeprom size in Bytes, 0 if no eeprom
  * @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM.
+ * @vdd_reg:   Optional regulator supplying the chip
  *
  * The @lock ensures that the chip is protected when certain operations are
  * in progress. When the read or write packet transfer is in progress, most
@@ -130,6 +132,7 @@ struct ks8851_net {
        struct spi_transfer     spi_xfer2[2];
 
        struct eeprom_93cx6     eeprom;
+       struct regulator        *vdd_reg;
 };
 
 static int msg_enable;
@@ -1414,6 +1417,21 @@ static int ks8851_probe(struct spi_device *spi)
        ks->spidev = spi;
        ks->tx_space = 6144;
 
+       ks->vdd_reg = regulator_get_optional(&spi->dev, "vdd");
+       if (IS_ERR(ks->vdd_reg)) {
+               ret = PTR_ERR(ks->vdd_reg);
+               if (ret == -EPROBE_DEFER)
+                       goto err_reg;
+       } else {
+               ret = regulator_enable(ks->vdd_reg);
+               if (ret) {
+                       dev_err(&spi->dev, "regulator enable fail: %d\n",
+                               ret);
+                       goto err_reg_en;
+               }
+       }
+
+
        mutex_init(&ks->lock);
        spin_lock_init(&ks->statelock);
 
@@ -1508,8 +1526,14 @@ static int ks8851_probe(struct spi_device *spi)
 err_netdev:
        free_irq(ndev->irq, ks);
 
-err_id:
 err_irq:
+err_id:
+       if (!IS_ERR(ks->vdd_reg))
+               regulator_disable(ks->vdd_reg);
+err_reg_en:
+       if (!IS_ERR(ks->vdd_reg))
+               regulator_put(ks->vdd_reg);
+err_reg:
        free_netdev(ndev);
        return ret;
 }
@@ -1523,6 +1547,10 @@ static int ks8851_remove(struct spi_device *spi)
 
        unregister_netdev(priv->netdev);
        free_irq(spi->irq, priv);
+       if (!IS_ERR(priv->vdd_reg)) {
+               regulator_disable(priv->vdd_reg);
+               regulator_put(priv->vdd_reg);
+       }
        free_netdev(priv->netdev);
 
        return 0;
index 1ded50ca1600195d3ab46daf3d5689c152b3d5cc..e46e8698e6309a67945121ad86cb0ee4a61ff2b6 100644 (file)
@@ -726,9 +726,6 @@ static int vxge_learn_mac(struct vxgedev *vdev, u8 *mac_header)
        int vpath_idx = 0;
        enum vxge_hw_status status = VXGE_HW_OK;
        struct vxge_vpath *vpath = NULL;
-       struct __vxge_hw_device *hldev;
-
-       hldev = pci_get_drvdata(vdev->pdev);
 
        mac_address = (u8 *)&mac_addr;
        memcpy(mac_address, mac_header, ETH_ALEN);
@@ -2443,9 +2440,6 @@ static void vxge_rem_msix_isr(struct vxgedev *vdev)
 
 static void vxge_rem_isr(struct vxgedev *vdev)
 {
-       struct __vxge_hw_device *hldev;
-       hldev = pci_get_drvdata(vdev->pdev);
-
 #ifdef CONFIG_PCI_MSI
        if (vdev->config.intr_type == MSI_X) {
                vxge_rem_msix_isr(vdev);
index 4146664d4d6a43978789081713b858b3f982de0e..27c4f131863bc30618ae5996411122f91685144b 100644 (file)
@@ -340,6 +340,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
                        if (qlcnic_sriov_vf_check(adapter))
                                return -EINVAL;
                        num_msix = 1;
+                       adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
                        adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
                }
        }
index 77f1bce432d2998b3d14b5b6f56c694a877a1ae6..7d4f54912bad526077b145109dc003e532b88d70 100644 (file)
@@ -807,7 +807,7 @@ qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio,
            !type->tc_param_valid)
                return;
 
-       if (tc < 0 || (tc > QLC_DCB_MAX_TC))
+       if (tc < 0 || (tc >= QLC_DCB_MAX_TC))
                return;
 
        tc_cfg = &type->tc_cfg[tc];
@@ -843,7 +843,7 @@ static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid,
            !type->tc_param_valid)
                return;
 
-       if (pgid < 0 || pgid > QLC_DCB_MAX_PG)
+       if (pgid < 0 || pgid >= QLC_DCB_MAX_PG)
                return;
 
        pgcfg = &type->pg_cfg[pgid];
index ba78c7481fa3432f32fd7d5a5e7c56b66423b801..1222865cfb7319b4ec085c035c00c862cff6dcd2 100644 (file)
@@ -816,9 +816,10 @@ static int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter)
 
                if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
                        qlcnic_disable_multi_tx(adapter);
+                       adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
 
                        err = qlcnic_enable_msi_legacy(adapter);
-                       if (!err)
+                       if (err)
                                return err;
                }
        }
@@ -3863,7 +3864,7 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
                strcpy(buf, "Tx");
        }
 
-       if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
+       if (!QLCNIC_IS_MSI_FAMILY(adapter)) {
                netdev_err(netdev, "No RSS/TSS support in INT-x mode\n");
                return -EINVAL;
        }
index 09acf15c3a564d1482a6e40960c6ef8dafa6f1cc..e5277a632671a1ca23877fb5ca46ab1397ca3cc2 100644 (file)
@@ -13,8 +13,6 @@
 #define QLC_VF_MIN_TX_RATE     100
 #define QLC_VF_MAX_TX_RATE     9999
 #define QLC_MAC_OPCODE_MASK    0x7
-#define QLC_MAC_STAR_ADD       6
-#define QLC_MAC_STAR_DEL       7
 #define QLC_VF_FLOOD_BIT       BIT_16
 #define QLC_FLOOD_MODE         0x5
 
@@ -1206,13 +1204,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
        struct qlcnic_vport *vp = vf->vp;
        u8 op, new_op;
 
-       if (((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_ADD) ||
-           ((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_DEL)) {
-               netdev_err(adapter->netdev, "MAC + any VLAN filter not allowed from VF %d\n",
-                          vf->pci_func);
-               return -EINVAL;
-       }
-
        if (!(cmd->req.arg[1] & BIT_8))
                return -EINVAL;
 
index ce2cfddbed504c1b960e32bc87691ff6965a1fce..656c65ddadb4af03ff032f8f2310ebb91a7f0189 100644 (file)
@@ -4765,7 +4765,9 @@ static int qlge_probe(struct pci_dev *pdev,
        ndev->features = ndev->hw_features;
        ndev->vlan_features = ndev->hw_features;
        /* vlan gets same features (except vlan filter) */
-       ndev->vlan_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+       ndev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER |
+                                NETIF_F_HW_VLAN_CTAG_TX |
+                                NETIF_F_HW_VLAN_CTAG_RX);
 
        if (test_bit(QL_DMA64, &qdev->flags))
                ndev->features |= NETIF_F_HIGHDMA;
index 91a67ae8f17b9bffc5bf86405a5788055b583ba0..3ff7bc3e7a23ba419c9957917a9471a939db54f2 100644 (file)
@@ -209,7 +209,7 @@ static const struct {
        [RTL_GIGA_MAC_VER_16] =
                _R("RTL8101e",          RTL_TD_0, NULL, JUMBO_1K, true),
        [RTL_GIGA_MAC_VER_17] =
-               _R("RTL8168b/8111b",    RTL_TD_1, NULL, JUMBO_4K, false),
+               _R("RTL8168b/8111b",    RTL_TD_0, NULL, JUMBO_4K, false),
        [RTL_GIGA_MAC_VER_18] =
                _R("RTL8168cp/8111cp",  RTL_TD_1, NULL, JUMBO_6K, false),
        [RTL_GIGA_MAC_VER_19] =
@@ -7118,6 +7118,8 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        mutex_init(&tp->wk.mutex);
+       u64_stats_init(&tp->rx_stats.syncp);
+       u64_stats_init(&tp->tx_stats.syncp);
 
        /* Get MAC address */
        for (i = 0; i < ETH_ALEN; i++)
index eb75fbd11a0115c73195f7d820ed051e3f720d71..d7a36829649a7eea1797057e0bb0e5773bc83c0e 100644 (file)
@@ -1668,6 +1668,13 @@ void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev)
        struct efx_ptp_data *ptp = efx->ptp_data;
        int code = EFX_QWORD_FIELD(*ev, MCDI_EVENT_CODE);
 
+       if (!ptp) {
+               if (net_ratelimit())
+                       netif_warn(efx, drv, efx->net_dev,
+                                  "Received PTP event but PTP not set up\n");
+               return;
+       }
+
        if (!ptp->enabled)
                return;
 
index c49d1fb169652199ebccc42db45b0b73323d6f28..75d11fa4eb0a75dae1bf8b9b057c962ac63c1393 100644 (file)
@@ -429,7 +429,9 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
        }
 
        /* Transfer ownership of the skb to the final buffer */
+#ifdef EFX_USE_PIO
 finish_packet:
+#endif
        buffer->skb = skb;
        buffer->flags = EFX_TX_BUF_SKB | dma_flags;
 
index e2f202e3932f518c78bc2c2febbe7efd32a39278..f2d7c702c77f3853fc05c90753f1ae90773d8753 100644 (file)
@@ -37,6 +37,17 @@ config DWMAC_SUNXI
          stmmac device driver. This driver is used for A20/A31
          GMAC    ethernet controller.
 
+config DWMAC_STI
+       bool "STi GMAC support"
+       depends on STMMAC_PLATFORM && ARCH_STI
+       default y
+       ---help---
+         Support for ethernet controller on STi SOCs.
+
+         This selects STi SoC glue layer support for the stmmac
+         device driver. This driver is used on for the STi series
+         SOCs GMAC ethernet controller.
+
 config STMMAC_PCI
        bool "STMMAC PCI bus support"
        depends on STMMAC_ETH && PCI
index ecadecea79b220c6c3e5d86f031d42c34df54e4d..dcef28775dadbeca184d8aca56358c389f1220e8 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
 stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
 stmmac-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
+stmmac-$(CONFIG_DWMAC_STI) += dwmac-sti.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
              chain_mode.o dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o \
              dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
index 72d282bf33a51e8e2cb0036cac6fd03fe19acdf0..c553f6b5a9131f0af16230f59ccd0557fe1116a5 100644 (file)
@@ -151,7 +151,7 @@ static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
                                          sizeof(struct dma_desc)));
 }
 
-const struct stmmac_chain_mode_ops chain_mode_ops = {
+const struct stmmac_mode_ops chain_mode_ops = {
        .init = stmmac_init_dma_chain,
        .is_jumbo_frm = stmmac_is_jumbo_frm,
        .jumbo_frm = stmmac_jumbo_frm,
index 7834a39939464a844fd4fd8bf8ecbc2f9f8847c0..74610f3aca9e5bc8670c49f4a25901c4b4575136 100644 (file)
@@ -419,20 +419,13 @@ struct mii_regs {
        unsigned int data;      /* MII Data */
 };
 
-struct stmmac_ring_mode_ops {
-       unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
-       unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
-       void (*refill_desc3) (void *priv, struct dma_desc *p);
-       void (*init_desc3) (struct dma_desc *p);
-       void (*clean_desc3) (void *priv, struct dma_desc *p);
-       int (*set_16kib_bfsize) (int mtu);
-};
-
-struct stmmac_chain_mode_ops {
+struct stmmac_mode_ops {
        void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
                      unsigned int extend_desc);
        unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
        unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
+       int (*set_16kib_bfsize)(int mtu);
+       void (*init_desc3)(struct dma_desc *p);
        void (*refill_desc3) (void *priv, struct dma_desc *p);
        void (*clean_desc3) (void *priv, struct dma_desc *p);
 };
@@ -441,8 +434,7 @@ struct mac_device_info {
        const struct stmmac_ops *mac;
        const struct stmmac_desc_ops *desc;
        const struct stmmac_dma_ops *dma;
-       const struct stmmac_ring_mode_ops *ring;
-       const struct stmmac_chain_mode_ops *chain;
+       const struct stmmac_mode_ops *mode;
        const struct stmmac_hwtimestamp *ptp;
        struct mii_regs mii;    /* MII register Addresses */
        struct mac_link link;
@@ -460,7 +452,7 @@ void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 void stmmac_set_mac(void __iomem *ioaddr, bool enable);
 
 void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
-extern const struct stmmac_ring_mode_ops ring_mode_ops;
-extern const struct stmmac_chain_mode_ops chain_mode_ops;
+extern const struct stmmac_mode_ops ring_mode_ops;
+extern const struct stmmac_mode_ops chain_mode_ops;
 
 #endif /* __COMMON_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
new file mode 100644 (file)
index 0000000..552bbc1
--- /dev/null
@@ -0,0 +1,330 @@
+/**
+ * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
+ *
+ * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
+ * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+#include <linux/phy.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+
+/**
+ *                     STi GMAC glue logic.
+ *                     --------------------
+ *
+ *              _
+ *             |  \
+ *     --------|0  \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK
+ * phyclk      |    |___________________________________________
+ *             |    |  |                       (phyclk-in)
+ *     --------|1  /   |
+ * int-clk     |_ /    |
+ *                     |        _
+ *                     |       |  \
+ *                     |_______|1  \ ETH_SEL_TX_RETIME_CLK
+ *                             |    |___________________________
+ *                             |    |          (tx-retime-clk)
+ *                      _______|0  /
+ *                     |       |_ /
+ *              _      |
+ *             |  \    |
+ *     --------|0  \   |
+ * clk_125     |    |__|
+ *             |    |  ETH_SEL_TXCLK_NOT_CLK125
+ *     --------|1  /
+ * txclk       |_ /
+ *
+ *
+ * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can
+ * generate 50MHz clock or MAC can generate it.
+ * This bit is configured by "st,ext-phyclk" property.
+ *
+ * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz
+ * clock either comes from clk-125 pin or txclk pin. This configuration is
+ * totally driven by the board wiring. This bit is configured by
+ * "st,tx-retime-src" property.
+ *
+ * TXCLK configuration is different for different phy interface modes
+ * and changes according to link speed in modes like RGMII.
+ *
+ * Below table summarizes the clock requirement and clock sources for
+ * supported phy interface modes with link speeds.
+ * ________________________________________________
+ *|  PHY_MODE  | 1000 Mbit Link | 100 Mbit Link   |
+ * ------------------------------------------------
+ *|    MII     |       n/a      |      25Mhz      |
+ *|            |                |      txclk      |
+ * ------------------------------------------------
+ *|    GMII    |     125Mhz     |      25Mhz      |
+ *|            |  clk-125/txclk |      txclk      |
+ * ------------------------------------------------
+ *|    RGMII   |     125Mhz     |      25Mhz      |
+ *|            |  clk-125/txclk |      clkgen     |
+ * ------------------------------------------------
+ *|    RMII    |       n/a      |      25Mhz      |
+ *|            |                |clkgen/phyclk-in |
+ * ------------------------------------------------
+ *
+ * TX lines are always retimed with a clk, which can vary depending
+ * on the board configuration. Below is the table of these bits
+ * in eth configuration register depending on source of retime clk.
+ *
+ *---------------------------------------------------------------
+ * src  | tx_rt_clk    | int_not_ext_phyclk    | txclk_n_clk125|
+ *---------------------------------------------------------------
+ * txclk |     0       |       n/a             |       1       |
+ *---------------------------------------------------------------
+ * ck_125|     0       |       n/a             |       0       |
+ *---------------------------------------------------------------
+ * phyclk|     1       |       0               |       n/a     |
+ *---------------------------------------------------------------
+ * clkgen|     1       |       1               |       n/a     |
+ *---------------------------------------------------------------
+ */
+
+ /* Register definition */
+
+ /* 3 bits [8:6]
+  *  [6:6]      ETH_SEL_TXCLK_NOT_CLK125
+  *  [7:7]      ETH_SEL_INTERNAL_NOTEXT_PHYCLK
+  *  [8:8]      ETH_SEL_TX_RETIME_CLK
+  *
+  */
+
+#define TX_RETIME_SRC_MASK             GENMASK(8, 6)
+#define ETH_SEL_TX_RETIME_CLK          BIT(8)
+#define ETH_SEL_INTERNAL_NOTEXT_PHYCLK BIT(7)
+#define ETH_SEL_TXCLK_NOT_CLK125       BIT(6)
+
+#define ENMII_MASK                     GENMASK(5, 5)
+#define ENMII                          BIT(5)
+
+/**
+ * 3 bits [4:2]
+ *     000-GMII/MII
+ *     001-RGMII
+ *     010-SGMII
+ *     100-RMII
+*/
+#define MII_PHY_SEL_MASK               GENMASK(4, 2)
+#define ETH_PHY_SEL_RMII               BIT(4)
+#define ETH_PHY_SEL_SGMII              BIT(3)
+#define ETH_PHY_SEL_RGMII              BIT(2)
+#define ETH_PHY_SEL_GMII               0x0
+#define ETH_PHY_SEL_MII                        0x0
+
+#define IS_PHY_IF_MODE_RGMII(iface)    (iface == PHY_INTERFACE_MODE_RGMII || \
+                       iface == PHY_INTERFACE_MODE_RGMII_ID || \
+                       iface == PHY_INTERFACE_MODE_RGMII_RXID || \
+                       iface == PHY_INTERFACE_MODE_RGMII_TXID)
+
+#define IS_PHY_IF_MODE_GBIT(iface)     (IS_PHY_IF_MODE_RGMII(iface) || \
+                       iface == PHY_INTERFACE_MODE_GMII)
+
+struct sti_dwmac {
+       int interface;
+       bool ext_phyclk;
+       bool is_tx_retime_src_clk_125;
+       struct clk *clk;
+       int reg;
+       struct device *dev;
+       struct regmap *regmap;
+};
+
+static u32 phy_intf_sels[] = {
+       [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
+       [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
+       [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
+       [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
+       [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
+       [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
+};
+
+enum {
+       TX_RETIME_SRC_NA = 0,
+       TX_RETIME_SRC_TXCLK = 1,
+       TX_RETIME_SRC_CLK_125,
+       TX_RETIME_SRC_PHYCLK,
+       TX_RETIME_SRC_CLKGEN,
+};
+
+static const char *const tx_retime_srcs[] = {
+       [TX_RETIME_SRC_NA] = "",
+       [TX_RETIME_SRC_TXCLK] = "txclk",
+       [TX_RETIME_SRC_CLK_125] = "clk_125",
+       [TX_RETIME_SRC_PHYCLK] = "phyclk",
+       [TX_RETIME_SRC_CLKGEN] = "clkgen",
+};
+
+static u32 tx_retime_val[] = {
+       [TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125,
+       [TX_RETIME_SRC_CLK_125] = 0x0,
+       [TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK,
+       [TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK |
+           ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
+};
+
+static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd)
+{
+       u32 src = 0, freq = 0;
+
+       if (spd == SPEED_100) {
+               if (dwmac->interface == PHY_INTERFACE_MODE_MII ||
+                   dwmac->interface == PHY_INTERFACE_MODE_GMII) {
+                       src = TX_RETIME_SRC_TXCLK;
+               } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
+                       if (dwmac->ext_phyclk) {
+                               src = TX_RETIME_SRC_PHYCLK;
+                       } else {
+                               src = TX_RETIME_SRC_CLKGEN;
+                               freq = 50000000;
+                       }
+
+               } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
+                       src = TX_RETIME_SRC_CLKGEN;
+                       freq = 25000000;
+               }
+
+               if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk)
+                       clk_set_rate(dwmac->clk, freq);
+
+       } else if (spd == SPEED_1000) {
+               if (dwmac->is_tx_retime_src_clk_125)
+                       src = TX_RETIME_SRC_CLK_125;
+               else
+                       src = TX_RETIME_SRC_TXCLK;
+       }
+
+       regmap_update_bits(dwmac->regmap, dwmac->reg,
+                          TX_RETIME_SRC_MASK, tx_retime_val[src]);
+}
+
+static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
+{
+       struct sti_dwmac *dwmac = priv;
+
+       if (dwmac->clk)
+               clk_disable_unprepare(dwmac->clk);
+}
+
+static void sti_fix_mac_speed(void *priv, unsigned int spd)
+{
+       struct sti_dwmac *dwmac = priv;
+
+       setup_retime_src(dwmac, spd);
+
+       return;
+}
+
+static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
+                               struct platform_device *pdev)
+{
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct regmap *regmap;
+       int err;
+
+       if (!np)
+               return -EINVAL;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
+       if (!res)
+               return -ENODATA;
+
+       regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       dwmac->dev = dev;
+       dwmac->interface = of_get_phy_mode(np);
+       dwmac->regmap = regmap;
+       dwmac->reg = res->start;
+       dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
+       dwmac->is_tx_retime_src_clk_125 = false;
+
+       if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
+               const char *rs;
+
+               err = of_property_read_string(np, "st,tx-retime-src", &rs);
+               if (err < 0) {
+                       dev_err(dev, "st,tx-retime-src not specified\n");
+                       return err;
+               }
+
+               if (!strcasecmp(rs, "clk_125"))
+                       dwmac->is_tx_retime_src_clk_125 = true;
+       }
+
+       dwmac->clk = devm_clk_get(dev, "sti-ethclk");
+
+       if (IS_ERR(dwmac->clk))
+               dwmac->clk = NULL;
+
+       return 0;
+}
+
+static int sti_dwmac_init(struct platform_device *pdev, void *priv)
+{
+       struct sti_dwmac *dwmac = priv;
+       struct regmap *regmap = dwmac->regmap;
+       int iface = dwmac->interface;
+       u32 reg = dwmac->reg;
+       u32 val, spd;
+
+       if (dwmac->clk)
+               clk_prepare_enable(dwmac->clk);
+
+       regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
+
+       val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
+       regmap_update_bits(regmap, reg, ENMII_MASK, val);
+
+       if (IS_PHY_IF_MODE_GBIT(iface))
+               spd = SPEED_1000;
+       else
+               spd = SPEED_100;
+
+       setup_retime_src(dwmac, spd);
+
+       return 0;
+}
+
+static void *sti_dwmac_setup(struct platform_device *pdev)
+{
+       struct sti_dwmac *dwmac;
+       int ret;
+
+       dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+       if (!dwmac)
+               return ERR_PTR(-ENOMEM);
+
+       ret = sti_dwmac_parse_data(dwmac, pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to parse OF data\n");
+               return ERR_PTR(ret);
+       }
+
+       return dwmac;
+}
+
+const struct stmmac_of_data sti_gmac_data = {
+       .fix_mac_speed = sti_fix_mac_speed,
+       .setup = sti_dwmac_setup,
+       .init = sti_dwmac_init,
+       .exit = sti_dwmac_exit,
+};
index a96c7c2f5f3f220b32df9c0ebad2b197e7ecd45a..650a4be6bce5243e046fcd226719e669f66444e8 100644 (file)
@@ -100,10 +100,9 @@ static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
 {
        struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
 
-       if (unlikely(priv->plat->has_gmac))
-               /* Fill DES3 in case of RING mode */
-               if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
-                       p->des3 = p->des2 + BUF_SIZE_8KiB;
+       /* Fill DES3 in case of RING mode */
+       if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
+               p->des3 = p->des2 + BUF_SIZE_8KiB;
 }
 
 /* In ring mode we need to fill the desc3 because it is used as buffer */
@@ -126,7 +125,7 @@ static int stmmac_set_16kib_bfsize(int mtu)
        return ret;
 }
 
-const struct stmmac_ring_mode_ops ring_mode_ops = {
+const struct stmmac_mode_ops ring_mode_ops = {
        .is_jumbo_frm = stmmac_is_jumbo_frm,
        .jumbo_frm = stmmac_jumbo_frm,
        .refill_desc3 = stmmac_refill_desc3,
index d9af26ed58ee7d3c231c64b110924420c41b765e..f9e60d7918c4ac0b800a664ecae26e0228033f53 100644 (file)
@@ -133,6 +133,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv);
 #ifdef CONFIG_DWMAC_SUNXI
 extern const struct stmmac_of_data sun7i_gmac_data;
 #endif
+#ifdef CONFIG_DWMAC_STI
+extern const struct stmmac_of_data sti_gmac_data;
+#endif
 extern struct platform_driver stmmac_pltfr_driver;
 static inline int stmmac_register_platform(void)
 {
index a2e7d2c96e3678c309377d3e4dbb416feb5fbc38..8543e1cfd55edb4a60f5cb543a1e5ea9fc18a097 100644 (file)
@@ -92,8 +92,8 @@ static int tc = TC_DEFAULT;
 module_param(tc, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(tc, "DMA threshold control value");
 
-#define DMA_BUFFER_SIZE        BUF_SIZE_4KiB
-static int buf_sz = DMA_BUFFER_SIZE;
+#define        DEFAULT_BUFSIZE 1536
+static int buf_sz = DEFAULT_BUFSIZE;
 module_param(buf_sz, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(buf_sz, "DMA buffer size");
 
@@ -136,8 +136,8 @@ static void stmmac_verify_args(void)
                dma_rxsize = DMA_RX_SIZE;
        if (unlikely(dma_txsize < 0))
                dma_txsize = DMA_TX_SIZE;
-       if (unlikely((buf_sz < DMA_BUFFER_SIZE) || (buf_sz > BUF_SIZE_16KiB)))
-               buf_sz = DMA_BUFFER_SIZE;
+       if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
+               buf_sz = DEFAULT_BUFSIZE;
        if (unlikely(flow_ctrl > 1))
                flow_ctrl = FLOW_AUTO;
        else if (likely(flow_ctrl < 0))
@@ -286,10 +286,25 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
 
        /* MAC core supports the EEE feature. */
        if (priv->dma_cap.eee) {
+               int tx_lpi_timer = priv->tx_lpi_timer;
+
                /* Check if the PHY supports EEE */
-               if (phy_init_eee(priv->phydev, 1))
+               if (phy_init_eee(priv->phydev, 1)) {
+                       /* To manage at run-time if the EEE cannot be supported
+                        * anymore (for example because the lp caps have been
+                        * changed).
+                        * In that case the driver disable own timers.
+                        */
+                       if (priv->eee_active) {
+                               pr_debug("stmmac: disable EEE\n");
+                               del_timer_sync(&priv->eee_ctrl_timer);
+                               priv->hw->mac->set_eee_timer(priv->ioaddr, 0,
+                                                            tx_lpi_timer);
+                       }
+                       priv->eee_active = 0;
                        goto out;
-
+               }
+               /* Activate the EEE and start timers */
                if (!priv->eee_active) {
                        priv->eee_active = 1;
                        init_timer(&priv->eee_ctrl_timer);
@@ -300,13 +315,13 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
 
                        priv->hw->mac->set_eee_timer(priv->ioaddr,
                                                     STMMAC_DEFAULT_LIT_LS,
-                                                    priv->tx_lpi_timer);
+                                                    tx_lpi_timer);
                } else
                        /* Set HW EEE according to the speed */
                        priv->hw->mac->set_eee_pls(priv->ioaddr,
                                                   priv->phydev->link);
 
-               pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
+               pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
 
                ret = true;
        }
@@ -886,10 +901,10 @@ static int stmmac_set_bfsize(int mtu, int bufsize)
                ret = BUF_SIZE_8KiB;
        else if (mtu >= BUF_SIZE_2KiB)
                ret = BUF_SIZE_4KiB;
-       else if (mtu >= DMA_BUFFER_SIZE)
+       else if (mtu > DEFAULT_BUFSIZE)
                ret = BUF_SIZE_2KiB;
        else
-               ret = DMA_BUFFER_SIZE;
+               ret = DEFAULT_BUFSIZE;
 
        return ret;
 }
@@ -951,9 +966,9 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
 
        p->des2 = priv->rx_skbuff_dma[i];
 
-       if ((priv->mode == STMMAC_RING_MODE) &&
+       if ((priv->hw->mode->init_desc3) &&
            (priv->dma_buf_sz == BUF_SIZE_16KiB))
-               priv->hw->ring->init_desc3(p);
+               priv->hw->mode->init_desc3(p);
 
        return 0;
 }
@@ -984,11 +999,8 @@ static int init_dma_desc_rings(struct net_device *dev)
        unsigned int bfsize = 0;
        int ret = -ENOMEM;
 
-       /* Set the max buffer size according to the DESC mode
-        * and the MTU. Note that RING mode allows 16KiB bsize.
-        */
-       if (priv->mode == STMMAC_RING_MODE)
-               bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu);
+       if (priv->hw->mode->set_16kib_bfsize)
+               bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
 
        if (bfsize < BUF_SIZE_16KiB)
                bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
@@ -1029,15 +1041,15 @@ static int init_dma_desc_rings(struct net_device *dev)
        /* Setup the chained descriptor addresses */
        if (priv->mode == STMMAC_CHAIN_MODE) {
                if (priv->extend_desc) {
-                       priv->hw->chain->init(priv->dma_erx, priv->dma_rx_phy,
-                                             rxsize, 1);
-                       priv->hw->chain->init(priv->dma_etx, priv->dma_tx_phy,
-                                             txsize, 1);
+                       priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
+                                            rxsize, 1);
+                       priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
+                                            txsize, 1);
                } else {
-                       priv->hw->chain->init(priv->dma_rx, priv->dma_rx_phy,
-                                             rxsize, 0);
-                       priv->hw->chain->init(priv->dma_tx, priv->dma_tx_phy,
-                                             txsize, 0);
+                       priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
+                                            rxsize, 0);
+                       priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
+                                            txsize, 0);
                }
        }
 
@@ -1288,7 +1300,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
                                         DMA_TO_DEVICE);
                        priv->tx_skbuff_dma[entry] = 0;
                }
-               priv->hw->ring->clean_desc3(priv, p);
+               priv->hw->mode->clean_desc3(priv, p);
 
                if (likely(skb != NULL)) {
                        dev_kfree_skb(skb);
@@ -1705,7 +1717,7 @@ static int stmmac_open(struct net_device *dev)
        priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
        priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
 
-       alloc_dma_desc_resources(priv);
+       ret = alloc_dma_desc_resources(priv);
        if (ret < 0) {
                pr_err("%s: DMA descriptors allocation failed\n", __func__);
                goto dma_desc_error;
@@ -1844,6 +1856,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        int nfrags = skb_shinfo(skb)->nr_frags;
        struct dma_desc *desc, *first;
        unsigned int nopaged_len = skb_headlen(skb);
+       unsigned int enh_desc = priv->plat->enh_desc;
 
        if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
                if (!netif_queue_stopped(dev)) {
@@ -1871,27 +1884,19 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        first = desc;
 
        /* To program the descriptors according to the size of the frame */
-       if (priv->mode == STMMAC_RING_MODE) {
-               is_jumbo = priv->hw->ring->is_jumbo_frm(skb->len,
-                                                       priv->plat->enh_desc);
-               if (unlikely(is_jumbo))
-                       entry = priv->hw->ring->jumbo_frm(priv, skb,
-                                                         csum_insertion);
-       } else {
-               is_jumbo = priv->hw->chain->is_jumbo_frm(skb->len,
-                                                        priv->plat->enh_desc);
-               if (unlikely(is_jumbo))
-                       entry = priv->hw->chain->jumbo_frm(priv, skb,
-                                                          csum_insertion);
-       }
+       if (enh_desc)
+               is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
+
        if (likely(!is_jumbo)) {
                desc->des2 = dma_map_single(priv->device, skb->data,
                                            nopaged_len, DMA_TO_DEVICE);
                priv->tx_skbuff_dma[entry] = desc->des2;
                priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
                                                csum_insertion, priv->mode);
-       } else
+       } else {
                desc = first;
+               entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
+       }
 
        for (i = 0; i < nfrags; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -2029,7 +2034,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
 
                        p->des2 = priv->rx_skbuff_dma[entry];
 
-                       priv->hw->ring->refill_desc3(priv, p);
+                       priv->hw->mode->refill_desc3(priv, p);
 
                        if (netif_msg_rx_status(priv))
                                pr_debug("\trefill entry #%d\n", entry);
@@ -2633,11 +2638,11 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
 
        /* To use the chained or ring mode */
        if (chain_mode) {
-               priv->hw->chain = &chain_mode_ops;
+               priv->hw->mode = &chain_mode_ops;
                pr_info(" Chain mode enabled\n");
                priv->mode = STMMAC_CHAIN_MODE;
        } else {
-               priv->hw->ring = &ring_mode_ops;
+               priv->hw->mode = &ring_mode_ops;
                pr_info(" Ring mode enabled\n");
                priv->mode = STMMAC_RING_MODE;
        }
index 5884a7d2063b9bf650a7940485f9e96ea2cb0022..8fb32a80f1c1999a18234a2daec7323affd3917a 100644 (file)
 static const struct of_device_id stmmac_dt_ids[] = {
 #ifdef CONFIG_DWMAC_SUNXI
        { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
+#endif
+#ifdef CONFIG_DWMAC_STI
+       { .compatible = "st,stih415-dwmac", .data = &sti_gmac_data},
+       { .compatible = "st,stih416-dwmac", .data = &sti_gmac_data},
+       { .compatible = "st,stid127-dwmac", .data = &sti_gmac_data},
 #endif
        /* SoC specific glue layers should come before generic bindings */
        { .compatible = "st,spear600-gmac"},
index bde63e3af96f6a0e005cd2cc9da93b83a53dc0db..7d6d8ec676c892ebeb633b7f54fcd91cca1267c1 100644 (file)
@@ -554,7 +554,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                 * common for both the interface as the interface shares
                 * the same hardware resource.
                 */
-               for (i = 0; i <= priv->data.slaves; i++)
+               for (i = 0; i < priv->data.slaves; i++)
                        if (priv->slaves[i].ndev->flags & IFF_PROMISC)
                                flag = true;
 
@@ -578,7 +578,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                        unsigned long timeout = jiffies + HZ;
 
                        /* Disable Learn for all ports */
-                       for (i = 0; i <= priv->data.slaves; i++) {
+                       for (i = 0; i < priv->data.slaves; i++) {
                                cpsw_ale_control_set(ale, i,
                                                     ALE_PORT_NOLEARN, 1);
                                cpsw_ale_control_set(ale, i,
@@ -606,7 +606,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                        cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
 
                        /* Enable Learn for all ports */
-                       for (i = 0; i <= priv->data.slaves; i++) {
+                       for (i = 0; i < priv->data.slaves; i++) {
                                cpsw_ale_control_set(ale, i,
                                                     ALE_PORT_NOLEARN, 0);
                                cpsw_ale_control_set(ale, i,
@@ -1164,11 +1164,17 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
 
 static void cpsw_slave_stop(struct cpsw_slave *slave, struct cpsw_priv *priv)
 {
+       u32 slave_port;
+
+       slave_port = cpsw_get_slave_port(priv, slave->slave_num);
+
        if (!slave->phy)
                return;
        phy_stop(slave->phy);
        phy_disconnect(slave->phy);
        slave->phy = NULL;
+       cpsw_ale_control_set(priv->ale, slave_port,
+                            ALE_PORT_STATE, ALE_PORT_STATE_DISABLE);
 }
 
 static int cpsw_ndo_open(struct net_device *ndev)
@@ -1878,14 +1884,29 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
                phyid = be32_to_cpup(parp+1);
                mdio = of_find_device_by_node(mdio_node);
-               snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
-                        PHY_ID_FMT, mdio->name, phyid);
+
+               if (strncmp(mdio->name, "gpio", 4) == 0) {
+                       /* GPIO bitbang MDIO driver attached */
+                       struct mii_bus *bus = dev_get_drvdata(&mdio->dev);
+
+                       snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+                                PHY_ID_FMT, bus->id, phyid);
+               } else {
+                       /* davinci MDIO driver attached */
+                       snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+                                PHY_ID_FMT, mdio->name, phyid);
+               }
 
                mac_addr = of_get_mac_address(slave_node);
                if (mac_addr)
                        memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
 
                slave_data->phy_if = of_get_phy_mode(slave_node);
+               if (slave_data->phy_if < 0) {
+                       pr_err("Missing or malformed slave[%d] phy-mode property\n",
+                              i);
+                       return slave_data->phy_if;
+               }
 
                if (data->dual_emac) {
                        if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
@@ -2208,10 +2229,6 @@ static int cpsw_probe(struct platform_device *pdev)
                goto clean_ale_ret;
        }
 
-       if (cpts_register(&pdev->dev, priv->cpts,
-                         data->cpts_clock_mult, data->cpts_clock_shift))
-               dev_err(priv->dev, "error registering cpts device\n");
-
        cpsw_notice(priv, probe, "initialized device (regs %pa, irq %d)\n",
                    &ss_res->start, ndev->irq);
 
index 364d0c7952c023d0cc60de6cc8d73460b000fbd1..88ef27067bf24a8b2569f533b63ac223d52280fe 100644 (file)
@@ -355,7 +355,7 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
        int i;
 
        spin_lock_irqsave(&ctlr->lock, flags);
-       if (ctlr->state != CPDMA_STATE_ACTIVE) {
+       if (ctlr->state == CPDMA_STATE_TEARDOWN) {
                spin_unlock_irqrestore(&ctlr->lock, flags);
                return -EINVAL;
        }
@@ -891,7 +891,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
        unsigned                timeout;
 
        spin_lock_irqsave(&chan->lock, flags);
-       if (chan->state != CPDMA_STATE_ACTIVE) {
+       if (chan->state == CPDMA_STATE_TEARDOWN) {
                spin_unlock_irqrestore(&chan->lock, flags);
                return -EINVAL;
        }
index cd9b164a0434acb3a51066b5d0e17262a4bdc0dd..8f0e69ce07ca3e03cfbf4cf1b22c92c9af27beeb 100644 (file)
@@ -1532,9 +1532,9 @@ static int emac_dev_open(struct net_device *ndev)
        struct device *emac_dev = &ndev->dev;
        u32 cnt;
        struct resource *res;
-       int ret;
+       int q, m, ret;
+       int res_num = 0, irq_num = 0;
        int i = 0;
-       int k = 0;
        struct emac_priv *priv = netdev_priv(ndev);
 
        pm_runtime_get(&priv->pdev->dev);
@@ -1564,15 +1564,24 @@ static int emac_dev_open(struct net_device *ndev)
        }
 
        /* Request IRQ */
+       while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ,
+                                           res_num))) {
+               for (irq_num = res->start; irq_num <= res->end; irq_num++) {
+                       dev_err(emac_dev, "Request IRQ %d\n", irq_num);
+                       if (request_irq(irq_num, emac_irq, 0, ndev->name,
+                                       ndev)) {
+                               dev_err(emac_dev,
+                                       "DaVinci EMAC: request_irq() failed\n");
+                               ret = -EBUSY;
 
-       while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
-               for (i = res->start; i <= res->end; i++) {
-                       if (devm_request_irq(&priv->pdev->dev, i, emac_irq,
-                                            0, ndev->name, ndev))
                                goto rollback;
+                       }
                }
-               k++;
+               res_num++;
        }
+       /* prepare counters for rollback in case of an error */
+       res_num--;
+       irq_num--;
 
        /* Start/Enable EMAC hardware */
        emac_hw_enable(priv);
@@ -1639,11 +1648,23 @@ static int emac_dev_open(struct net_device *ndev)
 
        return 0;
 
-rollback:
-
-       dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed");
-       ret = -EBUSY;
 err:
+       emac_int_disable(priv);
+       napi_disable(&priv->napi);
+
+rollback:
+       for (q = res_num; q >= 0; q--) {
+               res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, q);
+               /* at the first iteration, irq_num is already set to the
+                * right value
+                */
+               if (q != res_num)
+                       irq_num = res->end;
+
+               for (m = irq_num; m >= res->start; m--)
+                       free_irq(m, ndev);
+       }
+       cpdma_ctlr_stop(priv->dma);
        pm_runtime_put(&priv->pdev->dev);
        return ret;
 }
@@ -1659,6 +1680,9 @@ err:
  */
 static int emac_dev_stop(struct net_device *ndev)
 {
+       struct resource *res;
+       int i = 0;
+       int irq_num;
        struct emac_priv *priv = netdev_priv(ndev);
        struct device *emac_dev = &ndev->dev;
 
@@ -1674,6 +1698,13 @@ static int emac_dev_stop(struct net_device *ndev)
        if (priv->phydev)
                phy_disconnect(priv->phydev);
 
+       /* Free IRQ */
+       while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) {
+               for (irq_num = res->start; irq_num <= res->end; irq_num++)
+                       free_irq(irq_num, priv->ndev);
+               i++;
+       }
+
        if (netif_msg_drv(priv))
                dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name);
 
index 023237a657207995e367ec365269d155043377c0..17503da9f7a589d5f56484329179c4c68c4af429 100644 (file)
@@ -2071,7 +2071,7 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
 /* Return subqueue id on this core (one per core). */
 static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
-                                void *accel_priv)
+                                void *accel_priv, select_queue_fallback_t fallback)
 {
        return smp_processor_id();
 }
index ef312bc6b8658deabae28d179c39237564b8ede4..6ac20a6738f4df5862b49aea71955a4a51ee4842 100644 (file)
@@ -923,7 +923,7 @@ static int rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc) {
                dev_err(&pdev->dev,
                        "32-bit PCI DMA addresses not supported by the card!?\n");
-               goto err_out;
+               goto err_out_pci_disable;
        }
 
        /* sanity check */
@@ -931,7 +931,7 @@ static int rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
            (pci_resource_len(pdev, 1) < io_size)) {
                rc = -EIO;
                dev_err(&pdev->dev, "Insufficient PCI resources, aborting\n");
-               goto err_out;
+               goto err_out_pci_disable;
        }
 
        pioaddr = pci_resource_start(pdev, 0);
@@ -942,7 +942,7 @@ static int rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev = alloc_etherdev(sizeof(struct rhine_private));
        if (!dev) {
                rc = -ENOMEM;
-               goto err_out;
+               goto err_out_pci_disable;
        }
        SET_NETDEV_DEV(dev, &pdev->dev);
 
@@ -1084,6 +1084,8 @@ err_out_free_res:
        pci_release_regions(pdev);
 err_out_free_netdev:
        free_netdev(dev);
+err_out_pci_disable:
+       pci_disable_device(pdev);
 err_out:
        return rc;
 }
index 1ec65feebb9e29cb1b9bfe7ffe2343fdfad9c537..4bfdf8c7ada033cf964f1da66daba0137b499e6f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
@@ -600,7 +601,8 @@ static void axienet_start_xmit_done(struct net_device *ndev)
                size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
                packets++;
 
-               lp->tx_bd_ci = ++lp->tx_bd_ci % TX_BD_NUM;
+               ++lp->tx_bd_ci;
+               lp->tx_bd_ci %= TX_BD_NUM;
                cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
                status = cur_p->status;
        }
@@ -686,7 +688,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                                     skb_headlen(skb), DMA_TO_DEVICE);
 
        for (ii = 0; ii < num_frag; ii++) {
-               lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+               ++lp->tx_bd_tail;
+               lp->tx_bd_tail %= TX_BD_NUM;
                cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
                frag = &skb_shinfo(skb)->frags[ii];
                cur_p->phys = dma_map_single(ndev->dev.parent,
@@ -702,7 +705,8 @@ static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
        /* Start the transfer */
        axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
-       lp->tx_bd_tail = ++lp->tx_bd_tail % TX_BD_NUM;
+       ++lp->tx_bd_tail;
+       lp->tx_bd_tail %= TX_BD_NUM;
 
        return NETDEV_TX_OK;
 }
@@ -774,7 +778,8 @@ static void axienet_recv(struct net_device *ndev)
                cur_p->status = 0;
                cur_p->sw_id_offset = (u32) new_skb;
 
-               lp->rx_bd_ci = ++lp->rx_bd_ci % RX_BD_NUM;
+               ++lp->rx_bd_ci;
+               lp->rx_bd_ci %= RX_BD_NUM;
                cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
        }
 
index 7756118c2f0aee4c3671f45bc0bd13e15143d607..d6fce9750b9553b221759f18fd4ec48158af4e73 100644 (file)
@@ -88,8 +88,12 @@ static int netvsc_open(struct net_device *net)
 {
        struct net_device_context *net_device_ctx = netdev_priv(net);
        struct hv_device *device_obj = net_device_ctx->device_ctx;
+       struct netvsc_device *nvdev;
+       struct rndis_device *rdev;
        int ret = 0;
 
+       netif_carrier_off(net);
+
        /* Open up the device */
        ret = rndis_filter_open(device_obj);
        if (ret != 0) {
@@ -99,6 +103,11 @@ static int netvsc_open(struct net_device *net)
 
        netif_start_queue(net);
 
+       nvdev = hv_get_drvdata(device_obj);
+       rdev = nvdev->extension;
+       if (!rdev->link_state)
+               netif_carrier_on(net);
+
        return ret;
 }
 
@@ -229,23 +238,24 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
        struct net_device *net;
        struct net_device_context *ndev_ctx;
        struct netvsc_device *net_device;
+       struct rndis_device *rdev;
 
        net_device = hv_get_drvdata(device_obj);
+       rdev = net_device->extension;
+
+       rdev->link_state = status != 1;
+
        net = net_device->ndev;
 
-       if (!net) {
-               netdev_err(net, "got link status but net device "
-                               "not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED)
                return;
-       }
 
+       ndev_ctx = netdev_priv(net);
        if (status == 1) {
-               netif_carrier_on(net);
-               ndev_ctx = netdev_priv(net);
                schedule_delayed_work(&ndev_ctx->dwork, 0);
                schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
        } else {
-               netif_carrier_off(net);
+               schedule_delayed_work(&ndev_ctx->dwork, 0);
        }
 }
 
@@ -388,17 +398,35 @@ static const struct net_device_ops device_ops = {
  * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
  * another netif_notify_peers() into a delayed work, otherwise GARP packet
  * will not be sent after quick migration, and cause network disconnection.
+ * Also, we update the carrier status here.
  */
-static void netvsc_send_garp(struct work_struct *w)
+static void netvsc_link_change(struct work_struct *w)
 {
        struct net_device_context *ndev_ctx;
        struct net_device *net;
        struct netvsc_device *net_device;
+       struct rndis_device *rdev;
+       bool notify;
+
+       rtnl_lock();
 
        ndev_ctx = container_of(w, struct net_device_context, dwork.work);
        net_device = hv_get_drvdata(ndev_ctx->device_ctx);
+       rdev = net_device->extension;
        net = net_device->ndev;
-       netdev_notify_peers(net);
+
+       if (rdev->link_state) {
+               netif_carrier_off(net);
+               notify = false;
+       } else {
+               netif_carrier_on(net);
+               notify = true;
+       }
+
+       rtnl_unlock();
+
+       if (notify)
+               netdev_notify_peers(net);
 }
 
 
@@ -414,13 +442,12 @@ static int netvsc_probe(struct hv_device *dev,
        if (!net)
                return -ENOMEM;
 
-       /* Set initial state */
        netif_carrier_off(net);
 
        net_device_ctx = netdev_priv(net);
        net_device_ctx->device_ctx = dev;
        hv_set_drvdata(dev, net);
-       INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+       INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
        INIT_WORK(&net_device_ctx->work, do_set_multicast);
 
        net->netdev_ops = &device_ops;
@@ -443,13 +470,13 @@ static int netvsc_probe(struct hv_device *dev,
        }
        memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
 
-       netif_carrier_on(net);
-
        ret = register_netdev(net);
        if (ret != 0) {
                pr_err("Unable to register netdev.\n");
                rndis_filter_device_remove(dev);
                free_netdev(net);
+       } else {
+               schedule_delayed_work(&net_device_ctx->dwork, 0);
        }
 
        return ret;
index 1084e5de3ceb4c805d2ef9e98b90c6d68a9a9991..b54fd257652bb629b8228162712bb557e9023943 100644 (file)
@@ -243,6 +243,22 @@ static int rndis_filter_send_request(struct rndis_device *dev,
        return ret;
 }
 
+static void rndis_set_link_state(struct rndis_device *rdev,
+                                struct rndis_request *request)
+{
+       u32 link_status;
+       struct rndis_query_complete *query_complete;
+
+       query_complete = &request->response_msg.msg.query_complete;
+
+       if (query_complete->status == RNDIS_STATUS_SUCCESS &&
+           query_complete->info_buflen == sizeof(u32)) {
+               memcpy(&link_status, (void *)((unsigned long)query_complete +
+                      query_complete->info_buf_offset), sizeof(u32));
+               rdev->link_state = link_status != 0;
+       }
+}
+
 static void rndis_filter_receive_response(struct rndis_device *dev,
                                       struct rndis_message *resp)
 {
@@ -272,6 +288,10 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
                    sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
                        memcpy(&request->response_msg, resp,
                               resp->msg_len);
+                       if (request->request_msg.ndis_msg_type ==
+                           RNDIS_MSG_QUERY && request->request_msg.msg.
+                           query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS)
+                               rndis_set_link_state(dev, request);
                } else {
                        netdev_err(ndev,
                                "rndis response buffer overflow "
@@ -620,7 +640,6 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev)
        ret = rndis_filter_query_device(dev,
                                      RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
                                      &link_status, &size);
-       dev->link_state = (link_status != 0) ? true : false;
 
        return ret;
 }
index ab31544bc25487ac82b1703beef9df6c069e615e..a30258aad139e9ae3491c92211a191f9aea42cc6 100644 (file)
@@ -546,12 +546,12 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
        int rc;
        unsigned long flags;
 
-       spin_lock(&lp->lock);
+       spin_lock_irqsave(&lp->lock, flags);
        if  (lp->irq_busy) {
-               spin_unlock(&lp->lock);
+               spin_unlock_irqrestore(&lp->lock, flags);
                return -EBUSY;
        }
-       spin_unlock(&lp->lock);
+       spin_unlock_irqrestore(&lp->lock, flags);
 
        might_sleep();
 
@@ -725,10 +725,11 @@ static void at86rf230_irqwork_level(struct work_struct *work)
 static irqreturn_t at86rf230_isr(int irq, void *data)
 {
        struct at86rf230_local *lp = data;
+       unsigned long flags;
 
-       spin_lock(&lp->lock);
+       spin_lock_irqsave(&lp->lock, flags);
        lp->irq_busy = 1;
-       spin_unlock(&lp->lock);
+       spin_unlock_irqrestore(&lp->lock, flags);
 
        schedule_work(&lp->irqwork);
 
index c14d39bf32d06a6f8d1b42a29b36dcd84b25c8f6..d7b2e947184b549a5034e4a54423ecde9050d721 100644 (file)
@@ -180,7 +180,8 @@ static void ifb_setup(struct net_device *dev)
        dev->tx_queue_len = TX_Q_LIMIT;
 
        dev->features |= IFB_FEATURES;
-       dev->vlan_features |= IFB_FEATURES;
+       dev->vlan_features |= IFB_FEATURES & ~(NETIF_F_HW_VLAN_CTAG_TX |
+                                              NETIF_F_HW_VLAN_STAG_TX);
 
        dev->flags |= IFF_NOARP;
        dev->flags &= ~IFF_MULTICAST;
index 2dc82f1d2e700be81f999d8922348dc05288c580..3da44d5d91497801a141b373c60f8cd5890a1bf9 100644 (file)
@@ -210,13 +210,6 @@ config KINGSUN_DONGLE
          To compile it as a module, choose M here: the module will be called
          kingsun-sir.
 
-config EP7211_DONGLE
-       tristate "Cirrus Logic clps711x I/R support"
-       depends on IRTTY_SIR && ARCH_CLPS711X && IRDA
-       help
-         Say Y here if you want to build support for the Cirrus logic
-         EP7211 chipset's infrared module.
-
 config KSDAZZLE_DONGLE
        tristate "KingSun Dazzle IrDA-USB dongle"
        depends on IRDA && USB
index dfc64537f62f939f537fe012382d562978348c6c..be8ab5b9a4a270eecaec815cdfaf3f03dfba9701 100644 (file)
@@ -35,7 +35,6 @@ obj-$(CONFIG_MCP2120_DONGLE)  += mcp2120-sir.o
 obj-$(CONFIG_ACT200L_DONGLE)   += act200l-sir.o
 obj-$(CONFIG_MA600_DONGLE)     += ma600-sir.o
 obj-$(CONFIG_TOIM3232_DONGLE)  += toim3232-sir.o
-obj-$(CONFIG_EP7211_DONGLE)    += ep7211-sir.o
 obj-$(CONFIG_KINGSUN_DONGLE)   += kingsun-sir.o
 obj-$(CONFIG_KSDAZZLE_DONGLE)  += ksdazzle-sir.o
 obj-$(CONFIG_KS959_DONGLE)     += ks959-sir.o
diff --git a/drivers/net/irda/ep7211-sir.c b/drivers/net/irda/ep7211-sir.c
deleted file mode 100644 (file)
index 5fe1f4d..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * IR port driver for the Cirrus Logic CLPS711X processors
- *
- * Copyright 2001, Blue Mug Inc.  All rights reserved.
- * Copyright 2007, Samuel Ortiz <samuel@sortiz.org>
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <mach/hardware.h>
-
-#include "sir-dev.h"
-
-static int clps711x_dongle_open(struct sir_dev *dev)
-{
-       unsigned int syscon;
-
-       /* Turn on the SIR encoder. */
-       syscon = clps_readl(SYSCON1);
-       syscon |= SYSCON1_SIREN;
-       clps_writel(syscon, SYSCON1);
-
-       return 0;
-}
-
-static int clps711x_dongle_close(struct sir_dev *dev)
-{
-       unsigned int syscon;
-
-       /* Turn off the SIR encoder. */
-       syscon = clps_readl(SYSCON1);
-       syscon &= ~SYSCON1_SIREN;
-       clps_writel(syscon, SYSCON1);
-
-       return 0;
-}
-
-static struct dongle_driver clps711x_dongle = {
-       .owner          = THIS_MODULE,
-       .driver_name    = "EP7211 IR driver",
-       .type           = IRDA_EP7211_DONGLE,
-       .open           = clps711x_dongle_open,
-       .close          = clps711x_dongle_close,
-};
-
-static int clps711x_sir_probe(struct platform_device *pdev)
-{
-       return irda_register_dongle(&clps711x_dongle);
-}
-
-static int clps711x_sir_remove(struct platform_device *pdev)
-{
-       return irda_unregister_dongle(&clps711x_dongle);
-}
-
-static struct platform_driver clps711x_sir_driver = {
-       .driver = {
-               .name   = "sir-clps711x",
-               .owner  = THIS_MODULE,
-       },
-       .probe  = clps711x_sir_probe,
-       .remove = clps711x_sir_remove,
-};
-module_platform_driver(clps711x_sir_driver);
-
-MODULE_AUTHOR("Samuel Ortiz <samuel@sortiz.org>");
-MODULE_DESCRIPTION("EP7211 IR dongle driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("irda-dongle-13"); /* IRDA_EP7211_DONGLE */
index 177441afeb9680de599905bf75e8c1e10a9c7e0b..24b6dddd7f2f58445af7d0c5af47d399c31ac799 100644 (file)
@@ -522,7 +522,6 @@ static void irtty_close(struct tty_struct *tty)
        sirdev_put_instance(priv->dev);
 
        /* Stop tty */
-       irtty_stop_receiver(tty, TRUE);
        clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
        if (tty->ops->stop)
                tty->ops->stop(tty);
index 8433de4509c75a35cb65e7abdacb4f8968cb4008..1831fb7cd0174d9afd6696bf029d37a657b07222 100644 (file)
@@ -506,6 +506,9 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
 static struct lock_class_key macvlan_netdev_xmit_lock_key;
 static struct lock_class_key macvlan_netdev_addr_lock_key;
 
+#define ALWAYS_ON_FEATURES \
+       (NETIF_F_SG | NETIF_F_GEN_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX)
+
 #define MACVLAN_FEATURES \
        (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
         NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
@@ -539,7 +542,7 @@ static int macvlan_init(struct net_device *dev)
        dev->state              = (dev->state & ~MACVLAN_STATE_MASK) |
                                  (lowerdev->state & MACVLAN_STATE_MASK);
        dev->features           = lowerdev->features & MACVLAN_FEATURES;
-       dev->features           |= NETIF_F_LLTX;
+       dev->features           |= ALWAYS_ON_FEATURES;
        dev->gso_max_size       = lowerdev->gso_max_size;
        dev->iflink             = lowerdev->ifindex;
        dev->hard_header_len    = lowerdev->hard_header_len;
@@ -699,7 +702,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
        features = netdev_increment_features(vlan->lowerdev->features,
                                             features,
                                             mask);
-       features |= NETIF_F_LLTX;
+       features |= ALWAYS_ON_FEATURES;
 
        return features;
 }
@@ -879,14 +882,15 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        dev->priv_flags |= IFF_MACVLAN;
        err = netdev_upper_dev_link(lowerdev, dev);
        if (err)
-               goto destroy_port;
-
+               goto unregister_netdev;
 
        list_add_tail_rcu(&vlan->list, &port->vlans);
        netif_stacked_transfer_operstate(lowerdev, dev);
 
        return 0;
 
+unregister_netdev:
+       unregister_netdevice(dev);
 destroy_port:
        port->count -= 1;
        if (!port->count)
index 547725fa8671f5174f0ddbd0160a66ccc4144cac..98e7cbf720a5859b8639ebe0653c6ccfd9c51f02 100644 (file)
@@ -437,7 +437,10 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp,
                if (on) {
                        gpio_num = gpio_tab[EXTTS0_GPIO + index];
                        evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT;
-                       evnt |= EVNT_RISE;
+                       if (rq->extts.flags & PTP_FALLING_EDGE)
+                               evnt |= EVNT_FALL;
+                       else
+                               evnt |= EVNT_RISE;
                }
                ext_write(0, phydev, PAGE5, PTP_EVNT, evnt);
                return 0;
@@ -1003,11 +1006,6 @@ static int dp83640_probe(struct phy_device *phydev)
        } else
                list_add_tail(&dp83640->list, &clock->phylist);
 
-       if (clock->chosen && !list_empty(&clock->phylist))
-               recalibrate(clock);
-       else
-               enable_broadcast(dp83640->phydev, clock->page, 1);
-
        dp83640_clock_put(clock);
        return 0;
 
@@ -1058,6 +1056,21 @@ static void dp83640_remove(struct phy_device *phydev)
        kfree(dp83640);
 }
 
+static int dp83640_config_init(struct phy_device *phydev)
+{
+       struct dp83640_private *dp83640 = phydev->priv;
+       struct dp83640_clock *clock = dp83640->clock;
+
+       if (clock->chosen && !list_empty(&clock->phylist))
+               recalibrate(clock);
+       else
+               enable_broadcast(phydev, clock->page, 1);
+
+       enable_status_frames(phydev, true);
+       ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
+       return 0;
+}
+
 static int dp83640_ack_interrupt(struct phy_device *phydev)
 {
        int err = phy_read(phydev, MII_DP83640_MISR);
@@ -1195,11 +1208,6 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
 
        mutex_lock(&dp83640->clock->extreg_lock);
 
-       if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) {
-               enable_status_frames(phydev, true);
-               ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE);
-       }
-
        ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0);
        ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0);
 
@@ -1281,6 +1289,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
                }
                /* fall through */
        case HWTSTAMP_TX_ON:
+               skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                skb_queue_tail(&dp83640->tx_queue, skb);
                schedule_work(&dp83640->ts_work);
                break;
@@ -1330,6 +1339,7 @@ static struct phy_driver dp83640_driver = {
        .flags          = PHY_HAS_INTERRUPT,
        .probe          = dp83640_probe,
        .remove         = dp83640_remove,
+       .config_init    = dp83640_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
        .ack_interrupt  = dp83640_ack_interrupt,
index bb88bc7d81fb28436f7ee4094580a32e620ee705..9367acc84fbb2e54f3d058864d820bf8974d21c7 100644 (file)
@@ -170,6 +170,9 @@ static int sun4i_mdio_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id sun4i_mdio_dt_ids[] = {
+       { .compatible = "allwinner,sun4i-a10-mdio" },
+
+       /* Deprecated */
        { .compatible = "allwinner,sun4i-mdio" },
        { }
 };
index 19c9eca0ef2638165dc9dc087d87aee934d28348..76d96b9ebcdb94d2e57c3f52d5b49a41e7397ab4 100644 (file)
@@ -164,9 +164,9 @@ static const struct phy_setting settings[] = {
  *   of that setting.  Returns the index of the last setting if
  *   none of the others match.
  */
-static inline int phy_find_setting(int speed, int duplex)
+static inline unsigned int phy_find_setting(int speed, int duplex)
 {
-       int idx = 0;
+       unsigned int idx = 0;
 
        while (idx < ARRAY_SIZE(settings) &&
               (settings[idx].speed != speed || settings[idx].duplex != duplex))
@@ -185,7 +185,7 @@ static inline int phy_find_setting(int speed, int duplex)
  *   the mask in features.  Returns the index of the last setting
  *   if nothing else matches.
  */
-static inline int phy_find_valid(int idx, u32 features)
+static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
 {
        while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
                idx++;
@@ -204,7 +204,7 @@ static inline int phy_find_valid(int idx, u32 features)
 static void phy_sanitize_settings(struct phy_device *phydev)
 {
        u32 features = phydev->supported;
-       int idx;
+       unsigned int idx;
 
        /* Sanitize settings based on PHY capabilities */
        if ((features & SUPPORTED_Autoneg) == 0)
@@ -954,7 +954,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
            (phydev->interface == PHY_INTERFACE_MODE_RGMII))) {
                int eee_lp, eee_cap, eee_adv;
                u32 lp, cap, adv;
-               int idx, status;
+               int status;
+               unsigned int idx;
 
                /* Read phy status to properly get the right settings */
                status = phy_read_status(phydev);
index 4b03e63639b74e8fbac760ec2cd701940ad50686..2f6989b1e0dc801c9adea4d5e145a5dcf4d8ad26 100644 (file)
@@ -683,10 +683,9 @@ EXPORT_SYMBOL(phy_detach);
 int phy_suspend(struct phy_device *phydev)
 {
        struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
-       struct ethtool_wolinfo wol;
+       struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
 
        /* If the device has WOL enabled, we cannot suspend the PHY */
-       wol.cmd = ETHTOOL_GWOL;
        phy_ethtool_get_wol(phydev, &wol);
        if (wol.wolopts)
                return -EBUSY;
@@ -719,7 +718,7 @@ int phy_resume(struct phy_device *phydev)
 static int genphy_config_advert(struct phy_device *phydev)
 {
        u32 advertise;
-       int oldadv, adv;
+       int oldadv, adv, bmsr;
        int err, changed = 0;
 
        /* Only allow advertising what this PHY supports */
@@ -744,26 +743,36 @@ static int genphy_config_advert(struct phy_device *phydev)
                changed = 1;
        }
 
+       bmsr = phy_read(phydev, MII_BMSR);
+       if (bmsr < 0)
+               return bmsr;
+
+       /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all
+        * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a
+        * logical 1.
+        */
+       if (!(bmsr & BMSR_ESTATEN))
+               return changed;
+
        /* Configure gigabit if it's supported */
+       adv = phy_read(phydev, MII_CTRL1000);
+       if (adv < 0)
+               return adv;
+
+       oldadv = adv;
+       adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+
        if (phydev->supported & (SUPPORTED_1000baseT_Half |
                                 SUPPORTED_1000baseT_Full)) {
-               adv = phy_read(phydev, MII_CTRL1000);
-               if (adv < 0)
-                       return adv;
-
-               oldadv = adv;
-               adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
                adv |= ethtool_adv_to_mii_ctrl1000_t(advertise);
-
-               if (adv != oldadv) {
-                       err = phy_write(phydev, MII_CTRL1000, adv);
-
-                       if (err < 0)
-                               return err;
+               if (adv != oldadv)
                        changed = 1;
-               }
        }
 
+       err = phy_write(phydev, MII_CTRL1000, adv);
+       if (err < 0)
+               return err;
+
        return changed;
 }
 
@@ -906,6 +915,8 @@ int genphy_read_status(struct phy_device *phydev)
        int err;
        int lpa;
        int lpagb = 0;
+       int common_adv;
+       int common_adv_gb = 0;
 
        /* Update the link, but return if there was an error */
        err = genphy_update_link(phydev);
@@ -927,7 +938,7 @@ int genphy_read_status(struct phy_device *phydev)
 
                        phydev->lp_advertising =
                                mii_stat1000_to_ethtool_lpa_t(lpagb);
-                       lpagb &= adv << 2;
+                       common_adv_gb = lpagb & adv << 2;
                }
 
                lpa = phy_read(phydev, MII_LPA);
@@ -940,25 +951,25 @@ int genphy_read_status(struct phy_device *phydev)
                if (adv < 0)
                        return adv;
 
-               lpa &= adv;
+               common_adv = lpa & adv;
 
                phydev->speed = SPEED_10;
                phydev->duplex = DUPLEX_HALF;
                phydev->pause = 0;
                phydev->asym_pause = 0;
 
-               if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
+               if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
                        phydev->speed = SPEED_1000;
 
-                       if (lpagb & LPA_1000FULL)
+                       if (common_adv_gb & LPA_1000FULL)
                                phydev->duplex = DUPLEX_FULL;
-               } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+               } else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
                        phydev->speed = SPEED_100;
 
-                       if (lpa & LPA_100FULL)
+                       if (common_adv & LPA_100FULL)
                                phydev->duplex = DUPLEX_FULL;
                } else
-                       if (lpa & LPA_10FULL)
+                       if (common_adv & LPA_10FULL)
                                phydev->duplex = DUPLEX_FULL;
 
                if (phydev->duplex == DUPLEX_FULL) {
index 28407426fd6fdbc7dc0e21eb83c8acaba380065b..c8624a8235ab2f1020c4c387be290b631ed1b0dc 100644 (file)
@@ -1648,7 +1648,7 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
-                            void *accel_priv)
+                            void *accel_priv, select_queue_fallback_t fallback)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 44c4db8450f0347b4ea6ce861da7f05524ebdb5d..26f8635b027d3fb44ab12223000badc214098df0 100644 (file)
@@ -366,7 +366,7 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash)
  * hope the rxq no. may help here.
  */
 static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
-                           void *accel_priv)
+                           void *accel_priv, select_queue_fallback_t fallback)
 {
        struct tun_struct *tun = netdev_priv(dev);
        struct tun_flow_entry *e;
@@ -1686,7 +1686,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                                   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
                                   NETIF_F_HW_VLAN_STAG_TX;
                dev->features = dev->hw_features;
-               dev->vlan_features = dev->features;
+               dev->vlan_features = dev->features &
+                                    ~(NETIF_F_HW_VLAN_CTAG_TX |
+                                      NETIF_F_HW_VLAN_STAG_TX);
 
                INIT_LIST_HEAD(&tun->disabled);
                err = tun_attach(tun, file, false);
index 6b638a066c1d33edfa9082fde204d7da16898aa8..7e7269fd3707728d16705fc27c93c2f7a45b666f 100644 (file)
@@ -292,6 +292,21 @@ config USB_NET_SR9700
          This option adds support for CoreChip-sz SR9700 based USB 1.1
          10/100 Ethernet adapters.
 
+config USB_NET_SR9800
+       tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices"
+       depends on USB_USBNET
+       select CRC32
+       ---help---
+         Say Y if you want to use one of the following 100Mbps USB Ethernet
+         device based on the CoreChip-sz SR9800 chip.
+
+         This driver makes the adapter appear as a normal Ethernet interface,
+         typically on eth0, if it is the only ethernet device, or perhaps on
+         eth1, if you have a PCI or ISA ethernet card installed.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sr9800.
+
 config USB_NET_SMSC75XX
        tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
        depends on USB_USBNET
index b17b5e88bbaf71acc06640a0f3fe6967b53ff2ab..e2797f1e1b31ee51f82c11d50b23e6bd274d29ab 100644 (file)
@@ -11,10 +11,11 @@ obj-$(CONFIG_USB_HSO)               += hso.o
 obj-$(CONFIG_USB_NET_AX8817X)  += asix.o
 asix-y := asix_devices.o asix_common.o ax88172a.o
 obj-$(CONFIG_USB_NET_AX88179_178A)      += ax88179_178a.o
-obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o
+obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
 obj-$(CONFIG_USB_NET_CDC_EEM)  += cdc_eem.o
 obj-$(CONFIG_USB_NET_DM9601)   += dm9601.o
 obj-$(CONFIG_USB_NET_SR9700)   += sr9700.o
+obj-$(CONFIG_USB_NET_SR9800)   += sr9800.o
 obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o
 obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
 obj-$(CONFIG_USB_NET_GL620A)   += gl620a.o
index 9765a7d4766dcd4a717bd7cd0bea56c71953deb1..5d194093f3e1f3b3c1893faf0cf8ebb266facdad 100644 (file)
@@ -917,7 +917,8 @@ static const struct driver_info ax88178_info = {
        .status = asix_status,
        .link_reset = ax88178_link_reset,
        .reset = ax88178_reset,
-       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
+                FLAG_MULTI_PACKET,
        .rx_fixup = asix_rx_fixup_common,
        .tx_fixup = asix_tx_fixup,
 };
index d6f64dad05bcb707c0c26dbe2886abd73e760db1..054e59ca6946446389cd22eb1e851a6b4fad6633 100644 (file)
@@ -1029,20 +1029,12 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->mii.phy_id = 0x03;
        dev->mii.supports_gmii = 1;
 
-       if (usb_device_no_sg_constraint(dev->udev))
-               dev->can_dma_sg = 1;
-
        dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                              NETIF_F_RXCSUM;
 
        dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                                 NETIF_F_RXCSUM;
 
-       if (dev->can_dma_sg) {
-               dev->net->features |= NETIF_F_SG | NETIF_F_TSO;
-               dev->net->hw_features |= NETIF_F_SG | NETIF_F_TSO;
-       }
-
        /* Enable checksum offload */
        *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
               AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6;
@@ -1118,6 +1110,10 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        u16 hdr_off;
        u32 *pkt_hdr;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        skb_trim(skb, skb->len - 4);
        memcpy(&rx_hdr, skb_tail_pointer(skb), 4);
        le32_to_cpus(&rx_hdr);
@@ -1391,6 +1387,19 @@ static const struct driver_info ax88178a_info = {
        .tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info dlink_dub1312_info = {
+       .description = "D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter",
+       .bind = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct driver_info sitecom_info = {
        .description = "Sitecom USB 3.0 to Gigabit Adapter",
        .bind = ax88179_bind,
@@ -1417,6 +1426,19 @@ static const struct driver_info samsung_info = {
        .tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info lenovo_info = {
+       .description = "Lenovo OneLinkDock Gigabit LAN",
+       .bind = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset = ax88179_reset,
+       .stop = ax88179_stop,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct usb_device_id products[] = {
 {
        /* ASIX AX88179 10/100/1000 */
@@ -1426,6 +1448,10 @@ static const struct usb_device_id products[] = {
        /* ASIX AX88178A 10/100/1000 */
        USB_DEVICE(0x0b95, 0x178a),
        .driver_info = (unsigned long)&ax88178a_info,
+}, {
+       /* D-Link DUB-1312 USB 3.0 to Gigabit Ethernet Adapter */
+       USB_DEVICE(0x2001, 0x4a00),
+       .driver_info = (unsigned long)&dlink_dub1312_info,
 }, {
        /* Sitecom USB 3.0 to Gigabit Adapter */
        USB_DEVICE(0x0df6, 0x0072),
@@ -1434,6 +1460,10 @@ static const struct usb_device_id products[] = {
        /* Samsung USB Ethernet Adapter */
        USB_DEVICE(0x04e8, 0xa100),
        .driver_info = (unsigned long)&samsung_info,
+}, {
+       /* Lenovo OneLinkDock Gigabit LAN */
+       USB_DEVICE(0x17ef, 0x304b),
+       .driver_info = (unsigned long)&lenovo_info,
 },
        { },
 };
index 42e176912c8ea151606883c0b8563e45fa95a447..bd363b27e8540e3bfe2acc6173adcc8a1952f4b7 100644 (file)
@@ -652,6 +652,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* Samsung USB Ethernet Adapters */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, 0xa101, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
index dbff290ed0e4f5ac4752efbe56eeea0fda0c419f..d350d2795e1029cc71f197b2ca863586942d4d3f 100644 (file)
@@ -68,7 +68,6 @@ static struct usb_driver cdc_ncm_driver;
 static int cdc_ncm_setup(struct usbnet *dev)
 {
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
-       struct usb_cdc_ncm_ntb_parameters ncm_parm;
        u32 val;
        u8 flags;
        u8 iface_no;
@@ -82,22 +81,22 @@ static int cdc_ncm_setup(struct usbnet *dev)
        err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS,
                              USB_TYPE_CLASS | USB_DIR_IN
                              |USB_RECIP_INTERFACE,
-                             0, iface_no, &ncm_parm,
-                             sizeof(ncm_parm));
+                             0, iface_no, &ctx->ncm_parm,
+                             sizeof(ctx->ncm_parm));
        if (err < 0) {
                dev_err(&dev->intf->dev, "failed GET_NTB_PARAMETERS\n");
                return err; /* GET_NTB_PARAMETERS is required */
        }
 
        /* read correct set of parameters according to device mode */
-       ctx->rx_max = le32_to_cpu(ncm_parm.dwNtbInMaxSize);
-       ctx->tx_max = le32_to_cpu(ncm_parm.dwNtbOutMaxSize);
-       ctx->tx_remainder = le16_to_cpu(ncm_parm.wNdpOutPayloadRemainder);
-       ctx->tx_modulus = le16_to_cpu(ncm_parm.wNdpOutDivisor);
-       ctx->tx_ndp_modulus = le16_to_cpu(ncm_parm.wNdpOutAlignment);
+       ctx->rx_max = le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize);
+       ctx->tx_max = le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize);
+       ctx->tx_remainder = le16_to_cpu(ctx->ncm_parm.wNdpOutPayloadRemainder);
+       ctx->tx_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutDivisor);
+       ctx->tx_ndp_modulus = le16_to_cpu(ctx->ncm_parm.wNdpOutAlignment);
        /* devices prior to NCM Errata shall set this field to zero */
-       ctx->tx_max_datagrams = le16_to_cpu(ncm_parm.wNtbOutMaxDatagrams);
-       ntb_fmt_supported = le16_to_cpu(ncm_parm.bmNtbFormatsSupported);
+       ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
+       ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
 
        /* there are some minor differences in NCM and MBIM defaults */
        if (cdc_ncm_comm_intf_is_mbim(ctx->control->cur_altsetting)) {
@@ -146,7 +145,7 @@ static int cdc_ncm_setup(struct usbnet *dev)
        }
 
        /* inform device about NTB input size changes */
-       if (ctx->rx_max != le32_to_cpu(ncm_parm.dwNtbInMaxSize)) {
+       if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
                __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
 
                err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE,
@@ -162,14 +161,6 @@ static int cdc_ncm_setup(struct usbnet *dev)
                dev_dbg(&dev->intf->dev, "Using default maximum transmit length=%d\n",
                        CDC_NCM_NTB_MAX_SIZE_TX);
                ctx->tx_max = CDC_NCM_NTB_MAX_SIZE_TX;
-
-               /* Adding a pad byte here simplifies the handling in
-                * cdc_ncm_fill_tx_frame, by making tx_max always
-                * represent the real skb max size.
-                */
-               if (ctx->tx_max % usb_maxpacket(dev->udev, dev->out, 1) == 0)
-                       ctx->tx_max++;
-
        }
 
        /*
@@ -439,6 +430,10 @@ advance:
                goto error2;
        }
 
+       /* initialize data interface */
+       if (cdc_ncm_setup(dev))
+               goto error2;
+
        /* configure data interface */
        temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
        if (temp) {
@@ -453,12 +448,6 @@ advance:
                goto error2;
        }
 
-       /* initialize data interface */
-       if (cdc_ncm_setup(dev)) {
-               dev_dbg(&intf->dev, "cdc_ncm_setup() failed\n");
-               goto error2;
-       }
-
        usb_set_intfdata(ctx->data, dev);
        usb_set_intfdata(ctx->control, dev);
 
@@ -475,6 +464,15 @@ advance:
        dev->hard_mtu = ctx->tx_max;
        dev->rx_urb_size = ctx->rx_max;
 
+       /* cdc_ncm_setup will override dwNtbOutMaxSize if it is
+        * outside the sane range. Adding a pad byte here if necessary
+        * simplifies the handling in cdc_ncm_fill_tx_frame, making
+        * tx_max always represent the real skb max size.
+        */
+       if (ctx->tx_max != le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) &&
+           ctx->tx_max % usb_maxpacket(dev->udev, dev->out, 1) == 0)
+               ctx->tx_max++;
+
        return 0;
 
 error2:
index e4a8a93fbaf7eec07ca3af2d2c813c08609b9c12..1cc24e6f23e2528150a3e9a660e134732e5cd988 100644 (file)
@@ -84,6 +84,10 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        u32                     size;
        u32                     count;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        header = (struct gl_header *) skb->data;
 
        // get the packet count of the received skb
index 1a482344b3f507e97486059d56280dfd3f23d37c..660bd5ea9fc0b311918812af8d3959c830b96cf4 100644 (file)
@@ -1201,16 +1201,18 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb)
        struct hso_serial *serial = urb->context;
        int status = urb->status;
 
+       D4("\n--- Got serial_read_bulk callback %02x ---", status);
+
        /* sanity check */
        if (!serial) {
                D1("serial == NULL");
                return;
-       } else if (status) {
+       }
+       if (status) {
                handle_usb_error(status, __func__, serial->parent);
                return;
        }
 
-       D4("\n--- Got serial_read_bulk callback %02x ---", status);
        D1("Actual length = %d\n", urb->actual_length);
        DUMP1(urb->transfer_buffer, urb->actual_length);
 
@@ -1218,25 +1220,13 @@ static void hso_std_serial_read_bulk_callback(struct urb *urb)
        if (serial->port.count == 0)
                return;
 
-       if (status == 0) {
-               if (serial->parent->port_spec & HSO_INFO_CRC_BUG)
-                       fix_crc_bug(urb, serial->in_endp->wMaxPacketSize);
-               /* Valid data, handle RX data */
-               spin_lock(&serial->serial_lock);
-               serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
-               put_rxbuf_data_and_resubmit_bulk_urb(serial);
-               spin_unlock(&serial->serial_lock);
-       } else if (status == -ENOENT || status == -ECONNRESET) {
-               /* Unlinked - check for throttled port. */
-               D2("Port %d, successfully unlinked urb", serial->minor);
-               spin_lock(&serial->serial_lock);
-               serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
-               hso_resubmit_rx_bulk_urb(serial, urb);
-               spin_unlock(&serial->serial_lock);
-       } else {
-               D2("Port %d, status = %d for read urb", serial->minor, status);
-               return;
-       }
+       if (serial->parent->port_spec & HSO_INFO_CRC_BUG)
+               fix_crc_bug(urb, serial->in_endp->wMaxPacketSize);
+       /* Valid data, handle RX data */
+       spin_lock(&serial->serial_lock);
+       serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 1;
+       put_rxbuf_data_and_resubmit_bulk_urb(serial);
+       spin_unlock(&serial->serial_lock);
 }
 
 /*
index a305a7b2dae6f85ce4877a2f38e7d413688d5b1c..82d844a8ebd093e79c26ada9fc728fec8b10576e 100644 (file)
@@ -526,8 +526,9 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
        u8 status;
 
-       if (skb->len == 0) {
-               dev_err(&dev->udev->dev, "unexpected empty rx frame\n");
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len) {
+               dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
                return 0;
        }
 
index 0a85d92277750d061300f269b19f6c4be54dbe07..4cbdb1307f3e2ed0ad850a5ab076f80aaee26ce5 100644 (file)
@@ -364,6 +364,10 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        struct nc_trailer       *trailer;
        u16                     hdr_len, packet_len;
 
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        if (!(skb->len & 0x01)) {
                netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n",
                           skb->len, dev->net->hard_header_len, dev->hard_mtu,
index 23bdd5b9274ddb6becb5eabad2d4709b7b2a732d..313cb6cd4848e033bab664788c24c0a88ce55996 100644 (file)
@@ -80,10 +80,10 @@ static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
        __be16 proto;
 
-       /* usbnet rx_complete guarantees that skb->len is at least
-        * hard_header_len, so we can inspect the dest address without
-        * checking skb->len
-        */
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        switch (skb->data[0] & 0xf0) {
        case 0x40:
                proto = htons(ETH_P_IP);
@@ -712,6 +712,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x19d2, 0x1255, 3)},
        {QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1270, 5)},    /* ZTE MF667 */
        {QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
        {QMI_FIXED_INTF(0x19d2, 0x1402, 2)},    /* ZTE MF60 */
        {QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
@@ -723,6 +724,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 19)},   /* Sierra Wireless MC7710 in QMI mode */
        {QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
+       {QMI_FIXED_INTF(0x1199, 0x9051, 8)},    /* Netgear AirCard 340U */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
        {QMI_FIXED_INTF(0x2357, 0x9000, 4)},    /* TP-LINK MA260 */
@@ -730,6 +732,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)},    /* Telit LE920 */
        {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)},    /* Olivetti Olicard 200 */
        {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},    /* Cinterion PLxx */
+       {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)},    /* Cinterion PHxx,PXxx */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index e8fac732c6f1c9792124983adedf613253f70cfa..adb12f349a61fc58582d2092c49db5a9ceb7b7cf 100644 (file)
@@ -449,9 +449,6 @@ enum rtl8152_flags {
 #define MCU_TYPE_PLA                   0x0100
 #define MCU_TYPE_USB                   0x0000
 
-#define REALTEK_USB_DEVICE(vend, prod) \
-       USB_DEVICE_INTERFACE_CLASS(vend, prod, USB_CLASS_VENDOR_SPEC)
-
 struct rx_desc {
        __le32 opts1;
 #define RX_LEN_MASK                    0x7fff
@@ -2273,22 +2270,21 @@ static int rtl8152_open(struct net_device *netdev)
        struct r8152 *tp = netdev_priv(netdev);
        int res = 0;
 
+       rtl8152_set_speed(tp, AUTONEG_ENABLE,
+                         tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
+                         DUPLEX_FULL);
+       tp->speed = 0;
+       netif_carrier_off(netdev);
+       netif_start_queue(netdev);
+       set_bit(WORK_ENABLE, &tp->flags);
        res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
        if (res) {
                if (res == -ENODEV)
                        netif_device_detach(tp->netdev);
                netif_warn(tp, ifup, netdev, "intr_urb submit failed: %d\n",
                           res);
-               return res;
        }
 
-       rtl8152_set_speed(tp, AUTONEG_ENABLE,
-                         tp->mii.supports_gmii ? SPEED_1000 : SPEED_100,
-                         DUPLEX_FULL);
-       tp->speed = 0;
-       netif_carrier_off(netdev);
-       netif_start_queue(netdev);
-       set_bit(WORK_ENABLE, &tp->flags);
 
        return res;
 }
@@ -2298,8 +2294,8 @@ static int rtl8152_close(struct net_device *netdev)
        struct r8152 *tp = netdev_priv(netdev);
        int res = 0;
 
-       usb_kill_urb(tp->intr_urb);
        clear_bit(WORK_ENABLE, &tp->flags);
+       usb_kill_urb(tp->intr_urb);
        cancel_delayed_work_sync(&tp->schedule);
        netif_stop_queue(netdev);
        tasklet_disable(&tp->tl);
@@ -2740,6 +2736,12 @@ static int rtl8152_probe(struct usb_interface *intf,
        struct net_device *netdev;
        int ret;
 
+       if (udev->actconfig->desc.bConfigurationValue != 1) {
+               usb_driver_set_configuration(udev, 1);
+               return -ENODEV;
+       }
+
+       usb_reset_device(udev);
        netdev = alloc_etherdev(sizeof(struct r8152));
        if (!netdev) {
                dev_err(&intf->dev, "Out of memory\n");
@@ -2820,9 +2822,9 @@ static void rtl8152_disconnect(struct usb_interface *intf)
 
 /* table of devices that work with this driver */
 static struct usb_device_id rtl8152_table[] = {
-       {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)},
-       {REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)},
-       {REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)},
+       {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8152)},
+       {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8153)},
+       {USB_DEVICE(VENDOR_ID_SAMSUNG, PRODUCT_ID_SAMSUNG)},
        {}
 };
 
diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c
deleted file mode 100644 (file)
index f0a8791..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/mii.h>
-#include <linux/usb.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/usbnet.h>
-
-#define RTL815x_REQT_READ      0xc0
-#define RTL815x_REQT_WRITE     0x40
-#define RTL815x_REQ_GET_REGS   0x05
-#define RTL815x_REQ_SET_REGS   0x05
-
-#define MCU_TYPE_PLA           0x0100
-#define OCP_BASE               0xe86c
-#define BASE_MII               0xa400
-
-#define BYTE_EN_DWORD          0xff
-#define BYTE_EN_WORD           0x33
-#define BYTE_EN_BYTE           0x11
-
-#define R815x_PHY_ID           32
-#define REALTEK_VENDOR_ID      0x0bda
-
-
-static int pla_read_word(struct usb_device *udev, u16 index)
-{
-       int ret;
-       u8 shift = index & 2;
-       __le32 *tmp;
-
-       tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-       if (!tmp)
-               return -ENOMEM;
-
-       index &= ~3;
-
-       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                             RTL815x_REQ_GET_REGS, RTL815x_REQT_READ,
-                             index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500);
-       if (ret < 0)
-               goto out2;
-
-       ret = __le32_to_cpu(*tmp);
-       ret >>= (shift * 8);
-       ret &= 0xffff;
-
-out2:
-       kfree(tmp);
-       return ret;
-}
-
-static int pla_write_word(struct usb_device *udev, u16 index, u32 data)
-{
-       __le32 *tmp;
-       u32 mask = 0xffff;
-       u16 byen = BYTE_EN_WORD;
-       u8 shift = index & 2;
-       int ret;
-
-       tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-       if (!tmp)
-               return -ENOMEM;
-
-       data &= mask;
-
-       if (shift) {
-               byen <<= shift;
-               mask <<= (shift * 8);
-               data <<= (shift * 8);
-               index &= ~3;
-       }
-
-       ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                             RTL815x_REQ_GET_REGS, RTL815x_REQT_READ,
-                             index, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500);
-       if (ret < 0)
-               goto out3;
-
-       data |= __le32_to_cpu(*tmp) & ~mask;
-       *tmp = __cpu_to_le32(data);
-
-       ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                             RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE,
-                             index, MCU_TYPE_PLA | byen, tmp, sizeof(*tmp),
-                             500);
-
-out3:
-       kfree(tmp);
-       return ret;
-}
-
-static int ocp_reg_read(struct usbnet *dev, u16 addr)
-{
-       u16 ocp_base, ocp_index;
-       int ret;
-
-       ocp_base = addr & 0xf000;
-       ret = pla_write_word(dev->udev, OCP_BASE, ocp_base);
-       if (ret < 0)
-               goto out;
-
-       ocp_index = (addr & 0x0fff) | 0xb000;
-       ret = pla_read_word(dev->udev, ocp_index);
-
-out:
-       return ret;
-}
-
-static int ocp_reg_write(struct usbnet *dev, u16 addr, u16 data)
-{
-       u16 ocp_base, ocp_index;
-       int ret;
-
-       ocp_base = addr & 0xf000;
-       ret = pla_write_word(dev->udev, OCP_BASE, ocp_base);
-       if (ret < 0)
-               goto out1;
-
-       ocp_index = (addr & 0x0fff) | 0xb000;
-       ret = pla_write_word(dev->udev, ocp_index, data);
-
-out1:
-       return ret;
-}
-
-static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg)
-{
-       struct usbnet *dev = netdev_priv(netdev);
-       int ret;
-
-       if (phy_id != R815x_PHY_ID)
-               return -EINVAL;
-
-       if (usb_autopm_get_interface(dev->intf) < 0)
-               return -ENODEV;
-
-       ret = ocp_reg_read(dev, BASE_MII + reg * 2);
-
-       usb_autopm_put_interface(dev->intf);
-       return ret;
-}
-
-static
-void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val)
-{
-       struct usbnet *dev = netdev_priv(netdev);
-
-       if (phy_id != R815x_PHY_ID)
-               return;
-
-       if (usb_autopm_get_interface(dev->intf) < 0)
-               return;
-
-       ocp_reg_write(dev, BASE_MII + reg * 2, val);
-
-       usb_autopm_put_interface(dev->intf);
-}
-
-static int r8153_bind(struct usbnet *dev, struct usb_interface *intf)
-{
-       int status;
-
-       status = usbnet_cdc_bind(dev, intf);
-       if (status < 0)
-               return status;
-
-       dev->mii.dev = dev->net;
-       dev->mii.mdio_read = r815x_mdio_read;
-       dev->mii.mdio_write = r815x_mdio_write;
-       dev->mii.phy_id_mask = 0x3f;
-       dev->mii.reg_num_mask = 0x1f;
-       dev->mii.phy_id = R815x_PHY_ID;
-       dev->mii.supports_gmii = 1;
-
-       return status;
-}
-
-static int r8152_bind(struct usbnet *dev, struct usb_interface *intf)
-{
-       int status;
-
-       status = usbnet_cdc_bind(dev, intf);
-       if (status < 0)
-               return status;
-
-       dev->mii.dev = dev->net;
-       dev->mii.mdio_read = r815x_mdio_read;
-       dev->mii.mdio_write = r815x_mdio_write;
-       dev->mii.phy_id_mask = 0x3f;
-       dev->mii.reg_num_mask = 0x1f;
-       dev->mii.phy_id = R815x_PHY_ID;
-       dev->mii.supports_gmii = 0;
-
-       return status;
-}
-
-static const struct driver_info r8152_info = {
-       .description =  "RTL8152 ECM Device",
-       .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
-       .bind =         r8152_bind,
-       .unbind =       usbnet_cdc_unbind,
-       .status =       usbnet_cdc_status,
-       .manage_power = usbnet_manage_power,
-};
-
-static const struct driver_info r8153_info = {
-       .description =  "RTL8153 ECM Device",
-       .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
-       .bind =         r8153_bind,
-       .unbind =       usbnet_cdc_unbind,
-       .status =       usbnet_cdc_status,
-       .manage_power = usbnet_manage_power,
-};
-
-static const struct usb_device_id products[] = {
-{
-       USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM,
-                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-       .driver_info = (unsigned long) &r8152_info,
-},
-
-{
-       USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM,
-                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-       .driver_info = (unsigned long) &r8153_info,
-},
-
-       { },            /* END */
-};
-MODULE_DEVICE_TABLE(usb, products);
-
-static struct usb_driver r815x_driver = {
-       .name =         "r815x",
-       .id_table =     products,
-       .probe =        usbnet_probe,
-       .disconnect =   usbnet_disconnect,
-       .suspend =      usbnet_suspend,
-       .resume =       usbnet_resume,
-       .reset_resume = usbnet_resume,
-       .supports_autosuspend = 1,
-       .disable_hub_initiated_lpm = 1,
-};
-
-module_usb_driver(r815x_driver);
-
-MODULE_AUTHOR("Hayes Wang");
-MODULE_DESCRIPTION("Realtek USB ECM device");
-MODULE_LICENSE("GPL");
index a48bc0f20c1a860a66299d00391381cf58972b95..524a47a2812075490ac601b93590dd06d4caeccb 100644 (file)
@@ -492,6 +492,10 @@ EXPORT_SYMBOL_GPL(rndis_unbind);
  */
 int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        /* peripheral may have batched packets to us... */
        while (likely(skb->len)) {
                struct rndis_data_hdr   *hdr = (void *)skb->data;
index f17b9e02dd348166333d691a06b8b12b0a48a3e7..d9e7892262faa6a0543807d4d411163a5f59ac78 100644 (file)
@@ -2106,6 +2106,10 @@ static void smsc75xx_rx_csum_offload(struct usbnet *dev, struct sk_buff *skb,
 
 static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        while (skb->len > 0) {
                u32 rx_cmd_a, rx_cmd_b, align_count, size;
                struct sk_buff *ax_skb;
index 8dd54a0f7b2973a29596fdb5ef99143269ce30cc..424db65e43962545b1746df63deb23833bf0c18b 100644 (file)
@@ -1723,6 +1723,10 @@ static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
 
 static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
        while (skb->len > 0) {
                u32 header, align_count;
                struct sk_buff *ax_skb;
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c
new file mode 100644 (file)
index 0000000..b94a0fb
--- /dev/null
@@ -0,0 +1,874 @@
+/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices
+ *
+ * Author : Liu Junliang <liujunliang_ljl@163.com>
+ *
+ * Based on asix_common.c, asix_devices.c
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.*
+ */
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/usbnet.h>
+#include <linux/slab.h>
+#include <linux/if_vlan.h>
+
+#include "sr9800.h"
+
+static int sr_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                           u16 size, void *data)
+{
+       int err;
+
+       err = usbnet_read_cmd(dev, cmd, SR_REQ_RD_REG, value, index,
+                             data, size);
+       if ((err != size) && (err >= 0))
+               err = -EINVAL;
+
+       return err;
+}
+
+static int sr_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                            u16 size, void *data)
+{
+       int err;
+
+       err = usbnet_write_cmd(dev, cmd, SR_REQ_WR_REG, value, index,
+                             data, size);
+       if ((err != size) && (err >= 0))
+               err = -EINVAL;
+
+       return err;
+}
+
+static void
+sr_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                  u16 size, void *data)
+{
+       usbnet_write_cmd_async(dev, cmd, SR_REQ_WR_REG, value, index, data,
+                              size);
+}
+
+static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       int offset = 0;
+
+       /* This check is no longer done by usbnet */
+       if (skb->len < dev->net->hard_header_len)
+               return 0;
+
+       while (offset + sizeof(u32) < skb->len) {
+               struct sk_buff *sr_skb;
+               u16 size;
+               u32 header = get_unaligned_le32(skb->data + offset);
+
+               offset += sizeof(u32);
+               /* get the packet length */
+               size = (u16) (header & 0x7ff);
+               if (size != ((~header >> 16) & 0x07ff)) {
+                       netdev_err(dev->net, "%s : Bad Header Length\n",
+                                  __func__);
+                       return 0;
+               }
+
+               if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) ||
+                   (size + offset > skb->len)) {
+                       netdev_err(dev->net, "%s : Bad RX Length %d\n",
+                                  __func__, size);
+                       return 0;
+               }
+               sr_skb = netdev_alloc_skb_ip_align(dev->net, size);
+               if (!sr_skb)
+                       return 0;
+
+               skb_put(sr_skb, size);
+               memcpy(sr_skb->data, skb->data + offset, size);
+               usbnet_skb_return(dev, sr_skb);
+
+               offset += (size + 1) & 0xfffe;
+       }
+
+       if (skb->len != offset) {
+               netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__,
+                          skb->len);
+               return 0;
+       }
+
+       return 1;
+}
+
+static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+                                       gfp_t flags)
+{
+       int headroom = skb_headroom(skb);
+       int tailroom = skb_tailroom(skb);
+       u32 padbytes = 0xffff0000;
+       u32 packet_len;
+       int padlen;
+
+       padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4;
+
+       if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) {
+               if ((headroom < 4) || (tailroom < padlen)) {
+                       skb->data = memmove(skb->head + 4, skb->data,
+                                           skb->len);
+                       skb_set_tail_pointer(skb, skb->len);
+               }
+       } else {
+               struct sk_buff *skb2;
+               skb2 = skb_copy_expand(skb, 4, padlen, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       skb_push(skb, 4);
+       packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+       cpu_to_le32s(&packet_len);
+       skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
+
+       if (padlen) {
+               cpu_to_le32s(&padbytes);
+               memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
+               skb_put(skb, sizeof(padbytes));
+       }
+
+       return skb;
+}
+
+static void sr_status(struct usbnet *dev, struct urb *urb)
+{
+       struct sr9800_int_data *event;
+       int link;
+
+       if (urb->actual_length < 8)
+               return;
+
+       event = urb->transfer_buffer;
+       link = event->link & 0x01;
+       if (netif_carrier_ok(dev->net) != link) {
+               usbnet_link_change(dev, link, 1);
+               netdev_dbg(dev->net, "Link Status is: %d\n", link);
+       }
+
+       return;
+}
+
+static inline int sr_set_sw_mii(struct usbnet *dev)
+{
+       int ret;
+
+       ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
+       if (ret < 0)
+               netdev_err(dev->net, "Failed to enable software MII access\n");
+       return ret;
+}
+
+static inline int sr_set_hw_mii(struct usbnet *dev)
+{
+       int ret;
+
+       ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
+       if (ret < 0)
+               netdev_err(dev->net, "Failed to enable hardware MII access\n");
+       return ret;
+}
+
+static inline int sr_get_phy_addr(struct usbnet *dev)
+{
+       u8 buf[2];
+       int ret;
+
+       ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf);
+       if (ret < 0) {
+               netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n",
+                          __func__, ret);
+               goto out;
+       }
+       netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__,
+                  *((__le16 *)buf));
+
+       ret = buf[1];
+
+out:
+       return ret;
+}
+
+static int sr_sw_reset(struct usbnet *dev, u8 flags)
+{
+       int ret;
+
+       ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL);
+       if (ret < 0)
+               netdev_err(dev->net, "Failed to send software reset:%02x\n",
+                          ret);
+
+       return ret;
+}
+
+static u16 sr_read_rx_ctl(struct usbnet *dev)
+{
+       __le16 v;
+       int ret;
+
+       ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v);
+       if (ret < 0) {
+               netdev_err(dev->net, "Error reading RX_CTL register:%02x\n",
+                          ret);
+               goto out;
+       }
+
+       ret = le16_to_cpu(v);
+out:
+       return ret;
+}
+
+static int sr_write_rx_ctl(struct usbnet *dev, u16 mode)
+{
+       int ret;
+
+       netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode);
+       ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
+       if (ret < 0)
+               netdev_err(dev->net,
+                          "Failed to write RX_CTL mode to 0x%04x:%02x\n",
+                          mode, ret);
+
+       return ret;
+}
+
+static u16 sr_read_medium_status(struct usbnet *dev)
+{
+       __le16 v;
+       int ret;
+
+       ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v);
+       if (ret < 0) {
+               netdev_err(dev->net,
+                          "Error reading Medium Status register:%02x\n", ret);
+               return ret;     /* TODO: callers not checking for error ret */
+       }
+
+       return le16_to_cpu(v);
+}
+
+static int sr_write_medium_mode(struct usbnet *dev, u16 mode)
+{
+       int ret;
+
+       netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode);
+       ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       if (ret < 0)
+               netdev_err(dev->net,
+                          "Failed to write Medium Mode mode to 0x%04x:%02x\n",
+                          mode, ret);
+       return ret;
+}
+
+static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep)
+{
+       int ret;
+
+       netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value);
+       ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL);
+       if (ret < 0)
+               netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n",
+                          value, ret);
+       if (sleep)
+               msleep(sleep);
+
+       return ret;
+}
+
+/* SR9800 have a 16-bit RX_CTL value */
+static void sr_set_multicast(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct sr_data *data = (struct sr_data *)&dev->data;
+       u16 rx_ctl = SR_DEFAULT_RX_CTL;
+
+       if (net->flags & IFF_PROMISC) {
+               rx_ctl |= SR_RX_CTL_PRO;
+       } else if (net->flags & IFF_ALLMULTI ||
+                  netdev_mc_count(net) > SR_MAX_MCAST) {
+               rx_ctl |= SR_RX_CTL_AMALL;
+       } else if (netdev_mc_empty(net)) {
+               /* just broadcast and directed */
+       } else {
+               /* We use the 20 byte dev->data
+                * for our 8 byte filter buffer
+                * to avoid allocating memory that
+                * is tricky to free later
+                */
+               struct netdev_hw_addr *ha;
+               u32 crc_bits;
+
+               memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE);
+
+               /* Build the multicast hash filter. */
+               netdev_for_each_mc_addr(ha, net) {
+                       crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26;
+                       data->multi_filter[crc_bits >> 3] |=
+                           1 << (crc_bits & 7);
+               }
+
+               sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0,
+                                  SR_MCAST_FILTER_SIZE, data->multi_filter);
+
+               rx_ctl |= SR_RX_CTL_AM;
+       }
+
+       sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+}
+
+static int sr_mdio_read(struct net_device *net, int phy_id, int loc)
+{
+       struct usbnet *dev = netdev_priv(net);
+       __le16 res;
+
+       mutex_lock(&dev->phy_mutex);
+       sr_set_sw_mii(dev);
+       sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res);
+       sr_set_hw_mii(dev);
+       mutex_unlock(&dev->phy_mutex);
+
+       netdev_dbg(dev->net,
+                  "%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__,
+                  phy_id, loc, le16_to_cpu(res));
+
+       return le16_to_cpu(res);
+}
+
+static void
+sr_mdio_write(struct net_device *net, int phy_id, int loc, int val)
+{
+       struct usbnet *dev = netdev_priv(net);
+       __le16 res = cpu_to_le16(val);
+
+       netdev_dbg(dev->net,
+                  "%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__,
+                  phy_id, loc, val);
+       mutex_lock(&dev->phy_mutex);
+       sr_set_sw_mii(dev);
+       sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res);
+       sr_set_hw_mii(dev);
+       mutex_unlock(&dev->phy_mutex);
+}
+
+/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
+static u32 sr_get_phyid(struct usbnet *dev)
+{
+       int phy_reg;
+       u32 phy_id;
+       int i;
+
+       /* Poll for the rare case the FW or phy isn't ready yet.  */
+       for (i = 0; i < 100; i++) {
+               phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
+               if (phy_reg != 0 && phy_reg != 0xFFFF)
+                       break;
+               mdelay(1);
+       }
+
+       if (phy_reg <= 0 || phy_reg == 0xFFFF)
+               return 0;
+
+       phy_id = (phy_reg & 0xffff) << 16;
+
+       phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
+       if (phy_reg < 0)
+               return 0;
+
+       phy_id |= (phy_reg & 0xffff);
+
+       return phy_id;
+}
+
+static void
+sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u8 opt;
+
+       if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
+               wolinfo->supported = 0;
+               wolinfo->wolopts = 0;
+               return;
+       }
+       wolinfo->supported = WAKE_PHY | WAKE_MAGIC;
+       wolinfo->wolopts = 0;
+       if (opt & SR_MONITOR_LINK)
+               wolinfo->wolopts |= WAKE_PHY;
+       if (opt & SR_MONITOR_MAGIC)
+               wolinfo->wolopts |= WAKE_MAGIC;
+}
+
+static int
+sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+{
+       struct usbnet *dev = netdev_priv(net);
+       u8 opt = 0;
+
+       if (wolinfo->wolopts & WAKE_PHY)
+               opt |= SR_MONITOR_LINK;
+       if (wolinfo->wolopts & WAKE_MAGIC)
+               opt |= SR_MONITOR_MAGIC;
+
+       if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE,
+                        opt, 0, 0, NULL) < 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sr_get_eeprom_len(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct sr_data *data = (struct sr_data *)&dev->data;
+
+       return data->eeprom_len;
+}
+
+static int sr_get_eeprom(struct net_device *net,
+                             struct ethtool_eeprom *eeprom, u8 *data)
+{
+       struct usbnet *dev = netdev_priv(net);
+       __le16 *ebuf = (__le16 *)data;
+       int ret;
+       int i;
+
+       /* Crude hack to ensure that we don't overwrite memory
+        * if an odd length is supplied
+        */
+       if (eeprom->len % 2)
+               return -EINVAL;
+
+       eeprom->magic = SR_EEPROM_MAGIC;
+
+       /* sr9800 returns 2 bytes from eeprom on read */
+       for (i = 0; i < eeprom->len / 2; i++) {
+               ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i,
+                                 0, 2, &ebuf[i]);
+               if (ret < 0)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static void sr_get_drvinfo(struct net_device *net,
+                                struct ethtool_drvinfo *info)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct sr_data *data = (struct sr_data *)&dev->data;
+
+       /* Inherit standard device info */
+       usbnet_get_drvinfo(net, info);
+       strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+       strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       info->eedump_len = data->eeprom_len;
+}
+
+static u32 sr_get_link(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return mii_link_ok(&dev->mii);
+}
+
+static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static int sr_set_mac_address(struct net_device *net, void *p)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct sr_data *data = (struct sr_data *)&dev->data;
+       struct sockaddr *addr = p;
+
+       if (netif_running(net))
+               return -EBUSY;
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
+
+       /* We use the 20 byte dev->data
+        * for our 6 byte mac buffer
+        * to avoid allocating memory that
+        * is tricky to free later
+        */
+       memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
+       sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
+                          data->mac_addr);
+
+       return 0;
+}
+
+static const struct ethtool_ops sr9800_ethtool_ops = {
+       .get_drvinfo    = sr_get_drvinfo,
+       .get_link       = sr_get_link,
+       .get_msglevel   = usbnet_get_msglevel,
+       .set_msglevel   = usbnet_set_msglevel,
+       .get_wol        = sr_get_wol,
+       .set_wol        = sr_set_wol,
+       .get_eeprom_len = sr_get_eeprom_len,
+       .get_eeprom     = sr_get_eeprom,
+       .get_settings   = usbnet_get_settings,
+       .set_settings   = usbnet_set_settings,
+       .nway_reset     = usbnet_nway_reset,
+};
+
+static int sr9800_link_reset(struct usbnet *dev)
+{
+       struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
+       u16 mode;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = SR9800_MEDIUM_DEFAULT;
+
+       if (ethtool_cmd_speed(&ecmd) != SPEED_100)
+               mode &= ~SR_MEDIUM_PS;
+
+       if (ecmd.duplex != DUPLEX_FULL)
+               mode &= ~SR_MEDIUM_FD;
+
+       netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n",
+                  __func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
+
+       sr_write_medium_mode(dev, mode);
+
+       return 0;
+}
+
+
+static int sr9800_set_default_mode(struct usbnet *dev)
+{
+       u16 rx_ctl;
+       int ret;
+
+       sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+       sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+                     ADVERTISE_ALL | ADVERTISE_CSMA);
+       mii_nway_restart(&dev->mii);
+
+       ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT);
+       if (ret < 0)
+               goto out;
+
+       ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012,
+                               SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT,
+                               SR9800_IPG2_DEFAULT, 0, NULL);
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret);
+               goto out;
+       }
+
+       /* Set RX_CTL to default values with 2k buffer, and enable cactus */
+       ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL);
+       if (ret < 0)
+               goto out;
+
+       rx_ctl = sr_read_rx_ctl(dev);
+       netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n",
+                  rx_ctl);
+
+       rx_ctl = sr_read_medium_status(dev);
+       netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n",
+                  rx_ctl);
+
+       return 0;
+out:
+       return ret;
+}
+
+static int sr9800_reset(struct usbnet *dev)
+{
+       struct sr_data *data = (struct sr_data *)&dev->data;
+       int ret, embd_phy;
+       u16 rx_ctl;
+
+       ret = sr_write_gpio(dev,
+                       SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5);
+       if (ret < 0)
+               goto out;
+
+       embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
+
+       ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
+               goto out;
+       }
+
+       ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL);
+       if (ret < 0)
+               goto out;
+
+       msleep(150);
+
+       ret = sr_sw_reset(dev, SR_SWRESET_CLEAR);
+       if (ret < 0)
+               goto out;
+
+       msleep(150);
+
+       if (embd_phy) {
+               ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
+               if (ret < 0)
+                       goto out;
+       } else {
+               ret = sr_sw_reset(dev, SR_SWRESET_PRTE);
+               if (ret < 0)
+                       goto out;
+       }
+
+       msleep(150);
+       rx_ctl = sr_read_rx_ctl(dev);
+       netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
+       ret = sr_write_rx_ctl(dev, 0x0000);
+       if (ret < 0)
+               goto out;
+
+       rx_ctl = sr_read_rx_ctl(dev);
+       netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
+
+       ret = sr_sw_reset(dev, SR_SWRESET_PRL);
+       if (ret < 0)
+               goto out;
+
+       msleep(150);
+
+       ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL);
+       if (ret < 0)
+               goto out;
+
+       msleep(150);
+
+       ret = sr9800_set_default_mode(dev);
+       if (ret < 0)
+               goto out;
+
+       /* Rewrite MAC address */
+       memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
+       ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
+                                                       data->mac_addr);
+       if (ret < 0)
+               goto out;
+
+       return 0;
+
+out:
+       return ret;
+}
+
+static const struct net_device_ops sr9800_netdev_ops = {
+       .ndo_open               = usbnet_open,
+       .ndo_stop               = usbnet_stop,
+       .ndo_start_xmit         = usbnet_start_xmit,
+       .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_set_mac_address    = sr_set_mac_address,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_do_ioctl           = sr_ioctl,
+       .ndo_set_rx_mode        = sr_set_multicast,
+};
+
+static int sr9800_phy_powerup(struct usbnet *dev)
+{
+       int ret;
+
+       /* set the embedded Ethernet PHY in power-down state */
+       ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL);
+       if (ret < 0) {
+               netdev_err(dev->net, "Failed to power down PHY : %d\n", ret);
+               return ret;
+       }
+       msleep(20);
+
+       /* set the embedded Ethernet PHY in power-up state */
+       ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
+       if (ret < 0) {
+               netdev_err(dev->net, "Failed to reset PHY: %d\n", ret);
+               return ret;
+       }
+       msleep(600);
+
+       /* set the embedded Ethernet PHY in reset state */
+       ret = sr_sw_reset(dev, SR_SWRESET_CLEAR);
+       if (ret < 0) {
+               netdev_err(dev->net, "Failed to power up PHY: %d\n", ret);
+               return ret;
+       }
+       msleep(20);
+
+       /* set the embedded Ethernet PHY in power-up state */
+       ret = sr_sw_reset(dev, SR_SWRESET_IPRL);
+       if (ret < 0) {
+               netdev_err(dev->net, "Failed to reset PHY: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct sr_data *data = (struct sr_data *)&dev->data;
+       u16 led01_mux, led23_mux;
+       int ret, embd_phy;
+       u32 phyid;
+       u16 rx_ctl;
+
+       data->eeprom_len = SR9800_EEPROM_LEN;
+
+       usbnet_get_endpoints(dev, intf);
+
+       /* LED Setting Rule :
+        * AABB:CCDD
+        * AA : MFA0(LED0)
+        * BB : MFA1(LED1)
+        * CC : MFA2(LED2), Reserved for SR9800
+        * DD : MFA3(LED3), Reserved for SR9800
+        */
+       led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK;
+       led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE;
+       ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL);
+       if (ret < 0) {
+                       netdev_err(dev->net, "set LINK LED failed : %d\n", ret);
+                       goto out;
+       }
+
+       /* Get the MAC address */
+       ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN,
+                         dev->net->dev_addr);
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
+               return ret;
+       }
+       netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr);
+
+       /* Initialize MII structure */
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = sr_mdio_read;
+       dev->mii.mdio_write = sr_mdio_write;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0x1f;
+       dev->mii.phy_id = sr_get_phy_addr(dev);
+
+       dev->net->netdev_ops = &sr9800_netdev_ops;
+       dev->net->ethtool_ops = &sr9800_ethtool_ops;
+
+       embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
+       /* Reset the PHY to normal operation mode */
+       ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
+               return ret;
+       }
+
+       /* Init PHY routine */
+       ret = sr9800_phy_powerup(dev);
+       if (ret < 0)
+               goto out;
+
+       rx_ctl = sr_read_rx_ctl(dev);
+       netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl);
+       ret = sr_write_rx_ctl(dev, 0x0000);
+       if (ret < 0)
+               goto out;
+
+       rx_ctl = sr_read_rx_ctl(dev);
+       netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
+
+       /* Read PHYID register *AFTER* the PHY was reset properly */
+       phyid = sr_get_phyid(dev);
+       netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid);
+
+       /* medium mode setting */
+       ret = sr9800_set_default_mode(dev);
+       if (ret < 0)
+               goto out;
+
+       if (dev->udev->speed == USB_SPEED_HIGH) {
+               ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE,
+                       SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt,
+                       SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold,
+                       0, NULL);
+               if (ret < 0) {
+                       netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret);
+                       goto out;
+               }
+               dev->rx_urb_size =
+                       SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size;
+       } else {
+               ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE,
+                       SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt,
+                       SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold,
+                       0, NULL);
+               if (ret < 0) {
+                       netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret);
+                       goto out;
+               }
+               dev->rx_urb_size =
+                       SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size;
+       }
+       netdev_dbg(dev->net, "%s : setting rx_urb_size with : %zu\n", __func__,
+                  dev->rx_urb_size);
+       return 0;
+
+out:
+       return ret;
+}
+
+static const struct driver_info sr9800_driver_info = {
+       .description    = "CoreChip SR9800 USB 2.0 Ethernet",
+       .bind           = sr9800_bind,
+       .status         = sr_status,
+       .link_reset     = sr9800_link_reset,
+       .reset          = sr9800_reset,
+       .flags          = DRIVER_FLAG,
+       .rx_fixup       = sr_rx_fixup,
+       .tx_fixup       = sr_tx_fixup,
+};
+
+static const struct usb_device_id      products[] = {
+       {
+               USB_DEVICE(0x0fe6, 0x9800),     /* SR9800 Device  */
+               .driver_info = (unsigned long) &sr9800_driver_info,
+       },
+       {},             /* END */
+};
+
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver sr_driver = {
+       .name           = DRIVER_NAME,
+       .id_table       = products,
+       .probe          = usbnet_probe,
+       .suspend        = usbnet_suspend,
+       .resume         = usbnet_resume,
+       .disconnect     = usbnet_disconnect,
+       .supports_autosuspend = 1,
+};
+
+module_usb_driver(sr_driver);
+
+MODULE_AUTHOR("Liu Junliang <liujunliang_ljl@163.com");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_DESCRIPTION("SR9800 USB 2.0 USB2NET Dev : http://www.corechip-sz.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/sr9800.h b/drivers/net/usb/sr9800.h
new file mode 100644 (file)
index 0000000..18f6702
--- /dev/null
@@ -0,0 +1,202 @@
+/* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices
+ *
+ * Author : Liu Junliang <liujunliang_ljl@163.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef        _SR9800_H
+#define        _SR9800_H
+
+/* SR9800 spec. command table on Linux Platform */
+
+/* command : Software Station Management Control Reg */
+#define SR_CMD_SET_SW_MII              0x06
+/* command : PHY Read Reg */
+#define SR_CMD_READ_MII_REG            0x07
+/* command : PHY Write Reg */
+#define SR_CMD_WRITE_MII_REG           0x08
+/* command : Hardware Station Management Control Reg */
+#define SR_CMD_SET_HW_MII              0x0a
+/* command : SROM Read Reg */
+#define SR_CMD_READ_EEPROM             0x0b
+/* command : SROM Write Reg */
+#define SR_CMD_WRITE_EEPROM            0x0c
+/* command : SROM Write Enable Reg */
+#define SR_CMD_WRITE_ENABLE            0x0d
+/* command : SROM Write Disable Reg */
+#define SR_CMD_WRITE_DISABLE           0x0e
+/* command : RX Control Read Reg */
+#define SR_CMD_READ_RX_CTL             0x0f
+#define                SR_RX_CTL_PRO                   (1 << 0)
+#define                SR_RX_CTL_AMALL                 (1 << 1)
+#define                SR_RX_CTL_SEP                   (1 << 2)
+#define                SR_RX_CTL_AB                    (1 << 3)
+#define                SR_RX_CTL_AM                    (1 << 4)
+#define                SR_RX_CTL_AP                    (1 << 5)
+#define                SR_RX_CTL_ARP                   (1 << 6)
+#define                SR_RX_CTL_SO                    (1 << 7)
+#define                SR_RX_CTL_RH1M                  (1 << 8)
+#define                SR_RX_CTL_RH2M                  (1 << 9)
+#define                SR_RX_CTL_RH3M                  (1 << 10)
+/* command : RX Control Write Reg */
+#define SR_CMD_WRITE_RX_CTL            0x10
+/* command : IPG0/IPG1/IPG2 Control Read Reg */
+#define SR_CMD_READ_IPG012             0x11
+/* command : IPG0/IPG1/IPG2 Control Write Reg */
+#define SR_CMD_WRITE_IPG012            0x12
+/* command : Node ID Read Reg */
+#define SR_CMD_READ_NODE_ID            0x13
+/* command : Node ID Write Reg */
+#define SR_CMD_WRITE_NODE_ID           0x14
+/* command : Multicast Filter Array Read Reg */
+#define        SR_CMD_READ_MULTI_FILTER        0x15
+/* command : Multicast Filter Array Write Reg */
+#define SR_CMD_WRITE_MULTI_FILTER      0x16
+/* command : Eth/HomePNA PHY Address Reg */
+#define SR_CMD_READ_PHY_ID             0x19
+/* command : Medium Status Read Reg */
+#define SR_CMD_READ_MEDIUM_STATUS      0x1a
+#define                SR_MONITOR_LINK                 (1 << 1)
+#define                SR_MONITOR_MAGIC                (1 << 2)
+#define                SR_MONITOR_HSFS                 (1 << 4)
+/* command : Medium Status Write Reg */
+#define SR_CMD_WRITE_MEDIUM_MODE       0x1b
+#define                SR_MEDIUM_GM                    (1 << 0)
+#define                SR_MEDIUM_FD                    (1 << 1)
+#define                SR_MEDIUM_AC                    (1 << 2)
+#define                SR_MEDIUM_ENCK                  (1 << 3)
+#define                SR_MEDIUM_RFC                   (1 << 4)
+#define                SR_MEDIUM_TFC                   (1 << 5)
+#define                SR_MEDIUM_JFE                   (1 << 6)
+#define                SR_MEDIUM_PF                    (1 << 7)
+#define                SR_MEDIUM_RE                    (1 << 8)
+#define                SR_MEDIUM_PS                    (1 << 9)
+#define                SR_MEDIUM_RSV                   (1 << 10)
+#define                SR_MEDIUM_SBP                   (1 << 11)
+#define                SR_MEDIUM_SM                    (1 << 12)
+/* command : Monitor Mode Status Read Reg */
+#define SR_CMD_READ_MONITOR_MODE       0x1c
+/* command : Monitor Mode Status Write Reg */
+#define SR_CMD_WRITE_MONITOR_MODE      0x1d
+/* command : GPIO Status Read Reg */
+#define SR_CMD_READ_GPIOS              0x1e
+#define                SR_GPIO_GPO0EN          (1 << 0) /* GPIO0 Output enable */
+#define                SR_GPIO_GPO_0           (1 << 1) /* GPIO0 Output value */
+#define                SR_GPIO_GPO1EN          (1 << 2) /* GPIO1 Output enable */
+#define                SR_GPIO_GPO_1           (1 << 3) /* GPIO1 Output value */
+#define                SR_GPIO_GPO2EN          (1 << 4) /* GPIO2 Output enable */
+#define                SR_GPIO_GPO_2           (1 << 5) /* GPIO2 Output value */
+#define                SR_GPIO_RESERVED        (1 << 6) /* Reserved */
+#define                SR_GPIO_RSE             (1 << 7) /* Reload serial EEPROM */
+/* command : GPIO Status Write Reg */
+#define SR_CMD_WRITE_GPIOS             0x1f
+/* command : Eth PHY Power and Reset Control Reg */
+#define SR_CMD_SW_RESET                        0x20
+#define                SR_SWRESET_CLEAR                0x00
+#define                SR_SWRESET_RR                   (1 << 0)
+#define                SR_SWRESET_RT                   (1 << 1)
+#define                SR_SWRESET_PRTE                 (1 << 2)
+#define                SR_SWRESET_PRL                  (1 << 3)
+#define                SR_SWRESET_BZ                   (1 << 4)
+#define                SR_SWRESET_IPRL                 (1 << 5)
+#define                SR_SWRESET_IPPD                 (1 << 6)
+/* command : Software Interface Selection Status Read Reg */
+#define SR_CMD_SW_PHY_STATUS           0x21
+/* command : Software Interface Selection Status Write Reg */
+#define SR_CMD_SW_PHY_SELECT           0x22
+/* command : BULK in Buffer Size Reg */
+#define        SR_CMD_BULKIN_SIZE              0x2A
+/* command : LED_MUX Control Reg */
+#define        SR_CMD_LED_MUX                  0x70
+#define                SR_LED_MUX_TX_ACTIVE            (1 << 0)
+#define                SR_LED_MUX_RX_ACTIVE            (1 << 1)
+#define                SR_LED_MUX_COLLISION            (1 << 2)
+#define                SR_LED_MUX_DUP_COL              (1 << 3)
+#define                SR_LED_MUX_DUP                  (1 << 4)
+#define                SR_LED_MUX_SPEED                (1 << 5)
+#define                SR_LED_MUX_LINK_ACTIVE          (1 << 6)
+#define                SR_LED_MUX_LINK                 (1 << 7)
+
+/* Register Access Flags */
+#define SR_REQ_RD_REG   (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
+#define SR_REQ_WR_REG   (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
+
+/* Multicast Filter Array size & Max Number */
+#define        SR_MCAST_FILTER_SIZE            8
+#define        SR_MAX_MCAST                    64
+
+/* IPG0/1/2 Default Value */
+#define        SR9800_IPG0_DEFAULT             0x15
+#define        SR9800_IPG1_DEFAULT             0x0c
+#define        SR9800_IPG2_DEFAULT             0x12
+
+/* Medium Status Default Mode */
+#define SR9800_MEDIUM_DEFAULT  \
+       (SR_MEDIUM_FD | SR_MEDIUM_RFC | \
+        SR_MEDIUM_TFC | SR_MEDIUM_PS | \
+        SR_MEDIUM_AC | SR_MEDIUM_RE)
+
+/* RX Control Default Setting */
+#define SR_DEFAULT_RX_CTL      \
+       (SR_RX_CTL_SO | SR_RX_CTL_AB | SR_RX_CTL_RH1M)
+
+/* EEPROM Magic Number & EEPROM Size */
+#define SR_EEPROM_MAGIC                        0xdeadbeef
+#define SR9800_EEPROM_LEN              0xff
+
+/* SR9800 Driver Version and Driver Name */
+#define DRIVER_VERSION                 "11-Nov-2013"
+#define DRIVER_NAME                    "CoreChips"
+#define        DRIVER_FLAG             \
+       (FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |  FLAG_MULTI_PACKET)
+
+/* SR9800 BULKIN Buffer Size */
+#define SR9800_MAX_BULKIN_2K           0
+#define SR9800_MAX_BULKIN_4K           1
+#define SR9800_MAX_BULKIN_6K           2
+#define SR9800_MAX_BULKIN_8K           3
+#define SR9800_MAX_BULKIN_16K          4
+#define SR9800_MAX_BULKIN_20K          5
+#define SR9800_MAX_BULKIN_24K          6
+#define SR9800_MAX_BULKIN_32K          7
+
+struct {unsigned short size, byte_cnt, threshold; } SR9800_BULKIN_SIZE[] = {
+       /* 2k */
+       {2048, 0x8000, 0x8001},
+       /* 4k */
+       {4096, 0x8100, 0x8147},
+       /* 6k */
+       {6144, 0x8200, 0x81EB},
+       /* 8k */
+       {8192, 0x8300, 0x83D7},
+       /* 16 */
+       {16384, 0x8400, 0x851E},
+       /* 20k */
+       {20480, 0x8500, 0x8666},
+       /* 24k */
+       {24576, 0x8600, 0x87AE},
+       /* 32k */
+       {32768, 0x8700, 0x8A3D},
+};
+
+/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
+struct sr_data {
+       u8 multi_filter[SR_MCAST_FILTER_SIZE];
+       u8 mac_addr[ETH_ALEN];
+       u8 phymode;
+       u8 ledmode;
+       u8 eeprom_len;
+};
+
+struct sr9800_int_data {
+       __le16 res1;
+       u8 link;
+       __le16 res2;
+       u8 status;
+       __le16 res3;
+} __packed;
+
+#endif /* _SR9800_H */
index 4671da755e7b87f60758259021bcc5ab7f7c6cd1..f9e96c4275589ebc63b3d87432fe50471c287872 100644 (file)
@@ -542,17 +542,19 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
        }
        // else network stack removes extra byte if we forced a short packet
 
-       if (skb->len) {
-               /* all data was already cloned from skb inside the driver */
-               if (dev->driver_info->flags & FLAG_MULTI_PACKET)
-                       dev_kfree_skb_any(skb);
-               else
-                       usbnet_skb_return(dev, skb);
+       /* all data was already cloned from skb inside the driver */
+       if (dev->driver_info->flags & FLAG_MULTI_PACKET)
+               goto done;
+
+       if (skb->len < ETH_HLEN) {
+               dev->net->stats.rx_errors++;
+               dev->net->stats.rx_length_errors++;
+               netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len);
+       } else {
+               usbnet_skb_return(dev, skb);
                return;
        }
 
-       netif_dbg(dev, rx_err, dev->net, "drop\n");
-       dev->net->stats.rx_errors++;
 done:
        skb_queue_tail(&dev->done, skb);
 }
@@ -574,13 +576,6 @@ static void rx_complete (struct urb *urb)
        switch (urb_status) {
        /* success */
        case 0:
-               if (skb->len < dev->net->hard_header_len) {
-                       state = rx_cleanup;
-                       dev->net->stats.rx_errors++;
-                       dev->net->stats.rx_length_errors++;
-                       netif_dbg(dev, rx_err, dev->net,
-                                 "rx length %d\n", skb->len);
-               }
                break;
 
        /* stalls need manual reset. this is rare ... except that
@@ -757,14 +752,12 @@ EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
 // precondition: never called in_interrupt
 static void usbnet_terminate_urbs(struct usbnet *dev)
 {
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
        DECLARE_WAITQUEUE(wait, current);
        int temp;
 
        /* ensure there are no more active urbs */
-       add_wait_queue(&unlink_wakeup, &wait);
+       add_wait_queue(&dev->wait, &wait);
        set_current_state(TASK_UNINTERRUPTIBLE);
-       dev->wait = &unlink_wakeup;
        temp = unlink_urbs(dev, &dev->txq) +
                unlink_urbs(dev, &dev->rxq);
 
@@ -778,15 +771,14 @@ static void usbnet_terminate_urbs(struct usbnet *dev)
                                  "waited for %d urb completions\n", temp);
        }
        set_current_state(TASK_RUNNING);
-       dev->wait = NULL;
-       remove_wait_queue(&unlink_wakeup, &wait);
+       remove_wait_queue(&dev->wait, &wait);
 }
 
 int usbnet_stop (struct net_device *net)
 {
        struct usbnet           *dev = netdev_priv(net);
        struct driver_info      *info = dev->driver_info;
-       int                     retval;
+       int                     retval, pm;
 
        clear_bit(EVENT_DEV_OPEN, &dev->flags);
        netif_stop_queue (net);
@@ -796,6 +788,8 @@ int usbnet_stop (struct net_device *net)
                   net->stats.rx_packets, net->stats.tx_packets,
                   net->stats.rx_errors, net->stats.tx_errors);
 
+       /* to not race resume */
+       pm = usb_autopm_get_interface(dev->intf);
        /* allow minidriver to stop correctly (wireless devices to turn off
         * radio etc) */
        if (info->stop) {
@@ -822,6 +816,9 @@ int usbnet_stop (struct net_device *net)
        dev->flags = 0;
        del_timer_sync (&dev->delay);
        tasklet_kill (&dev->bh);
+       if (!pm)
+               usb_autopm_put_interface(dev->intf);
+
        if (info->manage_power &&
            !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags))
                info->manage_power(dev, 0);
@@ -1442,11 +1439,12 @@ static void usbnet_bh (unsigned long param)
        /* restart RX again after disabling due to high error rate */
        clear_bit(EVENT_RX_KILL, &dev->flags);
 
-       // waiting for all pending urbs to complete?
-       if (dev->wait) {
-               if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
-                       wake_up (dev->wait);
-               }
+       /* waiting for all pending urbs to complete?
+        * only then can we forgo submitting anew
+        */
+       if (waitqueue_active(&dev->wait)) {
+               if (dev->txq.qlen + dev->rxq.qlen + dev->done.qlen == 0)
+                       wake_up_all(&dev->wait);
 
        // or are we maybe short a few urbs?
        } else if (netif_running (dev->net) &&
@@ -1585,6 +1583,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        dev->driver_name = name;
        dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
                                | NETIF_MSG_PROBE | NETIF_MSG_LINK);
+       init_waitqueue_head(&dev->wait);
        skb_queue_head_init (&dev->rxq);
        skb_queue_head_init (&dev->txq);
        skb_queue_head_init (&dev->done);
@@ -1796,9 +1795,10 @@ int usbnet_resume (struct usb_interface *intf)
                spin_unlock_irq(&dev->txq.lock);
 
                if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
-                       /* handle remote wakeup ASAP */
-                       if (!dev->wait &&
-                               netif_device_present(dev->net) &&
+                       /* handle remote wakeup ASAP
+                        * we cannot race against stop
+                        */
+                       if (netif_device_present(dev->net) &&
                                !timer_pending(&dev->delay) &&
                                !test_bit(EVENT_RX_HALT, &dev->flags))
                                        rx_alloc_submit(dev, GFP_NOIO);
index 2ec2041b62d4eb215bf23f74ad82ba44332b8d3d..c0e7c64765abd449070a7bce6826a994c674b8c7 100644 (file)
@@ -285,7 +285,11 @@ static void veth_setup(struct net_device *dev)
        dev->ethtool_ops = &veth_ethtool_ops;
        dev->features |= NETIF_F_LLTX;
        dev->features |= VETH_FEATURES;
-       dev->vlan_features = dev->features;
+       dev->vlan_features = dev->features &
+                            ~(NETIF_F_HW_VLAN_CTAG_TX |
+                              NETIF_F_HW_VLAN_STAG_TX |
+                              NETIF_F_HW_VLAN_CTAG_RX |
+                              NETIF_F_HW_VLAN_STAG_RX);
        dev->destructor = veth_dev_free;
 
        dev->hw_features = VETH_FEATURES;
index d75f8edf4fb370300d13bd22adcfe66e754fb5a2..841b60831df1b2e83c12f55ee5e8fc90874b9475 100644 (file)
@@ -671,8 +671,7 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp)
                if (err)
                        break;
        } while (rq->vq->num_free);
-       if (unlikely(!virtqueue_kick(rq->vq)))
-               return false;
+       virtqueue_kick(rq->vq);
        return !oom;
 }
 
@@ -877,7 +876,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
        err = xmit_skb(sq, skb);
 
        /* This should not happen! */
-       if (unlikely(err) || unlikely(!virtqueue_kick(sq->vq))) {
+       if (unlikely(err)) {
                dev->stats.tx_fifo_errors++;
                if (net_ratelimit())
                        dev_warn(&dev->dev,
@@ -886,6 +885,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
                kfree_skb(skb);
                return NETDEV_TX_OK;
        }
+       virtqueue_kick(sq->vq);
 
        /* Don't wait up for transmitted skbs to be freed. */
        skb_orphan(skb);
@@ -1711,7 +1711,8 @@ static int virtnet_probe(struct virtio_device *vdev)
        /* If we can receive ANY GSO packets, we must allocate large ones. */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
            virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
-           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
+           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
                vi->big_packets = true;
 
        if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
index 3be786faaaec222f0226b8285dde01e88b147e59..0fa3b44f7342dc0cf979cf69b6b1d6c3444411f3 100644 (file)
@@ -1762,11 +1762,20 @@ vmxnet3_netpoll(struct net_device *netdev)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
-       if (adapter->intr.mask_mode == VMXNET3_IMM_ACTIVE)
-               vmxnet3_disable_all_intrs(adapter);
-
-       vmxnet3_do_poll(adapter, adapter->rx_queue[0].rx_ring[0].size);
-       vmxnet3_enable_all_intrs(adapter);
+       switch (adapter->intr.type) {
+#ifdef CONFIG_PCI_MSI
+       case VMXNET3_IT_MSIX: {
+               int i;
+               for (i = 0; i < adapter->num_rx_queues; i++)
+                       vmxnet3_msix_rx(0, &adapter->rx_queue[i]);
+               break;
+       }
+#endif
+       case VMXNET3_IT_MSI:
+       default:
+               vmxnet3_intr(0, adapter->netdev);
+               break;
+       }
 
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
index 026a313c2d2da4c3eb57d0c5f6a051bbbdc852b2..1236812c7be69975487e7956c24d39718997ec2b 100644 (file)
@@ -469,7 +469,6 @@ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan,
 /* Look up Ethernet address in forwarding table */
 static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan,
                                        const u8 *mac)
-
 {
        struct hlist_head *head = vxlan_fdb_head(vxlan, mac);
        struct vxlan_fdb *f;
@@ -596,10 +595,8 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, struct sk_buff
                        NAPI_GRO_CB(p)->same_flow = 0;
                        continue;
                }
-               goto found;
        }
 
-found:
        type = eh->h_proto;
 
        rcu_read_lock();
@@ -1321,6 +1318,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 
                neigh_release(n);
 
+               if (reply == NULL)
+                       goto out;
+
                skb_reset_mac_header(reply);
                __skb_pull(reply, skb_network_offset(reply));
                reply->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1342,15 +1342,103 @@ out:
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
+
+static struct sk_buff *vxlan_na_create(struct sk_buff *request,
+       struct neighbour *n, bool isrouter)
+{
+       struct net_device *dev = request->dev;
+       struct sk_buff *reply;
+       struct nd_msg *ns, *na;
+       struct ipv6hdr *pip6;
+       u8 *daddr;
+       int na_olen = 8; /* opt hdr + ETH_ALEN for target */
+       int ns_olen;
+       int i, len;
+
+       if (dev == NULL)
+               return NULL;
+
+       len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
+               sizeof(*na) + na_olen + dev->needed_tailroom;
+       reply = alloc_skb(len, GFP_ATOMIC);
+       if (reply == NULL)
+               return NULL;
+
+       reply->protocol = htons(ETH_P_IPV6);
+       reply->dev = dev;
+       skb_reserve(reply, LL_RESERVED_SPACE(request->dev));
+       skb_push(reply, sizeof(struct ethhdr));
+       skb_set_mac_header(reply, 0);
+
+       ns = (struct nd_msg *)skb_transport_header(request);
+
+       daddr = eth_hdr(request)->h_source;
+       ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns);
+       for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
+               if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
+                       daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
+                       break;
+               }
+       }
+
+       /* Ethernet header */
+       ether_addr_copy(eth_hdr(reply)->h_dest, daddr);
+       ether_addr_copy(eth_hdr(reply)->h_source, n->ha);
+       eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
+       reply->protocol = htons(ETH_P_IPV6);
+
+       skb_pull(reply, sizeof(struct ethhdr));
+       skb_set_network_header(reply, 0);
+       skb_put(reply, sizeof(struct ipv6hdr));
+
+       /* IPv6 header */
+
+       pip6 = ipv6_hdr(reply);
+       memset(pip6, 0, sizeof(struct ipv6hdr));
+       pip6->version = 6;
+       pip6->priority = ipv6_hdr(request)->priority;
+       pip6->nexthdr = IPPROTO_ICMPV6;
+       pip6->hop_limit = 255;
+       pip6->daddr = ipv6_hdr(request)->saddr;
+       pip6->saddr = *(struct in6_addr *)n->primary_key;
+
+       skb_pull(reply, sizeof(struct ipv6hdr));
+       skb_set_transport_header(reply, 0);
+
+       na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen);
+
+       /* Neighbor Advertisement */
+       memset(na, 0, sizeof(*na)+na_olen);
+       na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
+       na->icmph.icmp6_router = isrouter;
+       na->icmph.icmp6_override = 1;
+       na->icmph.icmp6_solicited = 1;
+       na->target = ns->target;
+       ether_addr_copy(&na->opt[2], n->ha);
+       na->opt[0] = ND_OPT_TARGET_LL_ADDR;
+       na->opt[1] = na_olen >> 3;
+
+       na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr,
+               &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6,
+               csum_partial(na, sizeof(*na)+na_olen, 0));
+
+       pip6->payload_len = htons(sizeof(*na)+na_olen);
+
+       skb_push(reply, sizeof(struct ipv6hdr));
+
+       reply->ip_summed = CHECKSUM_UNNECESSARY;
+
+       return reply;
+}
+
 static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
-       struct neighbour *n;
-       union vxlan_addr ipa;
+       struct nd_msg *msg;
        const struct ipv6hdr *iphdr;
        const struct in6_addr *saddr, *daddr;
-       struct nd_msg *msg;
-       struct inet6_dev *in6_dev = NULL;
+       struct neighbour *n;
+       struct inet6_dev *in6_dev;
 
        in6_dev = __in6_dev_get(dev);
        if (!in6_dev)
@@ -1363,19 +1451,20 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
        saddr = &iphdr->saddr;
        daddr = &iphdr->daddr;
 
-       if (ipv6_addr_loopback(daddr) ||
-           ipv6_addr_is_multicast(daddr))
-               goto out;
-
        msg = (struct nd_msg *)skb_transport_header(skb);
        if (msg->icmph.icmp6_code != 0 ||
            msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
                goto out;
 
-       n = neigh_lookup(ipv6_stub->nd_tbl, daddr, dev);
+       if (ipv6_addr_loopback(daddr) ||
+           ipv6_addr_is_multicast(&msg->target))
+               goto out;
+
+       n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
 
        if (n) {
                struct vxlan_fdb *f;
+               struct sk_buff *reply;
 
                if (!(n->nud_state & NUD_CONNECTED)) {
                        neigh_release(n);
@@ -1389,13 +1478,23 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
                        goto out;
                }
 
-               ipv6_stub->ndisc_send_na(dev, n, saddr, &msg->target,
-                                        !!in6_dev->cnf.forwarding,
-                                        true, false, false);
+               reply = vxlan_na_create(skb, n,
+                                       !!(f ? f->flags & NTF_ROUTER : 0));
+
                neigh_release(n);
+
+               if (reply == NULL)
+                       goto out;
+
+               if (netif_rx_ni(reply) == NET_RX_DROP)
+                       dev->stats.rx_dropped++;
+
        } else if (vxlan->flags & VXLAN_F_L3MISS) {
-               ipa.sin6.sin6_addr = *daddr;
-               ipa.sa.sa_family = AF_INET6;
+               union vxlan_addr ipa = {
+                       .sin6.sin6_addr = msg->target,
+                       .sa.sa_family = AF_INET6,
+               };
+
                vxlan_ip_miss(dev, &ipa);
        }
 
index 0d1c7592efa08eac1dc7d02340e9f13db0895d2b..19f7cb2cdef3c133fa2d04b4b2560d0acc6c2c35 100644 (file)
@@ -71,12 +71,9 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev,
                       const void *saddr, unsigned len)
 {
        struct frhdr            hdr;
-       struct dlci_local       *dlp;
        unsigned int            hlen;
        char                    *dest;
 
-       dlp = netdev_priv(dev);
-
        hdr.control = FRAD_I_UI;
        switch (type)
        {
@@ -107,11 +104,9 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev,
 
 static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
 {
-       struct dlci_local *dlp;
        struct frhdr            *hdr;
        int                                     process, header;
 
-       dlp = netdev_priv(dev);
        if (!pskb_may_pull(skb, sizeof(*hdr))) {
                netdev_notice(dev, "invalid data no header\n");
                dev->stats.rx_errors++;
index 8aa20df55e50d854407d7c84faf28ac11b1576e4..507d9a9ee69ad4b61ece2d334434691801682efe 100644 (file)
@@ -1764,7 +1764,7 @@ static struct usb_device_id ar5523_id_table[] = {
        AR5523_DEVICE_UG(0x07d1, 0x3a07),       /* D-Link / WUA-2340 rev A1 */
        AR5523_DEVICE_UG(0x1690, 0x0712),       /* Gigaset / AR5523 */
        AR5523_DEVICE_UG(0x1690, 0x0710),       /* Gigaset / SMCWUSBTG */
-       AR5523_DEVICE_UG(0x129b, 0x160c),       /* Gigaset / USB stick 108
+       AR5523_DEVICE_UG(0x129b, 0x160b),       /* Gigaset / USB stick 108
                                                   (CyberTAN Technology) */
        AR5523_DEVICE_UG(0x16ab, 0x7801),       /* Globalsun / AR5523_1 */
        AR5523_DEVICE_UX(0x16ab, 0x7811),       /* Globalsun / AR5523_2 */
index d6bc7cb61bfb9b31ffa478fc77aae84ef1c39905..1a2973b7acf2500f5c97c992315793d0b4b9a9a7 100644 (file)
@@ -110,7 +110,7 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band)
                ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
 
        if (ah->ah_version == AR5K_AR5210) {
-               srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+               srev = (ath5k_hw_reg_read(ah, AR5K_PHY(256)) >> 28) & 0xf;
                ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
        } else {
                srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
index 25243cbc07f0ba4ed9c27a6779ff2ea3be7be77d..b8daff78b9d124ed8790223d49ee8871d831b4f1 100644 (file)
@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
                        break;
                }
        }
+
+       if (is2GHz && !twiceMaxEdgePower)
+               twiceMaxEdgePower = 60;
+
        return twiceMaxEdgePower;
 }
 
index 1cc13569b17b8ed7126a9aae49a2d519c360337b..1b6b4d0cfa97a5df8c2a7e0d631c417377ba17b2 100644 (file)
@@ -57,7 +57,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
        {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
        {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
-       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
        {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
        {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
@@ -96,7 +96,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
        {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
        {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-       {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
+       {0x0000ae20, 0x000001a6, 0x000001a6, 0x000001aa, 0x000001aa},
        {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
 };
 
index 58da3468d1f0ac1b3de6522b7118640f2c80da76..99a203174f45a04b50248a370ca4113e256e75ca 100644 (file)
@@ -262,6 +262,8 @@ enum tid_aggr_state {
 struct ath9k_htc_sta {
        u8 index;
        enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID];
+       struct work_struct rc_update_work;
+       struct ath9k_htc_priv *htc_priv;
 };
 
 #define ATH9K_HTC_RXBUF 256
index f4e1de20d99c02a246b08bfed883acc6418af40e..c57d6b859c043207a11883b7a2584241c16aa7dd 100644 (file)
@@ -34,6 +34,10 @@ static int ath9k_htc_btcoex_enable;
 module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
 MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
 
+static int ath9k_ps_enable;
+module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
+MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
+
 #define CHAN2G(_freq, _idx)  { \
        .center_freq = (_freq), \
        .hw_value = (_idx), \
@@ -725,12 +729,14 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
                IEEE80211_HW_SPECTRUM_MGMT |
                IEEE80211_HW_HAS_RATE_CONTROL |
                IEEE80211_HW_RX_INCLUDES_FCS |
-               IEEE80211_HW_SUPPORTS_PS |
                IEEE80211_HW_PS_NULLFUNC_STACK |
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                IEEE80211_HW_MFP_CAPABLE |
                IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
+       if (ath9k_ps_enable)
+               hw->flags |= IEEE80211_HW_SUPPORTS_PS;
+
        hw->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_ADHOC) |
index 608d739d13782233db4271f9248c3472601b1a5f..c9254a61ca52d0984c23efdf4cb01aeb6b40ae23 100644 (file)
@@ -1270,18 +1270,50 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
        mutex_unlock(&priv->mutex);
 }
 
+static void ath9k_htc_sta_rc_update_work(struct work_struct *work)
+{
+       struct ath9k_htc_sta *ista =
+           container_of(work, struct ath9k_htc_sta, rc_update_work);
+       struct ieee80211_sta *sta =
+           container_of((void *)ista, struct ieee80211_sta, drv_priv);
+       struct ath9k_htc_priv *priv = ista->htc_priv;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_target_rate trate;
+
+       mutex_lock(&priv->mutex);
+       ath9k_htc_ps_wakeup(priv);
+
+       memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
+       ath9k_htc_setup_rate(priv, sta, &trate);
+       if (!ath9k_htc_send_rate_cmd(priv, &trate))
+               ath_dbg(common, CONFIG,
+                       "Supported rates for sta: %pM updated, rate caps: 0x%X\n",
+                       sta->addr, be32_to_cpu(trate.capflags));
+       else
+               ath_dbg(common, CONFIG,
+                       "Unable to update supported rates for sta: %pM\n",
+                       sta->addr);
+
+       ath9k_htc_ps_restore(priv);
+       mutex_unlock(&priv->mutex);
+}
+
 static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
                             struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta)
 {
        struct ath9k_htc_priv *priv = hw->priv;
+       struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
        int ret;
 
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
        ret = ath9k_htc_add_station(priv, vif, sta);
-       if (!ret)
+       if (!ret) {
+               INIT_WORK(&ista->rc_update_work, ath9k_htc_sta_rc_update_work);
+               ista->htc_priv = priv;
                ath9k_htc_init_rate(priv, sta);
+       }
        ath9k_htc_ps_restore(priv);
        mutex_unlock(&priv->mutex);
 
@@ -1293,12 +1325,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
                                struct ieee80211_sta *sta)
 {
        struct ath9k_htc_priv *priv = hw->priv;
-       struct ath9k_htc_sta *ista;
+       struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
        int ret;
 
+       cancel_work_sync(&ista->rc_update_work);
+
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
-       ista = (struct ath9k_htc_sta *) sta->drv_priv;
        htc_sta_drain(priv->htc, ista->index);
        ret = ath9k_htc_remove_station(priv, vif, sta);
        ath9k_htc_ps_restore(priv);
@@ -1311,28 +1344,12 @@ static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    struct ieee80211_sta *sta, u32 changed)
 {
-       struct ath9k_htc_priv *priv = hw->priv;
-       struct ath_common *common = ath9k_hw_common(priv->ah);
-       struct ath9k_htc_target_rate trate;
-
-       mutex_lock(&priv->mutex);
-       ath9k_htc_ps_wakeup(priv);
+       struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
 
-       if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
-               memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
-               ath9k_htc_setup_rate(priv, sta, &trate);
-               if (!ath9k_htc_send_rate_cmd(priv, &trate))
-                       ath_dbg(common, CONFIG,
-                               "Supported rates for sta: %pM updated, rate caps: 0x%X\n",
-                               sta->addr, be32_to_cpu(trate.capflags));
-               else
-                       ath_dbg(common, CONFIG,
-                               "Unable to update supported rates for sta: %pM\n",
-                               sta->addr);
-       }
+       if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED))
+               return;
 
-       ath9k_htc_ps_restore(priv);
-       mutex_unlock(&priv->mutex);
+       schedule_work(&ista->rc_update_work);
 }
 
 static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
index fbf43c05713f476f9e6551ad2948dc1ff412970a..9078a6c5a74e3b340266836f7c0151b242ccbc1e 100644 (file)
@@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
        if (AR_SREV_9300_20_OR_LATER(ah))
                udelay(50);
        else if (AR_SREV_9100(ah))
-               udelay(10000);
+               mdelay(10);
        else
                udelay(100);
 
@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
 bool ath9k_hw_check_alive(struct ath_hw *ah)
 {
        int count = 50;
-       u32 reg;
+       u32 reg, last_val;
 
        if (AR_SREV_9300(ah))
                return !ath9k_hw_detect_mac_hang(ah);
@@ -1542,9 +1542,14 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
        if (AR_SREV_9285_12_OR_LATER(ah))
                return true;
 
+       last_val = REG_READ(ah, AR_OBS_BUS_1);
        do {
                reg = REG_READ(ah, AR_OBS_BUS_1);
+               if (reg != last_val)
+                       return true;
 
+               udelay(1);
+               last_val = reg;
                if ((reg & 0x7E7FFFEF) == 0x00702400)
                        continue;
 
@@ -2051,9 +2056,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
 
        REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
                    AR_RTC_FORCE_WAKE_EN);
-
        if (AR_SREV_9100(ah))
-               udelay(10000);
+               mdelay(10);
        else
                udelay(50);
 
index c36de303c8f38d9545ecdb74b575e176ec1b1d25..1fc2e5a26b525b5695be27cd3d29d71b6732118d 100644 (file)
@@ -57,6 +57,10 @@ static int ath9k_bt_ant_diversity;
 module_param_named(bt_ant_diversity, ath9k_bt_ant_diversity, int, 0444);
 MODULE_PARM_DESC(bt_ant_diversity, "Enable WLAN/BT RX antenna diversity");
 
+static int ath9k_ps_enable;
+module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
+MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
+
 bool is_ath9k_unloaded;
 /* We use the hw_value as an index into our private channel structure */
 
@@ -903,13 +907,15 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
                IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
                IEEE80211_HW_SIGNAL_DBM |
-               IEEE80211_HW_SUPPORTS_PS |
                IEEE80211_HW_PS_NULLFUNC_STACK |
                IEEE80211_HW_SPECTRUM_MGMT |
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                IEEE80211_HW_SUPPORTS_RC_TABLE |
                IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
+       if (ath9k_ps_enable)
+               hw->flags |= IEEE80211_HW_SUPPORTS_PS;
+
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
                hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
 
index a0ebdd000fc20f83dac90401ba017dd1ebf3b570..82e340d3ec60a81cc83d2427bd9280e55ca3af3a 100644 (file)
@@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx_buf(struct ath_softc *sc,
                        return NULL;
 
                /*
-                * mark descriptor as zero-length and set the 'more'
-                * flag to ensure that both buffers get discarded
+                * Re-check previous descriptor, in case it has been filled
+                * in the mean time.
                 */
-               rs->rs_datalen = 0;
-               rs->rs_more = true;
+               ret = ath9k_hw_rxprocdesc(ah, ds, rs);
+               if (ret == -EINPROGRESS) {
+                       /*
+                        * mark descriptor as zero-length and set the 'more'
+                        * flag to ensure that both buffers get discarded
+                        */
+                       rs->rs_datalen = 0;
+                       rs->rs_more = true;
+               }
        }
 
        list_del(&bf->list);
@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_hdr *hdr;
        bool discard_current = sc->rx.discard_next;
-       int ret = 0;
 
        /*
         * Discard corrupt descriptors which are marked in
         * ath_get_next_rx_buf().
         */
-       sc->rx.discard_next = rx_stats->rs_more;
        if (discard_current)
-               return -EINVAL;
+               goto corrupt;
+
+       sc->rx.discard_next = false;
 
        /*
         * Discard zero-length packets.
         */
        if (!rx_stats->rs_datalen) {
                RX_STAT_INC(rx_len_err);
-               return -EINVAL;
+               goto corrupt;
        }
 
-        /*
-         * rs_status follows rs_datalen so if rs_datalen is too large
-         * we can take a hint that hardware corrupted it, so ignore
-         * those frames.
-         */
+       /*
+        * rs_status follows rs_datalen so if rs_datalen is too large
+        * we can take a hint that hardware corrupted it, so ignore
+        * those frames.
+        */
        if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
                RX_STAT_INC(rx_len_err);
-               return -EINVAL;
+               goto corrupt;
        }
 
        /* Only use status info from the last fragment */
@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
         * This is different from the other corrupt descriptor
         * condition handled above.
         */
-       if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
-               ret = -EINVAL;
-               goto exit;
-       }
+       if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
+               goto corrupt;
 
        hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
 
@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
                if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
                        RX_STAT_INC(rx_spectral);
 
-               ret = -EINVAL;
-               goto exit;
+               return -EINVAL;
        }
 
        /*
         * everything but the rate is checked here, the rate check is done
         * separately to avoid doing two lookups for a rate for each frame.
         */
-       if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
-               ret = -EINVAL;
-               goto exit;
-       }
+       if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
+               return -EINVAL;
 
        if (ath_is_mybeacon(common, hdr)) {
                RX_STAT_INC(rx_beacons);
@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
        /*
         * This shouldn't happen, but have a safety check anyway.
         */
-       if (WARN_ON(!ah->curchan)) {
-               ret = -EINVAL;
-               goto exit;
-       }
+       if (WARN_ON(!ah->curchan))
+               return -EINVAL;
 
-       if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
-               ret =-EINVAL;
-               goto exit;
-       }
+       if (ath9k_process_rate(common, hw, rx_stats, rx_status))
+               return -EINVAL;
 
        ath9k_process_rssi(common, hw, rx_stats, rx_status);
 
@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
                sc->rx.num_pkts++;
 #endif
 
-exit:
-       sc->rx.discard_next = false;
-       return ret;
+       return 0;
+
+corrupt:
+       sc->rx.discard_next = rx_stats->rs_more;
+       return -EINVAL;
 }
 
 static void ath9k_rx_skb_postprocess(struct ath_common *common,
index 0a75e2f68c9dc30043e32653d78f67799ab8b771..55897d508a76c7220d041f22c077cef2e435fff4 100644 (file)
@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
        for (tidno = 0, tid = &an->tid[tidno];
             tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
 
-               if (!tid->sched)
-                       continue;
-
                ac = tid->ac;
                txq = ac->txq;
 
                ath_txq_lock(sc, txq);
 
+               if (!tid->sched) {
+                       ath_txq_unlock(sc, txq);
+                       continue;
+               }
+
                buffered = ath_tid_has_buffered(tid);
 
                tid->sched = false;
@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
 
        ATH_TXBUF_RESET(bf);
 
-       if (tid) {
+       if (tid && ieee80211_is_data_present(hdr->frame_control)) {
                fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
                seqno = tid->seq_next;
                hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
                txq->stopped = true;
        }
 
+       if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
+               tid = ath_get_skb_tid(sc, txctl->an, skb);
+
        if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
                ath_txq_unlock(sc, txq);
                txq = sc->tx.uapsdq;
                ath_txq_lock(sc, txq);
        } else if (txctl->an &&
                   ieee80211_is_data_present(hdr->frame_control)) {
-               tid = ath_get_skb_tid(sc, txctl->an, skb);
-
                WARN_ON(tid->ac->txq != txctl->txq);
 
                if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
index 3e991897d7ca4dfe856d06f4027fc0dec5c726f1..ddaa9efd053df3a61e404ca96c60cd82dad3f0f2 100644 (file)
@@ -457,7 +457,6 @@ struct brcmf_sdio {
 
        u8 tx_hdrlen;           /* sdio bus header length for tx packet */
        bool txglom;            /* host tx glomming enable flag */
-       struct sk_buff *txglom_sgpad;   /* scatter-gather padding buffer */
        u16 head_align;         /* buffer pointer alignment */
        u16 sgentry_align;      /* scatter-gather buffer alignment */
 };
@@ -1944,19 +1943,21 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
        if (lastfrm && chain_pad)
                tail_pad += blksize - chain_pad;
        if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
-               pkt_pad = bus->txglom_sgpad;
-               if (pkt_pad == NULL)
-                         brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
+               pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop +
+                                               bus->head_align);
                if (pkt_pad == NULL)
                        return -ENOMEM;
                ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad);
-               if (unlikely(ret < 0))
+               if (unlikely(ret < 0)) {
+                       kfree_skb(pkt_pad);
                        return ret;
+               }
                memcpy(pkt_pad->data,
                       pkt->data + pkt->len - tail_chop,
                       tail_chop);
                *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
                skb_trim(pkt, pkt->len - tail_chop);
+               skb_trim(pkt_pad, tail_pad + tail_chop);
                __skb_queue_after(pktq, pkt, pkt_pad);
        } else {
                ntail = pkt->data_len + tail_pad -
@@ -2011,7 +2012,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
                        return ret;
                head_pad = (u16)ret;
                if (head_pad)
-                       memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen);
+                       memset(pkt_next->data + bus->tx_hdrlen, 0, head_pad);
 
                total_len += pkt_next->len;
 
@@ -3486,10 +3487,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
                bus->txglom = false;
                value = 1;
                pad_size = bus->sdiodev->func[2]->cur_blksize << 1;
-               bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size);
-               if (!bus->txglom_sgpad)
-                       brcmf_err("allocating txglom padding skb failed, reduced performance\n");
-
                err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
                                           &value, sizeof(u32));
                if (err < 0) {
@@ -4053,7 +4050,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
                        brcmf_sdio_chip_detach(&bus->ci);
                }
 
-               brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
                kfree(bus->rxbuf);
                kfree(bus->hdrbuf);
                kfree(bus);
index d36e252d2ccbc0041a5b0c1669fe396c2c18db73..596525528f50504afe3005d98ac0ab47d3e26453 100644 (file)
@@ -147,7 +147,7 @@ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
 
        if (!sta->ap && sta->u.sta.challenge)
                kfree(sta->u.sta.challenge);
-       del_timer(&sta->timer);
+       del_timer_sync(&sta->timer);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
        kfree(sta);
index aa7ad3a7a69b058e2e2d148279d3f9c0cc6b2afe..4e5c0f8c949610e9f3a6696f16018ce5bd3fe54e 100644 (file)
@@ -496,7 +496,7 @@ void hostap_init_proc(local_info_t *local)
 
 void hostap_remove_proc(local_info_t *local)
 {
-       remove_proc_subtree(local->ddev->name, hostap_proc);
+       proc_remove(local->proc);
 }
 
 
index c24d1d3d55f66a470d3e62663348e79eb729997f..73086c1629ca13be4e359badffd927a3fee43847 100644 (file)
@@ -696,6 +696,24 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return ret;
 }
 
+static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+               return false;
+       return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+               return false;
+       if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+               return true;
+
+       /* disabled by default */
+       return false;
+}
+
 static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif,
                                   enum ieee80211_ampdu_mlme_action action,
@@ -717,7 +735,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+               if (!iwl_enable_rx_ampdu(priv->cfg))
                        break;
                IWL_DEBUG_HT(priv, "start Rx\n");
                ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
@@ -729,7 +747,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
        case IEEE80211_AMPDU_TX_START:
                if (!priv->trans->ops->txq_enable)
                        break;
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+               if (!iwl_enable_tx_ampdu(priv->cfg))
                        break;
                IWL_DEBUG_HT(priv, "start Tx\n");
                ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
index c0d070c5df5ed73e14a64e141d6a7d2f2a3133b6..9cdd91cdf661825604e9ae8c89649213667b0b0e 100644 (file)
@@ -590,6 +590,7 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
                        sizeof(priv->tid_data[sta_id][tid]));
 
        priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+       priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
 
        priv->num_stations--;
 
index a6839dfcb82dd75029c1e377bbebb078464a8792..398dd096674cf17bd8112e8e7d06ad4ce57427f0 100644 (file)
@@ -1291,8 +1291,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data;
        struct iwl_ht_agg *agg;
        struct sk_buff_head reclaimed_skbs;
-       struct ieee80211_tx_info *info;
-       struct ieee80211_hdr *hdr;
        struct sk_buff *skb;
        int sta_id;
        int tid;
@@ -1379,22 +1377,28 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        freed = 0;
 
        skb_queue_walk(&reclaimed_skbs, skb) {
-               hdr = (struct ieee80211_hdr *)skb->data;
+               struct ieee80211_hdr *hdr = (void *)skb->data;
+               struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (ieee80211_is_data_qos(hdr->frame_control))
                        freed++;
                else
                        WARN_ON_ONCE(1);
 
-               info = IEEE80211_SKB_CB(skb);
                iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
 
+               memset(&info->status, 0, sizeof(info->status));
+               /* Packet was transmitted successfully, failures come as single
+                * frames because before failing a frame the firmware transmits
+                * it without aggregation at least once.
+                */
+               info->flags |= IEEE80211_TX_STAT_ACK;
+
                if (freed == 1) {
                        /* this is the first skb we deliver in this batch */
                        /* put the rate scaling data there */
                        info = IEEE80211_SKB_CB(skb);
                        memset(&info->status, 0, sizeof(info->status));
-                       info->flags |= IEEE80211_TX_STAT_ACK;
                        info->flags |= IEEE80211_TX_STAT_AMPDU;
                        info->status.ampdu_ack_len = ba_resp->txed_2_done;
                        info->status.ampdu_len = ba_resp->txed;
index c3728163be463224b4e3eb38b5573aa85370e193..75103554cd635061628470255dd7a6eae6e8b82f 100644 (file)
@@ -1286,7 +1286,7 @@ module_param_named(swcrypto, iwlwifi_mod_params.sw_crypto, int, S_IRUGO);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
 module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
 MODULE_PARM_DESC(11n_disable,
-       "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
+       "disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
 module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
                   int, S_IRUGO);
 MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
index 0a84ade7edac25b01d28df63158669083c442b8c..b29075c3da8e2e65e8c621c89fda3b5f9b586e79 100644 (file)
@@ -79,9 +79,12 @@ enum iwl_power_level {
        IWL_POWER_NUM
 };
 
-#define IWL_DISABLE_HT_ALL     BIT(0)
-#define IWL_DISABLE_HT_TXAGG   BIT(1)
-#define IWL_DISABLE_HT_RXAGG   BIT(2)
+enum iwl_disable_11n {
+       IWL_DISABLE_HT_ALL       = BIT(0),
+       IWL_DISABLE_HT_TXAGG     = BIT(1),
+       IWL_DISABLE_HT_RXAGG     = BIT(2),
+       IWL_ENABLE_HT_TXAGG      = BIT(3),
+};
 
 /**
  * struct iwl_mod_params
@@ -90,7 +93,7 @@ enum iwl_power_level {
  *
  * @sw_crypto: using hardware encryption, default = 0
  * @disable_11n: disable 11n capabilities, default = 0,
- *     use IWL_DISABLE_HT_* constants
+ *     use IWL_[DIS,EN]ABLE_HT_* constants
  * @amsdu_size_8K: enable 8K amsdu size, default = 0
  * @restart_fw: restart firmware, default = 1
  * @wd_disable: enable stuck queue check, default = 0
index f06f4cbe1317df1c5c035099178bf0aa1116895a..725e954d8475284a0f2b6332d3627c638dd6d01a 100644 (file)
@@ -182,6 +182,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 
        for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) {
                ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
+
+               if (ch_idx >= NUM_2GHZ_CHANNELS &&
+                   !data->sku_cap_band_52GHz_enable)
+                       ch_flags &= ~NVM_CHANNEL_VALID;
+
                if (!(ch_flags & NVM_CHANNEL_VALID)) {
                        IWL_DEBUG_EEPROM(dev,
                                         "Ch. %d Flags %x [%sGHz] - No traffic\n",
index 76cde6ce6551dc0a9996a91edc36cad5b40e5588..18a895a949d4520a02af0f34232f6a739a4c4552 100644 (file)
@@ -872,8 +872,11 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        lockdep_assert_held(&mvm->mutex);
 
-       /* Rssi update while not associated ?! */
-       if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT))
+       /*
+        * Rssi update while not associated - can happen since the statistics
+        * are handled asynchronously
+        */
+       if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
                return;
 
        /* No BT - reports should be disabled */
index 73cbba7424f2be42e5278f85c4e3f54289d06280..9426905de6b283dc0230cf51d5a694478da7797a 100644 (file)
@@ -504,6 +504,7 @@ struct iwl_scan_offload_profile {
  * @match_notify:      clients waiting for match found notification
  * @pass_match:                clients waiting for the results
  * @active_clients:    active clients bitmap - enum scan_framework_client
+ * @any_beacon_notify: clients waiting for match notification without match
  */
 struct iwl_scan_offload_profile_cfg {
        struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
@@ -512,7 +513,8 @@ struct iwl_scan_offload_profile_cfg {
        u8 match_notify;
        u8 pass_match;
        u8 active_clients;
-       u8 reserved[3];
+       u8 any_beacon_notify;
+       u8 reserved[2];
 } __packed;
 
 /**
index c49b5073c2513e39a0c0fb3610209213e1a7e4ea..c35b8661b39539403bd5c2503ac7ec6208cb99e0 100644 (file)
@@ -246,7 +246,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        else
                hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
-       if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) {
+       if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) {
                hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
                hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
                hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
@@ -328,6 +328,24 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
        ieee80211_free_txskb(hw, skb);
 }
 
+static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
+               return false;
+       return true;
+}
+
+static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg)
+{
+       if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
+               return false;
+       if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG)
+               return true;
+
+       /* enabled by default */
+       return true;
+}
+
 static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    enum ieee80211_ampdu_mlme_action action,
@@ -347,7 +365,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 
        switch (action) {
        case IEEE80211_AMPDU_RX_START:
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) {
+               if (!iwl_enable_rx_ampdu(mvm->cfg)) {
                        ret = -EINVAL;
                        break;
                }
@@ -357,7 +375,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
                break;
        case IEEE80211_AMPDU_TX_START:
-               if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) {
+               if (!iwl_enable_tx_ampdu(mvm->cfg)) {
                        ret = -EINVAL;
                        break;
                }
index e4ead86f06d69a7ebb99d2ceede388035dd6c89e..2b0ba1fc3c82fb457a897dbb8fe08d528b12d762 100644 (file)
@@ -152,7 +152,7 @@ enum iwl_power_scheme {
        IWL_POWER_SCHEME_LP
 };
 
-#define IWL_CONN_MAX_LISTEN_INTERVAL   70
+#define IWL_CONN_MAX_LISTEN_INTERVAL   10
 #define IWL_UAPSD_AC_INFO              (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
                                         IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
                                         IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
index 0e0007960612e7866b332e27a1f19af9c5847afc..742afc429c946c0c5defa31de5f7d720071d2485 100644 (file)
@@ -344,7 +344,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
 
        iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0);
 
-       cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL);
+       cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
+                                          TX_CMD_FLG_BT_DIS);
        cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id;
        cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
        cmd->tx_cmd.rate_n_flags =
@@ -807,6 +808,8 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
        profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN;
        profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN;
        profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN;
+       if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len)
+               profile_cfg->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN;
 
        for (i = 0; i < req->n_match_sets; i++) {
                profile = &profile_cfg->profiles[i];
index ec1812133235d8834ab5a235b66794e20d6a9bbd..3397f59cd4e4deb532be48e31c2906b45101f6a5 100644 (file)
@@ -652,7 +652,7 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-       static const u8 *baddr = _baddr;
+       const u8 *baddr = _baddr;
 
        lockdep_assert_held(&mvm->mutex);
 
index 90378c217bc76bba6a10a4d8bf0d02e8005f4673..76ee486039d7a082b9081f835e7b132bf08ecbe5 100644 (file)
@@ -659,8 +659,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
        rcu_read_lock();
 
        sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+       /*
+        * sta can't be NULL otherwise it'd mean that the sta has been freed in
+        * the firmware while we still have packets for it in the Tx queues.
+        */
+       if (WARN_ON_ONCE(!sta))
+               goto out;
 
-       if (!IS_ERR_OR_NULL(sta)) {
+       if (!IS_ERR(sta)) {
                mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
                if (tid != IWL_TID_NON_QOS) {
@@ -675,7 +681,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                        spin_unlock_bh(&mvmsta->lock);
                }
        } else {
-               sta = NULL;
                mvmsta = NULL;
        }
 
@@ -683,42 +688,38 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
         * If the txq is not an AMPDU queue, there is no chance we freed
         * several skbs. Check that out...
         */
-       if (txq_id < mvm->first_agg_queue && !WARN_ON(skb_freed > 1) &&
-           atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) {
-               if (mvmsta) {
-                       /*
-                        * If there are no pending frames for this STA, notify
-                        * mac80211 that this station can go to sleep in its
-                        * STA table.
-                        */
-                       if (mvmsta->vif->type == NL80211_IFTYPE_AP)
-                               ieee80211_sta_block_awake(mvm->hw, sta, false);
-                       /*
-                        * We might very well have taken mvmsta pointer while
-                        * the station was being removed. The remove flow might
-                        * have seen a pending_frame (because we didn't take
-                        * the lock) even if now the queues are drained. So make
-                        * really sure now that this the station is not being
-                        * removed. If it is, run the drain worker to remove it.
-                        */
-                       spin_lock_bh(&mvmsta->lock);
-                       sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
-                       if (!sta || PTR_ERR(sta) == -EBUSY) {
-                               /*
-                                * Station disappeared in the meantime:
-                                * so we are draining.
-                                */
-                               set_bit(sta_id, mvm->sta_drained);
-                               schedule_work(&mvm->sta_drained_wk);
-                       }
-                       spin_unlock_bh(&mvmsta->lock);
-               } else if (!mvmsta && PTR_ERR(sta) == -EBUSY) {
-                       /* Tx response without STA, so we are draining */
-                       set_bit(sta_id, mvm->sta_drained);
-                       schedule_work(&mvm->sta_drained_wk);
-               }
+       if (txq_id >= mvm->first_agg_queue)
+               goto out;
+
+       /* We can't free more than one frame at once on a shared queue */
+       WARN_ON(skb_freed > 1);
+
+       /* If we have still frames from this STA nothing to do here */
+       if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id]))
+               goto out;
+
+       if (mvmsta && mvmsta->vif->type == NL80211_IFTYPE_AP) {
+               /*
+                * If there are no pending frames for this STA, notify
+                * mac80211 that this station can go to sleep in its
+                * STA table.
+                * If mvmsta is not NULL, sta is valid.
+                */
+               ieee80211_sta_block_awake(mvm->hw, sta, false);
        }
 
+       if (PTR_ERR(sta) == -EBUSY || PTR_ERR(sta) == -ENOENT) {
+               /*
+                * We are draining and this was the last packet - pre_rcu_remove
+                * has been called already. We might be after the
+                * synchronize_net already.
+                * Don't rely on iwl_mvm_rm_sta to see the empty Tx queues.
+                */
+               set_bit(sta_id, mvm->sta_drained);
+               schedule_work(&mvm->sta_drained_wk);
+       }
+
+out:
        rcu_read_unlock();
 }
 
@@ -821,16 +822,12 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
        struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data;
        struct sk_buff_head reclaimed_skbs;
        struct iwl_mvm_tid_data *tid_data;
-       struct ieee80211_tx_info *info;
        struct ieee80211_sta *sta;
        struct iwl_mvm_sta *mvmsta;
-       struct ieee80211_hdr *hdr;
        struct sk_buff *skb;
        int sta_id, tid, freed;
-
        /* "flow" corresponds to Tx queue */
        u16 scd_flow = le16_to_cpu(ba_notif->scd_flow);
-
        /* "ssn" is start of block-ack Tx window, corresponds to index
         * (in Tx queue's circular buffer) of first TFD/frame in window */
        u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn);
@@ -887,22 +884,26 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
        freed = 0;
 
        skb_queue_walk(&reclaimed_skbs, skb) {
-               hdr = (struct ieee80211_hdr *)skb->data;
+               struct ieee80211_hdr *hdr = (void *)skb->data;
+               struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (ieee80211_is_data_qos(hdr->frame_control))
                        freed++;
                else
                        WARN_ON_ONCE(1);
 
-               info = IEEE80211_SKB_CB(skb);
                iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]);
 
+               memset(&info->status, 0, sizeof(info->status));
+               /* Packet was transmitted successfully, failures come as single
+                * frames because before failing a frame the firmware transmits
+                * it without aggregation at least once.
+                */
+               info->flags |= IEEE80211_TX_STAT_ACK;
+
                if (freed == 1) {
                        /* this is the first skb we deliver in this batch */
                        /* put the rate scaling data there */
-                       info = IEEE80211_SKB_CB(skb);
-                       memset(&info->status, 0, sizeof(info->status));
-                       info->flags |= IEEE80211_TX_STAT_ACK;
                        info->flags |= IEEE80211_TX_STAT_AMPDU;
                        info->status.ampdu_ack_len = ba_notif->txed_2_done;
                        info->status.ampdu_len = ba_notif->txed;
index a4a5e25623c30044db0333e1a0ced761c976ab89..86989df693566aa5b604be092a7910244cf04aee 100644 (file)
@@ -411,6 +411,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
                        mvm->status, table.valid);
        }
 
+       IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version);
+
        trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
                                      table.data1, table.data2, table.data3,
                                      table.blink1, table.blink2, table.ilink1,
index 3040924f5f3cf187bb12fcc78969548588031346..3872ead75488d6ac485a5cb147a4037988f7ee89 100644 (file)
@@ -359,20 +359,24 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 /* 7265 Series */
        {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5100, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5412, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
index 32f75007a825be6c24b6195d35a9f4e31d590961..cb6d189bc3e60fd9bfeb2e3e696caf822ebb9748 100644 (file)
@@ -621,7 +621,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                        id = *pos++;
                        elen = *pos++;
                        left -= 2;
-                       if (elen > left || elen == 0) {
+                       if (elen > left) {
                                lbs_deb_scan("scan response: invalid IE fmt\n");
                                goto done;
                        }
index 5e0eec4d71c7a5d61e4d65b73ca503aaaf54a085..5d9a8084665d5176fc3b54afd62c1b821c7278df 100644 (file)
@@ -189,8 +189,7 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
                vht_cap->header.len  =
                                cpu_to_le16(sizeof(struct ieee80211_vht_cap));
                memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header),
-                      (u8 *)bss_desc->bcn_vht_cap +
-                      sizeof(struct ieee_types_header),
+                      (u8 *)bss_desc->bcn_vht_cap,
                       le16_to_cpu(vht_cap->header.len));
 
                mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band);
index 6261f8c53d44bd7a6ba4f30651bfc8c67da6f4e5..7db1a89fdd9559fda27bf19a17c114e2b4643d56 100644 (file)
@@ -308,8 +308,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
                ht_cap->header.len =
                                cpu_to_le16(sizeof(struct ieee80211_ht_cap));
                memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header),
-                      (u8 *) bss_desc->bcn_ht_cap +
-                      sizeof(struct ieee_types_header),
+                      (u8 *)bss_desc->bcn_ht_cap,
                       le16_to_cpu(ht_cap->header.len));
 
                mwifiex_fill_cap_info(priv, radio_type, ht_cap);
index 4d79761b9c87e3121dee2c61151d54a5d5002cbe..9d3d2758ec355381ebaceea681e3fd2ebae5d753 100644 (file)
@@ -748,7 +748,7 @@ static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
 
 static u16
 mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
-                               void *accel_priv)
+                               void *accel_priv, select_queue_fallback_t fallback)
 {
        skb->priority = cfg80211_classify8021d(skb, NULL);
        return mwifiex_1d_to_wmm_queue[skb->priority];
index 03688aa14e8adb8575163e3a40aeda4a70a32c19..7fe7b53fb17a28d75cb7fa9a6fc315c9f0ddd937 100644 (file)
@@ -1211,6 +1211,12 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
                rd_index = card->rxbd_rdptr & reg->rx_mask;
                skb_data = card->rx_buf_list[rd_index];
 
+               /* If skb allocation was failed earlier for Rx packet,
+                * rx_buf_list[rd_index] would have been left with a NULL.
+                */
+               if (!skb_data)
+                       return -ENOMEM;
+
                MWIFIEX_SKB_PACB(skb_data, &buf_pa);
                pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE,
                                 PCI_DMA_FROMDEVICE);
@@ -1525,6 +1531,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
                        mwifiex_process_sleep_confirm_resp(adapter, skb->data,
                                                           skb->len);
+                       mwifiex_pcie_enable_host_int(adapter);
+                       if (mwifiex_write_reg(adapter,
+                                             PCIE_CPU_INT_EVENT,
+                                             CPU_INTR_SLEEP_CFM_DONE)) {
+                               dev_warn(adapter->dev,
+                                        "Write register failed\n");
+                               return -1;
+                       }
                        while (reg->sleep_cookie && (count++ < 10) &&
                               mwifiex_pcie_ok_to_access_hw(adapter))
                                usleep_range(50, 60);
@@ -1993,23 +2007,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                adapter->int_status |= pcie_ireg;
                spin_unlock_irqrestore(&adapter->int_lock, flags);
 
-               if (pcie_ireg & HOST_INTR_CMD_DONE) {
-                       if ((adapter->ps_state == PS_STATE_SLEEP_CFM) ||
-                           (adapter->ps_state == PS_STATE_SLEEP)) {
-                               mwifiex_pcie_enable_host_int(adapter);
-                               if (mwifiex_write_reg(adapter,
-                                                     PCIE_CPU_INT_EVENT,
-                                                     CPU_INTR_SLEEP_CFM_DONE)
-                                                     ) {
-                                       dev_warn(adapter->dev,
-                                                "Write register failed\n");
-                                       return;
-
-                               }
-                       }
-               } else if (!adapter->pps_uapsd_mode &&
-                          adapter->ps_state == PS_STATE_SLEEP &&
-                          mwifiex_pcie_ok_to_access_hw(adapter)) {
+               if (!adapter->pps_uapsd_mode &&
+                   adapter->ps_state == PS_STATE_SLEEP &&
+                   mwifiex_pcie_ok_to_access_hw(adapter)) {
                                /* Potentially for PCIe we could get other
                                 * interrupts like shared. Don't change power
                                 * state until cookie is set */
index 0a8a26e10f01a421361a5872065954a8ae79c614..668547c2de8464ed93fedc37066ef0fc3c50f320 100644 (file)
@@ -2101,12 +2101,12 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
                         curr_bss->ht_info_offset);
 
        if (curr_bss->bcn_vht_cap)
-               curr_bss->bcn_ht_cap = (void *)(curr_bss->beacon_buf +
-                                               curr_bss->vht_cap_offset);
+               curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
+                                                curr_bss->vht_cap_offset);
 
        if (curr_bss->bcn_vht_oper)
-               curr_bss->bcn_ht_oper = (void *)(curr_bss->beacon_buf +
-                                                curr_bss->vht_info_offset);
+               curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
+                                                 curr_bss->vht_info_offset);
 
        if (curr_bss->bcn_bss_co_2040)
                curr_bss->bcn_bss_co_2040 =
index e8ebbd4bc3cd3348b271a6d930781cb799b97300..208748804a55ee56dd1d8d7cbb445e7600525db5 100644 (file)
@@ -22,8 +22,6 @@
 
 #define USB_VERSION    "1.0"
 
-static const char usbdriver_name[] = "usb8xxx";
-
 static struct mwifiex_if_ops usb_ops;
 static struct semaphore add_remove_card_sem;
 static struct usb_card_rec *usb_card;
@@ -527,13 +525,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
                                                   MWIFIEX_BSS_ROLE_ANY),
                                  MWIFIEX_ASYNC_CMD);
 
-#ifdef CONFIG_PM
-       /* Resume handler may be called due to remote wakeup,
-        * force to exit suspend anyway
-        */
-       usb_disable_autosuspend(card->udev);
-#endif /* CONFIG_PM */
-
        return 0;
 }
 
@@ -567,13 +558,12 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf)
 }
 
 static struct usb_driver mwifiex_usb_driver = {
-       .name = usbdriver_name,
+       .name = "mwifiex_usb",
        .probe = mwifiex_usb_probe,
        .disconnect = mwifiex_usb_disconnect,
        .id_table = mwifiex_usb_table,
        .suspend = mwifiex_usb_suspend,
        .resume = mwifiex_usb_resume,
-       .supports_autosuspend = 1,
 };
 
 static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter)
index 13eaeed03898288d43abf107090346d513132820..981cf6e7c73be5b65f4a90bb05ef0e9023c592f4 100644 (file)
@@ -559,7 +559,8 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
        mwifiex_wmm_delete_all_ralist(priv);
        memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
 
-       if (priv->adapter->if_ops.clean_pcie_ring)
+       if (priv->adapter->if_ops.clean_pcie_ring &&
+           !priv->adapter->surprise_removed)
                priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
        spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
 }
index abc5f56f29fe1c96c3dc585af30f662c138c1cd7..2f1cd929c6f6d004b35ddf61197d83b2a57d7b2a 100644 (file)
@@ -1876,6 +1876,11 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
 
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
        /*
         * Initialize hw_mode information.
         */
index 9f16824cd1bccf80407633fa0864d1d7f0d6d257..d849d590de250b915ddda53ce64c703beef3215e 100644 (file)
@@ -1706,6 +1706,11 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_SUPPORTS_PS |
            IEEE80211_HW_PS_NULLFUNC_STACK;
 
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
        SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
index b8f5b06006c4393358d9be88cb11ef4f389476ef..41d4a8167dc32f368a8fdf061bea4fe9944fd0f1 100644 (file)
@@ -5460,14 +5460,15 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 
        rt2800_bbp_write(rt2x00dev, 68, 0x0b);
 
-       rt2800_bbp_write(rt2x00dev, 69, 0x0d);
-       rt2800_bbp_write(rt2x00dev, 70, 0x06);
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
        rt2800_bbp_write(rt2x00dev, 73, 0x13);
        rt2800_bbp_write(rt2x00dev, 75, 0x46);
        rt2800_bbp_write(rt2x00dev, 76, 0x28);
 
        rt2800_bbp_write(rt2x00dev, 77, 0x59);
 
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
        rt2800_bbp_write(rt2x00dev, 79, 0x13);
        rt2800_bbp_write(rt2x00dev, 80, 0x05);
        rt2800_bbp_write(rt2x00dev, 81, 0x33);
@@ -5510,7 +5511,6 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_rt(rt2x00dev, RT5392)) {
                rt2800_bbp_write(rt2x00dev, 134, 0xd0);
                rt2800_bbp_write(rt2x00dev, 135, 0xf6);
-               rt2800_bbp_write(rt2x00dev, 148, 0x84);
        }
 
        rt2800_disable_unused_dac_adc(rt2x00dev);
@@ -7458,10 +7458,9 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        u32 reg;
 
        /*
-        * Disable powersaving as default on PCI devices.
+        * Disable powersaving as default.
         */
-       if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
-               rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        /*
         * Initialize all hw fields.
index caddc1b427a919659200c539552a619af49c5d17..42a2e06512f2f0900ac7f9384b1e247013f2b11d 100644 (file)
@@ -764,7 +764,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        /*
         * Overwrite TX done handler
         */
-       PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
+       INIT_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
 
        return 0;
 }
index 8ec17aad0e520019fa0f93fbd50f1999885ea9ad..3867d1470b36aef5664bcab74e85f38702c8315d 100644 (file)
@@ -107,6 +107,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
        struct rtl8180_priv *priv = dev->priv;
        unsigned int count = 32;
        u8 signal, agc, sq;
+       dma_addr_t mapping;
 
        while (count--) {
                struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
@@ -128,6 +129,17 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
                        if (unlikely(!new_skb))
                                goto done;
 
+                       mapping = pci_map_single(priv->pdev,
+                                              skb_tail_pointer(new_skb),
+                                              MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+
+                       if (pci_dma_mapping_error(priv->pdev, mapping)) {
+                               kfree_skb(new_skb);
+                               dev_err(&priv->pdev->dev, "RX DMA map error\n");
+
+                               goto done;
+                       }
+
                        pci_unmap_single(priv->pdev,
                                         *((dma_addr_t *)skb->cb),
                                         MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
@@ -158,9 +170,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
 
                        skb = new_skb;
                        priv->rx_buf[priv->rx_idx] = skb;
-                       *((dma_addr_t *) skb->cb) =
-                               pci_map_single(priv->pdev, skb_tail_pointer(skb),
-                                              MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+                       *((dma_addr_t *) skb->cb) = mapping;
                }
 
        done:
@@ -266,6 +276,13 @@ static void rtl8180_tx(struct ieee80211_hw *dev,
        mapping = pci_map_single(priv->pdev, skb->data,
                                 skb->len, PCI_DMA_TODEVICE);
 
+       if (pci_dma_mapping_error(priv->pdev, mapping)) {
+               kfree_skb(skb);
+               dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
+               return;
+
+       }
+
        tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS |
                   RTL818X_TX_DESC_FLAG_LS |
                   (ieee80211_get_tx_rate(dev, info)->hw_value << 24) |
index 56aee067f324694ef5c83b376bac600c52b845cf..a6ad79f61bf9bc026328c8be87414a5a7ef223d8 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef RTL8187_H
 #define RTL8187_H
 
+#include <linux/cache.h>
+
 #include "rtl818x.h"
 #include "leds.h"
 
@@ -139,7 +141,10 @@ struct rtl8187_priv {
        u8 aifsn[4];
        u8 rfkill_mask;
        struct {
-               __le64 buf;
+               union {
+                       __le64 buf;
+                       u8 dummy1[L1_CACHE_BYTES];
+               } ____cacheline_aligned;
                struct sk_buff_head queue;
        } b_tx_status; /* This queue is used by both -b and non-b devices */
        struct mutex io_mutex;
@@ -147,7 +152,8 @@ struct rtl8187_priv {
                u8 bits8;
                __le16 bits16;
                __le32 bits32;
-       } *io_dmabuf;
+               u8 dummy2[L1_CACHE_BYTES];
+       } *io_dmabuf ____cacheline_aligned;
        bool rfkill_off;
        u16 seqno;
 };
index deedae3c54498370462ef4bc1bde40d7749ee0c8..d1c0191a195b909e5095fde8807eb671b307e374 100644 (file)
@@ -48,7 +48,7 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
 
        /*<2> Enable Adapter */
        if (rtlpriv->cfg->ops->hw_init(hw))
-               return 1;
+               return false;
        RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 
        /*<3> Enable Interrupt */
index a82b30a1996ca97cc5041ac47899171fef15e25e..2eb0b38384dd7cef1323f5817be961954d31f514 100644 (file)
@@ -937,14 +937,26 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
        bool is92c;
        int err;
        u8 tmp_u1b;
+       unsigned long flags;
 
        rtlpci->being_init_adapter = true;
+
+       /* Since this function can take a very long time (up to 350 ms)
+        * and can be called with irqs disabled, reenable the irqs
+        * to let the other devices continue being serviced.
+        *
+        * It is safe doing so since our own interrupts will only be enabled
+        * in a subsequent step.
+        */
+       local_save_flags(flags);
+       local_irq_enable();
+
        rtlpriv->intf_ops->disable_aspm(hw);
        rtstatus = _rtl92ce_init_mac(hw);
        if (!rtstatus) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
                err = 1;
-               return err;
+               goto exit;
        }
 
        err = rtl92c_download_fw(hw);
@@ -952,7 +964,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
                         "Failed to download FW. Init HW without FW now..\n");
                err = 1;
-               return err;
+               goto exit;
        }
 
        rtlhal->last_hmeboxnum = 0;
@@ -1032,6 +1044,8 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n");
        }
        rtl92c_dm_init(hw);
+exit:
+       local_irq_restore(flags);
        rtlpci->being_init_adapter = false;
        return err;
 }
index 123c4bb50e0a0c2eff220c4509c2ece5aab7b365..cde0eaf99714b4054176bd7a3cad9e850d97abea 100644 (file)
@@ -180,7 +180,7 @@ static void wl1251_rx_body(struct wl1251 *wl,
        wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
 
        /* The actual length doesn't include the target's alignment */
-       skb->len = desc->length  - PLCP_HEADER_LENGTH;
+       skb_trim(skb, desc->length - PLCP_HEADER_LENGTH);
 
        fc = (u16 *)skb->data;
 
index 4c76bcb9a879d23ad98aae968d529450606db6f8..ae413a2cbee71402b5cc3732940d262237d6c792 100644 (file)
@@ -143,11 +143,7 @@ struct xenvif {
        char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */
        struct xen_netif_rx_back_ring rx;
        struct sk_buff_head rx_queue;
-       bool rx_queue_stopped;
-       /* Set when the RX interrupt is triggered by the frontend.
-        * The worker thread may need to wake the queue.
-        */
-       bool rx_event;
+       RING_IDX rx_last_skb_slots;
 
        /* This array is allocated seperately as it is large */
        struct gnttab_copy *grant_copy_op;
index b9de31ea7fc48ac333f30dfa17041fdef893895a..301cc037fda886f2bc2de48a347a8693eadee178 100644 (file)
@@ -100,7 +100,6 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
 {
        struct xenvif *vif = dev_id;
 
-       vif->rx_event = true;
        xenvif_kick_thread(vif);
 
        return IRQ_HANDLED;
@@ -133,8 +132,7 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* If the skb is GSO then we'll also need an extra slot for the
         * metadata.
         */
-       if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
-           skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+       if (skb_is_gso(skb))
                min_slots_needed++;
 
        /* If the skb can't possibly fit in the remaining slots
index 6b62c3eb8e181411ab8508828ab1bacbb465d26a..438d0c09b7e6019b513f8e996f5549bb327463d2 100644 (file)
@@ -240,7 +240,7 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
        struct gnttab_copy *copy_gop;
        struct xenvif_rx_meta *meta;
        unsigned long bytes;
-       int gso_type;
+       int gso_type = XEN_NETIF_GSO_TYPE_NONE;
 
        /* Data must not cross a page boundary. */
        BUG_ON(size + offset > PAGE_SIZE<<compound_order(page));
@@ -299,12 +299,12 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
                }
 
                /* Leave a gap for the GSO descriptor. */
-               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
-                       gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
-               else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
-                       gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
-               else
-                       gso_type = XEN_NETIF_GSO_TYPE_NONE;
+               if (skb_is_gso(skb)) {
+                       if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+                               gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
+                       else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+                               gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
+               }
 
                if (*head && ((1 << gso_type) & vif->gso_mask))
                        vif->rx.req_cons++;
@@ -338,19 +338,15 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        int head = 1;
        int old_meta_prod;
        int gso_type;
-       int gso_size;
 
        old_meta_prod = npo->meta_prod;
 
-       if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
-               gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
-               gso_size = skb_shinfo(skb)->gso_size;
-       } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
-               gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
-               gso_size = skb_shinfo(skb)->gso_size;
-       } else {
-               gso_type = XEN_NETIF_GSO_TYPE_NONE;
-               gso_size = 0;
+       gso_type = XEN_NETIF_GSO_TYPE_NONE;
+       if (skb_is_gso(skb)) {
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+                       gso_type = XEN_NETIF_GSO_TYPE_TCPV4;
+               else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+                       gso_type = XEN_NETIF_GSO_TYPE_TCPV6;
        }
 
        /* Set up a GSO prefix descriptor, if necessary */
@@ -358,7 +354,7 @@ static int xenvif_gop_skb(struct sk_buff *skb,
                req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
                meta = npo->meta + npo->meta_prod++;
                meta->gso_type = gso_type;
-               meta->gso_size = gso_size;
+               meta->gso_size = skb_shinfo(skb)->gso_size;
                meta->size = 0;
                meta->id = req->id;
        }
@@ -368,7 +364,7 @@ static int xenvif_gop_skb(struct sk_buff *skb,
 
        if ((1 << gso_type) & vif->gso_mask) {
                meta->gso_type = gso_type;
-               meta->gso_size = gso_size;
+               meta->gso_size = skb_shinfo(skb)->gso_size;
        } else {
                meta->gso_type = XEN_NETIF_GSO_TYPE_NONE;
                meta->gso_size = 0;
@@ -476,7 +472,6 @@ static void xenvif_rx_action(struct xenvif *vif)
        unsigned long offset;
        struct skb_cb_overlay *sco;
        bool need_to_notify = false;
-       bool ring_full = false;
 
        struct netrx_pending_operations npo = {
                .copy  = vif->grant_copy_op,
@@ -486,7 +481,7 @@ static void xenvif_rx_action(struct xenvif *vif)
        skb_queue_head_init(&rxq);
 
        while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) {
-               int max_slots_needed;
+               RING_IDX max_slots_needed;
                int i;
 
                /* We need a cheap worse case estimate for the number of
@@ -501,17 +496,19 @@ static void xenvif_rx_action(struct xenvif *vif)
                        size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
                        max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE);
                }
-               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
-                   skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+               if (skb_is_gso(skb) &&
+                  (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
+                   skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6))
                        max_slots_needed++;
 
                /* If the skb may not fit then bail out now */
                if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) {
                        skb_queue_head(&vif->rx_queue, skb);
                        need_to_notify = true;
-                       ring_full = true;
+                       vif->rx_last_skb_slots = max_slots_needed;
                        break;
-               }
+               } else
+                       vif->rx_last_skb_slots = 0;
 
                sco = (struct skb_cb_overlay *)skb->cb;
                sco->meta_slots_used = xenvif_gop_skb(skb, &npo);
@@ -522,8 +519,6 @@ static void xenvif_rx_action(struct xenvif *vif)
 
        BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta));
 
-       vif->rx_queue_stopped = !npo.copy_prod && ring_full;
-
        if (!npo.copy_prod)
                goto done;
 
@@ -1473,8 +1468,8 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
 
 static inline int rx_work_todo(struct xenvif *vif)
 {
-       return (!skb_queue_empty(&vif->rx_queue) && !vif->rx_queue_stopped) ||
-               vif->rx_event;
+       return !skb_queue_empty(&vif->rx_queue) &&
+              xenvif_rx_ring_slots_available(vif, vif->rx_last_skb_slots);
 }
 
 static inline int tx_work_todo(struct xenvif *vif)
@@ -1560,8 +1555,6 @@ int xenvif_kthread(void *data)
                if (!skb_queue_empty(&vif->rx_queue))
                        xenvif_rx_action(vif);
 
-               vif->rx_event = false;
-
                if (skb_queue_empty(&vif->rx_queue) &&
                    netif_queue_stopped(vif->dev))
                        xenvif_start_queue(vif);
index ff04d4f95baa3561fbf42899bf95f69eab28412f..e30d80033cbc4bb4f93d4e84897ff6fb29417a91 100644 (file)
@@ -907,6 +907,7 @@ static int handle_incoming_queue(struct net_device *dev,
 
                /* Ethernet work: Delayed to here as it peeks the header. */
                skb->protocol = eth_type_trans(skb, dev);
+               skb_reset_network_header(skb);
 
                if (checksum_setup(dev, skb)) {
                        kfree_skb(skb);
@@ -1832,7 +1833,6 @@ static void netback_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -1847,6 +1847,10 @@ static void netback_changed(struct xenbus_device *dev,
                netdev_notify_peers(netdev);
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index d3dd41c840f1cd8d6784e4a61382cb3e4987ad1a..1a54f1ffaadb65d6a2d1d0735eea6e8eefbf09da 100644 (file)
@@ -99,11 +99,12 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr)
 static int of_bus_pci_match(struct device_node *np)
 {
        /*
+        * "pciex" is PCI Express
         * "vci" is for the /chaos bridge on 1st-gen PCI powermacs
         * "ht" is hypertransport
         */
-       return !strcmp(np->type, "pci") || !strcmp(np->type, "vci") ||
-               !strcmp(np->type, "ht");
+       return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex") ||
+               !strcmp(np->type, "vci") || !strcmp(np->type, "ht");
 }
 
 static void of_bus_pci_count_cells(struct device_node *np,
index ff85450d568399b1dec3fe6bf892c974ca28bedd..89e888a78899e2b61281f7007406e5f937cc28a0 100644 (file)
@@ -342,27 +342,72 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-/** Checks if the given "compat" string matches one of the strings in
- * the device's "compatible" property
+/**
+ * __of_device_is_compatible() - Check if the node matches given constraints
+ * @device: pointer to node
+ * @compat: required compatible string, NULL or "" for any match
+ * @type: required device_type value, NULL or "" for any match
+ * @name: required node name, NULL or "" for any match
+ *
+ * Checks if the given @compat, @type and @name strings match the
+ * properties of the given @device. A constraints can be skipped by
+ * passing NULL or an empty string as the constraint.
+ *
+ * Returns 0 for no match, and a positive integer on match. The return
+ * value is a relative score with larger values indicating better
+ * matches. The score is weighted for the most specific compatible value
+ * to get the highest score. Matching type is next, followed by matching
+ * name. Practically speaking, this results in the following priority
+ * order for matches:
+ *
+ * 1. specific compatible && type && name
+ * 2. specific compatible && type
+ * 3. specific compatible && name
+ * 4. specific compatible
+ * 5. general compatible && type && name
+ * 6. general compatible && type
+ * 7. general compatible && name
+ * 8. general compatible
+ * 9. type && name
+ * 10. type
+ * 11. name
  */
 static int __of_device_is_compatible(const struct device_node *device,
-                                    const char *compat)
+                                    const char *compat, const char *type, const char *name)
 {
-       const char* cp;
-       int cplen, l;
+       struct property *prop;
+       const char *cp;
+       int index = 0, score = 0;
+
+       /* Compatible match has highest priority */
+       if (compat && compat[0]) {
+               prop = __of_find_property(device, "compatible", NULL);
+               for (cp = of_prop_next_string(prop, NULL); cp;
+                    cp = of_prop_next_string(prop, cp), index++) {
+                       if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
+                               score = INT_MAX/2 - (index << 2);
+                               break;
+                       }
+               }
+               if (!score)
+                       return 0;
+       }
 
-       cp = __of_get_property(device, "compatible", &cplen);
-       if (cp == NULL)
-               return 0;
-       while (cplen > 0) {
-               if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
-                       return 1;
-               l = strlen(cp) + 1;
-               cp += l;
-               cplen -= l;
+       /* Matching type is better than matching name */
+       if (type && type[0]) {
+               if (!device->type || of_node_cmp(type, device->type))
+                       return 0;
+               score += 2;
        }
 
-       return 0;
+       /* Matching name is a bit better than not */
+       if (name && name[0]) {
+               if (!device->name || of_node_cmp(name, device->name))
+                       return 0;
+               score++;
+       }
+
+       return score;
 }
 
 /** Checks if the given "compat" string matches one of the strings in
@@ -375,7 +420,7 @@ int of_device_is_compatible(const struct device_node *device,
        int res;
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       res = __of_device_is_compatible(device, compat);
+       res = __of_device_is_compatible(device, compat, NULL, NULL);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return res;
 }
@@ -681,10 +726,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
        raw_spin_lock_irqsave(&devtree_lock, flags);
        np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
-               if (type
-                   && !(np->type && (of_node_cmp(np->type, type) == 0)))
-                       continue;
-               if (__of_device_is_compatible(np, compatible) &&
+               if (__of_device_is_compatible(np, compatible, type, NULL) &&
                    of_node_get(np))
                        break;
        }
@@ -734,43 +776,22 @@ static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
                                           const struct device_node *node)
 {
-       const char *cp;
-       int cplen, l;
+       const struct of_device_id *best_match = NULL;
+       int score, best_score = 0;
 
        if (!matches)
                return NULL;
 
-       cp = __of_get_property(node, "compatible", &cplen);
-       do {
-               const struct of_device_id *m = matches;
-
-               /* Check against matches with current compatible string */
-               while (m->name[0] || m->type[0] || m->compatible[0]) {
-                       int match = 1;
-                       if (m->name[0])
-                               match &= node->name
-                                       && !strcmp(m->name, node->name);
-                       if (m->type[0])
-                               match &= node->type
-                                       && !strcmp(m->type, node->type);
-                       if (m->compatible[0])
-                               match &= cp
-                                       && !of_compat_cmp(m->compatible, cp,
-                                                       strlen(m->compatible));
-                       if (match)
-                               return m;
-                       m++;
-               }
-
-               /* Get node's next compatible string */ 
-               if (cp) {
-                       l = strlen(cp) + 1;
-                       cp += l;
-                       cplen -= l;
+       for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
+               score = __of_device_is_compatible(node, matches->compatible,
+                                                 matches->type, matches->name);
+               if (score > best_score) {
+                       best_match = matches;
+                       best_score = score;
                }
-       } while (cp && (cplen > 0));
+       }
 
-       return NULL;
+       return best_match;
 }
 
 /**
@@ -778,10 +799,7 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
  *     @matches:       array of of device match structures to search in
  *     @node:          the of device structure to match against
  *
- *     Low level utility function used by device matching. Matching order
- *     is to compare each of the node's compatibles with all given matches
- *     first. This implies node's compatible is sorted from specific to
- *     generic while matches can be in any order.
+ *     Low level utility function used by device matching.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                         const struct device_node *node)
index 875b7b6f0d2a48bfdac42f40d6927cf59e6cf552..5b3c24f3cde57e8f0c26f578c1ef12fd0d58d650 100644 (file)
@@ -24,7 +24,11 @@ MODULE_LICENSE("GPL");
 
 static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed)
 {
-       phydev->supported |= PHY_DEFAULT_FEATURES;
+       /* The default values for phydev->supported are provided by the PHY
+        * driver "features" member, we want to reset to sane defaults fist
+        * before supporting higher speeds.
+        */
+       phydev->supported &= PHY_DEFAULT_FEATURES;
 
        switch (max_speed) {
        default:
@@ -44,7 +48,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
 {
        struct phy_device *phy;
        bool is_c45;
-       int rc, prev_irq;
+       int rc;
        u32 max_speed = 0;
 
        is_c45 = of_device_is_compatible(child,
@@ -54,12 +58,14 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
        if (!phy || IS_ERR(phy))
                return 1;
 
-       if (mdio->irq) {
-               prev_irq = mdio->irq[addr];
-               mdio->irq[addr] =
-                       irq_of_parse_and_map(child, 0);
-               if (!mdio->irq[addr])
-                       mdio->irq[addr] = prev_irq;
+       rc = irq_of_parse_and_map(child, 0);
+       if (rc > 0) {
+               phy->irq = rc;
+               if (mdio->irq)
+                       mdio->irq[addr] = rc;
+       } else {
+               if (mdio->irq)
+                       phy->irq = mdio->irq[addr];
        }
 
        /* Associate the OF node with the device structure so it
index e21012bde639cde305a8c14aab011fad020a7da2..6643d19209857dae4f6d2d1f9a3033280e2cc25e 100644 (file)
@@ -300,6 +300,72 @@ static void __init of_selftest_parse_interrupts_extended(void)
        of_node_put(np);
 }
 
+static struct of_device_id match_node_table[] = {
+       { .data = "A", .name = "name0", }, /* Name alone is lowest priority */
+       { .data = "B", .type = "type1", }, /* followed by type alone */
+
+       { .data = "Ca", .name = "name2", .type = "type1", }, /* followed by both together */
+       { .data = "Cb", .name = "name2", }, /* Only match when type doesn't match */
+       { .data = "Cc", .name = "name2", .type = "type2", },
+
+       { .data = "E", .compatible = "compat3" },
+       { .data = "G", .compatible = "compat2", },
+       { .data = "H", .compatible = "compat2", .name = "name5", },
+       { .data = "I", .compatible = "compat2", .type = "type1", },
+       { .data = "J", .compatible = "compat2", .type = "type1", .name = "name8", },
+       { .data = "K", .compatible = "compat2", .name = "name9", },
+       {}
+};
+
+static struct {
+       const char *path;
+       const char *data;
+} match_node_tests[] = {
+       { .path = "/testcase-data/match-node/name0", .data = "A", },
+       { .path = "/testcase-data/match-node/name1", .data = "B", },
+       { .path = "/testcase-data/match-node/a/name2", .data = "Ca", },
+       { .path = "/testcase-data/match-node/b/name2", .data = "Cb", },
+       { .path = "/testcase-data/match-node/c/name2", .data = "Cc", },
+       { .path = "/testcase-data/match-node/name3", .data = "E", },
+       { .path = "/testcase-data/match-node/name4", .data = "G", },
+       { .path = "/testcase-data/match-node/name5", .data = "H", },
+       { .path = "/testcase-data/match-node/name6", .data = "G", },
+       { .path = "/testcase-data/match-node/name7", .data = "I", },
+       { .path = "/testcase-data/match-node/name8", .data = "J", },
+       { .path = "/testcase-data/match-node/name9", .data = "K", },
+};
+
+static void __init of_selftest_match_node(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(match_node_tests); i++) {
+               np = of_find_node_by_path(match_node_tests[i].path);
+               if (!np) {
+                       selftest(0, "missing testcase node %s\n",
+                               match_node_tests[i].path);
+                       continue;
+               }
+
+               match = of_match_node(match_node_table, np);
+               if (!match) {
+                       selftest(0, "%s didn't match anything\n",
+                               match_node_tests[i].path);
+                       continue;
+               }
+
+               if (strcmp(match->data, match_node_tests[i].data) != 0) {
+                       selftest(0, "%s got wrong match. expected %s, got %s\n",
+                               match_node_tests[i].path, match_node_tests[i].data,
+                               (const char *)match->data);
+                       continue;
+               }
+               selftest(1, "passed");
+       }
+}
+
 static int __init of_selftest(void)
 {
        struct device_node *np;
@@ -316,6 +382,7 @@ static int __init of_selftest(void)
        of_selftest_property_match_string();
        of_selftest_parse_interrupts();
        of_selftest_parse_interrupts_extended();
+       of_selftest_match_node();
        pr_info("end of selftest - %i passed, %i failed\n",
                selftest_results.passed, selftest_results.failed);
        return 0;
diff --git a/drivers/of/testcase-data/testcases.dtsi b/drivers/of/testcase-data/testcases.dtsi
new file mode 100644 (file)
index 0000000..3a5b75a
--- /dev/null
@@ -0,0 +1,3 @@
+#include "tests-phandle.dtsi"
+#include "tests-interrupts.dtsi"
+#include "tests-match.dtsi"
diff --git a/drivers/of/testcase-data/tests-interrupts.dtsi b/drivers/of/testcase-data/tests-interrupts.dtsi
new file mode 100644 (file)
index 0000000..c843720
--- /dev/null
@@ -0,0 +1,58 @@
+
+/ {
+       testcase-data {
+               interrupts {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       test_intc0: intc0 {
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                       };
+
+                       test_intc1: intc1 {
+                               interrupt-controller;
+                               #interrupt-cells = <3>;
+                       };
+
+                       test_intc2: intc2 {
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       test_intmap0: intmap0 {
+                               #interrupt-cells = <1>;
+                               #address-cells = <0>;
+                               interrupt-map = <1 &test_intc0 9>,
+                                               <2 &test_intc1 10 11 12>,
+                                               <3 &test_intc2 13 14>,
+                                               <4 &test_intc2 15 16>;
+                       };
+
+                       test_intmap1: intmap1 {
+                               #interrupt-cells = <2>;
+                               interrupt-map = <0x5000 1 2 &test_intc0 15>;
+                       };
+
+                       interrupts0 {
+                               interrupt-parent = <&test_intc0>;
+                               interrupts = <1>, <2>, <3>, <4>;
+                       };
+
+                       interrupts1 {
+                               interrupt-parent = <&test_intmap0>;
+                               interrupts = <1>, <2>, <3>, <4>;
+                       };
+
+                       interrupts-extended0 {
+                               reg = <0x5000 0x100>;
+                               interrupts-extended = <&test_intc0 1>,
+                                                     <&test_intc1 2 3 4>,
+                                                     <&test_intc2 5 6>,
+                                                     <&test_intmap0 1>,
+                                                     <&test_intmap0 2>,
+                                                     <&test_intmap0 3>,
+                                                     <&test_intmap1 1 2>;
+                       };
+               };
+       };
+};
diff --git a/drivers/of/testcase-data/tests-match.dtsi b/drivers/of/testcase-data/tests-match.dtsi
new file mode 100644 (file)
index 0000000..c9e5411
--- /dev/null
@@ -0,0 +1,19 @@
+
+/ {
+       testcase-data {
+               match-node {
+                       name0 { };
+                       name1 { device_type = "type1"; };
+                       a { name2 { device_type = "type1"; }; };
+                       b { name2 { }; };
+                       c { name2 { device_type = "type2"; }; };
+                       name3 { compatible = "compat3"; };
+                       name4 { compatible = "compat2", "compat3"; };
+                       name5 { compatible = "compat2", "compat3"; };
+                       name6 { compatible = "compat1", "compat2", "compat3"; };
+                       name7 { compatible = "compat2"; device_type = "type1"; };
+                       name8 { compatible = "compat2"; device_type = "type1"; };
+                       name9 { compatible = "compat2"; };
+               };
+       };
+};
diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi
new file mode 100644 (file)
index 0000000..0007d3c
--- /dev/null
@@ -0,0 +1,39 @@
+
+/ {
+       testcase-data {
+               phandle-tests {
+                       provider0: provider0 {
+                               #phandle-cells = <0>;
+                       };
+
+                       provider1: provider1 {
+                               #phandle-cells = <1>;
+                       };
+
+                       provider2: provider2 {
+                               #phandle-cells = <2>;
+                       };
+
+                       provider3: provider3 {
+                               #phandle-cells = <3>;
+                       };
+
+                       consumer-a {
+                               phandle-list =  <&provider1 1>,
+                                               <&provider2 2 0>,
+                                               <0>,
+                                               <&provider3 4 4 3>,
+                                               <&provider2 5 100>,
+                                               <&provider0>,
+                                               <&provider1 7>;
+                               phandle-list-names = "first", "second", "third";
+
+                               phandle-list-bad-phandle = <12345678 0 0>;
+                               phandle-list-bad-args = <&provider2 1 0>,
+                                                       <&provider3 0>;
+                               empty-property;
+                               unterminated-string = [40 41 42 43];
+                       };
+               };
+       };
+};
index 00660cc502c5e0df1da9946281ba2b6fa6d08afc..38901665c77086a20a6bd1cd087f24971c0d172b 100644 (file)
@@ -162,8 +162,6 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
 
                avail = *r;
                pci_clip_resource_to_region(bus, &avail, region);
-               if (!resource_size(&avail))
-                       continue;
 
                /*
                 * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to
index 13478ecd411306115b666a9e344754966ce3012b..0e79665afd445ebb8e6198a274960978c58c619e 100644 (file)
 #define PCIE_DEBUG_CTRL         0x1a60
 #define  PCIE_DEBUG_SOFT_RESET         BIT(20)
 
-/*
- * This product ID is registered by Marvell, and used when the Marvell
- * SoC is not the root complex, but an endpoint on the PCIe bus. It is
- * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI
- * bridge.
- */
-#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846
-
 /* PCI configuration space of a PCI-to-PCI bridge */
 struct mvebu_sw_pci_bridge {
        u16 vendor;
@@ -388,7 +380,8 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
 
        bridge->class = PCI_CLASS_BRIDGE_PCI;
        bridge->vendor = PCI_VENDOR_ID_MARVELL;
-       bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
+       bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16;
+       bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff;
        bridge->header_type = PCI_HEADER_TYPE_BRIDGE;
        bridge->cache_line_size = 0x10;
 
index cd929aed3613314068ed7a4baf2bb6e5c6cb9f1f..7c7a388c85ab3679732f7971552790057abec4f5 100644 (file)
@@ -210,10 +210,29 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
        }
 }
 
+static void dock_event(acpi_handle handle, u32 type, void *data)
+{
+       struct acpiphp_context *context;
+
+       mutex_lock(&acpiphp_context_lock);
+       context = acpiphp_get_context(handle);
+       if (!context || WARN_ON(context->handle != handle)
+           || context->func.parent->is_going_away) {
+               mutex_unlock(&acpiphp_context_lock);
+               return;
+       }
+       get_bridge(context->func.parent);
+       acpiphp_put_context(context);
+       mutex_unlock(&acpiphp_context_lock);
+
+       hotplug_event(handle, type, data);
+
+       put_bridge(context->func.parent);
+}
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
        .fixup = post_dock_fixups,
-       .handler = hotplug_event,
+       .handler = dock_event,
 };
 
 /* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -441,7 +460,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
        list_del(&bridge->list);
        mutex_unlock(&bridge_mutex);
 
+       mutex_lock(&acpiphp_context_lock);
        bridge->is_going_away = true;
+       mutex_unlock(&acpiphp_context_lock);
 }
 
 /**
@@ -709,6 +730,17 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
        return (unsigned int)sta;
 }
 
+static inline bool device_status_valid(unsigned int sta)
+{
+       /*
+        * ACPI spec says that _STA may return bit 0 clear with bit 3 set
+        * if the device is valid but does not require a device driver to be
+        * loaded (Section 6.3.7 of ACPI 5.0A).
+        */
+       unsigned int mask = ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_FUNCTIONING;
+       return (sta & mask) == mask;
+}
+
 /**
  * trim_stale_devices - remove PCI devices that are not responding.
  * @dev: PCI device to start walking the hierarchy from.
@@ -724,7 +756,7 @@ static void trim_stale_devices(struct pci_dev *dev)
                unsigned long long sta;
 
                status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-               alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
+               alive = (ACPI_SUCCESS(status) && device_status_valid(sta))
                        || acpiphp_no_hotplug(handle);
        }
        if (!alive) {
@@ -742,7 +774,7 @@ static void trim_stale_devices(struct pci_dev *dev)
 
                /* The device is a bridge. so check the bus below it. */
                pm_runtime_get_sync(&dev->dev);
-               list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+               list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
                        trim_stale_devices(child);
 
                pm_runtime_put(&dev->dev);
@@ -771,10 +803,10 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                mutex_lock(&slot->crit_sect);
                if (slot_no_hotplug(slot)) {
                        ; /* do nothing */
-               } else if (get_slot_status(slot) == ACPI_STA_ALL) {
+               } else if (device_status_valid(get_slot_status(slot))) {
                        /* remove stale devices if any */
-                       list_for_each_entry_safe(dev, tmp, &bus->devices,
-                                                bus_list)
+                       list_for_each_entry_safe_reverse(dev, tmp,
+                                                        &bus->devices, bus_list)
                                if (PCI_SLOT(dev->devfn) == slot->device)
                                        trim_stale_devices(dev);
 
@@ -805,7 +837,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
        int i;
        unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 
-       list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+       list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
                for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
                        struct resource *res = &dev->resource[i];
                        if ((res->flags & type_mask) && !res->start &&
@@ -829,7 +861,11 @@ void acpiphp_check_host_bridge(acpi_handle handle)
 
        bridge = acpiphp_handle_to_bridge(handle);
        if (bridge) {
+               pci_lock_rescan_remove();
+
                acpiphp_check_bridge(bridge);
+
+               pci_unlock_rescan_remove();
                put_bridge(bridge);
        }
 }
@@ -852,6 +888,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
 
        mutex_unlock(&acpiphp_context_lock);
 
+       pci_lock_rescan_remove();
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
        switch (type) {
@@ -905,6 +942,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
                break;
        }
 
+       pci_unlock_rescan_remove();
        if (bridge)
                put_bridge(bridge);
 }
@@ -915,11 +953,9 @@ static void hotplug_event_work(void *data, u32 type)
        acpi_handle handle = context->handle;
 
        acpi_scan_lock_acquire();
-       pci_lock_rescan_remove();
 
        hotplug_event(handle, type, context);
 
-       pci_unlock_rescan_remove();
        acpi_scan_lock_release();
        acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
        put_bridge(context->func.parent);
@@ -937,6 +973,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 {
        struct acpiphp_context *context;
        u32 ost_code = ACPI_OST_SC_SUCCESS;
+       acpi_status status;
 
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
@@ -972,13 +1009,20 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 
        mutex_lock(&acpiphp_context_lock);
        context = acpiphp_get_context(handle);
-       if (context && !WARN_ON(context->handle != handle)) {
-               get_bridge(context->func.parent);
-               acpiphp_put_context(context);
-               acpi_hotplug_execute(hotplug_event_work, context, type);
+       if (!context || WARN_ON(context->handle != handle)
+           || context->func.parent->is_going_away)
+               goto err_out;
+
+       get_bridge(context->func.parent);
+       acpiphp_put_context(context);
+       status = acpi_hotplug_execute(hotplug_event_work, context, type);
+       if (ACPI_SUCCESS(status)) {
                mutex_unlock(&acpiphp_context_lock);
                return;
        }
+       put_bridge(context->func.parent);
+
+ err_out:
        mutex_unlock(&acpiphp_context_lock);
        ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
index 7a0fec6ce5717baac5ef564c743d129cbc03a892..955ab7990c5bd7045f2bf896e6d4c65989176089 100644 (file)
@@ -545,9 +545,15 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
                return -ENOMEM;
        list_for_each_entry(entry, &pdev->msi_list, list) {
                char *name = kmalloc(20, GFP_KERNEL);
+               if (!name)
+                       goto error_attrs;
+
                msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
-               if (!msi_dev_attr)
+               if (!msi_dev_attr) {
+                       kfree(name);
                        goto error_attrs;
+               }
+
                sprintf(name, "%d", entry->irq);
                sysfs_attr_init(&msi_dev_attr->attr);
                msi_dev_attr->attr.name = name;
@@ -589,6 +595,7 @@ error_attrs:
                ++count;
                msi_attr = msi_attrs[count];
        }
+       kfree(msi_attrs);
        return ret;
 }
 
@@ -959,7 +966,6 @@ EXPORT_SYMBOL(pci_disable_msi);
 /**
  * pci_msix_vec_count - return the number of device's MSI-X table entries
  * @dev: pointer to the pci_dev data structure of MSI-X device function
-
  * This function returns the number of device's MSI-X table entries and
  * therefore the number of MSI-X vectors device is capable of sending.
  * It returns a negative errno if the device is not capable of sending MSI-X
index 1febe90831b442303b7414faec770d4850ca53ed..fdbc294821e6468d55ca7d5fd68162b407607e97 100644 (file)
@@ -1181,6 +1181,8 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state);
 static int do_pci_enable_device(struct pci_dev *dev, int bars)
 {
        int err;
+       u16 cmd;
+       u8 pin;
 
        err = pci_set_power_state(dev, PCI_D0);
        if (err < 0 && err != -EIO)
@@ -1190,6 +1192,17 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
                return err;
        pci_fixup_device(pci_fixup_enable, dev);
 
+       if (dev->msi_enabled || dev->msix_enabled)
+               return 0;
+
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       if (pin) {
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               if (cmd & PCI_COMMAND_INTX_DISABLE)
+                       pci_write_config_word(dev, PCI_COMMAND,
+                                             cmd & ~PCI_COMMAND_INTX_DISABLE);
+       }
+
        return 0;
 }
 
index afa2354f6600e72d904ea907ee92f775010ae8a9..c7a551c2d5f1b4d39b982d85222537ec3fbfb804 100644 (file)
@@ -5,7 +5,7 @@
 menu "PHY Subsystem"
 
 config GENERIC_PHY
-       tristate "PHY Core"
+       bool "PHY Core"
        help
          Generic PHY support.
 
@@ -61,6 +61,7 @@ config PHY_EXYNOS_DP_VIDEO
 config BCM_KONA_USB2_PHY
        tristate "Broadcom Kona USB2 PHY Driver"
        depends on GENERIC_PHY
+       depends on HAS_IOMEM
        help
          Enable this to support the Broadcom Kona USB 2.0 PHY.
 
index 645c867c12573e554d43e3700155db5469841caa..6c738376daff5110a791c3c3f6492ab818971165 100644 (file)
@@ -162,6 +162,9 @@ int phy_init(struct phy *phy)
 {
        int ret;
 
+       if (!phy)
+               return 0;
+
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
@@ -173,6 +176,8 @@ int phy_init(struct phy *phy)
                        dev_err(&phy->dev, "phy init failed --> %d\n", ret);
                        goto out;
                }
+       } else {
+               ret = 0; /* Override possible ret == -ENOTSUPP */
        }
        ++phy->init_count;
 
@@ -187,6 +192,9 @@ int phy_exit(struct phy *phy)
 {
        int ret;
 
+       if (!phy)
+               return 0;
+
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
@@ -212,6 +220,9 @@ int phy_power_on(struct phy *phy)
 {
        int ret;
 
+       if (!phy)
+               return 0;
+
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
@@ -223,6 +234,8 @@ int phy_power_on(struct phy *phy)
                        dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
                        goto out;
                }
+       } else {
+               ret = 0; /* Override possible ret == -ENOTSUPP */
        }
        ++phy->power_count;
        mutex_unlock(&phy->mutex);
@@ -240,6 +253,9 @@ int phy_power_off(struct phy *phy)
 {
        int ret;
 
+       if (!phy)
+               return 0;
+
        mutex_lock(&phy->mutex);
        if (phy->power_count == 1 && phy->ops->power_off) {
                ret =  phy->ops->power_off(phy);
@@ -308,7 +324,7 @@ err0:
  */
 void phy_put(struct phy *phy)
 {
-       if (IS_ERR(phy))
+       if (!phy || IS_ERR(phy))
                return;
 
        module_put(phy->ops->owner);
@@ -328,6 +344,9 @@ void devm_phy_put(struct device *dev, struct phy *phy)
 {
        int r;
 
+       if (!phy)
+               return;
+
        r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
        dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
 }
@@ -389,17 +408,11 @@ struct phy *phy_get(struct device *dev, const char *string)
                index = of_property_match_string(dev->of_node, "phy-names",
                        string);
                phy = of_phy_get(dev, index);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "unable to find phy\n");
-                       return phy;
-               }
        } else {
                phy = phy_lookup(dev, string);
-               if (IS_ERR(phy)) {
-                       dev_err(dev, "unable to find phy\n");
-                       return phy;
-               }
        }
+       if (IS_ERR(phy))
+               return phy;
 
        if (!try_module_get(phy->ops->owner))
                return ERR_PTR(-EPROBE_DEFER);
@@ -410,6 +423,27 @@ struct phy *phy_get(struct device *dev, const char *string)
 }
 EXPORT_SYMBOL_GPL(phy_get);
 
+/**
+ * phy_optional_get() - lookup and obtain a reference to an optional phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or the name of the controller
+ * port for non-dt case
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * NULL if there is no such phy.  The caller is responsible for
+ * calling phy_put() to release that count.
+ */
+struct phy *phy_optional_get(struct device *dev, const char *string)
+{
+       struct phy *phy = phy_get(dev, string);
+
+       if (PTR_ERR(phy) == -ENODEV)
+               phy = NULL;
+
+       return phy;
+}
+EXPORT_SYMBOL_GPL(phy_optional_get);
+
 /**
  * devm_phy_get() - lookup and obtain a reference to a phy.
  * @dev: device that requests this phy
@@ -440,6 +474,30 @@ struct phy *devm_phy_get(struct device *dev, const char *string)
 }
 EXPORT_SYMBOL_GPL(devm_phy_get);
 
+/**
+ * devm_phy_optional_get() - lookup and obtain a reference to an optional phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or phy device name
+ * for non-dt case
+ *
+ * Gets the phy using phy_get(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres
+ * data, then, devres data is freed. This differs to devm_phy_get() in
+ * that if the phy does not exist, it is not considered an error and
+ * -ENODEV will not be returned. Instead the NULL phy is returned,
+ * which can be passed to all other phy consumer calls.
+ */
+struct phy *devm_phy_optional_get(struct device *dev, const char *string)
+{
+       struct phy *phy = devm_phy_get(dev, string);
+
+       if (PTR_ERR(phy) == -ENODEV)
+               phy = NULL;
+
+       return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_optional_get);
+
 /**
  * phy_create() - create a new phy
  * @dev: device that is creating the new phy
index 1dbe6ce7b2ce795e0a81ec3a632a8b6d6927f2bc..0786fef842e7fd878507d4342074db65b942c47b 100644 (file)
@@ -76,10 +76,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
        if (IS_ERR(state->regs))
                return PTR_ERR(state->regs);
 
-       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
        if (IS_ERR(phy)) {
                dev_err(dev, "failed to create Display Port PHY\n");
@@ -87,6 +83,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
        }
        phy_set_drvdata(phy, state);
 
+       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        return 0;
 }
 
index 0c5efab11af18a5b2b7367014747e0b34984b585..7f139326a6424e8b38d5fdd9049f26d85e679e6c 100644 (file)
@@ -134,11 +134,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
        dev_set_drvdata(dev, state);
        spin_lock_init(&state->slock);
 
-       phy_provider = devm_of_phy_provider_register(dev,
-                                       exynos_mipi_video_phy_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
                struct phy *phy = devm_phy_create(dev,
                                        &exynos_mipi_video_phy_ops, NULL);
@@ -152,6 +147,11 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
                phy_set_drvdata(phy, &state->phys[i]);
        }
 
+       phy_provider = devm_of_phy_provider_register(dev,
+                                       exynos_mipi_video_phy_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        return 0;
 }
 
index d43786f6243742ed378fb1b7d3c6756fd111381d..d70ecd6a1b3f51e60077559159912e2564e6b1a1 100644 (file)
@@ -99,17 +99,17 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
        if (IS_ERR(priv->clk))
                return PTR_ERR(priv->clk);
 
-       phy_provider = devm_of_phy_provider_register(&pdev->dev,
-                                                    of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL);
        if (IS_ERR(phy))
                return PTR_ERR(phy);
 
        phy_set_drvdata(phy, priv);
 
+       phy_provider = devm_of_phy_provider_register(&pdev->dev,
+                                                    of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        /* The boot loader may of left it on. Turn it off. */
        phy_mvebu_sata_power_off(phy);
 
index bfc5c337f99a8178278d9aa8f0b9b7be74f41889..7699752fba11bfbfa8acff589d794262d2882cc4 100644 (file)
@@ -177,11 +177,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
        phy->phy.otg            = otg;
        phy->phy.type           = USB_PHY_TYPE_USB2;
 
-       phy_provider = devm_of_phy_provider_register(phy->dev,
-                       of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        control_node = of_parse_phandle(node, "ctrl-module", 0);
        if (!control_node) {
                dev_err(&pdev->dev, "Failed to get control device phandle\n");
@@ -214,6 +209,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
 
        phy_set_drvdata(generic_phy, phy);
 
+       phy_provider = devm_of_phy_provider_register(phy->dev,
+                       of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
        if (IS_ERR(phy->wkupclk)) {
                dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
index daf65e68aaab53c663847e05d2dcf1fbdb035544..c3ace1db8136eedef379691bc6fa532b4ff5d67c 100644 (file)
@@ -695,11 +695,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        otg->set_host           = twl4030_set_host;
        otg->set_peripheral     = twl4030_set_peripheral;
 
-       phy_provider = devm_of_phy_provider_register(twl->dev,
-               of_phy_simple_xlate);
-       if (IS_ERR(phy_provider))
-               return PTR_ERR(phy_provider);
-
        phy = devm_phy_create(twl->dev, &ops, init_data);
        if (IS_ERR(phy)) {
                dev_dbg(&pdev->dev, "Failed to create PHY\n");
@@ -708,6 +703,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 
        phy_set_drvdata(phy, twl);
 
+       phy_provider = devm_of_phy_provider_register(twl->dev,
+               of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
        /* init spinlock for workqueue */
        spin_lock_init(&twl->lock);
 
index be361b7cd30f240e4b1a78abbb3acd253620b035..1e4e69384baaed11ae859ce6a784eef0d8fa0f9c 100644 (file)
@@ -217,7 +217,7 @@ config PINCTRL_IMX28
        select PINCTRL_MXS
 
 config PINCTRL_MSM
-       tristate
+       bool
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
index 5ee61a470016fa8f2753cf21fc2e6ff0966d8d78..c0fe6091566a4766cffbe515ed796fe7e2a3bee5 100644 (file)
@@ -851,7 +851,9 @@ static struct pinctrl *create_pinctrl(struct device *dev)
        kref_init(&p->users);
 
        /* Add the pinctrl handle to the global list */
+       mutex_lock(&pinctrl_list_mutex);
        list_add_tail(&p->node, &pinctrl_list);
+       mutex_unlock(&pinctrl_list_mutex);
 
        return p;
 }
@@ -1642,8 +1644,10 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
                            device_root, pctldev, &pinctrl_groups_ops);
        debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
                            device_root, pctldev, &pinctrl_gpioranges_ops);
-       pinmux_init_device_debugfs(device_root, pctldev);
-       pinconf_init_device_debugfs(device_root, pctldev);
+       if (pctldev->desc->pmxops)
+               pinmux_init_device_debugfs(device_root, pctldev);
+       if (pctldev->desc->confops)
+               pinconf_init_device_debugfs(device_root, pctldev);
 }
 
 static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
index 38c6f8b9790e9a5921f966a5165cb35978f82f5f..d990e33d8aa778b9a8cb1a3143db5345122ab584 100644 (file)
@@ -1286,22 +1286,22 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
 
        switch (type) {
        case IRQ_TYPE_EDGE_RISING:
-               irq_set_handler(d->irq, handle_simple_irq);
+               __irq_set_handler_locked(d->irq, handle_simple_irq);
                writel_relaxed(mask, pio + PIO_ESR);
                writel_relaxed(mask, pio + PIO_REHLSR);
                break;
        case IRQ_TYPE_EDGE_FALLING:
-               irq_set_handler(d->irq, handle_simple_irq);
+               __irq_set_handler_locked(d->irq, handle_simple_irq);
                writel_relaxed(mask, pio + PIO_ESR);
                writel_relaxed(mask, pio + PIO_FELLSR);
                break;
        case IRQ_TYPE_LEVEL_LOW:
-               irq_set_handler(d->irq, handle_level_irq);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
                writel_relaxed(mask, pio + PIO_LSR);
                writel_relaxed(mask, pio + PIO_FELLSR);
                break;
        case IRQ_TYPE_LEVEL_HIGH:
-               irq_set_handler(d->irq, handle_level_irq);
+               __irq_set_handler_locked(d->irq, handle_level_irq);
                writel_relaxed(mask, pio + PIO_LSR);
                writel_relaxed(mask, pio + PIO_REHLSR);
                break;
@@ -1310,7 +1310,7 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
                 * disable additional interrupt modes:
                 * fall back to default behavior
                 */
-               irq_set_handler(d->irq, handle_simple_irq);
+               __irq_set_handler_locked(d->irq, handle_simple_irq);
                writel_relaxed(mask, pio + PIO_AIMDR);
                return 0;
        case IRQ_TYPE_NONE:
index 4669c53f99b0a4fc8e30ab4678263be292f014fd..eb2500212147bdc72177f3e67c31ed23f7e6ea6a 100644 (file)
@@ -1435,7 +1435,7 @@ int __init capri_pinctrl_probe(struct platform_device *pdev)
 }
 
 static struct of_device_id capri_pinctrl_of_match[] = {
-       { .compatible = "brcm,capri-pinctrl", },
+       { .compatible = "brcm,bcm11351-pinctrl", },
        { },
 };
 
index 17aecde1b51d912584765556188121fa82413795..815384b377b5fc192a4cdab6eba6c413e62c53fd 100644 (file)
@@ -45,7 +45,7 @@ struct imx1_pinctrl {
 #define MX1_DDIR 0x00
 #define MX1_OCR 0x04
 #define MX1_ICONFA 0x0c
-#define MX1_ICONFB 0x10
+#define MX1_ICONFB 0x14
 #define MX1_GIUS 0x20
 #define MX1_GPR 0x38
 #define MX1_PUEN 0x40
@@ -97,13 +97,13 @@ static void imx1_write_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
        u32 old_val;
        u32 new_val;
 
-       dev_dbg(ipctl->dev, "write: register 0x%p offset %d value 0x%x\n",
-                       reg, offset, value);
-
        /* Use the next register if the pin's port pin number is >=16 */
        if (pin_id % 32 >= 16)
                reg += 0x04;
 
+       dev_dbg(ipctl->dev, "write: register 0x%p offset %d value 0x%x\n",
+                       reg, offset, value);
+
        /* Get current state of pins */
        old_val = readl(reg);
        old_val &= mask;
@@ -139,7 +139,7 @@ static int imx1_read_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
                u32 reg_offset)
 {
        void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
-       int offset = pin_id % 16;
+       int offset = (pin_id % 16) * 2;
 
        /* Use the next register if the pin's port pin number is >=16 */
        if (pin_id % 32 >= 16)
index 9ccf681dad2f4993cdf3ef20a9099a17ae62dcb9..f9fabe9bf47d433b9152cd438e259e568b3b9ff5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -584,7 +585,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,
        spin_lock_irqsave(&pctl->lock, flags);
 
        regval = readl(pctl->membase + reg);
-       regval &= ~IRQ_CFG_IRQ_MASK;
+       regval &= ~(IRQ_CFG_IRQ_MASK << index);
        writel(regval | (mode << index), pctl->membase + reg);
 
        spin_unlock_irqrestore(&pctl->lock, flags);
@@ -665,6 +666,7 @@ static struct irq_chip sunxi_pinctrl_irq_chip = {
 
 static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 {
+       struct irq_chip *chip = irq_get_chip(irq);
        struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
        const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
 
@@ -674,10 +676,12 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
        if (reg) {
                int irqoffset;
 
+               chained_irq_enter(chip, desc);
                for_each_set_bit(irqoffset, &reg, SUNXI_IRQ_NUMBER) {
                        int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
                        generic_handle_irq(pin_irq);
                }
+               chained_irq_exit(chip, desc);
        }
 }
 
index 01c494f8a14f0119493d783624b86831549ccdb0..552b0e97077a858b0c1aeda6d9f1a83e4803ae35 100644 (file)
@@ -511,7 +511,7 @@ static inline u32 sunxi_pull_offset(u16 pin)
 
 static inline u32 sunxi_irq_cfg_reg(u16 irq)
 {
-       u8 reg = irq / IRQ_CFG_IRQ_PER_REG;
+       u8 reg = irq / IRQ_CFG_IRQ_PER_REG * 0x04;
        return reg + IRQ_CFG_REG;
 }
 
@@ -523,7 +523,7 @@ static inline u32 sunxi_irq_cfg_offset(u16 irq)
 
 static inline u32 sunxi_irq_ctrl_reg(u16 irq)
 {
-       u8 reg = irq / IRQ_CTRL_IRQ_PER_REG;
+       u8 reg = irq / IRQ_CTRL_IRQ_PER_REG * 0x04;
        return reg + IRQ_CTRL_REG;
 }
 
@@ -535,7 +535,7 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
 
 static inline u32 sunxi_irq_status_reg(u16 irq)
 {
-       u8 reg = irq / IRQ_STATUS_IRQ_PER_REG;
+       u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
        return reg + IRQ_STATUS_REG;
 }
 
index a2e93a2b5ff487aa0dad6fc8c9f2d863e6debb07..e767355ab0ad7a02fc5a1ff8cb62ad0cd943f698 100644 (file)
@@ -645,7 +645,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
                                 GFP_KERNEL);
        if (!pmx->regs) {
                dev_err(&pdev->dev, "Can't alloc regs pointer\n");
-               return -ENODEV;
+               return -ENOMEM;
        }
 
        for (i = 0; i < pmx->nbanks; i++) {
index 77d103fe39d90c8ad0bb82485ec1896dd1b5889a..567d6918d50b226b7841c84a98b2343ad552a03e 100644 (file)
@@ -89,7 +89,8 @@ enum {
 
        /* GPSR6 */
        FN_IP13_10, FN_IP13_11, FN_IP13_12, FN_IP13_13, FN_IP13_14,
-       FN_IP13_15, FN_IP13_18_16, FN_IP13_21_19, FN_IP13_22, FN_IP13_24_23,
+       FN_IP13_15, FN_IP13_18_16, FN_IP13_21_19,
+       FN_IP13_22, FN_IP13_24_23, FN_SD1_CLK,
        FN_IP13_25, FN_IP13_26, FN_IP13_27, FN_IP13_30_28, FN_IP14_1_0,
        FN_IP14_2, FN_IP14_3, FN_IP14_4, FN_IP14_5, FN_IP14_6, FN_IP14_7,
        FN_IP14_10_8, FN_IP14_13_11, FN_IP14_16_14, FN_IP14_19_17,
@@ -788,6 +789,7 @@ static const u16 pinmux_data[] = {
        PINMUX_DATA(USB1_PWEN_MARK, FN_USB1_PWEN),
        PINMUX_DATA(USB1_OVC_MARK, FN_USB1_OVC),
        PINMUX_DATA(DU0_DOTCLKIN_MARK, FN_DU0_DOTCLKIN),
+       PINMUX_DATA(SD1_CLK_MARK, FN_SD1_CLK),
 
        /* IPSR0 */
        PINMUX_IPSR_DATA(IP0_0, D0),
@@ -3825,7 +3827,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
                GP_6_11_FN, FN_IP13_25,
                GP_6_10_FN, FN_IP13_24_23,
                GP_6_9_FN, FN_IP13_22,
-               0, 0,
+               GP_6_8_FN, FN_SD1_CLK,
                GP_6_7_FN, FN_IP13_21_19,
                GP_6_6_FN, FN_IP13_18_16,
                GP_6_5_FN, FN_IP13_15,
index 37b42651d76ac5ba502ee7fa90417c24304e6122..dde0285544d6ad95a6c392955df3ce976c3e11a4 100644 (file)
@@ -413,7 +413,7 @@ static const struct sirfsoc_padmux ac97_padmux = {
        .funcval = 0,
 };
 
-static const unsigned ac97_pins[] = { 33, 34, 35, 36 };
+static const unsigned ac97_pins[] = { 43, 44, 45, 46 };
 
 static const struct sirfsoc_muxmask spi1_muxmask[] = {
        {
index a0d6152701cdf3d3aa5a64bbb435f93526d0a324..617a4916b50fc1d8fec129e001f717c00de13880 100644 (file)
@@ -598,7 +598,7 @@ static unsigned int sirfsoc_gpio_irq_startup(struct irq_data *d)
 {
        struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
-       if (gpio_lock_as_irq(&bank->chip.gc, d->hwirq))
+       if (gpio_lock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE))
                dev_err(bank->chip.gc.dev,
                        "unable to lock HW IRQ %lu for IRQ\n",
                        d->hwirq);
@@ -611,7 +611,7 @@ static void sirfsoc_gpio_irq_shutdown(struct irq_data *d)
        struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
 
        sirfsoc_gpio_irq_mask(d);
-       gpio_unlock_as_irq(&bank->chip.gc, d->hwirq);
+       gpio_unlock_as_irq(&bank->chip.gc, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
 }
 
 static struct irq_chip sirfsoc_irq_chip = {
index b28d1af9c2320642c8ee855b07eb15c2355c4948..9802b67040cc6a49a1e4f8df15db337ae912b778 100644 (file)
@@ -276,7 +276,20 @@ static int wmt_pctl_dt_node_to_map_pull(struct wmt_pinctrl_data *data,
        if (!configs)
                return -ENOMEM;
 
-       configs[0] = pull;
+       switch (pull) {
+       case 0:
+               configs[0] = PIN_CONFIG_BIAS_DISABLE;
+               break;
+       case 1:
+               configs[0] = PIN_CONFIG_BIAS_PULL_DOWN;
+               break;
+       case 2:
+               configs[0] = PIN_CONFIG_BIAS_PULL_UP;
+               break;
+       default:
+               configs[0] = PIN_CONFIG_BIAS_DISABLE;
+               dev_err(data->dev, "invalid pull state %d - disabling\n", pull);
+       }
 
        map->type = PIN_MAP_TYPE_CONFIGS_PIN;
        map->data.configs.group_or_pin = data->groups[group];
index 167f3d00c916d2e30a63dcc31d260a45d1e5cada..66977ebf13b30cba09b6bb1b7c06eeb07e2e5bd0 100644 (file)
@@ -183,9 +183,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        struct resource r = {0};
        int i, flags;
 
-       if (acpi_dev_resource_memory(res, &r)
-           || acpi_dev_resource_io(res, &r)
-           || acpi_dev_resource_address_space(res, &r)
+       if (acpi_dev_resource_address_space(res, &r)
            || acpi_dev_resource_ext_address_space(res, &r)) {
                pnp_add_resource(dev, &r);
                return AE_OK;
@@ -217,6 +215,17 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        }
 
        switch (res->type) {
+       case ACPI_RESOURCE_TYPE_MEMORY24:
+       case ACPI_RESOURCE_TYPE_MEMORY32:
+       case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+               if (acpi_dev_resource_memory(res, &r))
+                       pnp_add_resource(dev, &r);
+               break;
+       case ACPI_RESOURCE_TYPE_IO:
+       case ACPI_RESOURCE_TYPE_FIXED_IO:
+               if (acpi_dev_resource_io(res, &r))
+                       pnp_add_resource(dev, &r);
+               break;
        case ACPI_RESOURCE_TYPE_DMA:
                dma = &res->data.dma;
                if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
index 769d265b221b9c3abee2b8ea86a1d84ef00ac795..deb7f4bcdb7b6b6a770ce08f1d2535dccfa82100 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "pnpbios.h"
 
-static struct {
+__visible struct {
        u16 offset;
        u16 segment;
 } pnp_bios_callpoint;
@@ -41,6 +41,7 @@ asmlinkage void pnp_bios_callfunc(void);
 
 __asm__(".text                 \n"
        __ALIGN_STR "\n"
+       ".globl pnp_bios_callfunc\n"
        "pnp_bios_callfunc:\n"
        "       pushl %edx      \n"
        "       pushl %ecx      \n"
@@ -66,9 +67,9 @@ static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
  * after PnP BIOS oopses.
  */
 
-u32 pnp_bios_fault_esp;
-u32 pnp_bios_fault_eip;
-u32 pnp_bios_is_utter_crap = 0;
+__visible u32 pnp_bios_fault_esp;
+__visible u32 pnp_bios_fault_eip;
+__visible u32 pnp_bios_is_utter_crap = 0;
 
 static spinlock_t pnp_bios_lock;
 
index 563174891c90d07b7c9cc5c711588fd249695dd1..041f9b638d28c5f788ee2c828d29b853728f67b4 100644 (file)
@@ -192,7 +192,7 @@ static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uV)
 
        /*
         * Voltage is measured in units of 1.22mV. The voltage is stored as
-        * a 10-bit number plus sign, in the upper bits of a 16-bit register
+        * a 12-bit number plus sign, in the upper bits of a 16-bit register
         */
        err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
        if (err)
index 80edb7d8cb547702df7b364f087f25aade3729d8..0b4cf9d63291d0e152197c0eeffb1eb128818dd3 100644 (file)
@@ -444,8 +444,6 @@ static int isp1704_charger_probe(struct platform_device *pdev)
                ret = PTR_ERR(isp->phy);
                goto fail0;
        }
-       if (!isp->phy)
-               goto fail0;
 
        isp->dev = &pdev->dev;
        platform_set_drvdata(pdev, isp);
index c7ff6d67f158179aa891a1d41b8a10952191f240..0fbac861080dac5cd6c4f62dc59338444205a60a 100644 (file)
@@ -148,7 +148,7 @@ static void max17040_get_online(struct i2c_client *client)
 {
        struct max17040_chip *chip = i2c_get_clientdata(client);
 
-       if (chip->pdata->battery_online)
+       if (chip->pdata && chip->pdata->battery_online)
                chip->online = chip->pdata->battery_online();
        else
                chip->online = 1;
@@ -158,7 +158,8 @@ static void max17040_get_status(struct i2c_client *client)
 {
        struct max17040_chip *chip = i2c_get_clientdata(client);
 
-       if (!chip->pdata->charger_online || !chip->pdata->charger_enable) {
+       if (!chip->pdata || !chip->pdata->charger_online
+                       || !chip->pdata->charger_enable) {
                chip->status = POWER_SUPPLY_STATUS_UNKNOWN;
                return;
        }
index fb7300837feef25a6b2a80de582baf01031bf22a..bc1e5139ba2957712e9800182fe6d7a24c568468 100644 (file)
@@ -699,8 +699,6 @@ int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
 
        BUG_ON(!bytes);
 
-       PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
-
        spin_lock_irqsave(&priv->rx_list.lock, flags);
        if (priv->rx_list.bytes_held >= bytes) {
                dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
@@ -1052,7 +1050,7 @@ static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
        INIT_LIST_HEAD(&priv->rx_list.head);
        spin_lock_init(&priv->rx_list.lock);
 
-       INIT_WORK(&priv->rx_list.work.work, NULL);
+       INIT_WORK(&priv->rx_list.work.work, ps3_vuart_work);
        priv->rx_list.work.trigger = 0;
        priv->rx_list.work.dev = dev;
 
index 8a843a04c22456bb5c9856a92aba876c03beeca9..a40b9c34e9fffcd2bce08169cd7a256de067027f 100644 (file)
@@ -52,8 +52,10 @@ lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
                offset = pwm_map->output[i];
 
                /* Return an error if the pin is already assigned */
-               if (test_and_set_bit(offset, &lp3943->pin_used))
+               if (test_and_set_bit(offset, &lp3943->pin_used)) {
+                       kfree(pwm_map);
                        return ERR_PTR(-EBUSY);
+               }
        }
 
        return pwm_map;
index b4b0d83f9ef6437dfb97f33037aaee1acf7bda59..7061ac0ad4287c0d84edb39058ef6abc295e43ce 100644 (file)
@@ -678,6 +678,7 @@ struct tsi721_bdma_chan {
        struct list_head        free_list;
        dma_cookie_t            completed_cookie;
        struct tasklet_struct   tasklet;
+       bool                    active;
 };
 
 #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
index 502663f5f7c65a847f45881dcac4821081a314cf..91245f5dbe81a7d235f13a2dd2edbe741508d584 100644 (file)
@@ -206,8 +206,8 @@ void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan)
 {
        /* Disable BDMA channel interrupts */
        iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE);
-
-       tasklet_schedule(&bdma_chan->tasklet);
+       if (bdma_chan->active)
+               tasklet_schedule(&bdma_chan->tasklet);
 }
 
 #ifdef CONFIG_PCI_MSI
@@ -562,7 +562,7 @@ static int tsi721_alloc_chan_resources(struct dma_chan *dchan)
        }
 #endif /* CONFIG_PCI_MSI */
 
-       tasklet_enable(&bdma_chan->tasklet);
+       bdma_chan->active = true;
        tsi721_bdma_interrupt_enable(bdma_chan, 1);
 
        return bdma_chan->bd_num - 1;
@@ -576,9 +576,7 @@ err_out:
 static void tsi721_free_chan_resources(struct dma_chan *dchan)
 {
        struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan);
-#ifdef CONFIG_PCI_MSI
        struct tsi721_device *priv = to_tsi721(dchan->device);
-#endif
        LIST_HEAD(list);
 
        dev_dbg(dchan->device->dev, "%s: Entry\n", __func__);
@@ -589,14 +587,25 @@ static void tsi721_free_chan_resources(struct dma_chan *dchan)
        BUG_ON(!list_empty(&bdma_chan->active_list));
        BUG_ON(!list_empty(&bdma_chan->queue));
 
-       tasklet_disable(&bdma_chan->tasklet);
+       tsi721_bdma_interrupt_enable(bdma_chan, 0);
+       bdma_chan->active = false;
+
+#ifdef CONFIG_PCI_MSI
+       if (priv->flags & TSI721_USING_MSIX) {
+               synchronize_irq(priv->msix[TSI721_VECT_DMA0_DONE +
+                                          bdma_chan->id].vector);
+               synchronize_irq(priv->msix[TSI721_VECT_DMA0_INT +
+                                          bdma_chan->id].vector);
+       } else
+#endif
+       synchronize_irq(priv->pdev->irq);
+
+       tasklet_kill(&bdma_chan->tasklet);
 
        spin_lock_bh(&bdma_chan->lock);
        list_splice_init(&bdma_chan->free_list, &list);
        spin_unlock_bh(&bdma_chan->lock);
 
-       tsi721_bdma_interrupt_enable(bdma_chan, 0);
-
 #ifdef CONFIG_PCI_MSI
        if (priv->flags & TSI721_USING_MSIX) {
                free_irq(priv->msix[TSI721_VECT_DMA0_DONE +
@@ -790,6 +799,7 @@ int tsi721_register_dma(struct tsi721_device *priv)
                bdma_chan->dchan.cookie = 1;
                bdma_chan->dchan.chan_id = i;
                bdma_chan->id = i;
+               bdma_chan->active = false;
 
                spin_lock_init(&bdma_chan->lock);
 
@@ -799,7 +809,6 @@ int tsi721_register_dma(struct tsi721_device *priv)
 
                tasklet_init(&bdma_chan->tasklet, tsi721_dma_tasklet,
                             (unsigned long)bdma_chan);
-               tasklet_disable(&bdma_chan->tasklet);
                list_add_tail(&bdma_chan->dchan.device_node,
                              &mport->dma.channels);
        }
index 77b46d0b37a604fa31f7b90fb270d8ac59023e0c..e10febe9ec341e0c99a899cb7040b9e1cd8a1a8f 100644 (file)
@@ -498,7 +498,7 @@ static int ab3100_regulator_register(struct platform_device *pdev,
                                     struct ab3100_platform_data *plfdata,
                                     struct regulator_init_data *init_data,
                                     struct device_node *np,
-                                    int id)
+                                    unsigned long id)
 {
        struct regulator_desc *desc;
        struct ab3100_regulator *reg;
@@ -646,7 +646,7 @@ ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
                err = ab3100_regulator_register(
                        pdev, NULL, ab3100_regulator_matches[i].init_data,
                        ab3100_regulator_matches[i].of_node,
-                       (int) ab3100_regulator_matches[i].driver_data);
+                       (unsigned long)ab3100_regulator_matches[i].driver_data);
                if (err) {
                        ab3100_regulators_remove(pdev);
                        return err;
index b38a6b669e8cf0951a38c3cb589a589372f18d3f..afca1bc24f262251abf3352d2e09d6452959805b 100644 (file)
@@ -953,6 +953,8 @@ static int machine_constraints_current(struct regulator_dev *rdev,
        return 0;
 }
 
+static int _regulator_do_enable(struct regulator_dev *rdev);
+
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
@@ -1013,10 +1015,9 @@ static int set_machine_constraints(struct regulator_dev *rdev,
        /* If the constraints say the regulator should be on at this point
         * and we have control then make sure it is enabled.
         */
-       if ((rdev->constraints->always_on || rdev->constraints->boot_on) &&
-           ops->enable) {
-               ret = ops->enable(rdev);
-               if (ret < 0) {
+       if (rdev->constraints->always_on || rdev->constraints->boot_on) {
+               ret = _regulator_do_enable(rdev);
+               if (ret < 0 && ret != -EINVAL) {
                        rdev_err(rdev, "failed to enable\n");
                        goto out;
                }
@@ -1272,6 +1273,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
                                if (r->dev.parent &&
                                        node == r->dev.of_node)
                                        return r;
+                       *ret = -EPROBE_DEFER;
+                       return NULL;
                } else {
                        /*
                         * If we couldn't even get the node then it's
@@ -1312,7 +1315,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        struct regulator_dev *rdev;
        struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
        const char *devname = NULL;
-       int ret = -EPROBE_DEFER;
+       int ret;
 
        if (id == NULL) {
                pr_err("get() with no identifier\n");
@@ -1322,6 +1325,11 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        if (dev)
                devname = dev_name(dev);
 
+       if (have_full_constraints())
+               ret = -ENODEV;
+       else
+               ret = -EPROBE_DEFER;
+
        mutex_lock(&regulator_list_mutex);
 
        rdev = regulator_dev_lookup(dev, id, &ret);
@@ -1352,7 +1360,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
                goto found;
        /* Don't log an error when called from regulator_get_optional() */
        } else if (!have_full_constraints() || exclusive) {
-               dev_err(dev, "dummy supplies not allowed\n");
+               dev_warn(dev, "dummy supplies not allowed\n");
        }
 
        mutex_unlock(&regulator_list_mutex);
@@ -1900,8 +1908,6 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
 
        trace_regulator_disable_complete(rdev_get_name(rdev));
 
-       _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
-                            NULL);
        return 0;
 }
 
@@ -1925,6 +1931,8 @@ static int _regulator_disable(struct regulator_dev *rdev)
                                rdev_err(rdev, "failed to disable\n");
                                return ret;
                        }
+                       _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
+                                       NULL);
                }
 
                rdev->use_count = 0;
@@ -1977,20 +1985,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
 
-       /* force disable */
-       if (rdev->desc->ops->disable) {
-               /* ah well, who wants to live forever... */
-               ret = rdev->desc->ops->disable(rdev);
-               if (ret < 0) {
-                       rdev_err(rdev, "failed to force disable\n");
-                       return ret;
-               }
-               /* notify other consumers that power has been forced off */
-               _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
-                       REGULATOR_EVENT_DISABLE, NULL);
+       ret = _regulator_do_disable(rdev);
+       if (ret < 0) {
+               rdev_err(rdev, "failed to force disable\n");
+               return ret;
        }
 
-       return ret;
+       _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+                       REGULATOR_EVENT_DISABLE, NULL);
+
+       return 0;
 }
 
 /**
@@ -3623,23 +3627,18 @@ int regulator_suspend_finish(void)
 
        mutex_lock(&regulator_list_mutex);
        list_for_each_entry(rdev, &regulator_list, list) {
-               struct regulator_ops *ops = rdev->desc->ops;
-
                mutex_lock(&rdev->mutex);
-               if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
-                               ops->enable) {
-                       error = ops->enable(rdev);
+               if (rdev->use_count > 0  || rdev->constraints->always_on) {
+                       error = _regulator_do_enable(rdev);
                        if (error)
                                ret = error;
                } else {
                        if (!have_full_constraints())
                                goto unlock;
-                       if (!ops->disable)
-                               goto unlock;
                        if (!_regulator_is_enabled(rdev))
                                goto unlock;
 
-                       error = ops->disable(rdev);
+                       error = _regulator_do_disable(rdev);
                        if (error)
                                ret = error;
                }
@@ -3813,7 +3812,7 @@ static int __init regulator_init_complete(void)
                ops = rdev->desc->ops;
                c = rdev->constraints;
 
-               if (!ops->disable || (c && c->always_on))
+               if (c && c->always_on)
                        continue;
 
                mutex_lock(&rdev->mutex);
@@ -3834,7 +3833,7 @@ static int __init regulator_init_complete(void)
                        /* We log since this may kill the system if it
                         * goes wrong. */
                        rdev_info(rdev, "disabling\n");
-                       ret = ops->disable(rdev);
+                       ret = _regulator_do_disable(rdev);
                        if (ret != 0)
                                rdev_err(rdev, "couldn't disable: %d\n", ret);
                } else {
index 7f340206d329d452710a319deba4869a2d6c603b..b14ebdad5dd2508f30854ac97e2b803cb5fa6e03 100644 (file)
@@ -576,7 +576,9 @@ static int da9055_regulator_probe(struct platform_device *pdev)
        /* Only LDO 5 and 6 has got the over current interrupt */
        if (pdev->id == DA9055_ID_LDO5 || pdev->id ==  DA9055_ID_LDO6) {
                irq = platform_get_irq_byname(pdev, "REGULATOR");
-               irq = regmap_irq_get_virq(da9055->irq_data, irq);
+               if (irq < 0)
+                       return irq;
+
                ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                                                da9055_ldo5_6_oc_irq,
                                                IRQF_TRIGGER_HIGH |
index 56727eb745df69171d77fac8313e6ea3ab2499ef..91e99a2c8dc14354c4f60368f025fef15d78786e 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Regulator driver for DA9063 PMIC series
  *
@@ -60,7 +61,8 @@ struct da9063_regulator_info {
        .desc.ops = &da9063_ldo_ops, \
        .desc.min_uV = (min_mV) * 1000, \
        .desc.uV_step = (step_mV) * 1000, \
-       .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1), \
+       .desc.n_voltages = (((max_mV) - (min_mV))/(step_mV) + 1 \
+               + (DA9063_V##regl_name##_BIAS)), \
        .desc.enable_reg = DA9063_REG_##regl_name##_CONT, \
        .desc.enable_mask = DA9063_LDO_EN, \
        .desc.vsel_reg = DA9063_REG_V##regl_name##_A, \
index b1078ba3f39381338f2691f7585961337cf536c1..e0619526708c88393069abf4411fa2ff9473e510 100644 (file)
@@ -166,12 +166,14 @@ static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev)
 
        ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches,
                        MAX14577_REG_MAX);
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
-               return ret;
-       }
+       else
+               ret = 0;
 
-       return 0;
+       of_node_put(np);
+
+       return ret;
 }
 
 static inline struct regulator_init_data *match_init_data(int index)
index d9e557990577d33029e24e57cb6bf20740ea3ab6..cd0b9e35a56d90ccc4fd78fe5fe781f2f009cd77 100644 (file)
@@ -441,6 +441,7 @@ common_reg:
        for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
                if (!reg_np) {
                        config.init_data = pdata->regulators[i].initdata;
+                       config.of_node = pdata->regulators[i].reg_node;
                } else {
                        config.init_data = rdata[i].init_data;
                        config.of_node = rdata[i].of_node;
index d7164bb75d3e0bf2a88a61c1a82e6c79072cd8b5..d958dfa051254866808fe6c36cf9db7184627b94 100644 (file)
@@ -535,7 +535,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
                return -ENODEV;
        }
 
-       regulators_np = of_find_node_by_name(pmic_np, "regulators");
+       regulators_np = of_get_child_by_name(pmic_np, "regulators");
        if (!regulators_np) {
                dev_err(iodev->dev, "could not find regulators sub-node\n");
                return -EINVAL;
@@ -591,6 +591,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
                rmode++;
        }
 
+       of_node_put(regulators_np);
+
        if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
                pdata->buck2_gpiodvs = true;
 
index 7afd373b9595ff68b16238fc37688102dbaa04f4..c4cde9c08f1ffa9ed5c7c1d91a10b745ef7fdb3e 100644 (file)
@@ -580,10 +580,12 @@ static int s3c_rtc_suspend(struct device *dev)
 
        clk_enable(rtc_clk);
        /* save TICNT for anyone using periodic interrupts */
-       ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
        if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
                ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
                ticnt_en_save &= S3C64XX_RTCCON_TICEN;
+               ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT);
+       } else {
+               ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
        }
        s3c_rtc_enable(pdev, 0);
 
@@ -605,10 +607,15 @@ static int s3c_rtc_resume(struct device *dev)
 
        clk_enable(rtc_clk);
        s3c_rtc_enable(pdev, 1);
-       writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
-       if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
-               tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
-               writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
+       if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
+               writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
+               if (ticnt_en_save) {
+                       tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
+                       writew(tmp | ticnt_en_save,
+                                       s3c_rtc_base + S3C2410_RTCCON);
+               }
+       } else {
+               writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
        }
 
        if (device_may_wakeup(dev) && wake_en) {
index eb5d22795c47a55744381ee3f9e70c1666701835..5af7f0bd6125702358cb1fbab5830c5a77506e7b 100644 (file)
@@ -922,7 +922,7 @@ static int __init con3215_init(void)
                raw3215_freelist = req;
        }
 
-       cdev = ccw_device_probe_console();
+       cdev = ccw_device_create_console(&raw3215_ccw_driver);
        if (IS_ERR(cdev))
                return -ENODEV;
 
@@ -932,6 +932,12 @@ static int __init con3215_init(void)
        cdev->handler = raw3215_irq;
 
        raw->flags |= RAW3215_FIXED;
+       if (ccw_device_enable_console(cdev)) {
+               ccw_device_destroy_console(cdev);
+               raw3215_free_info(raw);
+               raw3215[0] = NULL;
+               return -ENODEV;
+       }
 
        /* Request the console irq */
        if (raw3215_startup(raw) != 0) {
index 699fd3e363dfba2f7b0fe8dbab3f43961ec1a108..75ffe9980c3e1cb8e141c6e29d01cef98aaf862f 100644 (file)
@@ -7,6 +7,7 @@
  *     Copyright IBM Corp. 2003, 2009
  */
 
+#include <linux/module.h>
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -30,6 +31,9 @@
 
 static struct raw3270_fn con3270_fn;
 
+static bool auto_update = 1;
+module_param(auto_update, bool, 0);
+
 /*
  * Main 3270 console view data structure.
  */
@@ -204,6 +208,8 @@ con3270_update(struct con3270 *cp)
        struct string *s, *n;
        int rc;
 
+       if (!auto_update && !raw3270_view_active(&cp->view))
+               return;
        if (cp->view.dev)
                raw3270_activate_view(&cp->view);
 
@@ -529,6 +535,7 @@ con3270_flush(void)
        if (!cp->view.dev)
                return;
        raw3270_pm_unfreeze(&cp->view);
+       raw3270_activate_view(&cp->view);
        spin_lock_irqsave(&cp->view.lock, flags);
        con3270_wait_write(cp);
        cp->nr_up = 0;
@@ -576,7 +583,6 @@ static struct console con3270 = {
 static int __init
 con3270_init(void)
 {
-       struct ccw_device *cdev;
        struct raw3270 *rp;
        void *cbuf;
        int i;
@@ -591,10 +597,7 @@ con3270_init(void)
                cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
        }
 
-       cdev = ccw_device_probe_console();
-       if (IS_ERR(cdev))
-               return -ENODEV;
-       rp = raw3270_setup_console(cdev);
+       rp = raw3270_setup_console();
        if (IS_ERR(rp))
                return PTR_ERR(rp);
 
index 2cdec21e8924ea7b0403aafd1b0bae172a76416e..9f849df4381e1388c87b89bfc33f2b350ce54dda 100644 (file)
@@ -275,6 +275,15 @@ __raw3270_start(struct raw3270 *rp, struct raw3270_view *view,
        return 0;
 }
 
+int
+raw3270_view_active(struct raw3270_view *view)
+{
+       struct raw3270 *rp = view->dev;
+
+       return rp && rp->view == view &&
+               !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags);
+}
+
 int
 raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
 {
@@ -776,22 +785,37 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
 }
 
 #ifdef CONFIG_TN3270_CONSOLE
+/* Tentative definition - see below for actual definition. */
+static struct ccw_driver raw3270_ccw_driver;
+
 /*
  * Setup 3270 device configured as console.
  */
-struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
+struct raw3270 __init *raw3270_setup_console(void)
 {
+       struct ccw_device *cdev;
        unsigned long flags;
        struct raw3270 *rp;
        char *ascebc;
        int rc;
 
+       cdev = ccw_device_create_console(&raw3270_ccw_driver);
+       if (IS_ERR(cdev))
+               return ERR_CAST(cdev);
+
        rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
        ascebc = kzalloc(256, GFP_KERNEL);
        rc = raw3270_setup_device(cdev, rp, ascebc);
        if (rc)
                return ERR_PTR(rc);
        set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);
+
+       rc = ccw_device_enable_console(cdev);
+       if (rc) {
+               ccw_device_destroy_console(cdev);
+               return ERR_PTR(rc);
+       }
+
        spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
        do {
                __raw3270_reset_device(rp);
index 7b73ff8c1bd7a59a5c60fe9d7886371c48d4d2c4..e1e41c2861fbb34db1d035b4f51965cb39b41aa7 100644 (file)
@@ -173,6 +173,7 @@ int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *);
 int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *);
 int raw3270_reset(struct raw3270_view *);
 struct raw3270_view *raw3270_view(struct raw3270_view *);
+int raw3270_view_active(struct raw3270_view *);
 
 /* Reference count inliner for view structures. */
 static inline void
@@ -190,7 +191,7 @@ raw3270_put_view(struct raw3270_view *view)
                wake_up(&raw3270_wait_queue);
 }
 
-struct raw3270 *raw3270_setup_console(struct ccw_device *cdev);
+struct raw3270 *raw3270_setup_console(void);
 void raw3270_wait_cons_dev(struct raw3270 *);
 
 /* Notifier for device addition/removal */
index 82f2c389b4d1f51e882de45cd5e0fadfa3405f3e..14196ea0fdf3ad878b6fe527733d8390f0ba6a25 100644 (file)
@@ -20,7 +20,9 @@ struct read_info_sccb {
        struct  sccb_header header;     /* 0-7 */
        u16     rnmax;                  /* 8-9 */
        u8      rnsize;                 /* 10 */
-       u8      _reserved0[24 - 11];    /* 11-15 */
+       u8      _reserved0[16 - 11];    /* 11-15 */
+       u16     ncpurl;                 /* 16-17 */
+       u8      _reserved7[24 - 18];    /* 18-23 */
        u8      loadparm[8];            /* 24-31 */
        u8      _reserved1[48 - 32];    /* 32-47 */
        u64     facilities;             /* 48-55 */
@@ -32,13 +34,16 @@ struct read_info_sccb {
        u8      _reserved4[100 - 92];   /* 92-99 */
        u32     rnsize2;                /* 100-103 */
        u64     rnmax2;                 /* 104-111 */
-       u8      _reserved5[4096 - 112]; /* 112-4095 */
+       u8      _reserved5[120 - 112];  /* 112-119 */
+       u16     hcpua;                  /* 120-121 */
+       u8      _reserved6[4096 - 122]; /* 122-4095 */
 } __packed __aligned(PAGE_SIZE);
 
 static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata;
 static unsigned int sclp_con_has_vt220 __initdata;
 static unsigned int sclp_con_has_linemode __initdata;
 static unsigned long sclp_hsa_size;
+static unsigned int sclp_max_cpu;
 static struct sclp_ipl_info sclp_ipl_info;
 
 u64 sclp_facilities;
@@ -102,6 +107,15 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
        sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
        sclp_rzm <<= 20;
 
+       if (!sccb->hcpua) {
+               if (MACHINE_IS_VM)
+                       sclp_max_cpu = 64;
+               else
+                       sclp_max_cpu = sccb->ncpurl;
+       } else {
+               sclp_max_cpu = sccb->hcpua + 1;
+       }
+
        /* Save IPL information */
        sclp_ipl_info.is_valid = 1;
        if (sccb->flags & 0x2)
@@ -129,6 +143,11 @@ unsigned long long sclp_get_rzm(void)
        return sclp_rzm;
 }
 
+unsigned int sclp_get_max_cpu(void)
+{
+       return sclp_max_cpu;
+}
+
 /*
  * This function will be called after sclp_facilities_detect(), which gets
  * called from early.c code. The sclp_facilities_detect() function retrieves
@@ -184,9 +203,9 @@ static long __init sclp_hsa_size_init(struct sdias_sccb *sccb)
        sccb_init_eq_size(sccb);
        if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
                return -EIO;
-       if (sccb->evbuf.blk_cnt != 0)
-               return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
-       return 0;
+       if (sccb->evbuf.blk_cnt == 0)
+               return 0;
+       return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
 }
 
 static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
@@ -195,6 +214,8 @@ static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
        sccb->length = PAGE_SIZE;
        if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
                return -EIO;
+       if (((struct sdias_sccb *) sccb)->evbuf.blk_cnt == 0)
+               return 0;
        return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE;
 }
 
index f055df0b167fc83e1f2f6f17e0aef47e129007b4..445564c790f65ddc587d2a8185468c28b9e711a7 100644 (file)
@@ -186,55 +186,71 @@ void airq_iv_release(struct airq_iv *iv)
 EXPORT_SYMBOL(airq_iv_release);
 
 /**
- * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector
+ * airq_iv_alloc - allocate irq bits from an interrupt vector
  * @iv: pointer to an interrupt vector structure
+ * @num: number of consecutive irq bits to allocate
  *
- * Returns the bit number of the allocated irq, or -1UL if no bit
- * is available or the AIRQ_IV_ALLOC flag has not been specified
+ * Returns the bit number of the first irq in the allocated block of irqs,
+ * or -1UL if no bit is available or the AIRQ_IV_ALLOC flag has not been
+ * specified
  */
-unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
+unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)
 {
-       unsigned long bit;
+       unsigned long bit, i;
 
-       if (!iv->avail)
+       if (!iv->avail || num == 0)
                return -1UL;
        spin_lock(&iv->lock);
        bit = find_first_bit_inv(iv->avail, iv->bits);
-       if (bit < iv->bits) {
-               clear_bit_inv(bit, iv->avail);
-               if (bit >= iv->end)
-                       iv->end = bit + 1;
-       } else
+       while (bit + num <= iv->bits) {
+               for (i = 1; i < num; i++)
+                       if (!test_bit_inv(bit + i, iv->avail))
+                               break;
+               if (i >= num) {
+                       /* Found a suitable block of irqs */
+                       for (i = 0; i < num; i++)
+                               clear_bit_inv(bit + i, iv->avail);
+                       if (bit + num >= iv->end)
+                               iv->end = bit + num + 1;
+                       break;
+               }
+               bit = find_next_bit_inv(iv->avail, iv->bits, bit + i + 1);
+       }
+       if (bit + num > iv->bits)
                bit = -1UL;
        spin_unlock(&iv->lock);
        return bit;
 
 }
-EXPORT_SYMBOL(airq_iv_alloc_bit);
+EXPORT_SYMBOL(airq_iv_alloc);
 
 /**
- * airq_iv_free_bit - free an irq bit of an interrupt vector
+ * airq_iv_free - free irq bits of an interrupt vector
  * @iv: pointer to interrupt vector structure
- * @bit: number of the irq bit to free
+ * @bit: number of the first irq bit to free
+ * @num: number of consecutive irq bits to free
  */
-void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
+void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num)
 {
-       if (!iv->avail)
+       unsigned long i;
+
+       if (!iv->avail || num == 0)
                return;
        spin_lock(&iv->lock);
-       /* Clear (possibly left over) interrupt bit */
-       clear_bit_inv(bit, iv->vector);
-       /* Make the bit position available again */
-       set_bit_inv(bit, iv->avail);
-       if (bit == iv->end - 1) {
+       for (i = 0; i < num; i++) {
+               /* Clear (possibly left over) interrupt bit */
+               clear_bit_inv(bit + i, iv->vector);
+               /* Make the bit positions available again */
+               set_bit_inv(bit + i, iv->avail);
+       }
+       if (bit + num >= iv->end) {
                /* Find new end of bit-field */
-               while (--iv->end > 0)
-                       if (!test_bit_inv(iv->end - 1, iv->avail))
-                               break;
+               while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail))
+                       iv->end--;
        }
        spin_unlock(&iv->lock);
 }
-EXPORT_SYMBOL(airq_iv_free_bit);
+EXPORT_SYMBOL(airq_iv_free);
 
 /**
  * airq_iv_scan - scan interrupt vector for non-zero bits
index f6b9188c5af581b8c0d587932c5de1af5d996951..9f0ea6cb6922619dfe04803c284002431110e11f 100644 (file)
@@ -610,6 +610,7 @@ void chsc_chp_online(struct chp_id chpid)
                css_wait_for_slow_path();
                for_each_subchannel_staged(__s390_process_res_acc, NULL,
                                           &link);
+               css_schedule_reprobe();
        }
 }
 
index 7b29d0be0ca33b610443a2059374a54fb0802f26..1d3661af7bd83c47afc4a468446278f121df056c 100644 (file)
@@ -173,8 +173,7 @@ static struct css_driver chsc_subchannel_driver = {
 
 static int __init chsc_init_dbfs(void)
 {
-       chsc_debug_msg_id = debug_register("chsc_msg", 16, 1,
-                                          16 * sizeof(long));
+       chsc_debug_msg_id = debug_register("chsc_msg", 8, 1, 4 * sizeof(long));
        if (!chsc_debug_msg_id)
                goto out;
        debug_register_view(chsc_debug_msg_id, &debug_sprintf_view);
index 88e35d85d205f7c21de1f81860865386a7845289..d691e6a13aae934622376d60140409475aa39783 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/chpid.h>
 #include <asm/airq.h>
 #include <asm/isc.h>
-#include <asm/cputime.h>
+#include <linux/cputime.h>
 #include <asm/fcx.h>
 #include <asm/nmi.h>
 #include <asm/crw.h>
@@ -54,7 +54,7 @@ debug_info_t *cio_debug_crw_id;
  */
 static int __init cio_debug_init(void)
 {
-       cio_debug_msg_id = debug_register("cio_msg", 16, 1, 16 * sizeof(long));
+       cio_debug_msg_id = debug_register("cio_msg", 16, 1, 11 * sizeof(long));
        if (!cio_debug_msg_id)
                goto out_unregister;
        debug_register_view(cio_debug_msg_id, &debug_sprintf_view);
@@ -64,7 +64,7 @@ static int __init cio_debug_init(void)
                goto out_unregister;
        debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view);
        debug_set_level(cio_debug_trace_id, 2);
-       cio_debug_crw_id = debug_register("cio_crw", 16, 1, 16 * sizeof(long));
+       cio_debug_crw_id = debug_register("cio_crw", 8, 1, 8 * sizeof(long));
        if (!cio_debug_crw_id)
                goto out_unregister;
        debug_register_view(cio_debug_crw_id, &debug_sprintf_view);
@@ -342,8 +342,9 @@ static int cio_check_config(struct subchannel *sch, struct schib *schib)
  */
 int cio_commit_config(struct subchannel *sch)
 {
-       struct schib schib;
        int ccode, retry, ret = 0;
+       struct schib schib;
+       struct irb irb;
 
        if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib))
                return -ENODEV;
@@ -367,7 +368,10 @@ int cio_commit_config(struct subchannel *sch)
                        ret = -EAGAIN;
                        break;
                case 1: /* status pending */
-                       return -EBUSY;
+                       ret = -EBUSY;
+                       if (tsch(sch->schid, &irb))
+                               return ret;
+                       break;
                case 2: /* busy */
                        udelay(100); /* allow for recovery */
                        ret = -EBUSY;
@@ -403,7 +407,6 @@ EXPORT_SYMBOL_GPL(cio_update_schib);
  */
 int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
 {
-       int retry;
        int ret;
 
        CIO_TRACE_EVENT(2, "ensch");
@@ -418,20 +421,14 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
        sch->config.isc = sch->isc;
        sch->config.intparm = intparm;
 
-       for (retry = 0; retry < 3; retry++) {
+       ret = cio_commit_config(sch);
+       if (ret == -EIO) {
+               /*
+                * Got a program check in msch. Try without
+                * the concurrent sense bit the next time.
+                */
+               sch->config.csense = 0;
                ret = cio_commit_config(sch);
-               if (ret == -EIO) {
-                       /*
-                        * Got a program check in msch. Try without
-                        * the concurrent sense bit the next time.
-                        */
-                       sch->config.csense = 0;
-               } else if (ret == -EBUSY) {
-                       struct irb irb;
-                       if (tsch(sch->schid, &irb) != 0)
-                               break;
-               } else
-                       break;
        }
        CIO_HEX_EVENT(2, &ret, sizeof(ret));
        return ret;
@@ -444,7 +441,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
  */
 int cio_disable_subchannel(struct subchannel *sch)
 {
-       int retry;
        int ret;
 
        CIO_TRACE_EVENT(2, "dissch");
@@ -456,16 +452,8 @@ int cio_disable_subchannel(struct subchannel *sch)
                return -ENODEV;
 
        sch->config.ena = 0;
+       ret = cio_commit_config(sch);
 
-       for (retry = 0; retry < 3; retry++) {
-               ret = cio_commit_config(sch);
-               if (ret == -EBUSY) {
-                       struct irb irb;
-                       if (tsch(sch->schid, &irb) != 0)
-                               break;
-               } else
-                       break;
-       }
        CIO_HEX_EVENT(2, &ret, sizeof(ret));
        return ret;
 }
index e9d783563cbb8894182efcfde40376eb731d286b..d8d9b5b5cc56f9508cd9bae511c592867775a3cc 100644 (file)
@@ -1571,12 +1571,27 @@ out:
        return rc;
 }
 
+static void ccw_device_set_int_class(struct ccw_device *cdev)
+{
+       struct ccw_driver *cdrv = cdev->drv;
+
+       /* Note: we interpret class 0 in this context as an uninitialized
+        * field since it translates to a non-I/O interrupt class. */
+       if (cdrv->int_class != 0)
+               cdev->private->int_class = cdrv->int_class;
+       else
+               cdev->private->int_class = IRQIO_CIO;
+}
+
 #ifdef CONFIG_CCW_CONSOLE
-static int ccw_device_console_enable(struct ccw_device *cdev,
-                                    struct subchannel *sch)
+int __init ccw_device_enable_console(struct ccw_device *cdev)
 {
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
        int rc;
 
+       if (!cdev->drv || !cdev->handler)
+               return -EINVAL;
+
        io_subchannel_init_fields(sch);
        rc = cio_commit_config(sch);
        if (rc)
@@ -1609,12 +1624,11 @@ out_unlock:
        return rc;
 }
 
-struct ccw_device *ccw_device_probe_console(void)
+struct ccw_device * __init ccw_device_create_console(struct ccw_driver *drv)
 {
        struct io_subchannel_private *io_priv;
        struct ccw_device *cdev;
        struct subchannel *sch;
-       int ret;
 
        sch = cio_probe_console();
        if (IS_ERR(sch))
@@ -1631,18 +1645,23 @@ struct ccw_device *ccw_device_probe_console(void)
                kfree(io_priv);
                return cdev;
        }
+       cdev->drv = drv;
        set_io_private(sch, io_priv);
-       ret = ccw_device_console_enable(cdev, sch);
-       if (ret) {
-               set_io_private(sch, NULL);
-               put_device(&sch->dev);
-               put_device(&cdev->dev);
-               kfree(io_priv);
-               return ERR_PTR(ret);
-       }
+       ccw_device_set_int_class(cdev);
        return cdev;
 }
 
+void __init ccw_device_destroy_console(struct ccw_device *cdev)
+{
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+       struct io_subchannel_private *io_priv = to_io_private(sch);
+
+       set_io_private(sch, NULL);
+       put_device(&sch->dev);
+       put_device(&cdev->dev);
+       kfree(io_priv);
+}
+
 /**
  * ccw_device_wait_idle() - busy wait for device to become idle
  * @cdev: ccw device
@@ -1726,15 +1745,8 @@ ccw_device_probe (struct device *dev)
        int ret;
 
        cdev->drv = cdrv; /* to let the driver call _set_online */
-       /* Note: we interpret class 0 in this context as an uninitialized
-        * field since it translates to a non-I/O interrupt class. */
-       if (cdrv->int_class != 0)
-               cdev->private->int_class = cdrv->int_class;
-       else
-               cdev->private->int_class = IRQIO_CIO;
-
+       ccw_device_set_int_class(cdev);
        ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
-
        if (ret) {
                cdev->drv = NULL;
                cdev->private->int_class = IRQIO_CIO;
index 8acaae18bd11c404d4b6a25e4771846c39e4c837..a563e4c00590d5737b50ad08ee654f0aba551dc7 100644 (file)
@@ -359,14 +359,12 @@ static inline int multicast_outbound(struct qdio_q *q)
 #define need_siga_sync_out_after_pci(q)        \
        (unlikely(q->irq_ptr->siga_flag.sync_out_after_pci))
 
-#define for_each_input_queue(irq_ptr, q, i)    \
-       for (i = 0, q = irq_ptr->input_qs[0];   \
-               i < irq_ptr->nr_input_qs;       \
-               q = irq_ptr->input_qs[++i])
-#define for_each_output_queue(irq_ptr, q, i)   \
-       for (i = 0, q = irq_ptr->output_qs[0];  \
-               i < irq_ptr->nr_output_qs;      \
-               q = irq_ptr->output_qs[++i])
+#define for_each_input_queue(irq_ptr, q, i)            \
+       for (i = 0; i < irq_ptr->nr_input_qs &&         \
+               ({ q = irq_ptr->input_qs[i]; 1; }); i++)
+#define for_each_output_queue(irq_ptr, q, i)           \
+       for (i = 0; i < irq_ptr->nr_output_qs &&        \
+               ({ q = irq_ptr->output_qs[i]; 1; }); i++)
 
 #define prev_buf(bufnr)        \
        ((bufnr + QDIO_MAX_BUFFERS_MASK) & QDIO_MAX_BUFFERS_MASK)
index c883a085c0591cd8a0673d495f36e74f9f6e0427..77466c4faabb67b96851fa22c8674d3f6cc4a4a0 100644 (file)
@@ -996,7 +996,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
                }
        }
 
-       if (!pci_out_supported(q))
+       if (!(irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED))
                return;
 
        for_each_output_queue(irq_ptr, q, i) {
index dc542e0a3055a6abb63314ee6dd20ecc451c7d2d..0bc91e46395a8d84ad8c989b6d2a7844593c3ba0 100644 (file)
@@ -311,7 +311,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
        } __packed * msg = ap_msg->message;
 
        int rcblen = CEIL4(xcRB->request_control_blk_length);
-       int replylen;
+       int replylen, req_sumlen, resp_sumlen;
        char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
        char *function_code;
 
@@ -321,12 +321,34 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
                xcRB->request_data_length;
        if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
                return -EINVAL;
+
+       /* Overflow check
+          sum must be greater (or equal) than the largest operand */
+       req_sumlen = CEIL4(xcRB->request_control_blk_length) +
+                       xcRB->request_data_length;
+       if ((CEIL4(xcRB->request_control_blk_length) <=
+                                               xcRB->request_data_length) ?
+               (req_sumlen < xcRB->request_data_length) :
+               (req_sumlen < CEIL4(xcRB->request_control_blk_length))) {
+               return -EINVAL;
+       }
+
        replylen = sizeof(struct type86_fmt2_msg) +
                CEIL4(xcRB->reply_control_blk_length) +
                xcRB->reply_data_length;
        if (replylen > MSGTYPE06_MAX_MSG_SIZE)
                return -EINVAL;
 
+       /* Overflow check
+          sum must be greater (or equal) than the largest operand */
+       resp_sumlen = CEIL4(xcRB->reply_control_blk_length) +
+                       xcRB->reply_data_length;
+       if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ?
+               (resp_sumlen < xcRB->reply_data_length) :
+               (resp_sumlen < CEIL4(xcRB->reply_control_blk_length))) {
+               return -EINVAL;
+       }
+
        /* prepare type6 header */
        msg->hdr = static_type6_hdrX;
        memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
index c3a83df07894e51195d914111c15be2c615f09c1..a0aff2eb247c2fb9657aff821299404aa2d20ddc 100644 (file)
@@ -33,8 +33,8 @@ struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
        /*                   N  P  A    M  L  V                      H  */
        [QETH_DBF_SETUP] = {"qeth_setup",
                                8, 1,   8, 5, &debug_hex_ascii_view, NULL},
-       [QETH_DBF_MSG]   = {"qeth_msg",
-                               8, 1, 128, 3, &debug_sprintf_view,   NULL},
+       [QETH_DBF_MSG]   = {"qeth_msg", 8, 1, 11 * sizeof(long), 3,
+                           &debug_sprintf_view, NULL},
        [QETH_DBF_CTRL]  = {"qeth_control",
                8, 1, QETH_DBF_CTRL_LEN, 5, &debug_hex_ascii_view, NULL},
 };
@@ -1660,7 +1660,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
                                QDIO_FLAG_CLEANUP_USING_CLEAR);
                if (rc)
                        QETH_CARD_TEXT_(card, 3, "1err%d", rc);
-               qdio_free(CARD_DDEV(card));
                atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED);
                break;
        case QETH_QDIO_CLEANING:
@@ -2605,6 +2604,7 @@ static int qeth_mpc_initialize(struct qeth_card *card)
        return 0;
 out_qdio:
        qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
+       qdio_free(CARD_DDEV(card));
        return rc;
 }
 
@@ -4906,9 +4906,11 @@ retry:
        if (retries < 3)
                QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n",
                        dev_name(&card->gdev->dev));
+       rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
        ccw_device_set_offline(CARD_DDEV(card));
        ccw_device_set_offline(CARD_WDEV(card));
        ccw_device_set_offline(CARD_RDEV(card));
+       qdio_free(CARD_DDEV(card));
        rc = ccw_device_set_online(CARD_RDEV(card));
        if (rc)
                goto retriable;
@@ -4918,7 +4920,6 @@ retry:
        rc = ccw_device_set_online(CARD_DDEV(card));
        if (rc)
                goto retriable;
-       rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
 retriable:
        if (rc == -ERESTARTSYS) {
                QETH_DBF_TEXT(SETUP, 2, "break1");
index 0710550093ce6ac5fea8ddbf80f8409bbc1186f6..908d82529ee9c3e04a42caf92b9e0787836ef7d0 100644 (file)
@@ -1091,6 +1091,7 @@ out_remove:
        ccw_device_set_offline(CARD_DDEV(card));
        ccw_device_set_offline(CARD_WDEV(card));
        ccw_device_set_offline(CARD_RDEV(card));
+       qdio_free(CARD_DDEV(card));
        if (recover_flag == CARD_STATE_RECOVER)
                card->state = CARD_STATE_RECOVER;
        else
@@ -1132,6 +1133,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
                rc = (rc2) ? rc2 : rc3;
        if (rc)
                QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+       qdio_free(CARD_DDEV(card));
        if (recover_flag == CARD_STATE_UP)
                card->state = CARD_STATE_RECOVER;
        /* let user_space know that device is offline */
@@ -1194,6 +1196,7 @@ static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
                qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
        qeth_qdio_clear_card(card, 0);
        qeth_clear_qdio_buffers(card);
+       qdio_free(CARD_DDEV(card));
 }
 
 static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
index 0f430424c3b8b0aec231c3e2ca69d739c0c29701..3524d34ff694c273afefc7d85bfa17b6bce38af9 100644 (file)
@@ -3447,6 +3447,7 @@ out_remove:
        ccw_device_set_offline(CARD_DDEV(card));
        ccw_device_set_offline(CARD_WDEV(card));
        ccw_device_set_offline(CARD_RDEV(card));
+       qdio_free(CARD_DDEV(card));
        if (recover_flag == CARD_STATE_RECOVER)
                card->state = CARD_STATE_RECOVER;
        else
@@ -3493,6 +3494,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
                rc = (rc2) ? rc2 : rc3;
        if (rc)
                QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
+       qdio_free(CARD_DDEV(card));
        if (recover_flag == CARD_STATE_UP)
                card->state = CARD_STATE_RECOVER;
        /* let user_space know that device is offline */
@@ -3545,6 +3547,7 @@ static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
                qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
        qeth_qdio_clear_card(card, 0);
        qeth_clear_qdio_buffers(card);
+       qdio_free(CARD_DDEV(card));
 }
 
 static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
index 6b4678a7900a086e711d4bf9a7f6004bc2efcb3c..4ccb5d869389e353113692d20f02f66d002046cd 100644 (file)
@@ -507,7 +507,6 @@ static int jsflash_init(void)
        }
 
        /* Let us be really paranoid for modifications to probing code. */
-       /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
        if (sparc_cpu_model != sun4m) {
                /* We must be on sun4m because we use MMU Bypass ASI. */
                return -ENXIO;
index a3e6c8a3ff0faa852f163185c46e98d80fb49a43..296c936cc03cc43397ba4905d53ac1fd7b050f89 100644 (file)
@@ -90,6 +90,7 @@
 #include <linux/init.h>
 #include <linux/nvram.h>
 #include <linux/bitops.h>
+#include <linux/wait.h>
 
 #include <asm/setup.h>
 #include <asm/atarihw.h>
@@ -549,8 +550,10 @@ static void falcon_get_lock(void)
 
        local_irq_save(flags);
 
-       while (!in_irq() && falcon_got_lock && stdma_others_waiting())
-               sleep_on(&falcon_fairness_wait);
+       wait_event_cmd(falcon_fairness_wait,
+               in_interrupt() || !falcon_got_lock || !stdma_others_waiting(),
+               local_irq_restore(flags),
+               local_irq_save(flags));
 
        while (!falcon_got_lock) {
                if (in_irq())
@@ -562,7 +565,10 @@ static void falcon_get_lock(void)
                        falcon_trying_lock = 0;
                        wake_up(&falcon_try_wait);
                } else {
-                       sleep_on(&falcon_try_wait);
+                       wait_event_cmd(falcon_try_wait,
+                               falcon_got_lock && !falcon_trying_lock,
+                               local_irq_restore(flags),
+                               local_irq_save(flags));
                }
        }
 
index 1f375051483a428d24c63c206fb24a40cda06211..5642a9b250c2fe11201510460563ec576c70461c 100644 (file)
@@ -325,7 +325,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
                if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
                        continue;
 
-               if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
+               if (sc->device->lun != abrt_task->sc->device->lun)
                        continue;
 
                /* Invalidate WRB Posted for this Task */
index ed880891cb7c4b7c038ee73aac032b77108377d4..e9279a8c1e1c31ecb33daba06dceed4273eadd11 100644 (file)
@@ -594,13 +594,13 @@ static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
                mp_req->mp_resp_bd = NULL;
        }
        if (mp_req->req_buf) {
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                     mp_req->req_buf,
                                     mp_req->req_buf_dma);
                mp_req->req_buf = NULL;
        }
        if (mp_req->resp_buf) {
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                     mp_req->resp_buf,
                                     mp_req->resp_buf_dma);
                mp_req->resp_buf = NULL;
@@ -622,7 +622,7 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
 
        mp_req->req_len = sizeof(struct fcp_cmnd);
        io_req->data_xfer_len = mp_req->req_len;
-       mp_req->req_buf = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+       mp_req->req_buf = dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                             &mp_req->req_buf_dma,
                                             GFP_ATOMIC);
        if (!mp_req->req_buf) {
@@ -631,7 +631,7 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
                return FAILED;
        }
 
-       mp_req->resp_buf = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+       mp_req->resp_buf = dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                              &mp_req->resp_buf_dma,
                                              GFP_ATOMIC);
        if (!mp_req->resp_buf) {
@@ -639,8 +639,8 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
                bnx2fc_free_mp_resc(io_req);
                return FAILED;
        }
-       memset(mp_req->req_buf, 0, PAGE_SIZE);
-       memset(mp_req->resp_buf, 0, PAGE_SIZE);
+       memset(mp_req->req_buf, 0, CNIC_PAGE_SIZE);
+       memset(mp_req->resp_buf, 0, CNIC_PAGE_SIZE);
 
        /* Allocate and map mp_req_bd and mp_resp_bd */
        sz = sizeof(struct fcoe_bd_ctx);
@@ -665,7 +665,7 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
        mp_req_bd = mp_req->mp_req_bd;
        mp_req_bd->buf_addr_lo = (u32)addr & 0xffffffff;
        mp_req_bd->buf_addr_hi = (u32)((u64)addr >> 32);
-       mp_req_bd->buf_len = PAGE_SIZE;
+       mp_req_bd->buf_len = CNIC_PAGE_SIZE;
        mp_req_bd->flags = 0;
 
        /*
@@ -677,7 +677,7 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
        addr = mp_req->resp_buf_dma;
        mp_resp_bd->buf_addr_lo = (u32)addr & 0xffffffff;
        mp_resp_bd->buf_addr_hi = (u32)((u64)addr >> 32);
-       mp_resp_bd->buf_len = PAGE_SIZE;
+       mp_resp_bd->buf_len = CNIC_PAGE_SIZE;
        mp_resp_bd->flags = 0;
 
        return SUCCESS;
index 4d93177dfb530c4446d959bd97fb71cd5dee86d1..d9bae5672273762dba7d183b4bedcc5206c1f9fe 100644 (file)
@@ -673,7 +673,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
 
        /* Allocate and map SQ */
        tgt->sq_mem_size = tgt->max_sqes * BNX2FC_SQ_WQE_SIZE;
-       tgt->sq_mem_size = (tgt->sq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+       tgt->sq_mem_size = (tgt->sq_mem_size + (CNIC_PAGE_SIZE - 1)) &
+                          CNIC_PAGE_MASK;
 
        tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
                                     &tgt->sq_dma, GFP_KERNEL);
@@ -686,7 +687,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
 
        /* Allocate and map CQ */
        tgt->cq_mem_size = tgt->max_cqes * BNX2FC_CQ_WQE_SIZE;
-       tgt->cq_mem_size = (tgt->cq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+       tgt->cq_mem_size = (tgt->cq_mem_size + (CNIC_PAGE_SIZE - 1)) &
+                          CNIC_PAGE_MASK;
 
        tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
                                     &tgt->cq_dma, GFP_KERNEL);
@@ -699,7 +701,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
 
        /* Allocate and map RQ and RQ PBL */
        tgt->rq_mem_size = tgt->max_rqes * BNX2FC_RQ_WQE_SIZE;
-       tgt->rq_mem_size = (tgt->rq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+       tgt->rq_mem_size = (tgt->rq_mem_size + (CNIC_PAGE_SIZE - 1)) &
+                          CNIC_PAGE_MASK;
 
        tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
                                        &tgt->rq_dma, GFP_KERNEL);
@@ -710,8 +713,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        }
        memset(tgt->rq, 0, tgt->rq_mem_size);
 
-       tgt->rq_pbl_size = (tgt->rq_mem_size / PAGE_SIZE) * sizeof(void *);
-       tgt->rq_pbl_size = (tgt->rq_pbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+       tgt->rq_pbl_size = (tgt->rq_mem_size / CNIC_PAGE_SIZE) * sizeof(void *);
+       tgt->rq_pbl_size = (tgt->rq_pbl_size + (CNIC_PAGE_SIZE - 1)) &
+                          CNIC_PAGE_MASK;
 
        tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
                                         &tgt->rq_pbl_dma, GFP_KERNEL);
@@ -722,7 +726,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        }
 
        memset(tgt->rq_pbl, 0, tgt->rq_pbl_size);
-       num_pages = tgt->rq_mem_size / PAGE_SIZE;
+       num_pages = tgt->rq_mem_size / CNIC_PAGE_SIZE;
        page = tgt->rq_dma;
        pbl = (u32 *)tgt->rq_pbl;
 
@@ -731,13 +735,13 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
                pbl++;
                *pbl = (u32)((u64)page >> 32);
                pbl++;
-               page += PAGE_SIZE;
+               page += CNIC_PAGE_SIZE;
        }
 
        /* Allocate and map XFERQ */
        tgt->xferq_mem_size = tgt->max_sqes * BNX2FC_XFERQ_WQE_SIZE;
-       tgt->xferq_mem_size = (tgt->xferq_mem_size + (PAGE_SIZE - 1)) &
-                              PAGE_MASK;
+       tgt->xferq_mem_size = (tgt->xferq_mem_size + (CNIC_PAGE_SIZE - 1)) &
+                              CNIC_PAGE_MASK;
 
        tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
                                        &tgt->xferq_dma, GFP_KERNEL);
@@ -750,8 +754,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
 
        /* Allocate and map CONFQ & CONFQ PBL */
        tgt->confq_mem_size = tgt->max_sqes * BNX2FC_CONFQ_WQE_SIZE;
-       tgt->confq_mem_size = (tgt->confq_mem_size + (PAGE_SIZE - 1)) &
-                              PAGE_MASK;
+       tgt->confq_mem_size = (tgt->confq_mem_size + (CNIC_PAGE_SIZE - 1)) &
+                              CNIC_PAGE_MASK;
 
        tgt->confq = dma_alloc_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
                                        &tgt->confq_dma, GFP_KERNEL);
@@ -763,9 +767,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        memset(tgt->confq, 0, tgt->confq_mem_size);
 
        tgt->confq_pbl_size =
-               (tgt->confq_mem_size / PAGE_SIZE) * sizeof(void *);
+               (tgt->confq_mem_size / CNIC_PAGE_SIZE) * sizeof(void *);
        tgt->confq_pbl_size =
-               (tgt->confq_pbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (tgt->confq_pbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
 
        tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev,
                                            tgt->confq_pbl_size,
@@ -777,7 +781,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        }
 
        memset(tgt->confq_pbl, 0, tgt->confq_pbl_size);
-       num_pages = tgt->confq_mem_size / PAGE_SIZE;
+       num_pages = tgt->confq_mem_size / CNIC_PAGE_SIZE;
        page = tgt->confq_dma;
        pbl = (u32 *)tgt->confq_pbl;
 
@@ -786,7 +790,7 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
                pbl++;
                *pbl = (u32)((u64)page >> 32);
                pbl++;
-               page += PAGE_SIZE;
+               page += CNIC_PAGE_SIZE;
        }
 
        /* Allocate and map ConnDB */
@@ -805,8 +809,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
 
        /* Allocate and map LCQ */
        tgt->lcq_mem_size = (tgt->max_sqes + 8) * BNX2FC_SQ_WQE_SIZE;
-       tgt->lcq_mem_size = (tgt->lcq_mem_size + (PAGE_SIZE - 1)) &
-                            PAGE_MASK;
+       tgt->lcq_mem_size = (tgt->lcq_mem_size + (CNIC_PAGE_SIZE - 1)) &
+                            CNIC_PAGE_MASK;
 
        tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
                                      &tgt->lcq_dma, GFP_KERNEL);
index e4cf23df4b4f094d64a40332c81facd39da4097c..b87a1933f8809381d974392e6e7b3e7f208b86aa 100644 (file)
@@ -61,7 +61,7 @@ static void bnx2i_adjust_qp_size(struct bnx2i_hba *hba)
         * yield integral num of page buffers
         */
        /* adjust SQ */
-       num_elements_per_pg = PAGE_SIZE / BNX2I_SQ_WQE_SIZE;
+       num_elements_per_pg = CNIC_PAGE_SIZE / BNX2I_SQ_WQE_SIZE;
        if (hba->max_sqes < num_elements_per_pg)
                hba->max_sqes = num_elements_per_pg;
        else if (hba->max_sqes % num_elements_per_pg)
@@ -69,7 +69,7 @@ static void bnx2i_adjust_qp_size(struct bnx2i_hba *hba)
                                 ~(num_elements_per_pg - 1);
 
        /* adjust CQ */
-       num_elements_per_pg = PAGE_SIZE / BNX2I_CQE_SIZE;
+       num_elements_per_pg = CNIC_PAGE_SIZE / BNX2I_CQE_SIZE;
        if (hba->max_cqes < num_elements_per_pg)
                hba->max_cqes = num_elements_per_pg;
        else if (hba->max_cqes % num_elements_per_pg)
@@ -77,7 +77,7 @@ static void bnx2i_adjust_qp_size(struct bnx2i_hba *hba)
                                 ~(num_elements_per_pg - 1);
 
        /* adjust RQ */
-       num_elements_per_pg = PAGE_SIZE / BNX2I_RQ_WQE_SIZE;
+       num_elements_per_pg = CNIC_PAGE_SIZE / BNX2I_RQ_WQE_SIZE;
        if (hba->max_rqes < num_elements_per_pg)
                hba->max_rqes = num_elements_per_pg;
        else if (hba->max_rqes % num_elements_per_pg)
@@ -959,7 +959,7 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
 
        /* SQ page table */
        memset(ep->qp.sq_pgtbl_virt, 0, ep->qp.sq_pgtbl_size);
-       num_pages = ep->qp.sq_mem_size / PAGE_SIZE;
+       num_pages = ep->qp.sq_mem_size / CNIC_PAGE_SIZE;
        page = ep->qp.sq_phys;
 
        if (cnic_dev_10g)
@@ -973,7 +973,7 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
                        ptbl++;
                        *ptbl = (u32) ((u64) page >> 32);
                        ptbl++;
-                       page += PAGE_SIZE;
+                       page += CNIC_PAGE_SIZE;
                } else {
                        /* PTE is written in big endian format for
                         * 5706/5708/5709 devices */
@@ -981,13 +981,13 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
                        ptbl++;
                        *ptbl = (u32) page;
                        ptbl++;
-                       page += PAGE_SIZE;
+                       page += CNIC_PAGE_SIZE;
                }
        }
 
        /* RQ page table */
        memset(ep->qp.rq_pgtbl_virt, 0, ep->qp.rq_pgtbl_size);
-       num_pages = ep->qp.rq_mem_size / PAGE_SIZE;
+       num_pages = ep->qp.rq_mem_size / CNIC_PAGE_SIZE;
        page = ep->qp.rq_phys;
 
        if (cnic_dev_10g)
@@ -1001,7 +1001,7 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
                        ptbl++;
                        *ptbl = (u32) ((u64) page >> 32);
                        ptbl++;
-                       page += PAGE_SIZE;
+                       page += CNIC_PAGE_SIZE;
                } else {
                        /* PTE is written in big endian format for
                         * 5706/5708/5709 devices */
@@ -1009,13 +1009,13 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
                        ptbl++;
                        *ptbl = (u32) page;
                        ptbl++;
-                       page += PAGE_SIZE;
+                       page += CNIC_PAGE_SIZE;
                }
        }
 
        /* CQ page table */
        memset(ep->qp.cq_pgtbl_virt, 0, ep->qp.cq_pgtbl_size);
-       num_pages = ep->qp.cq_mem_size / PAGE_SIZE;
+       num_pages = ep->qp.cq_mem_size / CNIC_PAGE_SIZE;
        page = ep->qp.cq_phys;
 
        if (cnic_dev_10g)
@@ -1029,7 +1029,7 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
                        ptbl++;
                        *ptbl = (u32) ((u64) page >> 32);
                        ptbl++;
-                       page += PAGE_SIZE;
+                       page += CNIC_PAGE_SIZE;
                } else {
                        /* PTE is written in big endian format for
                         * 5706/5708/5709 devices */
@@ -1037,7 +1037,7 @@ static void setup_qp_page_tables(struct bnx2i_endpoint *ep)
                        ptbl++;
                        *ptbl = (u32) page;
                        ptbl++;
-                       page += PAGE_SIZE;
+                       page += CNIC_PAGE_SIZE;
                }
        }
 }
@@ -1064,11 +1064,11 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
        /* Allocate page table memory for SQ which is page aligned */
        ep->qp.sq_mem_size = hba->max_sqes * BNX2I_SQ_WQE_SIZE;
        ep->qp.sq_mem_size =
-               (ep->qp.sq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (ep->qp.sq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
        ep->qp.sq_pgtbl_size =
-               (ep->qp.sq_mem_size / PAGE_SIZE) * sizeof(void *);
+               (ep->qp.sq_mem_size / CNIC_PAGE_SIZE) * sizeof(void *);
        ep->qp.sq_pgtbl_size =
-               (ep->qp.sq_pgtbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (ep->qp.sq_pgtbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
 
        ep->qp.sq_pgtbl_virt =
                dma_alloc_coherent(&hba->pcidev->dev, ep->qp.sq_pgtbl_size,
@@ -1101,11 +1101,11 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
        /* Allocate page table memory for CQ which is page aligned */
        ep->qp.cq_mem_size = hba->max_cqes * BNX2I_CQE_SIZE;
        ep->qp.cq_mem_size =
-               (ep->qp.cq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (ep->qp.cq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
        ep->qp.cq_pgtbl_size =
-               (ep->qp.cq_mem_size / PAGE_SIZE) * sizeof(void *);
+               (ep->qp.cq_mem_size / CNIC_PAGE_SIZE) * sizeof(void *);
        ep->qp.cq_pgtbl_size =
-               (ep->qp.cq_pgtbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (ep->qp.cq_pgtbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
 
        ep->qp.cq_pgtbl_virt =
                dma_alloc_coherent(&hba->pcidev->dev, ep->qp.cq_pgtbl_size,
@@ -1144,11 +1144,11 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
        /* Allocate page table memory for RQ which is page aligned */
        ep->qp.rq_mem_size = hba->max_rqes * BNX2I_RQ_WQE_SIZE;
        ep->qp.rq_mem_size =
-               (ep->qp.rq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (ep->qp.rq_mem_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
        ep->qp.rq_pgtbl_size =
-               (ep->qp.rq_mem_size / PAGE_SIZE) * sizeof(void *);
+               (ep->qp.rq_mem_size / CNIC_PAGE_SIZE) * sizeof(void *);
        ep->qp.rq_pgtbl_size =
-               (ep->qp.rq_pgtbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+               (ep->qp.rq_pgtbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
 
        ep->qp.rq_pgtbl_virt =
                dma_alloc_coherent(&hba->pcidev->dev, ep->qp.rq_pgtbl_size,
@@ -1270,7 +1270,7 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
        bnx2i_adjust_qp_size(hba);
 
        iscsi_init.flags =
-               ISCSI_PAGE_SIZE_4K << ISCSI_KWQE_INIT1_PAGE_SIZE_SHIFT;
+               (CNIC_PAGE_BITS - 8) << ISCSI_KWQE_INIT1_PAGE_SIZE_SHIFT;
        if (en_tcp_dack)
                iscsi_init.flags |= ISCSI_KWQE_INIT1_DELAYED_ACK_ENABLE;
        iscsi_init.reserved0 = 0;
@@ -1288,15 +1288,15 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
                        ((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16));
        iscsi_init.num_ccells_per_conn = hba->num_ccell;
        iscsi_init.num_tasks_per_conn = hba->max_sqes;
-       iscsi_init.sq_wqes_per_page = PAGE_SIZE / BNX2I_SQ_WQE_SIZE;
+       iscsi_init.sq_wqes_per_page = CNIC_PAGE_SIZE / BNX2I_SQ_WQE_SIZE;
        iscsi_init.sq_num_wqes = hba->max_sqes;
        iscsi_init.cq_log_wqes_per_page =
-               (u8) bnx2i_power_of2(PAGE_SIZE / BNX2I_CQE_SIZE);
+               (u8) bnx2i_power_of2(CNIC_PAGE_SIZE / BNX2I_CQE_SIZE);
        iscsi_init.cq_num_wqes = hba->max_cqes;
        iscsi_init.cq_num_pages = (hba->max_cqes * BNX2I_CQE_SIZE +
-                                  (PAGE_SIZE - 1)) / PAGE_SIZE;
+                                  (CNIC_PAGE_SIZE - 1)) / CNIC_PAGE_SIZE;
        iscsi_init.sq_num_pages = (hba->max_sqes * BNX2I_SQ_WQE_SIZE +
-                                  (PAGE_SIZE - 1)) / PAGE_SIZE;
+                                  (CNIC_PAGE_SIZE - 1)) / CNIC_PAGE_SIZE;
        iscsi_init.rq_buffer_size = BNX2I_RQ_WQE_SIZE;
        iscsi_init.rq_num_wqes = hba->max_rqes;
 
index 854dad7d5b03318d10077d2e367eeb6ca8242dc6..c8b0aff5bbd4aa86d79b64516acf87d97c8894bd 100644 (file)
@@ -525,7 +525,7 @@ static int bnx2i_setup_mp_bdt(struct bnx2i_hba *hba)
        struct iscsi_bd *mp_bdt;
        u64 addr;
 
-       hba->mp_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+       hba->mp_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                            &hba->mp_bd_dma, GFP_KERNEL);
        if (!hba->mp_bd_tbl) {
                printk(KERN_ERR "unable to allocate Middle Path BDT\n");
@@ -533,11 +533,12 @@ static int bnx2i_setup_mp_bdt(struct bnx2i_hba *hba)
                goto out;
        }
 
-       hba->dummy_buffer = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+       hba->dummy_buffer = dma_alloc_coherent(&hba->pcidev->dev,
+                                              CNIC_PAGE_SIZE,
                                               &hba->dummy_buf_dma, GFP_KERNEL);
        if (!hba->dummy_buffer) {
                printk(KERN_ERR "unable to alloc Middle Path Dummy Buffer\n");
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                  hba->mp_bd_tbl, hba->mp_bd_dma);
                hba->mp_bd_tbl = NULL;
                rc = -1;
@@ -548,7 +549,7 @@ static int bnx2i_setup_mp_bdt(struct bnx2i_hba *hba)
        addr = (unsigned long) hba->dummy_buf_dma;
        mp_bdt->buffer_addr_lo = addr & 0xffffffff;
        mp_bdt->buffer_addr_hi = addr >> 32;
-       mp_bdt->buffer_length = PAGE_SIZE;
+       mp_bdt->buffer_length = CNIC_PAGE_SIZE;
        mp_bdt->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
                        ISCSI_BD_FIRST_IN_BD_CHAIN;
 out:
@@ -565,12 +566,12 @@ out:
 static void bnx2i_free_mp_bdt(struct bnx2i_hba *hba)
 {
        if (hba->mp_bd_tbl) {
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                  hba->mp_bd_tbl, hba->mp_bd_dma);
                hba->mp_bd_tbl = NULL;
        }
        if (hba->dummy_buffer) {
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                  hba->dummy_buffer, hba->dummy_buf_dma);
                hba->dummy_buffer = NULL;
        }
@@ -934,14 +935,14 @@ static void bnx2i_conn_free_login_resources(struct bnx2i_hba *hba,
                                            struct bnx2i_conn *bnx2i_conn)
 {
        if (bnx2i_conn->gen_pdu.resp_bd_tbl) {
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                  bnx2i_conn->gen_pdu.resp_bd_tbl,
                                  bnx2i_conn->gen_pdu.resp_bd_dma);
                bnx2i_conn->gen_pdu.resp_bd_tbl = NULL;
        }
 
        if (bnx2i_conn->gen_pdu.req_bd_tbl) {
-               dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                  bnx2i_conn->gen_pdu.req_bd_tbl,
                                  bnx2i_conn->gen_pdu.req_bd_dma);
                bnx2i_conn->gen_pdu.req_bd_tbl = NULL;
@@ -998,13 +999,13 @@ static int bnx2i_conn_alloc_login_resources(struct bnx2i_hba *hba,
        bnx2i_conn->gen_pdu.resp_wr_ptr = bnx2i_conn->gen_pdu.resp_buf;
 
        bnx2i_conn->gen_pdu.req_bd_tbl =
-               dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                   &bnx2i_conn->gen_pdu.req_bd_dma, GFP_KERNEL);
        if (bnx2i_conn->gen_pdu.req_bd_tbl == NULL)
                goto login_req_bd_tbl_failure;
 
        bnx2i_conn->gen_pdu.resp_bd_tbl =
-               dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+               dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                   &bnx2i_conn->gen_pdu.resp_bd_dma,
                                   GFP_KERNEL);
        if (bnx2i_conn->gen_pdu.resp_bd_tbl == NULL)
@@ -1013,7 +1014,7 @@ static int bnx2i_conn_alloc_login_resources(struct bnx2i_hba *hba,
        return 0;
 
 login_resp_bd_tbl_failure:
-       dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+       dma_free_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                          bnx2i_conn->gen_pdu.req_bd_tbl,
                          bnx2i_conn->gen_pdu.req_bd_dma);
        bnx2i_conn->gen_pdu.req_bd_tbl = NULL;
index 4911310a38f5e42fd9d292b89de93b57369c7419..22a9bb1abae1473062b06031494bb38b2cc11576 100644 (file)
@@ -311,9 +311,8 @@ static inline struct Scsi_Host *to_shost(struct isci_host *ihost)
 }
 
 #define for_each_isci_host(id, ihost, pdev) \
-       for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
-            id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
-            ihost = to_pci_info(pdev)->hosts[++id])
+       for (id = 0; id < SCI_MAX_CONTROLLERS && \
+            (ihost = to_pci_info(pdev)->hosts[id]); id++)
 
 static inline void wait_for_start(struct isci_host *ihost)
 {
index 85c77f6b802bdcba5795ced971a39e29f39ae8b9..ac879745ef8007ab2a4973aff26e3c950e8f1dba 100644 (file)
@@ -615,13 +615,6 @@ static void sci_apc_agent_link_up(struct isci_host *ihost,
                                          SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
        } else {
                /* the phy is already the part of the port */
-               u32 port_state = iport->sm.current_state_id;
-
-               /* if the PORT'S state is resetting then the link up is from
-                * port hard reset in this case, we need to tell the port
-                * that link up is recieved
-                */
-               BUG_ON(port_state != SCI_PORT_RESETTING);
                port_agent->phy_ready_mask |= 1 << phy_index;
                sci_port_link_up(iport, iphy);
        }
index 0d30ca849e8f71502c9ecddfa9aa539e4e59af0f..5d6fda72d659770d080e2c4201c4d3e6c7af1adc 100644 (file)
@@ -801,7 +801,7 @@ int isci_task_I_T_nexus_reset(struct domain_device *dev)
                /* XXX: need to cleanup any ireqs targeting this
                 * domain_device
                 */
-               ret = TMF_RESP_FUNC_COMPLETE;
+               ret = -ENODEV;
                goto out;
        }
 
index d2895836f9fa4c00fec1a46d993074ecb3edeaea..766098af4eb79aebf8f080b6906db8aeade896e7 100644 (file)
@@ -700,46 +700,26 @@ void sas_probe_sata(struct asd_sas_port *port)
 
 }
 
-static bool sas_ata_flush_pm_eh(struct asd_sas_port *port, const char *func)
+static void sas_ata_flush_pm_eh(struct asd_sas_port *port, const char *func)
 {
        struct domain_device *dev, *n;
-       bool retry = false;
 
        list_for_each_entry_safe(dev, n, &port->dev_list, dev_list_node) {
-               int rc;
-
                if (!dev_is_sata(dev))
                        continue;
 
                sas_ata_wait_eh(dev);
-               rc = dev->sata_dev.pm_result;
-               if (rc == -EAGAIN)
-                       retry = true;
-               else if (rc) {
-                       /* since we don't have a
-                        * ->port_{suspend|resume} routine in our
-                        *  ata_port ops, and no entanglements with
-                        *  acpi, suspend should just be mechanical trip
-                        *  through eh, catch cases where these
-                        *  assumptions are invalidated
-                        */
-                       WARN_ONCE(1, "failed %s %s error: %d\n", func,
-                                dev_name(&dev->rphy->dev), rc);
-               }
 
                /* if libata failed to power manage the device, tear it down */
                if (ata_dev_disabled(sas_to_ata_dev(dev)))
                        sas_fail_probe(dev, func, -ENODEV);
        }
-
-       return retry;
 }
 
 void sas_suspend_sata(struct asd_sas_port *port)
 {
        struct domain_device *dev;
 
- retry:
        mutex_lock(&port->ha->disco_mutex);
        list_for_each_entry(dev, &port->dev_list, dev_list_node) {
                struct sata_device *sata;
@@ -751,20 +731,17 @@ void sas_suspend_sata(struct asd_sas_port *port)
                if (sata->ap->pm_mesg.event == PM_EVENT_SUSPEND)
                        continue;
 
-               sata->pm_result = -EIO;
-               ata_sas_port_async_suspend(sata->ap, &sata->pm_result);
+               ata_sas_port_suspend(sata->ap);
        }
        mutex_unlock(&port->ha->disco_mutex);
 
-       if (sas_ata_flush_pm_eh(port, __func__))
-               goto retry;
+       sas_ata_flush_pm_eh(port, __func__);
 }
 
 void sas_resume_sata(struct asd_sas_port *port)
 {
        struct domain_device *dev;
 
- retry:
        mutex_lock(&port->ha->disco_mutex);
        list_for_each_entry(dev, &port->dev_list, dev_list_node) {
                struct sata_device *sata;
@@ -776,13 +753,11 @@ void sas_resume_sata(struct asd_sas_port *port)
                if (sata->ap->pm_mesg.event == PM_EVENT_ON)
                        continue;
 
-               sata->pm_result = -EIO;
-               ata_sas_port_async_resume(sata->ap, &sata->pm_result);
+               ata_sas_port_resume(sata->ap);
        }
        mutex_unlock(&port->ha->disco_mutex);
 
-       if (sas_ata_flush_pm_eh(port, __func__))
-               goto retry;
+       sas_ata_flush_pm_eh(port, __func__);
 }
 
 /**
index e1fe95ef23e11353aed91a8da9dd1d1f8ef2a9c3..266724b6b8996d451c4bf81c2ff5f0dbee5c1de5 100644 (file)
@@ -2996,8 +2996,7 @@ struct qla_hw_data {
                                IS_QLA82XX(ha) || IS_QLA83XX(ha) || \
                                IS_QLA8044(ha))
 #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha))
-#define IS_NOPOLLING_TYPE(ha)  ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || \
-                       IS_QLA83XX(ha)) && (ha)->flags.msix_enabled)
+#define IS_NOPOLLING_TYPE(ha)  (IS_QLA81XX(ha) && (ha)->flags.msix_enabled)
 #define IS_FAC_REQUIRED(ha)    (IS_QLA81XX(ha) || IS_QLA83XX(ha))
 #define IS_NOCACHE_VPD_TYPE(ha)        (IS_QLA81XX(ha) || IS_QLA83XX(ha))
 #define IS_ALOGIO_CAPABLE(ha)  (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha))
index 9bc86b9e86b172145443d161e0715658df6acdc7..0a1dcb43d18bdb6b4c734e0ad38ac956ddeb5fe7 100644 (file)
@@ -2880,6 +2880,7 @@ static int
 qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
 {
 #define MIN_MSIX_COUNT 2
+#define ATIO_VECTOR    2
        int i, ret;
        struct msix_entry *entries;
        struct qla_msix_entry *qentry;
@@ -2936,34 +2937,47 @@ msix_failed:
        }
 
        /* Enable MSI-X vectors for the base queue */
-       for (i = 0; i < ha->msix_count; i++) {
+       for (i = 0; i < 2; i++) {
                qentry = &ha->msix_entries[i];
-               if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
-                       ret = request_irq(qentry->vector,
-                               qla83xx_msix_entries[i].handler,
-                               0, qla83xx_msix_entries[i].name, rsp);
-               } else if (IS_P3P_TYPE(ha)) {
+               if (IS_P3P_TYPE(ha))
                        ret = request_irq(qentry->vector,
                                qla82xx_msix_entries[i].handler,
                                0, qla82xx_msix_entries[i].name, rsp);
-               } else {
+               else
                        ret = request_irq(qentry->vector,
                                msix_entries[i].handler,
                                0, msix_entries[i].name, rsp);
-               }
-               if (ret) {
-                       ql_log(ql_log_fatal, vha, 0x00cb,
-                           "MSI-X: unable to register handler -- %x/%d.\n",
-                           qentry->vector, ret);
-                       qla24xx_disable_msix(ha);
-                       ha->mqenable = 0;
-                       goto msix_out;
-               }
+               if (ret)
+                       goto msix_register_fail;
                qentry->have_irq = 1;
                qentry->rsp = rsp;
                rsp->msix = qentry;
        }
 
+       /*
+        * If target mode is enable, also request the vector for the ATIO
+        * queue.
+        */
+       if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
+               qentry = &ha->msix_entries[ATIO_VECTOR];
+               ret = request_irq(qentry->vector,
+                       qla83xx_msix_entries[ATIO_VECTOR].handler,
+                       0, qla83xx_msix_entries[ATIO_VECTOR].name, rsp);
+               qentry->have_irq = 1;
+               qentry->rsp = rsp;
+               rsp->msix = qentry;
+       }
+
+msix_register_fail:
+       if (ret) {
+               ql_log(ql_log_fatal, vha, 0x00cb,
+                   "MSI-X: unable to register handler -- %x/%d.\n",
+                   qentry->vector, ret);
+               qla24xx_disable_msix(ha);
+               ha->mqenable = 0;
+               goto msix_out;
+       }
+
        /* Enable MSI-X vector for response queue update for queue 0 */
        if (IS_QLA83XX(ha)) {
                if (ha->msixbase && ha->mqiobase &&
index 9e80d61e5a3aa0f62e0dbc6d9aeae8632d81935c..0cb73074c1997409c4e63f6d39ac51e641eff088 100644 (file)
@@ -790,17 +790,32 @@ static inline int test_tgt_sess_count(struct qla_tgt *tgt)
 }
 
 /* Called by tcm_qla2xxx configfs code */
-void qlt_stop_phase1(struct qla_tgt *tgt)
+int qlt_stop_phase1(struct qla_tgt *tgt)
 {
        struct scsi_qla_host *vha = tgt->vha;
        struct qla_hw_data *ha = tgt->ha;
        unsigned long flags;
 
+       mutex_lock(&qla_tgt_mutex);
+       if (!vha->fc_vport) {
+               struct Scsi_Host *sh = vha->host;
+               struct fc_host_attrs *fc_host = shost_to_fc_host(sh);
+               bool npiv_vports;
+
+               spin_lock_irqsave(sh->host_lock, flags);
+               npiv_vports = (fc_host->npiv_vports_inuse);
+               spin_unlock_irqrestore(sh->host_lock, flags);
+
+               if (npiv_vports) {
+                       mutex_unlock(&qla_tgt_mutex);
+                       return -EPERM;
+               }
+       }
        if (tgt->tgt_stop || tgt->tgt_stopped) {
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e,
                    "Already in tgt->tgt_stop or tgt_stopped state\n");
-               dump_stack();
-               return;
+               mutex_unlock(&qla_tgt_mutex);
+               return -EPERM;
        }
 
        ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
@@ -815,6 +830,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt)
        qlt_clear_tgt_db(tgt, true);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
        mutex_unlock(&vha->vha_tgt.tgt_mutex);
+       mutex_unlock(&qla_tgt_mutex);
 
        flush_delayed_work(&tgt->sess_del_work);
 
@@ -841,6 +857,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt)
 
        /* Wait for sessions to clear out (just in case) */
        wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
+       return 0;
 }
 EXPORT_SYMBOL(qlt_stop_phase1);
 
@@ -2595,8 +2612,6 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
                return -ENOMEM;
        }
 
-       INIT_LIST_HEAD(&cmd->cmd_list);
-
        memcpy(&cmd->atio, atio, sizeof(*atio));
        cmd->state = QLA_TGT_STATE_NEW;
        cmd->tgt = vha->vha_tgt.qla_tgt;
@@ -3187,7 +3202,8 @@ restart:
                ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c,
                    "SRR cmd %p (se_cmd %p, tag %d, op %x), "
                    "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag,
-                   se_cmd->t_task_cdb[0], cmd->sg_cnt, cmd->offset);
+                   se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0,
+                   cmd->sg_cnt, cmd->offset);
 
                qlt_handle_srr(vha, sctio, imm);
 
@@ -4183,6 +4199,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
        tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
        tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
 
+       if (base_vha->fc_vport)
+               return 0;
+
        mutex_lock(&qla_tgt_mutex);
        list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
        mutex_unlock(&qla_tgt_mutex);
@@ -4196,6 +4215,10 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
        if (!vha->vha_tgt.qla_tgt)
                return 0;
 
+       if (vha->fc_vport) {
+               qlt_release(vha->vha_tgt.qla_tgt);
+               return 0;
+       }
        mutex_lock(&qla_tgt_mutex);
        list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry);
        mutex_unlock(&qla_tgt_mutex);
@@ -4267,6 +4290,12 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
                        continue;
                }
+               if (tgt->tgt_stop) {
+                       pr_debug("MODE_TARGET in shutdown on qla2xxx(%d)\n",
+                                host->host_no);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+                       continue;
+               }
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
                if (!scsi_host_get(host)) {
@@ -4281,12 +4310,11 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
                        scsi_host_put(host);
                        continue;
                }
-               mutex_unlock(&qla_tgt_mutex);
-
                rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn);
                if (rc != 0)
                        scsi_host_put(host);
 
+               mutex_unlock(&qla_tgt_mutex);
                return rc;
        }
        mutex_unlock(&qla_tgt_mutex);
index 1d10eecad499a3598dc3bbd1dc566416d210c54a..ce33d8c26406da00ccb67943093bae5f3fdec0b9 100644 (file)
@@ -855,7 +855,6 @@ struct qla_tgt_cmd {
        uint16_t loop_id;       /* to save extra sess dereferences */
        struct qla_tgt *tgt;    /* to save extra sess dereferences */
        struct scsi_qla_host *vha;
-       struct list_head cmd_list;
 
        struct atio_from_isp atio;
 };
@@ -1002,7 +1001,7 @@ extern void qlt_modify_vp_config(struct scsi_qla_host *,
 extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
 extern int qlt_mem_alloc(struct qla_hw_data *);
 extern void qlt_mem_free(struct qla_hw_data *);
-extern void qlt_stop_phase1(struct qla_tgt *);
+extern int qlt_stop_phase1(struct qla_tgt *);
 extern void qlt_stop_phase2(struct qla_tgt *);
 extern irqreturn_t qla83xx_msix_atio_q(int, void *);
 extern void qlt_83xx_iospace_config(struct qla_hw_data *);
index 75a141bbe74d178834a9f58c6fc723734e63758f..788c4fe2b0c9ec7a8113078c318421d7407ae855 100644 (file)
@@ -182,20 +182,6 @@ static int tcm_qla2xxx_npiv_parse_wwn(
        return 0;
 }
 
-static ssize_t tcm_qla2xxx_npiv_format_wwn(char *buf, size_t len,
-                                       u64 wwpn, u64 wwnn)
-{
-       u8 b[8], b2[8];
-
-       put_unaligned_be64(wwpn, b);
-       put_unaligned_be64(wwnn, b2);
-       return snprintf(buf, len,
-               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x,"
-               "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
-               b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
-               b2[0], b2[1], b2[2], b2[3], b2[4], b2[5], b2[6], b2[7]);
-}
-
 static char *tcm_qla2xxx_npiv_get_fabric_name(void)
 {
        return "qla2xxx_npiv";
@@ -227,15 +213,6 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
        return lport->lport_naa_name;
 }
 
-static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
-{
-       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
-                               struct tcm_qla2xxx_tpg, se_tpg);
-       struct tcm_qla2xxx_lport *lport = tpg->lport;
-
-       return &lport->lport_npiv_name[0];
-}
-
 static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg)
 {
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
@@ -941,15 +918,41 @@ static ssize_t tcm_qla2xxx_tpg_show_enable(
                        atomic_read(&tpg->lport_tpg_enabled));
 }
 
+static void tcm_qla2xxx_depend_tpg(struct work_struct *work)
+{
+       struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
+                               struct tcm_qla2xxx_tpg, tpg_base_work);
+       struct se_portal_group *se_tpg = &base_tpg->se_tpg;
+       struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
+
+       if (!configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
+                                 &se_tpg->tpg_group.cg_item)) {
+               atomic_set(&base_tpg->lport_tpg_enabled, 1);
+               qlt_enable_vha(base_vha);
+       }
+       complete(&base_tpg->tpg_base_comp);
+}
+
+static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)
+{
+       struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
+                               struct tcm_qla2xxx_tpg, tpg_base_work);
+       struct se_portal_group *se_tpg = &base_tpg->se_tpg;
+       struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
+
+       if (!qlt_stop_phase1(base_vha->vha_tgt.qla_tgt)) {
+               atomic_set(&base_tpg->lport_tpg_enabled, 0);
+               configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
+                                      &se_tpg->tpg_group.cg_item);
+       }
+       complete(&base_tpg->tpg_base_comp);
+}
+
 static ssize_t tcm_qla2xxx_tpg_store_enable(
        struct se_portal_group *se_tpg,
        const char *page,
        size_t count)
 {
-       struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
-       struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
-                       struct tcm_qla2xxx_lport, lport_wwn);
-       struct scsi_qla_host *vha = lport->qla_vha;
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
                        struct tcm_qla2xxx_tpg, se_tpg);
        unsigned long op;
@@ -964,19 +967,28 @@ static ssize_t tcm_qla2xxx_tpg_store_enable(
                pr_err("Illegal value for tpg_enable: %lu\n", op);
                return -EINVAL;
        }
-
        if (op) {
-               atomic_set(&tpg->lport_tpg_enabled, 1);
-               qlt_enable_vha(vha);
+               if (atomic_read(&tpg->lport_tpg_enabled))
+                       return -EEXIST;
+
+               INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_depend_tpg);
        } else {
-               if (!vha->vha_tgt.qla_tgt) {
-                       pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n");
-                       return -ENODEV;
-               }
-               atomic_set(&tpg->lport_tpg_enabled, 0);
-               qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+               if (!atomic_read(&tpg->lport_tpg_enabled))
+                       return count;
+
+               INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_undepend_tpg);
        }
+       init_completion(&tpg->tpg_base_comp);
+       schedule_work(&tpg->tpg_base_work);
+       wait_for_completion(&tpg->tpg_base_comp);
 
+       if (op) {
+               if (!atomic_read(&tpg->lport_tpg_enabled))
+                       return -ENODEV;
+       } else {
+               if (atomic_read(&tpg->lport_tpg_enabled))
+                       return -EPERM;
+       }
        return count;
 }
 
@@ -1053,11 +1065,64 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg)
        /*
         * Clear local TPG=1 pointer for non NPIV mode.
         */
-               lport->tpg_1 = NULL;
-
+       lport->tpg_1 = NULL;
        kfree(tpg);
 }
 
+static ssize_t tcm_qla2xxx_npiv_tpg_show_enable(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       return tcm_qla2xxx_tpg_show_enable(se_tpg, page);
+}
+
+static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
+       struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
+                       struct tcm_qla2xxx_lport, lport_wwn);
+       struct scsi_qla_host *vha = lport->qla_vha;
+       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+                       struct tcm_qla2xxx_tpg, se_tpg);
+       unsigned long op;
+       int rc;
+
+       rc = kstrtoul(page, 0, &op);
+       if (rc < 0) {
+               pr_err("kstrtoul() returned %d\n", rc);
+               return -EINVAL;
+       }
+       if ((op != 1) && (op != 0)) {
+               pr_err("Illegal value for tpg_enable: %lu\n", op);
+               return -EINVAL;
+       }
+       if (op) {
+               if (atomic_read(&tpg->lport_tpg_enabled))
+                       return -EEXIST;
+
+               atomic_set(&tpg->lport_tpg_enabled, 1);
+               qlt_enable_vha(vha);
+       } else {
+               if (!atomic_read(&tpg->lport_tpg_enabled))
+                       return count;
+
+               atomic_set(&tpg->lport_tpg_enabled, 0);
+               qlt_stop_phase1(vha->vha_tgt.qla_tgt);
+       }
+
+       return count;
+}
+
+TF_TPG_BASE_ATTR(tcm_qla2xxx_npiv, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = {
+        &tcm_qla2xxx_npiv_tpg_enable.attr,
+        NULL,
+};
+
 static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
        struct se_wwn *wwn,
        struct config_group *group,
@@ -1650,6 +1715,9 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
        struct scsi_qla_host *npiv_vha;
        struct tcm_qla2xxx_lport *lport =
                        (struct tcm_qla2xxx_lport *)target_lport_ptr;
+       struct tcm_qla2xxx_lport *base_lport =
+                       (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
+       struct tcm_qla2xxx_tpg *base_tpg;
        struct fc_vport_identifiers vport_id;
 
        if (!qla_tgt_mode_enabled(base_vha)) {
@@ -1657,6 +1725,13 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
                return -EPERM;
        }
 
+       if (!base_lport || !base_lport->tpg_1 ||
+           !atomic_read(&base_lport->tpg_1->lport_tpg_enabled)) {
+               pr_err("qla2xxx base_lport or tpg_1 not available\n");
+               return -EPERM;
+       }
+       base_tpg = base_lport->tpg_1;
+
        memset(&vport_id, 0, sizeof(vport_id));
        vport_id.port_name = npiv_wwpn;
        vport_id.node_name = npiv_wwnn;
@@ -1675,7 +1750,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
        npiv_vha = (struct scsi_qla_host *)vport->dd_data;
        npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr;
        lport->qla_vha = npiv_vha;
-
        scsi_host_get(npiv_vha->host);
        return 0;
 }
@@ -1714,8 +1788,6 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
        }
        lport->lport_npiv_wwpn = npiv_wwpn;
        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);
 
        ret = tcm_qla2xxx_init_lport(lport);
@@ -1824,7 +1896,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
 static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
        .get_fabric_name                = tcm_qla2xxx_npiv_get_fabric_name,
        .get_fabric_proto_ident         = tcm_qla2xxx_get_fabric_proto_ident,
-       .tpg_get_wwn                    = tcm_qla2xxx_npiv_get_fabric_wwn,
+       .tpg_get_wwn                    = tcm_qla2xxx_get_fabric_wwn,
        .tpg_get_tag                    = tcm_qla2xxx_get_tag,
        .tpg_get_default_depth          = tcm_qla2xxx_get_default_depth,
        .tpg_get_pr_transport_id        = tcm_qla2xxx_get_pr_transport_id,
@@ -1935,7 +2007,7 @@ static int tcm_qla2xxx_register_configfs(void)
         */
        npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs =
-           tcm_qla2xxx_tpg_attrs;
+           tcm_qla2xxx_npiv_tpg_attrs;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
        npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
index 275d8b9a7a34121d4d7d356659bfe92816219a3f..33aaac8c7d5936bbdd3e2d9f934f2c92f2083331 100644 (file)
@@ -4,8 +4,6 @@
 #define TCM_QLA2XXX_VERSION    "v0.1"
 /* length of ASCII WWPNs including pad */
 #define TCM_QLA2XXX_NAMELEN    32
-/* lenth of ASCII NPIV 'WWPN+WWNN' including pad */
-#define TCM_QLA2XXX_NPIV_NAMELEN 66
 
 #include "qla_target.h"
 
@@ -43,6 +41,9 @@ struct tcm_qla2xxx_tpg {
        struct tcm_qla2xxx_tpg_attrib tpg_attrib;
        /* Returned by tcm_qla2xxx_make_tpg() */
        struct se_portal_group se_tpg;
+       /* Items for dealing with configfs_depend_item */
+       struct completion tpg_base_comp;
+       struct work_struct tpg_base_work;
 };
 
 struct tcm_qla2xxx_fc_loopid {
@@ -62,8 +63,6 @@ struct tcm_qla2xxx_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 */
        struct btree_head32 lport_fcport_map;
        /* vmalloc-ed memory for fc_port pointers for 16-bit FC loop ID */
index 7bd7f0d5f050a2ece3f176b1f05ca2f8936270a3..62ec84b42e31cfb77f1aad4e040da30e3a104ef6 100644 (file)
@@ -1684,7 +1684,7 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
 
        host_dev = scsi_get_device(shost);
        if (host_dev && host_dev->dma_mask)
-               bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT;
+               bounce_limit = (u64)dma_max_pfn(host_dev) << PAGE_SHIFT;
 
        return bounce_limit;
 }
index 17d7404272400dd1a76989a3965e0c4b85343036..9969fa1ef7c4ef09ac4fc72c942c5ef72703ae49 100644 (file)
@@ -1419,6 +1419,9 @@ static void storvsc_device_destroy(struct scsi_device *sdevice)
 {
        struct stor_mem_pools *memp = sdevice->hostdata;
 
+       if (!memp)
+               return;
+
        mempool_destroy(memp->request_mempool);
        kmem_cache_destroy(memp->request_pool);
        kfree(memp);
index ba9310bc9acb7449a91ccb59b8f7de5c09c5801d..581ee2a8856b157641eb5a6b2c13389241b4ea90 100644 (file)
@@ -376,10 +376,10 @@ config SPI_PXA2XX_PCI
        def_tristate SPI_PXA2XX && PCI
 
 config SPI_RSPI
-       tristate "Renesas RSPI controller"
+       tristate "Renesas RSPI/QSPI controller"
        depends on (SUPERH && SH_DMAE_BASE) || ARCH_SHMOBILE
        help
-         SPI driver for Renesas RSPI blocks.
+         SPI driver for Renesas RSPI and QSPI blocks.
 
 config SPI_S3C24XX
        tristate "Samsung S3C24XX series SPI"
index 31534b51715aa95e29664cc80d44d71b5131d0ab..c3b2fb9b6713c997b1338d5df13470e0227a5d93 100644 (file)
@@ -132,9 +132,9 @@ static int ath79_spi_setup_cs(struct spi_device *spi)
 
                flags = GPIOF_DIR_OUT;
                if (spi->mode & SPI_CS_HIGH)
-                       flags |= GPIOF_INIT_HIGH;
-               else
                        flags |= GPIOF_INIT_LOW;
+               else
+                       flags |= GPIOF_INIT_HIGH;
 
                status = gpio_request_one(cdata->gpio, flags,
                                          dev_name(&spi->dev));
index b0842f75101647616ada3a3db4f545a57b519be0..5d7b07f083266e64ab0d91436c10ae89a9ec112c 100644 (file)
@@ -1455,6 +1455,14 @@ static int atmel_spi_suspend(struct device *dev)
 {
        struct spi_master       *master = dev_get_drvdata(dev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
+       int ret;
+
+       /* Stop the queue running */
+       ret = spi_master_suspend(master);
+       if (ret) {
+               dev_warn(dev, "cannot suspend master\n");
+               return ret;
+       }
 
        clk_disable_unprepare(as->clk);
        return 0;
@@ -1464,9 +1472,16 @@ static int atmel_spi_resume(struct device *dev)
 {
        struct spi_master       *master = dev_get_drvdata(dev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
+       int ret;
 
        clk_prepare_enable(as->clk);
-       return 0;
+
+       /* Start the queue running */
+       ret = spi_master_resume(master);
+       if (ret)
+               dev_err(dev, "problem starting queue (%d)\n", ret);
+
+       return ret;
 }
 
 static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume);
index cabed8f9119e1af30d80766420d548b94567c91c..28ae470397a9e0a7c77c88f5370327e73df01a67 100644 (file)
@@ -514,7 +514,8 @@ static int mcfqspi_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int mcfqspi_runtime_suspend(struct device *dev)
 {
-       struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
 
        clk_disable(mcfqspi->clk);
 
@@ -523,7 +524,8 @@ static int mcfqspi_runtime_suspend(struct device *dev)
 
 static int mcfqspi_runtime_resume(struct device *dev)
 {
-       struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
 
        clk_enable(mcfqspi->clk);
 
index ec79f726672a14f7644810101afe59e82322976c..a25392065d9b838ef852e93d09e53d0d121ac485 100644 (file)
@@ -420,7 +420,6 @@ static int dspi_suspend(struct device *dev)
 
 static int dspi_resume(struct device *dev)
 {
-
        struct spi_master *master = dev_get_drvdata(dev);
        struct fsl_dspi *dspi = spi_master_get_devdata(master);
 
@@ -504,7 +503,7 @@ static int dspi_probe(struct platform_device *pdev)
        clk_prepare_enable(dspi->clk);
 
        init_waitqueue_head(&dspi->waitq);
-       platform_set_drvdata(pdev, dspi);
+       platform_set_drvdata(pdev, master);
 
        ret = spi_bitbang_start(&dspi->bitbang);
        if (ret != 0) {
@@ -525,7 +524,8 @@ out_master_put:
 
 static int dspi_remove(struct platform_device *pdev)
 {
-       struct fsl_dspi *dspi = platform_get_drvdata(pdev);
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct fsl_dspi *dspi = spi_master_get_devdata(master);
 
        /* Disconnect from the SPI framework */
        spi_bitbang_stop(&dspi->bitbang);
index a5474ef9d2a0cf4ad7367ee1e0399fae2e982145..47f15d97e7fa41efeede0bce941d4584a0c07be5 100644 (file)
@@ -948,8 +948,8 @@ static int spi_imx_remove(struct platform_device *pdev)
        spi_bitbang_stop(&spi_imx->bitbang);
 
        writel(0, spi_imx->base + MXC_CSPICTRL);
-       clk_disable_unprepare(spi_imx->clk_ipg);
-       clk_disable_unprepare(spi_imx->clk_per);
+       clk_unprepare(spi_imx->clk_ipg);
+       clk_unprepare(spi_imx->clk_per);
        spi_master_put(master);
 
        return 0;
index 50406306bc209493152eca0a5b636811e30593d6..bae97ffec4b9952f10a1affc3ca3741d537e91af 100644 (file)
@@ -361,6 +361,8 @@ static int nuc900_spi_probe(struct platform_device *pdev)
        init_completion(&hw->done);
 
        master->mode_bits          = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       if (hw->pdata->lsb)
+               master->mode_bits |= SPI_LSB_FIRST;
        master->num_chipselect     = hw->pdata->num_cs;
        master->bus_num            = hw->pdata->bus_num;
        hw->bitbang.master         = hw->master;
index 2e7f38c7a9610b11f63fd36c816f311b3372d66d..88eb57e858b379ac258abad703bf532b60852669 100644 (file)
@@ -915,7 +915,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
        /* Set Tx DMA */
        param = &dma->param_tx;
        param->dma_dev = &dma_dev->dev;
-       param->chan_id = data->master->bus_num * 2; /* Tx = 0, 2 */
+       param->chan_id = data->ch * 2; /* Tx = 0, 2 */;
        param->tx_reg = data->io_base_addr + PCH_SPDWR;
        param->width = width;
        chan = dma_request_channel(mask, pch_spi_filter, param);
@@ -930,7 +930,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
        /* Set Rx DMA */
        param = &dma->param_rx;
        param->dma_dev = &dma_dev->dev;
-       param->chan_id = data->master->bus_num * 2 + 1; /* Rx = Tx + 1 */
+       param->chan_id = data->ch * 2 + 1; /* Rx = Tx + 1 */;
        param->rx_reg = data->io_base_addr + PCH_SPDRR;
        param->width = width;
        chan = dma_request_channel(mask, pch_spi_filter, param);
@@ -1452,6 +1452,11 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
 
        pch_spi_set_master_mode(master);
 
+       if (use_dma) {
+               dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
+               pch_alloc_dma_buf(board_dat, data);
+       }
+
        ret = spi_register_master(master);
        if (ret != 0) {
                dev_err(&plat_dev->dev,
@@ -1459,14 +1464,10 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
                goto err_spi_register_master;
        }
 
-       if (use_dma) {
-               dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
-               pch_alloc_dma_buf(board_dat, data);
-       }
-
        return 0;
 
 err_spi_register_master:
+       pch_free_dma_buf(board_dat, data);
        free_irq(board_dat->pdev->irq, data);
 err_request_irq:
        pch_spi_free_resources(board_dat, data);
index 23756b0f90363c2f776718925cf7fba84d13c4a3..d0b28bba38be6bfff2a420e9fc2850e5c84c690b 100644 (file)
@@ -755,9 +755,7 @@ static void spi_pump_messages(struct kthread_work *work)
        ret = master->transfer_one_message(master, master->cur_msg);
        if (ret) {
                dev_err(&master->dev,
-                       "failed to transfer one message from queue: %d\n", ret);
-               master->cur_msg->status = ret;
-               spi_finalize_current_message(master);
+                       "failed to transfer one message from queue\n");
                return;
        }
 }
index 23948f16701206926ec9a76ce347641316d692c5..713a9722678746f24363e3b9f3f4a0f89cc145ad 100644 (file)
@@ -295,21 +295,29 @@ static ssize_t ashmem_read(struct file *file, char __user *buf,
 
        /* If size is not set, or set to 0, always return EOF. */
        if (asma->size == 0)
-               goto out;
+               goto out_unlock;
 
        if (!asma->file) {
                ret = -EBADF;
-               goto out;
+               goto out_unlock;
        }
 
-       ret = asma->file->f_op->read(asma->file, buf, len, pos);
-       if (ret < 0)
-               goto out;
+       mutex_unlock(&ashmem_mutex);
 
-       /** Update backing file pos, since f_ops->read() doesn't */
-       asma->file->f_pos = *pos;
+       /*
+        * asma and asma->file are used outside the lock here.  We assume
+        * once asma->file is set it will never be changed, and will not
+        * be destroyed until all references to the file are dropped and
+        * ashmem_release is called.
+        */
+       ret = asma->file->f_op->read(asma->file, buf, len, pos);
+       if (ret >= 0) {
+               /** Update backing file pos, since f_ops->read() doesn't */
+               asma->file->f_pos = *pos;
+       }
+       return ret;
 
-out:
+out_unlock:
        mutex_unlock(&ashmem_mutex);
        return ret;
 }
@@ -498,6 +506,7 @@ out:
 
 static int set_name(struct ashmem_area *asma, void __user *name)
 {
+       int len;
        int ret = 0;
        char local_name[ASHMEM_NAME_LEN];
 
@@ -510,21 +519,19 @@ static int set_name(struct ashmem_area *asma, void __user *name)
         * variable that does not need protection and later copy the local
         * variable to the structure member with lock held.
         */
-       if (copy_from_user(local_name, name, ASHMEM_NAME_LEN))
-               return -EFAULT;
-
+       len = strncpy_from_user(local_name, name, ASHMEM_NAME_LEN);
+       if (len < 0)
+               return len;
+       if (len == ASHMEM_NAME_LEN)
+               local_name[ASHMEM_NAME_LEN - 1] = '\0';
        mutex_lock(&ashmem_mutex);
        /* cannot change an existing mapping's name */
-       if (unlikely(asma->file)) {
+       if (unlikely(asma->file))
                ret = -EINVAL;
-               goto out;
-       }
-       memcpy(asma->name + ASHMEM_NAME_PREFIX_LEN,
-               local_name, ASHMEM_NAME_LEN);
-       asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0';
-out:
-       mutex_unlock(&ashmem_mutex);
+       else
+               strcpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name);
 
+       mutex_unlock(&ashmem_mutex);
        return ret;
 }
 
index eaec1dab7fe489fbbc9d171a4acdf5f78d765df6..1432d956769c2d5511716a5e8d3ea1eb5a667b68 100644 (file)
@@ -2904,7 +2904,7 @@ static int binder_node_release(struct binder_node *node, int refs)
                refs++;
 
                if (!ref->death)
-                       goto out;
+                       continue;
 
                death++;
 
@@ -2917,7 +2917,6 @@ static int binder_node_release(struct binder_node *node, int refs)
                        BUG();
        }
 
-out:
        binder_debug(BINDER_DEBUG_DEAD_BINDER,
                     "node %d now dead, refs %d, death %d\n",
                     node->debug_id, refs, death);
index af6cd370b30f3e890e5edc9bdec864efb4f8b9b8..ee3a7380e53b129ed04320940d6cae57cbbd4226 100644 (file)
@@ -35,9 +35,14 @@ struct compat_ion_custom_data {
        compat_ulong_t arg;
 };
 
+struct compat_ion_handle_data {
+       compat_int_t handle;
+};
+
 #define COMPAT_ION_IOC_ALLOC   _IOWR(ION_IOC_MAGIC, 0, \
                                      struct compat_ion_allocation_data)
-#define COMPAT_ION_IOC_FREE    _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
+#define COMPAT_ION_IOC_FREE    _IOWR(ION_IOC_MAGIC, 1, \
+                                     struct compat_ion_handle_data)
 #define COMPAT_ION_IOC_CUSTOM  _IOWR(ION_IOC_MAGIC, 6, \
                                      struct compat_ion_custom_data)
 
@@ -64,6 +69,19 @@ static int compat_get_ion_allocation_data(
        return err;
 }
 
+static int compat_get_ion_handle_data(
+                       struct compat_ion_handle_data __user *data32,
+                       struct ion_handle_data __user *data)
+{
+       compat_int_t i;
+       int err;
+
+       err = get_user(i, &data32->handle);
+       err |= put_user(i, &data->handle);
+
+       return err;
+}
+
 static int compat_put_ion_allocation_data(
                        struct compat_ion_allocation_data __user *data32,
                        struct ion_allocation_data __user *data)
@@ -132,8 +150,8 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        }
        case COMPAT_ION_IOC_FREE:
        {
-               struct compat_ion_allocation_data __user *data32;
-               struct ion_allocation_data __user *data;
+               struct compat_ion_handle_data __user *data32;
+               struct ion_handle_data __user *data;
                int err;
 
                data32 = compat_ptr(arg);
@@ -141,7 +159,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                if (data == NULL)
                        return -EFAULT;
 
-               err = compat_get_ion_allocation_data(data32, data);
+               err = compat_get_ion_handle_data(data32, data);
                if (err)
                        return err;
 
index 55b2002753f2251875fac6e9e66f5bf4c83efb42..01cdc8aee898a35cd98fc3437a31b1b066f6b92a 100644 (file)
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/sizes.h>
+#include <linux/io.h>
 #include "ion.h"
 #include "ion_priv.h"
 
@@ -57,7 +59,7 @@ struct ion_platform_heap dummy_heaps[] = {
 };
 
 struct ion_platform_data dummy_ion_pdata = {
-       .nr = 4,
+       .nr = ARRAY_SIZE(dummy_heaps),
        .heaps = dummy_heaps,
 };
 
@@ -69,7 +71,7 @@ static int __init ion_dummy_init(void)
        heaps = kzalloc(sizeof(struct ion_heap *) * dummy_ion_pdata.nr,
                        GFP_KERNEL);
        if (!heaps)
-               return PTR_ERR(heaps);
+               return -ENOMEM;
 
 
        /* Allocate a dummy carveout heap */
@@ -128,6 +130,7 @@ err:
        }
        return err;
 }
+device_initcall(ion_dummy_init);
 
 static void __exit ion_dummy_exit(void)
 {
@@ -152,7 +155,4 @@ static void __exit ion_dummy_exit(void)
 
        return;
 }
-
-module_init(ion_dummy_init);
-module_exit(ion_dummy_exit);
-
+__exitcall(ion_dummy_exit);
index 296c74f98dc08c6cabbd8203fc4b535b59aedf30..37e64d51394ccecb90dde57bb6f6f84be123939b 100644 (file)
@@ -243,12 +243,12 @@ int ion_heap_init_deferred_free(struct ion_heap *heap)
        init_waitqueue_head(&heap->waitqueue);
        heap->task = kthread_run(ion_heap_deferred_free, heap,
                                 "%s", heap->name);
-       sched_setscheduler(heap->task, SCHED_IDLE, &param);
        if (IS_ERR(heap->task)) {
                pr_err("%s: creating thread for deferred free failed\n",
                       __func__);
                return PTR_RET(heap->task);
        }
+       sched_setscheduler(heap->task, SCHED_IDLE, &param);
        return 0;
 }
 
index d98673981cc40cc83b70db1b5aa9a49a99b4ad35..fc2e4fccf69d216d60761e67775df69f6fd5ea45 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _ION_PRIV_H
 #define _ION_PRIV_H
 
+#include <linux/device.h>
 #include <linux/dma-direction.h>
 #include <linux/kref.h>
 #include <linux/mm_types.h>
index 7f0729130d6583d776734e9df7a89b234b150065..9849f3963e752f01b99450c7636132fba3aefda5 100644 (file)
@@ -124,6 +124,7 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap,
 
                info->page = page;
                info->order = orders[i];
+               INIT_LIST_HEAD(&info->list);
                return info;
        }
        kfree(info);
@@ -145,12 +146,15 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
        struct list_head pages;
        struct page_info *info, *tmp_info;
        int i = 0;
-       long size_remaining = PAGE_ALIGN(size);
+       unsigned long size_remaining = PAGE_ALIGN(size);
        unsigned int max_order = orders[0];
 
        if (align > PAGE_SIZE)
                return -EINVAL;
 
+       if (size / PAGE_SIZE > totalram_pages / 2)
+               return -ENOMEM;
+
        INIT_LIST_HEAD(&pages);
        while (size_remaining > 0) {
                info = alloc_largest_available(sys_heap, buffer, size_remaining,
index 585040be5f1828916c648f46670b6be182ed2812..5aaf71d6974b16efed469637dcb1ca296b924ebf 100644 (file)
@@ -35,10 +35,27 @@ struct sw_sync_pt {
        u32                     value;
 };
 
+#if IS_ENABLED(CONFIG_SW_SYNC)
 struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
 void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
 
 struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
+#else
+static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name)
+{
+       return NULL;
+}
+
+static inline void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc)
+{
+}
+
+static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj,
+               u32 value)
+{
+       return NULL;
+}
+#endif /* IS_ENABLED(CONFIG_SW_SYNC) */
 
 #endif /* __KERNEL __ */
 
index 38e5d3b5ed9b605d7d8c5c6f017bb7d0cffa3ab8..3d05f662110bb0d0d4718ed9a9a8408964eee5b2 100644 (file)
@@ -79,27 +79,27 @@ static void sync_timeline_free(struct kref *kref)
                container_of(kref, struct sync_timeline, kref);
        unsigned long flags;
 
-       if (obj->ops->release_obj)
-               obj->ops->release_obj(obj);
-
        spin_lock_irqsave(&sync_timeline_list_lock, flags);
        list_del(&obj->sync_timeline_list);
        spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
 
+       if (obj->ops->release_obj)
+               obj->ops->release_obj(obj);
+
        kfree(obj);
 }
 
 void sync_timeline_destroy(struct sync_timeline *obj)
 {
        obj->destroyed = true;
+       smp_wmb();
 
        /*
-        * If this is not the last reference, signal any children
-        * that their parent is going away.
+        * signal any children that their parent is going away.
         */
+       sync_timeline_signal(obj);
 
-       if (!kref_put(&obj->kref, sync_timeline_free))
-               sync_timeline_signal(obj);
+       kref_put(&obj->kref, sync_timeline_free);
 }
 EXPORT_SYMBOL(sync_timeline_destroy);
 
index 8dfdd2732bdc329b3865c010d0afdb8e1e248337..95a2358267bad3704d2500287e417735735cdb82 100644 (file)
@@ -40,7 +40,7 @@ static INT bcm_close(struct net_device *dev)
 }
 
 static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
-                           void *accel_priv)
+                           void *accel_priv, select_queue_fallback_t fallback)
 {
        return ClassifyPacket(netdev_priv(dev), skb);
 }
index 246080316c9014a91509da617551a20d7eddc4fa..5b15033a94bf6106cc5b26b9da157ba24be60613 100644 (file)
@@ -616,8 +616,6 @@ int comedi_auto_config(struct device *hardware_device,
        ret = driver->auto_attach(dev, context);
        if (ret >= 0)
                ret = comedi_device_postconfig(dev);
-       if (ret < 0)
-               comedi_device_detach(dev);
        mutex_unlock(&dev->mutex);
 
        if (ret < 0) {
index 593676cf706a2cc3a327b3b1ed0daeefb046a5b7..d9ad2c0fdda208bdcfc521e3b35c5e55f18ef971 100644 (file)
@@ -494,6 +494,7 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
                                 struct comedi_insn *insn, unsigned int *data)
 {
        struct pci1710_private *devpriv = dev->private;
+       unsigned int val;
        int n, chan, range, ofs;
 
        chan = CR_CHAN(insn->chanspec);
@@ -509,11 +510,14 @@ static int pci171x_insn_write_ao(struct comedi_device *dev,
                outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
                ofs = PCI171x_DA1;
        }
+       val = devpriv->ao_data[chan];
 
-       for (n = 0; n < insn->n; n++)
-               outw(data[n], dev->iobase + ofs);
+       for (n = 0; n < insn->n; n++) {
+               val = data[n];
+               outw(val, dev->iobase + ofs);
+       }
 
-       devpriv->ao_data[chan] = data[n];
+       devpriv->ao_data[chan] = val;
 
        return n;
 
@@ -679,6 +683,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
                                 struct comedi_insn *insn, unsigned int *data)
 {
        struct pci1710_private *devpriv = dev->private;
+       unsigned int val;
        int n, rangereg, chan;
 
        chan = CR_CHAN(insn->chanspec);
@@ -688,13 +693,15 @@ static int pci1720_insn_write_ao(struct comedi_device *dev,
                outb(rangereg, dev->iobase + PCI1720_RANGE);
                devpriv->da_ranges = rangereg;
        }
+       val = devpriv->ao_data[chan];
 
        for (n = 0; n < insn->n; n++) {
-               outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
+               val = data[n];
+               outw(val, dev->iobase + PCI1720_DA0 + (chan << 1));
                outb(0, dev->iobase + PCI1720_SYNCOUT); /*  update outputs */
        }
 
-       devpriv->ao_data[chan] = data[n];
+       devpriv->ao_data[chan] = val;
 
        return n;
 }
index 3beeb12541522b2bf8cd04bd898754d3f9365487..88c60b6020c48b971682f2d31700dd549ecdd1af 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/usb.h>
 #include <linux/fcntl.h>
 #include <linux/compiler.h>
+#include <asm/unaligned.h>
 
 #include "comedi_fc.h"
 #include "../comedidev.h"
@@ -792,7 +793,8 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev,
                }
 
                /* 32 bits big endian from the A/D converter */
-               val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf) + 1)));
+               val = be32_to_cpu(get_unaligned((uint32_t
+                                                *)(devpriv->insn_buf + 1)));
                val &= 0x00ffffff;      /* strip status byte */
                val ^= 0x00800000;      /* convert to unsigned */
 
@@ -1357,7 +1359,7 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan)
                return ret;
 
        /* 32 bits big endian from the A/D converter */
-       val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf)+1)));
+       val = be32_to_cpu(get_unaligned((uint32_t *)(devpriv->insn_buf + 1)));
        val &= 0x00ffffff;      /* strip status byte */
        val ^= 0x00800000;      /* convert to unsigned */
 
index 4a08e16e42f719470cd9a0b63de557d2b3ff704b..79206cb3fb946e785021607c7b12474bff9d73a5 100644 (file)
@@ -866,6 +866,8 @@ c4_ioctl (struct net_device *ndev, struct ifreq *ifr, int cmd)
             _IOC_SIZE (iocmd));
 #endif
     iolen = _IOC_SIZE (iocmd);
+    if (iolen > sizeof(arg))
+        return -EFAULT;
     data = ifr->ifr_data + sizeof (iocmd);
     if (copy_from_user (&arg, data, iolen))
         return -EFAULT;
index 1f61b89eca44c084cb714052d5eb3fb3a7ba2566..33ac7fb88cbd3b98b24b1eb50209e4a0b5c6100e 100644 (file)
@@ -2232,177 +2232,6 @@ done:
        return rtn;
 }
 
-/*
- * Common Packet Handling code
- */
-
-static void handle_data_in_packet(struct nd_struct *nd, struct ch_struct *ch,
-                                 long dlen, long plen, int n1, u8 *dbuf)
-{
-       char *error;
-       long n;
-       long remain;
-       u8 *buf;
-       u8 *b;
-
-       remain = nd->nd_remain;
-       nd->nd_tx_work = 1;
-
-       /*
-        *  Otherwise data should appear only when we are
-        *  in the CS_READY state.
-        */
-
-       if (ch->ch_state < CS_READY) {
-               error = "Data received before RWIN established";
-               nd->nd_remain = 0;
-               nd->nd_state = NS_SEND_ERROR;
-               nd->nd_error = error;
-       }
-
-       /*
-        *  Assure that the data received is within the
-        *  allowable window.
-        */
-
-       n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff;
-
-       if (dlen > n) {
-               error = "Receive data overrun";
-               nd->nd_remain = 0;
-               nd->nd_state = NS_SEND_ERROR;
-               nd->nd_error = error;
-       }
-
-       /*
-        *  If we received 3 or less characters,
-        *  assume it is a human typing, and set RTIME
-        *  to 10 milliseconds.
-        *
-        *  If we receive 10 or more characters,
-        *  assume its not a human typing, and set RTIME
-        *  to 100 milliseconds.
-        */
-
-       if (ch->ch_edelay != DGRP_RTIME) {
-               if (ch->ch_rtime != ch->ch_edelay) {
-                       ch->ch_rtime = ch->ch_edelay;
-                       ch->ch_flag |= CH_PARAM;
-               }
-       } else if (dlen <= 3) {
-               if (ch->ch_rtime != 10) {
-                       ch->ch_rtime = 10;
-                       ch->ch_flag |= CH_PARAM;
-               }
-       } else {
-               if (ch->ch_rtime != DGRP_RTIME) {
-                       ch->ch_rtime = DGRP_RTIME;
-                       ch->ch_flag |= CH_PARAM;
-               }
-       }
-
-       /*
-        *  If a portion of the packet is outside the
-        *  buffer, shorten the effective length of the
-        *  data packet to be the amount of data received.
-        */
-
-       if (remain < plen)
-               dlen -= plen - remain;
-
-       /*
-        *  Detect if receive flush is now complete.
-        */
-
-       if ((ch->ch_flag & CH_RX_FLUSH) != 0 &&
-                       ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >=
-                       ((nd->nd_seq_in    - nd->nd_seq_out) & SEQ_MASK)) {
-               ch->ch_flag &= ~CH_RX_FLUSH;
-       }
-
-       /*
-        *  If we are ready to receive, move the data into
-        *  the receive buffer.
-        */
-
-       ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff;
-
-       if (ch->ch_state == CS_READY &&
-                       (ch->ch_tun.un_open_count != 0) &&
-                       (ch->ch_tun.un_flag & UN_CLOSING) == 0 &&
-                       (ch->ch_cflag & CF_CREAD) != 0 &&
-                       (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 &&
-                       (ch->ch_send & RR_RX_FLUSH) == 0) {
-
-               if (ch->ch_rin + dlen >= RBUF_MAX) {
-                       n = RBUF_MAX - ch->ch_rin;
-
-                       memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n);
-
-                       ch->ch_rin = 0;
-                       dbuf += n;
-                       dlen -= n;
-               }
-
-               memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen);
-
-               ch->ch_rin += dlen;
-
-
-               /*
-                *  If we are not in fastcook mode, or
-                *  if there is a fastcook thread
-                *  waiting for data, send the data to
-                *  the line discipline.
-                */
-
-               if ((ch->ch_flag & CH_FAST_READ) == 0 ||
-                               ch->ch_inwait != 0) {
-                       dgrp_input(ch);
-               }
-
-               /*
-                *  If there is a read thread waiting
-                *  in select, and we are in fastcook
-                *  mode, wake him up.
-                */
-
-               if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) &&
-                               (ch->ch_flag & CH_FAST_READ) != 0)
-                       wake_up_interruptible(&ch->ch_tun.un_tty->read_wait);
-
-               /*
-                * Wake any thread waiting in the
-                * fastcook loop.
-                */
-
-               if ((ch->ch_flag & CH_INPUT) != 0) {
-                       ch->ch_flag &= ~CH_INPUT;
-                       wake_up_interruptible(&ch->ch_flag_wait);
-               }
-       }
-
-       /*
-        *  Fabricate and insert a data packet header to
-        *  preced the remaining data when it comes in.
-        */
-
-       if (remain < plen) {
-               dlen = plen - remain;
-               b = buf;
-
-               b[0] = 0x90 + n1;
-               put_unaligned_be16(dlen, b + 1);
-
-               remain = 3;
-               if (remain > 0 && b != buf)
-                       memcpy(buf, b, remain);
-
-               nd->nd_remain = remain;
-               return;
-       }
-}
-
 /**
  * dgrp_receive() -- decode data packets received from the remote PortServer.
  * @nd: pointer to a node structure
@@ -2477,8 +2306,7 @@ static void dgrp_receive(struct nd_struct *nd)
                        plen = dlen + 1;
 
                        dbuf = b + 1;
-                       handle_data_in_packet(nd, ch, dlen, plen, n1, dbuf);
-                       break;
+                       goto data;
 
                /*
                 *  Process 2-byte header data packet.
@@ -2492,8 +2320,7 @@ static void dgrp_receive(struct nd_struct *nd)
                        plen = dlen + 2;
 
                        dbuf = b + 2;
-                       handle_data_in_packet(nd, ch, dlen, plen, n1, dbuf);
-                       break;
+                       goto data;
 
                /*
                 *  Process 3-byte header data packet.
@@ -2508,6 +2335,159 @@ static void dgrp_receive(struct nd_struct *nd)
 
                        dbuf = b + 3;
 
+               /*
+                *  Common packet handling code.
+                */
+
+data:
+                       nd->nd_tx_work = 1;
+
+                       /*
+                        *  Otherwise data should appear only when we are
+                        *  in the CS_READY state.
+                        */
+
+                       if (ch->ch_state < CS_READY) {
+                               error = "Data received before RWIN established";
+                               goto prot_error;
+                       }
+
+                       /*
+                        *  Assure that the data received is within the
+                        *  allowable window.
+                        */
+
+                       n = (ch->ch_s_rwin - ch->ch_s_rin) & 0xffff;
+
+                       if (dlen > n) {
+                               error = "Receive data overrun";
+                               goto prot_error;
+                       }
+
+                       /*
+                        *  If we received 3 or less characters,
+                        *  assume it is a human typing, and set RTIME
+                        *  to 10 milliseconds.
+                        *
+                        *  If we receive 10 or more characters,
+                        *  assume its not a human typing, and set RTIME
+                        *  to 100 milliseconds.
+                        */
+
+                       if (ch->ch_edelay != DGRP_RTIME) {
+                               if (ch->ch_rtime != ch->ch_edelay) {
+                                       ch->ch_rtime = ch->ch_edelay;
+                                       ch->ch_flag |= CH_PARAM;
+                               }
+                       } else if (dlen <= 3) {
+                               if (ch->ch_rtime != 10) {
+                                       ch->ch_rtime = 10;
+                                       ch->ch_flag |= CH_PARAM;
+                               }
+                       } else {
+                               if (ch->ch_rtime != DGRP_RTIME) {
+                                       ch->ch_rtime = DGRP_RTIME;
+                                       ch->ch_flag |= CH_PARAM;
+                               }
+                       }
+
+                       /*
+                        *  If a portion of the packet is outside the
+                        *  buffer, shorten the effective length of the
+                        *  data packet to be the amount of data received.
+                        */
+
+                       if (remain < plen)
+                               dlen -= plen - remain;
+
+                       /*
+                        *  Detect if receive flush is now complete.
+                        */
+
+                       if ((ch->ch_flag & CH_RX_FLUSH) != 0 &&
+                           ((ch->ch_flush_seq - nd->nd_seq_out) & SEQ_MASK) >=
+                           ((nd->nd_seq_in    - nd->nd_seq_out) & SEQ_MASK)) {
+                               ch->ch_flag &= ~CH_RX_FLUSH;
+                       }
+
+                       /*
+                        *  If we are ready to receive, move the data into
+                        *  the receive buffer.
+                        */
+
+                       ch->ch_s_rin = (ch->ch_s_rin + dlen) & 0xffff;
+
+                       if (ch->ch_state == CS_READY &&
+                           (ch->ch_tun.un_open_count != 0) &&
+                           (ch->ch_tun.un_flag & UN_CLOSING) == 0 &&
+                           (ch->ch_cflag & CF_CREAD) != 0 &&
+                           (ch->ch_flag & (CH_BAUD0 | CH_RX_FLUSH)) == 0 &&
+                           (ch->ch_send & RR_RX_FLUSH) == 0) {
+
+                               if (ch->ch_rin + dlen >= RBUF_MAX) {
+                                       n = RBUF_MAX - ch->ch_rin;
+
+                                       memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, n);
+
+                                       ch->ch_rin = 0;
+                                       dbuf += n;
+                                       dlen -= n;
+                               }
+
+                               memcpy(ch->ch_rbuf + ch->ch_rin, dbuf, dlen);
+
+                               ch->ch_rin += dlen;
+
+
+                               /*
+                                *  If we are not in fastcook mode, or
+                                *  if there is a fastcook thread
+                                *  waiting for data, send the data to
+                                *  the line discipline.
+                                */
+
+                               if ((ch->ch_flag & CH_FAST_READ) == 0 ||
+                                   ch->ch_inwait != 0) {
+                                       dgrp_input(ch);
+                               }
+
+                               /*
+                                *  If there is a read thread waiting
+                                *  in select, and we are in fastcook
+                                *  mode, wake him up.
+                                */
+
+                               if (waitqueue_active(&ch->ch_tun.un_tty->read_wait) &&
+                                   (ch->ch_flag & CH_FAST_READ) != 0)
+                                       wake_up_interruptible(&ch->ch_tun.un_tty->read_wait);
+
+                               /*
+                                * Wake any thread waiting in the
+                                * fastcook loop.
+                                */
+
+                               if ((ch->ch_flag & CH_INPUT) != 0) {
+                                       ch->ch_flag &= ~CH_INPUT;
+
+                                       wake_up_interruptible(&ch->ch_flag_wait);
+                               }
+                       }
+
+                       /*
+                        *  Fabricate and insert a data packet header to
+                        *  preced the remaining data when it comes in.
+                        */
+
+                       if (remain < plen) {
+                               dlen = plen - remain;
+                               b = buf;
+
+                               b[0] = 0x90 + n1;
+                               put_unaligned_be16(dlen, b + 1);
+
+                               remain = 3;
+                               goto done;
+                       }
                        break;
 
                /*
index 8af136e9c9dc16e1ab5f5f5cecf7dfe1579c528b..b22142ee52625c8bce4130b24cf0e9046544a050 100644 (file)
@@ -2036,6 +2036,13 @@ static void fwserial_auto_connect(struct work_struct *work)
                schedule_delayed_work(&peer->connect, CONNECT_RETRY_DELAY);
 }
 
+static void fwserial_peer_workfn(struct work_struct *work)
+{
+       struct fwtty_peer *peer = to_peer(work, work);
+
+       peer->workfn(work);
+}
+
 /**
  * fwserial_add_peer - add a newly probed 'serial' unit device as a 'peer'
  * @serial: aggregate representing the specific fw_card to add the peer to
@@ -2100,7 +2107,7 @@ static int fwserial_add_peer(struct fw_serial *serial, struct fw_unit *unit)
        peer->port = NULL;
 
        init_timer(&peer->timer);
-       INIT_WORK(&peer->work, NULL);
+       INIT_WORK(&peer->work, fwserial_peer_workfn);
        INIT_DELAYED_WORK(&peer->connect, fwserial_auto_connect);
 
        /* associate peer with specific fw_card */
@@ -2702,7 +2709,7 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
 
                } else {
                        peer->work_params.plug_req = pkt->plug_req;
-                       PREPARE_WORK(&peer->work, fwserial_handle_plug_req);
+                       peer->workfn = fwserial_handle_plug_req;
                        queue_work(system_unbound_wq, &peer->work);
                }
                break;
@@ -2731,7 +2738,7 @@ static int fwserial_parse_mgmt_write(struct fwtty_peer *peer,
                        fwtty_err(&peer->unit, "unplug req: busy\n");
                        rcode = RCODE_CONFLICT_ERROR;
                } else {
-                       PREPARE_WORK(&peer->work, fwserial_handle_unplug_req);
+                       peer->workfn = fwserial_handle_unplug_req;
                        queue_work(system_unbound_wq, &peer->work);
                }
                break;
index 54f7f9b9b2123a120a48595a878723b5d89d465e..98b853d4acbcf16181984bf3f529c24f4bab3a1c 100644 (file)
@@ -91,6 +91,7 @@ struct fwtty_peer {
        struct rcu_head         rcu;
 
        spinlock_t              lock;
+       work_func_t             workfn;
        struct work_struct      work;
        struct peer_work_params work_params;
        struct timer_list       timer;
index f8788bf0a7d39ed02c284a4f5cb8ea51c8dbae98..cdeffe75496b2531f106c044105f686d5f1c2018 100644 (file)
@@ -635,11 +635,14 @@ static int gdm_usb_probe(struct usb_interface *intf,
 #endif /* CONFIG_WIMAX_GDM72XX_USB_PM */
 
        ret = register_wimax_device(phy_dev, &intf->dev);
+       if (ret)
+               release_usb(udev);
 
 out:
        if (ret) {
                kfree(phy_dev);
                kfree(udev);
+               usb_put_dev(usbdev);
        } else {
                usb_set_intfdata(intf, phy_dev);
        }
index 35154d60faf6120813bb26bf2477994e66fd259f..c9fedb79e3a2d2cec92f04a7860c6e2c055bd0fc 100644 (file)
@@ -77,7 +77,6 @@ struct iio_channel_info {
        uint64_t mask;
        unsigned be;
        unsigned is_signed;
-       unsigned enabled;
        unsigned location;
 };
 
@@ -335,6 +334,7 @@ inline int build_channel_array(const char *device_dir,
        while (ent = readdir(dp), ent != NULL) {
                if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
                           "_en") == 0) {
+                       int current_enabled = 0;
                        current = &(*ci_array)[count++];
                        ret = asprintf(&filename,
                                       "%s/%s", scan_el_dir, ent->d_name);
@@ -350,10 +350,10 @@ inline int build_channel_array(const char *device_dir,
                                ret = -errno;
                                goto error_cleanup_array;
                        }
-                       fscanf(sysfsfp, "%u", &current->enabled);
+                       fscanf(sysfsfp, "%u", &current_enabled);
                        fclose(sysfsfp);
 
-                       if (!current->enabled) {
+                       if (!current_enabled) {
                                free(filename);
                                count--;
                                continue;
index 5ea36410f716e7cb380f60bfbfee83dfde160d52..5708ffc62aec94debe2c9a6aa8b6562f6a40623f 100644 (file)
@@ -393,7 +393,7 @@ static const struct iio_event_spec ad799x_events[] = {
        }, {
                .type = IIO_EV_TYPE_THRESH,
                .dir = IIO_EV_DIR_FALLING,
-               .mask_separate = BIT(IIO_EV_INFO_VALUE),
+               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
                        BIT(IIO_EV_INFO_ENABLE),
        }, {
                .type = IIO_EV_TYPE_THRESH,
@@ -409,7 +409,13 @@ static const struct iio_event_spec ad799x_events[] = {
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
        .scan_index = (_index), \
-       .scan_type = IIO_ST('u', _realbits, 16, 12 - (_realbits)), \
+       .scan_type = { \
+               .sign = 'u', \
+               .realbits = (_realbits), \
+               .storagebits = 16, \
+               .shift = 12 - (_realbits), \
+               .endianness = IIO_BE, \
+       }, \
        .event_spec = _ev_spec, \
        .num_event_specs = _num_ev_spec, \
 }
@@ -588,7 +594,8 @@ static int ad799x_probe(struct i2c_client *client,
        return 0;
 
 error_free_irq:
-       free_irq(client->irq, indio_dev);
+       if (client->irq > 0)
+               free_irq(client->irq, indio_dev);
 error_cleanup_ring:
        ad799x_ring_cleanup(indio_dev);
 error_disable_reg:
index df71669bb60ea51be793903d7a62df399e388c55..514844efac75833252f25891d591dad1d844092c 100644 (file)
@@ -757,6 +757,7 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
        }
 
        /* if it is released, wait for the next touch via IRQ */
+       lradc->cur_plate = LRADC_TOUCH;
        mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
@@ -1035,8 +1036,6 @@ SHOW_SCALE_AVAILABLE_ATTR(4);
 SHOW_SCALE_AVAILABLE_ATTR(5);
 SHOW_SCALE_AVAILABLE_ATTR(6);
 SHOW_SCALE_AVAILABLE_ATTR(7);
-SHOW_SCALE_AVAILABLE_ATTR(8);
-SHOW_SCALE_AVAILABLE_ATTR(9);
 SHOW_SCALE_AVAILABLE_ATTR(10);
 SHOW_SCALE_AVAILABLE_ATTR(11);
 SHOW_SCALE_AVAILABLE_ATTR(12);
@@ -1053,8 +1052,6 @@ static struct attribute *mxs_lradc_attributes[] = {
        &iio_dev_attr_in_voltage5_scale_available.dev_attr.attr,
        &iio_dev_attr_in_voltage6_scale_available.dev_attr.attr,
        &iio_dev_attr_in_voltage7_scale_available.dev_attr.attr,
-       &iio_dev_attr_in_voltage8_scale_available.dev_attr.attr,
-       &iio_dev_attr_in_voltage9_scale_available.dev_attr.attr,
        &iio_dev_attr_in_voltage10_scale_available.dev_attr.attr,
        &iio_dev_attr_in_voltage11_scale_available.dev_attr.attr,
        &iio_dev_attr_in_voltage12_scale_available.dev_attr.attr,
@@ -1613,7 +1610,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
                         * of the array.
                         */
                        scale_uv = ((u64)lradc->vref_mv[i] * 100000000) >>
-                                  (iio->channels[i].scan_type.realbits - s);
+                                  (LRADC_RESOLUTION - s);
                        lradc->scale_avail[i][s].nano =
                                        do_div(scale_uv, 100000000) * 10;
                        lradc->scale_avail[i][s].integer = scale_uv;
index 0a4298b744e6e686f8bdef9175d06666c1b5cf49..2b96665da8a25aa0390462897d777039a6ff2c9e 100644 (file)
@@ -629,7 +629,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
        struct iio_buffer *buffer;
 
        buffer = iio_kfifo_allocate(indio_dev);
-       if (buffer)
+       if (!buffer)
                return -ENOMEM;
 
        iio_device_attach_buffer(indio_dev, buffer);
index 09ef5fb8bae6f9cb4b99f936b2fcb52739f9edd9..236ed66f116a29fda3af7fc6764b506cacbef16a 100644 (file)
@@ -88,9 +88,9 @@ static int imx_drm_driver_unload(struct drm_device *drm)
 
        imx_drm_device_put();
 
-       drm_vblank_cleanup(imxdrm->drm);
-       drm_kms_helper_poll_fini(imxdrm->drm);
-       drm_mode_config_cleanup(imxdrm->drm);
+       drm_vblank_cleanup(drm);
+       drm_kms_helper_poll_fini(drm);
+       drm_mode_config_cleanup(drm);
 
        return 0;
 }
@@ -142,19 +142,19 @@ EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
 
 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
 {
-       return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
+       return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
 }
 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
 
 void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
 {
-       drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
+       drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
 }
 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
 
 void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
 {
-       drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe);
+       drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
 }
 EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
 
@@ -369,29 +369,6 @@ static void imx_drm_connector_unregister(
        drm_mode_group_reinit(imxdrm->drm);
 }
 
-/*
- * register a crtc to the drm core
- */
-static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
-{
-       struct imx_drm_device *imxdrm = __imx_drm_device();
-       int ret;
-
-       ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
-       if (ret)
-               return ret;
-
-       drm_crtc_helper_add(imx_drm_crtc->crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
-
-       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
-
-       drm_mode_group_reinit(imxdrm->drm);
-
-       return 0;
-}
-
 /*
  * Called by the CRTC driver when all CRTCs are registered. This
  * puts all the pieces together and initializes the driver.
@@ -424,15 +401,15 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
 
        mutex_lock(&imxdrm->mutex);
 
-       drm_kms_helper_poll_init(imxdrm->drm);
+       drm_kms_helper_poll_init(drm);
 
        /* setup the grouping for the legacy output */
-       ret = drm_mode_group_init_legacy_group(imxdrm->drm,
-                       &imxdrm->drm->primary->mode_group);
+       ret = drm_mode_group_init_legacy_group(drm,
+                       &drm->primary->mode_group);
        if (ret)
                goto err_kms;
 
-       ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
+       ret = drm_vblank_init(drm, MAX_CRTC);
        if (ret)
                goto err_kms;
 
@@ -441,7 +418,7 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
         * by drm timer once a current process gives up ownership of
         * vblank event.(after drm_vblank_put function is called)
         */
-       imxdrm->drm->vblank_disable_allowed = true;
+       drm->vblank_disable_allowed = true;
 
        if (!imx_drm_device_get()) {
                ret = -EINVAL;
@@ -536,10 +513,18 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 
        *new_crtc = imx_drm_crtc;
 
-       ret = imx_drm_crtc_register(imx_drm_crtc);
+       ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
        if (ret)
                goto err_register;
 
+       drm_crtc_helper_add(crtc,
+                       imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
+
+       drm_crtc_init(imxdrm->drm, crtc,
+                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
+
+       drm_mode_group_reinit(imxdrm->drm);
+
        imx_drm_update_possible_crtcs();
 
        mutex_unlock(&imxdrm->mutex);
index f3a1f5e2e492a465d9f3a85d6e981ba3c594489d..62ce0e86f14b50cfe7392bc5b47dd8871616af2b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/hdmi.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
@@ -52,11 +53,6 @@ enum hdmi_datamap {
        YCbCr422_12B = 0x12,
 };
 
-enum hdmi_colorimetry {
-       ITU601,
-       ITU709,
-};
-
 enum imx_hdmi_devtype {
        IMX6Q_HDMI,
        IMX6DL_HDMI,
@@ -489,12 +485,12 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
 
        if (is_color_space_conversion(hdmi)) {
                if (hdmi->hdmi_data.enc_out_format == RGB) {
-                       if (hdmi->hdmi_data.colorimetry == ITU601)
+                       if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
                                csc_coeff = &csc_coeff_rgb_out_eitu601;
                        else
                                csc_coeff = &csc_coeff_rgb_out_eitu709;
                } else if (hdmi->hdmi_data.enc_in_format == RGB) {
-                       if (hdmi->hdmi_data.colorimetry == ITU601)
+                       if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
                                csc_coeff = &csc_coeff_rgb_in_eitu601;
                        else
                                csc_coeff = &csc_coeff_rgb_in_eitu709;
@@ -1140,16 +1136,16 @@ static void hdmi_config_AVI(struct imx_hdmi *hdmi)
        /* Set up colorimetry */
        if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
                colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
-               if (hdmi->hdmi_data.colorimetry == ITU601)
+               if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
                        ext_colorimetry =
                                HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
-               else /* hdmi->hdmi_data.colorimetry == ITU709 */
+               else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
                        ext_colorimetry =
                                HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
        } else if (hdmi->hdmi_data.enc_out_format != RGB) {
-               if (hdmi->hdmi_data.colorimetry == ITU601)
+               if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
                        colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
-               else /* hdmi->hdmi_data.colorimetry == ITU709 */
+               else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
                        colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
                ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
        } else { /* Carries no data */
@@ -1379,9 +1375,9 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode)
                (hdmi->vic == 21) || (hdmi->vic == 22) ||
                (hdmi->vic == 2) || (hdmi->vic == 3) ||
                (hdmi->vic == 17) || (hdmi->vic == 18))
-               hdmi->hdmi_data.colorimetry = ITU601;
+               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
        else
-               hdmi->hdmi_data.colorimetry = ITU709;
+               hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
 
        if ((hdmi->vic == 10) || (hdmi->vic == 11) ||
                (hdmi->vic == 12) || (hdmi->vic == 13) ||
index 22742d6d62a8012692c62749024b242e67e3d21d..0a2b6cb3775ee3001d4edc56d312527b6f468a8e 100644 (file)
@@ -9,5 +9,6 @@
 * Other minor misc cleanups...
 
 Please send any patches to Greg Kroah-Hartman <greg@kroah.com>, Andreas Dilger
-<andreas.dilger@intel.com> and Peng Tao <tao.peng@emc.com>. CCing
-hpdd-discuss <hpdd-discuss@lists.01.org> would be great too.
+<andreas.dilger@intel.com>, Oleg Drokin <oleg.drokin@intel.com> and
+Peng Tao <tao.peng@emc.com>. CCing hpdd-discuss <hpdd-discuss@lists.01.org>
+would be great too.
index 596a15fc899676709adf21fa437c91f53284bb17..037ae8a6d5319ee230fb9cb5de131b115db2cf43 100644 (file)
@@ -61,6 +61,8 @@ struct kuc_hdr {
        __u16 kuc_msglen;     /* Including header */
 } __attribute__((aligned(sizeof(__u64))));
 
+#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE)
+
 #define KUC_MAGIC  0x191C /*Lustre9etLinC */
 #define KUC_FL_BLOCK 0x01   /* Wait for send */
 
index d0d942ced01a57c804efdfa712fa62977678c911..dddccca120c90be3a5d4a366b1a55caabe873971 100644 (file)
@@ -120,7 +120,7 @@ do {                                                \
 do {                                                                       \
        LASSERT(!in_interrupt() ||                                          \
                ((size) <= LIBCFS_VMALLOC_SIZE &&                           \
-                ((mask) & GFP_ATOMIC)) != 0);                      \
+                ((mask) & __GFP_WAIT) == 0));                              \
 } while (0)
 
 #define LIBCFS_ALLOC_POST(ptr, size)                                       \
index 93648632ba26f7fd0ab2390cbe5f427040393bcd..6f58ead2039343d1257381d5dcf05faff433044c 100644 (file)
@@ -529,7 +529,7 @@ kiblnd_kvaddr_to_page (unsigned long vaddr)
 {
        struct page *page;
 
-       if (is_vmalloc_addr(vaddr)) {
+       if (is_vmalloc_addr((void *)vaddr)) {
                page = vmalloc_to_page ((void *)vaddr);
                LASSERT (page != NULL);
                return page;
index 68a4f52ec998c14795d6f356e807b798c2dfa794..b7b53b579c8524abf460898212264b716ba0aac2 100644 (file)
@@ -924,7 +924,7 @@ ksocknal_launch_packet (lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id)
 int
 ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 {
-       int            mpflag = 0;
+       int            mpflag = 1;
        int            type = lntmsg->msg_type;
        lnet_process_id_t target = lntmsg->msg_target;
        unsigned int      payload_niov = lntmsg->msg_niov;
@@ -993,8 +993,9 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 
        /* The first fragment will be set later in pro_pack */
        rc = ksocknal_launch_packet(ni, tx, target);
-       if (lntmsg->msg_vmflush)
+       if (!mpflag)
                cfs_memory_pressure_restore(mpflag);
+
        if (rc == 0)
                return (0);
 
index 6b6c0240e8243010f6bf5d20809b8667c70ebc39..7893d83e131ffcf451b584b0556c0685216bf0dd 100644 (file)
@@ -760,7 +760,8 @@ static inline void hsm_set_cl_error(int *flags, int error)
        *flags |= (error << CLF_HSM_ERR_L);
 }
 
-#define CR_MAXSIZE cfs_size_round(2*NAME_MAX + 1 + sizeof(struct changelog_rec))
+#define CR_MAXSIZE cfs_size_round(2*NAME_MAX + 1 + \
+                                 sizeof(struct changelog_ext_rec))
 
 struct changelog_rec {
        __u16            cr_namelen;
index 22d0acc95bc57f9e5c52f1ff62a42a39f4ea6079..52b7731bcc38679b0e4b6f1360c8a3baf7c76ac4 100644 (file)
@@ -1086,7 +1086,7 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
                break;
        case Q_GETQUOTA:
                if (((type == USRQUOTA &&
-                     uid_eq(current_euid(), make_kuid(&init_user_ns, id))) ||
+                     !uid_eq(current_euid(), make_kuid(&init_user_ns, id))) ||
                     (type == GRPQUOTA &&
                      !in_egroup_p(make_kgid(&init_user_ns, id)))) &&
                    (!cfs_capable(CFS_CAP_SYS_ADMIN) ||
index d1ad91c34ddcdad89ece9f1b4f21639b34dda9a4..83013927e13152d8b414dc715ec19df49f827dac 100644 (file)
@@ -1430,7 +1430,7 @@ static struct kuc_hdr *changelog_kuc_hdr(char *buf, int len, int flags)
 {
        struct kuc_hdr *lh = (struct kuc_hdr *)buf;
 
-       LASSERT(len <= CR_MAXSIZE);
+       LASSERT(len <= KUC_CHANGELOG_MSG_MAXSIZE);
 
        lh->kuc_magic = KUC_MAGIC;
        lh->kuc_transport = KUC_TRANSPORT_CHANGELOG;
@@ -1503,7 +1503,7 @@ static int mdc_changelog_send_thread(void *csdata)
        CDEBUG(D_CHANGELOG, "changelog to fp=%p start "LPU64"\n",
               cs->cs_fp, cs->cs_startrec);
 
-       OBD_ALLOC(cs->cs_buf, CR_MAXSIZE);
+       OBD_ALLOC(cs->cs_buf, KUC_CHANGELOG_MSG_MAXSIZE);
        if (cs->cs_buf == NULL)
                GOTO(out, rc = -ENOMEM);
 
@@ -1540,7 +1540,7 @@ out:
        if (ctxt)
                llog_ctxt_put(ctxt);
        if (cs->cs_buf)
-               OBD_FREE(cs->cs_buf, CR_MAXSIZE);
+               OBD_FREE(cs->cs_buf, KUC_CHANGELOG_MSG_MAXSIZE);
        OBD_FREE_PTR(cs);
        return rc;
 }
index 10bb41c2fb6d538a8c3febd47288d9aee9f8e297..eecb1f2a5574fa8ecffc536931bf37a9a2912169 100644 (file)
@@ -59,7 +59,7 @@ static int go7007_loader_probe(struct usb_interface *interface,
 
        if (usbdev->descriptor.bNumConfigurations != 1) {
                dev_err(&interface->dev, "can't handle multiple config\n");
-               return -ENODEV;
+               goto failed2;
        }
 
        vendor = le16_to_cpu(usbdev->descriptor.idVendor);
@@ -108,6 +108,7 @@ static int go7007_loader_probe(struct usb_interface *interface,
        return 0;
 
 failed2:
+       usb_put_dev(usbdev);
        dev_err(&interface->dev, "probe failed\n");
        return -ENODEV;
 }
@@ -115,6 +116,7 @@ failed2:
 static void go7007_loader_disconnect(struct usb_interface *interface)
 {
        dev_info(&interface->dev, "disconnect\n");
+       usb_put_dev(interface_to_usbdev(interface));
        usb_set_intfdata(interface, NULL);
 }
 
index eedffed17e391d3243443c443ff9338bf494c440..31b269a5fff768bb7fff82edfca35ead48c93fe7 100644 (file)
@@ -307,7 +307,7 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
 }
 
 static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
-                               void *accel_priv)
+                               void *accel_priv, select_queue_fallback_t fallback)
 {
        return (u16)smp_processor_id();
 }
@@ -892,6 +892,11 @@ static int xlr_setup_mdio(struct xlr_net_priv *priv,
        priv->mii_bus->write = xlr_mii_write;
        priv->mii_bus->parent = &pdev->dev;
        priv->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+       if (priv->mii_bus->irq == NULL) {
+               pr_err("irq alloc failed\n");
+               mdiobus_free(priv->mii_bus);
+               return -ENOMEM;
+       }
        priv->mii_bus->irq[priv->phy_addr] = priv->ndev->irq;
 
        /* Scan only the enabled address */
index 47e0a91238a107da2db14ab873685c582dcb59b9..5a001d9b425295eb8079a66c38c16baf8f36db7c 100644 (file)
@@ -275,13 +275,6 @@ enum cvmx_usb_pipe_flags {
  */
 #define MAX_TRANSFER_PACKETS   ((1<<10)-1)
 
-enum {
-       USB_CLOCK_TYPE_REF_12,
-       USB_CLOCK_TYPE_REF_24,
-       USB_CLOCK_TYPE_REF_48,
-       USB_CLOCK_TYPE_CRYSTAL_12,
-};
-
 /**
  * Logical transactions may take numerous low level
  * transactions, especially when splits are concerned. This
@@ -471,19 +464,6 @@ struct octeon_hcd {
 /* Returns the IO address to push/pop stuff data from the FIFOs */
 #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000)
 
-static int octeon_usb_get_clock_type(void)
-{
-       switch (cvmx_sysinfo_get()->board_type) {
-       case CVMX_BOARD_TYPE_BBGW_REF:
-       case CVMX_BOARD_TYPE_LANAI2_A:
-       case CVMX_BOARD_TYPE_LANAI2_U:
-       case CVMX_BOARD_TYPE_LANAI2_G:
-       case CVMX_BOARD_TYPE_UBNT_E100:
-               return USB_CLOCK_TYPE_CRYSTAL_12;
-       }
-       return USB_CLOCK_TYPE_REF_48;
-}
-
 /**
  * Read a USB 32bit CSR. It performs the necessary address swizzle
  * for 32bit CSRs and logs the value in a readable format if
@@ -582,37 +562,6 @@ static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
                return 0; /* Data0 */
 }
 
-
-/**
- * Return the number of USB ports supported by this Octeon
- * chip. If the chip doesn't support USB, or is not supported
- * by this API, a zero will be returned. Most Octeon chips
- * support one usb port, but some support two ports.
- * cvmx_usb_initialize() must be called on independent
- * struct cvmx_usb_state.
- *
- * Returns: Number of port, zero if usb isn't supported
- */
-static int cvmx_usb_get_num_ports(void)
-{
-       int arch_ports = 0;
-
-       if (OCTEON_IS_MODEL(OCTEON_CN56XX))
-               arch_ports = 1;
-       else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
-               arch_ports = 2;
-       else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
-               arch_ports = 1;
-       else if (OCTEON_IS_MODEL(OCTEON_CN31XX))
-               arch_ports = 1;
-       else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
-               arch_ports = 1;
-       else
-               arch_ports = 0;
-
-       return arch_ports;
-}
-
 /**
  * Initialize a USB port for use. This must be called before any
  * other access to the Octeon USB port is made. The port starts
@@ -628,41 +577,16 @@ static int cvmx_usb_get_num_ports(void)
  * Returns: 0 or a negative error code.
  */
 static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
-                              int usb_port_number)
+                              int usb_port_number,
+                              enum cvmx_usb_initialize_flags flags)
 {
        union cvmx_usbnx_clk_ctl usbn_clk_ctl;
        union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
-       enum cvmx_usb_initialize_flags flags = 0;
        int i;
 
        /* At first allow 0-1 for the usb port number */
        if ((usb_port_number < 0) || (usb_port_number > 1))
                return -EINVAL;
-       /* For all chips except 52XX there is only one port */
-       if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0))
-               return -EINVAL;
-       /* Try to determine clock type automatically */
-       if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) {
-               /* Only 12 MHZ crystals are supported */
-               flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;
-       } else {
-               flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
-
-               switch (octeon_usb_get_clock_type()) {
-               case USB_CLOCK_TYPE_REF_12:
-                       flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
-                       break;
-               case USB_CLOCK_TYPE_REF_24:
-                       flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
-                       break;
-               case USB_CLOCK_TYPE_REF_48:
-                       flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
-                       break;
-               default:
-                       return -EINVAL;
-                       break;
-               }
-       }
 
        memset(usb, 0, sizeof(*usb));
        usb->init_flags = flags;
@@ -3431,7 +3355,6 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
        return 0;
 }
 
-
 static const struct hc_driver octeon_hc_driver = {
        .description            = "Octeon USB",
        .product_desc           = "Octeon Host Controller",
@@ -3448,15 +3371,74 @@ static const struct hc_driver octeon_hc_driver = {
        .hub_control            = octeon_usb_hub_control,
 };
 
-
-static int octeon_usb_driver_probe(struct device *dev)
+static int octeon_usb_probe(struct platform_device *pdev)
 {
        int status;
-       int usb_num = to_platform_device(dev)->id;
-       int irq = platform_get_irq(to_platform_device(dev), 0);
+       int initialize_flags;
+       int usb_num;
+       struct resource *res_mem;
+       struct device_node *usbn_node;
+       int irq = platform_get_irq(pdev, 0);
+       struct device *dev = &pdev->dev;
        struct octeon_hcd *priv;
        struct usb_hcd *hcd;
        unsigned long flags;
+       u32 clock_rate = 48000000;
+       bool is_crystal_clock = false;
+       const char *clock_type;
+       int i;
+
+       if (dev->of_node == NULL) {
+               dev_err(dev, "Error: empty of_node\n");
+               return -ENXIO;
+       }
+       usbn_node = dev->of_node->parent;
+
+       i = of_property_read_u32(usbn_node,
+                                "refclk-frequency", &clock_rate);
+       if (i) {
+               dev_err(dev, "No USBN \"refclk-frequency\"\n");
+               return -ENXIO;
+       }
+       switch (clock_rate) {
+       case 12000000:
+               initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
+               break;
+       case 24000000:
+               initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
+               break;
+       case 48000000:
+               initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
+               break;
+       default:
+               dev_err(dev, "Illebal USBN \"refclk-frequency\" %u\n", clock_rate);
+               return -ENXIO;
+
+       }
+
+       i = of_property_read_string(usbn_node,
+                                   "refclk-type", &clock_type);
+
+       if (!i && strcmp("crystal", clock_type) == 0)
+               is_crystal_clock = true;
+
+       if (is_crystal_clock)
+               initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;
+       else
+               initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res_mem == NULL) {
+               dev_err(dev, "found no memory resource\n");
+               return -ENXIO;
+       }
+       usb_num = (res_mem->start >> 44) & 1;
+
+       if (irq < 0) {
+               /* Defective device tree, but we know how to fix it. */
+               irq_hw_number_t hwirq = usb_num ? (1 << 6) + 17 : 56;
+               irq = irq_create_mapping(NULL, hwirq);
+       }
 
        /*
         * Set the DMA mask to 64bits so we get buffers already translated for
@@ -3465,6 +3447,26 @@ static int octeon_usb_driver_probe(struct device *dev)
        dev->coherent_dma_mask = ~0;
        dev->dma_mask = &dev->coherent_dma_mask;
 
+       /*
+        * Only cn52XX and cn56XX have DWC_OTG USB hardware and the
+        * IOB priority registers.  Under heavy network load USB
+        * hardware can be starved by the IOB causing a crash.  Give
+        * it a priority boost if it has been waiting more than 400
+        * cycles to avoid this situation.
+        *
+        * Testing indicates that a cnt_val of 8192 is not sufficient,
+        * but no failures are seen with 4096.  We choose a value of
+        * 400 to give a safety factor of 10.
+        */
+       if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
+               union cvmx_iob_n2c_l2c_pri_cnt pri_cnt;
+
+               pri_cnt.u64 = 0;
+               pri_cnt.s.cnt_enb = 1;
+               pri_cnt.s.cnt_val = 400;
+               cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64);
+       }
+
        hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev));
        if (!hcd) {
                dev_dbg(dev, "Failed to allocate memory for HCD\n");
@@ -3478,7 +3480,7 @@ static int octeon_usb_driver_probe(struct device *dev)
        tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv);
        INIT_LIST_HEAD(&priv->dequeue_list);
 
-       status = cvmx_usb_initialize(&priv->usb, usb_num);
+       status = cvmx_usb_initialize(&priv->usb, usb_num, initialize_flags);
        if (status) {
                dev_dbg(dev, "USB initialization failed with %d\n", status);
                kfree(hcd);
@@ -3492,7 +3494,7 @@ static int octeon_usb_driver_probe(struct device *dev)
        cvmx_usb_poll(&priv->usb);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       status = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       status = usb_add_hcd(hcd, irq, 0);
        if (status) {
                dev_dbg(dev, "USB add HCD failed with %d\n", status);
                kfree(hcd);
@@ -3500,14 +3502,15 @@ static int octeon_usb_driver_probe(struct device *dev)
        }
        device_wakeup_enable(hcd->self.controller);
 
-       dev_dbg(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);
+       dev_info(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq);
 
        return 0;
 }
 
-static int octeon_usb_driver_remove(struct device *dev)
+static int octeon_usb_remove(struct platform_device *pdev)
 {
        int status;
+       struct device *dev = &pdev->dev;
        struct usb_hcd *hcd = dev_get_drvdata(dev);
        struct octeon_hcd *priv = hcd_to_octeon(hcd);
        unsigned long flags;
@@ -3525,85 +3528,41 @@ static int octeon_usb_driver_remove(struct device *dev)
        return 0;
 }
 
-static struct device_driver octeon_usb_driver = {
-       .name   = "OcteonUSB",
-       .bus    = &platform_bus_type,
-       .probe  = octeon_usb_driver_probe,
-       .remove = octeon_usb_driver_remove,
+static struct of_device_id octeon_usb_match[] = {
+       {
+               .compatible = "cavium,octeon-5750-usbc",
+       },
+       {},
 };
 
+static struct platform_driver octeon_usb_driver = {
+       .driver = {
+               .name       = "OcteonUSB",
+               .owner          = THIS_MODULE,
+               .of_match_table = octeon_usb_match,
+       },
+       .probe      = octeon_usb_probe,
+       .remove     = octeon_usb_remove,
+};
 
-#define MAX_USB_PORTS   10
-static struct platform_device *pdev_glob[MAX_USB_PORTS];
-static int octeon_usb_registered;
-static int __init octeon_usb_module_init(void)
+static int __init octeon_usb_driver_init(void)
 {
-       int num_devices = cvmx_usb_get_num_ports();
-       int device;
-
-       if (usb_disabled() || num_devices == 0)
-               return -ENODEV;
-
-       if (driver_register(&octeon_usb_driver))
-               return -ENOMEM;
-
-       octeon_usb_registered = 1;
-
-       /*
-        * Only cn52XX and cn56XX have DWC_OTG USB hardware and the
-        * IOB priority registers.  Under heavy network load USB
-        * hardware can be starved by the IOB causing a crash.  Give
-        * it a priority boost if it has been waiting more than 400
-        * cycles to avoid this situation.
-        *
-        * Testing indicates that a cnt_val of 8192 is not sufficient,
-        * but no failures are seen with 4096.  We choose a value of
-        * 400 to give a safety factor of 10.
-        */
-       if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
-               union cvmx_iob_n2c_l2c_pri_cnt pri_cnt;
-
-               pri_cnt.u64 = 0;
-               pri_cnt.s.cnt_enb = 1;
-               pri_cnt.s.cnt_val = 400;
-               cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64);
-       }
-
-       for (device = 0; device < num_devices; device++) {
-               struct resource irq_resource;
-               struct platform_device *pdev;
-               memset(&irq_resource, 0, sizeof(irq_resource));
-               irq_resource.start = (device == 0) ? OCTEON_IRQ_USB0 : OCTEON_IRQ_USB1;
-               irq_resource.end = irq_resource.start;
-               irq_resource.flags = IORESOURCE_IRQ;
-               pdev = platform_device_register_simple((char *)octeon_usb_driver.  name, device, &irq_resource, 1);
-               if (IS_ERR(pdev)) {
-                       driver_unregister(&octeon_usb_driver);
-                       octeon_usb_registered = 0;
-                       return PTR_ERR(pdev);
-               }
-               if (device < MAX_USB_PORTS)
-                       pdev_glob[device] = pdev;
+       if (usb_disabled())
+               return 0;
 
-       }
-       return 0;
+       return platform_driver_register(&octeon_usb_driver);
 }
+module_init(octeon_usb_driver_init);
 
-static void __exit octeon_usb_module_cleanup(void)
+static void __exit octeon_usb_driver_exit(void)
 {
-       int i;
+       if (usb_disabled())
+               return;
 
-       for (i = 0; i < MAX_USB_PORTS; i++)
-               if (pdev_glob[i]) {
-                       platform_device_unregister(pdev_glob[i]);
-                       pdev_glob[i] = NULL;
-               }
-       if (octeon_usb_registered)
-               driver_unregister(&octeon_usb_driver);
+       platform_driver_unregister(&octeon_usb_driver);
 }
+module_exit(octeon_usb_driver_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
-MODULE_DESCRIPTION("Cavium Networks Octeon USB Host driver.");
-module_init(octeon_usb_module_init);
-module_exit(octeon_usb_module_cleanup);
+MODULE_AUTHOR("Cavium, Inc. <support@cavium.com>");
+MODULE_DESCRIPTION("Cavium Inc. OCTEON USB Host driver.");
index cb060364dfe7abd8933fd51e8c1c0003653052cf..5d965cf06d59c60c717e5b9b87b74605f720ec5c 100644 (file)
@@ -668,8 +668,8 @@ void oz_binding_add(const char *net_dev)
        if (binding) {
                binding->ptype.type = __constant_htons(OZ_ETHERTYPE);
                binding->ptype.func = oz_pkt_recv;
-               memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
                if (net_dev && *net_dev) {
+                       memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
                        oz_dbg(ON, "Adding binding: %s\n", net_dev);
                        binding->ptype.dev =
                                dev_get_by_name(&init_net, net_dev);
@@ -680,6 +680,7 @@ void oz_binding_add(const char *net_dev)
                        }
                } else {
                        oz_dbg(ON, "Binding to all netcards\n");
+                       memset(binding->name, 0, OZ_MAX_BINDING_LEN);
                        binding->ptype.dev = NULL;
                }
                if (binding) {
index 153ec61493ab6ef94a4ec71f886b8a700ecad4ad..96df62f95b6bbec0c3e6d0fe066d898f43d5b829 100644 (file)
@@ -912,12 +912,12 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
        unsigned char *pbuf;
        u32 wpa_ielen = 0;
        u8 *pbssid = GetAddr3Ptr(pframe);
-       u32 hidden_ssid = 0;
        struct HT_info_element *pht_info = NULL;
        struct rtw_ieee80211_ht_cap *pht_cap = NULL;
        u32 bcn_channel;
        unsigned short  ht_cap_info;
        unsigned char   ht_info_infos_0;
+       int ssid_len;
 
        if (is_client_associated_to_ap(Adapter) == false)
                return true;
@@ -999,21 +999,15 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
        }
 
        /* checking SSID */
+       ssid_len = 0;
        p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
-       if (p == NULL) {
-               DBG_88E("%s marc: cannot find SSID for survey event\n", __func__);
-               hidden_ssid = true;
-       } else {
-               hidden_ssid = false;
-       }
-
-       if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
-               memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
-               bssid->Ssid.SsidLength = *(p + 1);
-       } else {
-               bssid->Ssid.SsidLength = 0;
-               bssid->Ssid.Ssid[0] = '\0';
+       if (p) {
+               ssid_len = *(p + 1);
+               if (ssid_len > NDIS_802_11_LENGTH_SSID)
+                       ssid_len = 0;
        }
+       memcpy(bssid->Ssid.Ssid, (p + 2), ssid_len);
+       bssid->Ssid.SsidLength = ssid_len;
 
        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
                                "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__, bssid->Ssid.Ssid,
index dec992569476cf23f4bb93379fe3b3ce13ce0d9e..4ad80ae1067f0fbe70eefe7b2efab5f08db76962 100644 (file)
@@ -2500,7 +2500,7 @@ static int rtw_mp_ioctl_hdl(struct net_device *dev, struct iw_request_info *info
                 ("rtw_mp_ioctl_hdl: subcode [%d], len[%d], buffer_len[%d]\r\n",
                  poidparam->subcode, poidparam->len, len));
 
-       if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
+       if (poidparam->subcode >= ARRAY_SIZE(mp_ioctl_hdl)) {
                RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("no matching drvext subcodes\r\n"));
                ret = -EINVAL;
                goto _rtw_mp_ioctl_hdl_exit;
@@ -3164,9 +3164,7 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
        u8 *p2pie;
        uint p2pielen = 0, attr_contentlen = 0;
        u8 attr_content[100] = {0x00};
-
-       u8 go_devadd_str[17 + 10] = {0x00};
-       /*  +10 is for the str "go_devadd =", we have to clear it at wrqu->data.pointer */
+       u8 go_devadd_str[17 + 12] = {};
 
        /*      Commented by Albert 20121209 */
        /*      The input data is the GO's interface address which the application wants to know its device address. */
@@ -3223,12 +3221,12 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev,
        spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
 
        if (!blnMatch)
-               sprintf(go_devadd_str, "\n\ndev_add = NULL");
+               snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL");
        else
-               sprintf(go_devadd_str, "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+               snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
                        attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]);
 
-       if (copy_to_user(wrqu->data.pointer, go_devadd_str, 10 + 17))
+       if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str)))
                return -EFAULT;
        return ret;
 }
index 68f98fa114d2ec5feb124533824fcebae59a374e..7c9ee58f47bb741ebc4b78b99b112f4ac2fdce5d 100644 (file)
@@ -653,7 +653,7 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb)
 }
 
 static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
-                           void *accel_priv)
+                           void *accel_priv, select_queue_fallback_t fallback)
 {
        struct adapter  *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
index 0a341d6ec51fa3def524ee33e9b583c172876894..2f40ff5901d64706e82e2f120208c62ef5b291f8 100644 (file)
@@ -53,8 +53,9 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
        /*=== Customer ID ===*/
        /****** 8188EUS ********/
-       {USB_DEVICE(0x8179, 0x07B8)}, /* Abocom - Abocom */
+       {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
+       {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
        {}      /* Terminating entry */
 };
 
index 2aa5dac2f1dfea02e12b261c79d905c05d4b9a6e..abccc9dabd6550a3c316d16f4ae1d99d330d2d11 100644 (file)
@@ -1,6 +1,6 @@
 config R8821AE
        tristate "RealTek RTL8821AE Wireless LAN NIC driver"
-       depends on PCI && WLAN
+       depends on PCI && WLAN && MAC80211
        depends on m
        select WIRELESS_EXT
        select WEXT_PRIV
index cfe88a1efd55ac0eb6ce1982275fcd02ec504b3d..76bef93ad70a8d99895e308c9b9c19d336c595c6 100644 (file)
@@ -1414,7 +1414,7 @@ struct rtl_dm {
 
 
        /*88e tx power tracking*/
-       u8 bb_swing_idx_ofdm[2];
+       u8 bb_swing_idx_ofdm[MAX_RF_PATH];
        u8 bb_swing_idx_ofdm_current;
        u8 bb_swing_idx_ofdm_base[MAX_RF_PATH];
        bool bb_swing_flag_Ofdm;
index 3c8d28b771e0bba93de1337d8671dc784f6d355e..81ff8522405c29eb69675982cd3dc0407728964a 100644 (file)
@@ -169,14 +169,14 @@ static void *my_malloc(size_t size)
        struct pool *p;
 
        p = calloc(1, sizeof(struct pool));
-       if (!p) {
-               free(p);
+       if (!p)
                return NULL;
-       }
 
        p->mem = calloc(1, size);
-       if (!p->mem)
+       if (!p->mem) {
+               free(p);
                return NULL;
+       }
 
        p->next = pool_head;
        pool_head = p;
index 9b51586d11d92bb3bbc893086d4cb7f9f9bcd912..0141bc34d5cc3e43c5ea122347456935b5613bd4 100644 (file)
@@ -149,7 +149,8 @@ static int valid_args(__u32 rhport, enum usb_device_speed speed)
        case USB_SPEED_WIRELESS:
                break;
        default:
-               pr_err("speed %d\n", speed);
+               pr_err("Failed attach request for unsupported USB speed: %s\n",
+                       usb_speed_string(speed));
                return -EINVAL;
        }
 
index 4a1ddaf5e00f85bf3bcd6e4e41238449216464e4..187fc060de26bc732a434790c159b2274a83ebfc 100644 (file)
@@ -1061,7 +1061,7 @@ static int wireless_set_essid(struct net_device *dev, struct iw_request_info *in
                goto out;
        }
 
-       if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN + 1) {
+       if (data->flags != 0 && data->length > HCF_MAX_NAME_LEN) {
                ret = -EINVAL;
                goto out;
        }
index 7f1a7ce4b771a791cdf636906fd5fcdcc16c9ba6..b83ec378d04f8f1ed5fbc820429c6f1657b4d7a0 100644 (file)
@@ -785,7 +785,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
        spin_unlock_bh(&conn->cmd_lock);
 
        list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
-               list_del(&cmd->i_conn_node);
+               list_del_init(&cmd->i_conn_node);
                iscsit_free_cmd(cmd, false);
        }
 }
@@ -3708,7 +3708,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state
                break;
        case ISTATE_REMOVE:
                spin_lock_bh(&conn->cmd_lock);
-               list_del(&cmd->i_conn_node);
+               list_del_init(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
                iscsit_free_cmd(cmd, false);
@@ -4151,7 +4151,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
        spin_lock_bh(&conn->cmd_lock);
        list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
 
-               list_del(&cmd->i_conn_node);
+               list_del_init(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
                iscsit_increment_maxcmdsn(cmd, sess);
@@ -4196,6 +4196,10 @@ int iscsit_close_connection(
        iscsit_stop_timers_for_cmds(conn);
        iscsit_stop_nopin_response_timer(conn);
        iscsit_stop_nopin_timer(conn);
+
+       if (conn->conn_transport->iscsit_wait_conn)
+               conn->conn_transport->iscsit_wait_conn(conn);
+
        iscsit_free_queue_reqs_for_conn(conn);
 
        /*
index e048d6439f4a67bac09c27010bc07953ddac78d4..cda4d80cfaef999e45e4ac8a6b894513a3a44ad6 100644 (file)
@@ -507,7 +507,9 @@ int iscsit_handle_status_snack(
        u32 last_statsn;
        int found_cmd;
 
-       if (conn->exp_statsn > begrun) {
+       if (!begrun) {
+               begrun = conn->exp_statsn;
+       } else if (conn->exp_statsn > begrun) {
                pr_err("Got Status SNACK Begrun: 0x%08x, RunLength:"
                        " 0x%08x but already got ExpStatSN: 0x%08x on CID:"
                        " %hu.\n", begrun, runlength, conn->exp_statsn,
index 33be1fb1df32f2850b6ceb1d54b3b5340a2b6bb1..4ca8fd2a70db4c05597f6b4bfbac171ce58ea8c7 100644 (file)
@@ -138,7 +138,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
                list_for_each_entry_safe(cmd, cmd_tmp,
                                &cr->conn_recovery_cmd_list, i_conn_node) {
 
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                        cmd->conn = NULL;
                        spin_unlock(&cr->conn_recovery_cmd_lock);
                        iscsit_free_cmd(cmd, true);
@@ -160,7 +160,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
                list_for_each_entry_safe(cmd, cmd_tmp,
                                &cr->conn_recovery_cmd_list, i_conn_node) {
 
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                        cmd->conn = NULL;
                        spin_unlock(&cr->conn_recovery_cmd_lock);
                        iscsit_free_cmd(cmd, true);
@@ -216,7 +216,7 @@ int iscsit_remove_cmd_from_connection_recovery(
        }
        cr = cmd->cr;
 
-       list_del(&cmd->i_conn_node);
+       list_del_init(&cmd->i_conn_node);
        return --cr->cmd_count;
 }
 
@@ -297,7 +297,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
                if (!(cmd->cmd_flags & ICF_OOO_CMDSN))
                        continue;
 
-               list_del(&cmd->i_conn_node);
+               list_del_init(&cmd->i_conn_node);
 
                spin_unlock_bh(&conn->cmd_lock);
                iscsit_free_cmd(cmd, true);
@@ -335,7 +335,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
        /*
         * Only perform connection recovery on ISCSI_OP_SCSI_CMD or
         * ISCSI_OP_NOOP_OUT opcodes.  For all other opcodes call
-        * list_del(&cmd->i_conn_node); to release the command to the
+        * list_del_init(&cmd->i_conn_node); to release the command to the
         * session pool and remove it from the connection's list.
         *
         * Also stop the DataOUT timer, which will be restarted after
@@ -351,7 +351,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
                                " CID: %hu\n", cmd->iscsi_opcode,
                                cmd->init_task_tag, cmd->cmd_sn, conn->cid);
 
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                        spin_unlock_bh(&conn->cmd_lock);
                        iscsit_free_cmd(cmd, true);
                        spin_lock_bh(&conn->cmd_lock);
@@ -371,7 +371,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
                 */
                if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
                     iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
-                       list_del(&cmd->i_conn_node);
+                       list_del_init(&cmd->i_conn_node);
                        spin_unlock_bh(&conn->cmd_lock);
                        iscsit_free_cmd(cmd, true);
                        spin_lock_bh(&conn->cmd_lock);
@@ -393,7 +393,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
 
                cmd->sess = conn->sess;
 
-               list_del(&cmd->i_conn_node);
+               list_del_init(&cmd->i_conn_node);
                spin_unlock_bh(&conn->cmd_lock);
 
                iscsit_free_all_datain_reqs(cmd);
index 39761837608d3a2ff059356e1049779580182952..44a5471de00ffe95c5fccdf5462931efa0acc361 100644 (file)
@@ -137,7 +137,7 @@ struct iscsi_portal_group *iscsit_get_tpg_from_np(
        list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
 
                spin_lock(&tpg->tpg_state_lock);
-               if (tpg->tpg_state == TPG_STATE_FREE) {
+               if (tpg->tpg_state != TPG_STATE_ACTIVE) {
                        spin_unlock(&tpg->tpg_state_lock);
                        continue;
                }
index 12da9b386169b7ece6150387777bf467426dc42e..c3d9df6aaf5f35bc4665355bf7cfe18c9e522aa7 100644 (file)
@@ -500,7 +500,7 @@ static inline int core_alua_state_lba_dependent(
 
                        if (segment_mult) {
                                u64 tmp = lba;
-                               start_lba = sector_div(tmp, segment_size * segment_mult);
+                               start_lba = do_div(tmp, segment_size * segment_mult);
 
                                last_lba = first_lba + segment_size - 1;
                                if (start_lba >= first_lba &&
index 2f5d77932c80052448ab752fdc32d6942b3fc50c..3013287a2aaa192fdacdfde7eb87bcd48eb0aff4 100644 (file)
@@ -2009,7 +2009,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
        sense_reason_t ret = TCM_NO_SENSE;
-       int pr_holder = 0;
+       int pr_holder = 0, type;
 
        if (!se_sess || !se_lun) {
                pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
@@ -2131,6 +2131,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                        ret = TCM_RESERVATION_CONFLICT;
                        goto out;
                }
+               type = pr_reg->pr_res_type;
 
                spin_lock(&pr_tmpl->registration_lock);
                /*
@@ -2161,6 +2162,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                 * Release the calling I_T Nexus registration now..
                 */
                __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1);
+               pr_reg = NULL;
 
                /*
                 * From spc4r17, section 5.7.11.3 Unregistering
@@ -2174,8 +2176,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                 * RESERVATIONS RELEASED.
                 */
                if (pr_holder &&
-                   (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
-                    pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
+                   (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
+                    type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
                        list_for_each_entry(pr_reg_p,
                                        &pr_tmpl->registration_list,
                                        pr_reg_list) {
@@ -2194,7 +2196,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
        ret = core_scsi3_update_and_write_aptpl(dev, aptpl);
 
 out:
-       core_scsi3_put_pr_reg(pr_reg);
+       if (pr_reg)
+               core_scsi3_put_pr_reg(pr_reg);
        return ret;
 }
 
index fa3cae393e13e64056da79e9a8daf43bfe8dc721..77e6531fb0a1c0a25ed16b71d1936ec37c2ed50a 100644 (file)
@@ -1074,23 +1074,36 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
        struct scatterlist *psg;
        void *paddr, *addr;
        unsigned int i, len, left;
+       unsigned int offset = sg_off;
 
        left = sectors * dev->prot_length;
 
        for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
+               unsigned int psg_len, copied = 0;
 
-               len = min(psg->length, left);
                paddr = kmap_atomic(sg_page(psg)) + psg->offset;
-               addr = kmap_atomic(sg_page(sg)) + sg_off;
+               psg_len = min(left, psg->length);
+               while (psg_len) {
+                       len = min(psg_len, sg->length - offset);
+                       addr = kmap_atomic(sg_page(sg)) + sg->offset + offset;
 
-               if (read)
-                       memcpy(paddr, addr, len);
-               else
-                       memcpy(addr, paddr, len);
+                       if (read)
+                               memcpy(paddr + copied, addr, len);
+                       else
+                               memcpy(addr, paddr + copied, len);
 
-               left -= len;
+                       left -= len;
+                       offset += len;
+                       copied += len;
+                       psg_len -= len;
+
+                       if (offset >= sg->length) {
+                               sg = sg_next(sg);
+                               offset = 0;
+                       }
+                       kunmap_atomic(addr);
+               }
                kunmap_atomic(paddr);
-               kunmap_atomic(addr);
        }
 }
 
@@ -1155,7 +1168,7 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
 {
        struct se_device *dev = cmd->se_dev;
        struct se_dif_v1_tuple *sdt;
-       struct scatterlist *dsg;
+       struct scatterlist *dsg, *psg = sg;
        sector_t sector = start;
        void *daddr, *paddr;
        int i, j, offset = sg_off;
@@ -1163,14 +1176,14 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
 
        for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) {
                daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
-               paddr = kmap_atomic(sg_page(sg)) + sg->offset;
+               paddr = kmap_atomic(sg_page(psg)) + sg->offset;
 
                for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) {
 
-                       if (offset >= sg->length) {
+                       if (offset >= psg->length) {
                                kunmap_atomic(paddr);
-                               sg = sg_next(sg);
-                               paddr = kmap_atomic(sg_page(sg)) + sg->offset;
+                               psg = sg_next(psg);
+                               paddr = kmap_atomic(sg_page(psg)) + psg->offset;
                                offset = 0;
                        }
 
index 43c5ca9878bc5b6f3f1d675c04779b245ccc1a22..3bebc71ea033908e8e64843ba98b295b030a78ad 100644 (file)
@@ -440,8 +440,8 @@ check_scsi_name:
                padding = ((-scsi_target_len) & 3);
                if (padding)
                        scsi_target_len += padding;
-               if (scsi_name_len > 256)
-                       scsi_name_len = 256;
+               if (scsi_target_len > 256)
+                       scsi_target_len = 256;
 
                buf[off-1] = scsi_target_len;
                off += scsi_target_len;
index c50fd9f11aab8b0dfb8b90991378a51bf8255d1b..2956250b7225c99d77a7475b27d1bf881231539f 100644 (file)
@@ -669,9 +669,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
                return;
        }
 
-       if (!success)
-               cmd->transport_state |= CMD_T_FAILED;
-
        /*
         * Check for case where an explicit ABORT_TASK has been received
         * and transport_wait_for_tasks() will be waiting for completion..
@@ -681,7 +678,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                complete(&cmd->t_transport_stop_comp);
                return;
-       } else if (cmd->transport_state & CMD_T_FAILED) {
+       } else if (!success) {
                INIT_WORK(&cmd->work, target_complete_failure_work);
        } else {
                INIT_WORK(&cmd->work, target_complete_ok_work);
@@ -1604,6 +1601,9 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_CHECK_CONDITION_ABORT_CMD:
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
        case TCM_CHECK_CONDITION_NOT_READY:
+       case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
+       case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
+       case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
                break;
        case TCM_OUT_OF_RESOURCES:
                sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
index 35c066489a19ecd1def35f044e45dc52d55688a1..5f88d767671e956fa400b039f2cc21de9bc58621 100644 (file)
@@ -136,6 +136,7 @@ config SPEAR_THERMAL
 config RCAR_THERMAL
        tristate "Renesas R-Car thermal driver"
        depends on ARCH_SHMOBILE || COMPILE_TEST
+       depends on HAS_IOMEM
        help
          Enable this to plug the R-Car thermal sensor driver into the Linux
          thermal framework.
@@ -210,8 +211,16 @@ config ACPI_INT3403_THERMAL
        tristate "ACPI INT3403 thermal driver"
        depends on X86 && ACPI
        help
-         This driver uses ACPI INT3403 device objects. If present, it will
-         register each INT3403 thermal sensor as a thermal zone.
+         Newer laptops and tablets that use ACPI may have thermal sensors
+         outside the core CPU/SOC for thermal safety reasons. These
+         temperature sensors are also exposed for the OS to use via the so
+         called INT3403 ACPI object. This driver will, on devices that have
+         such sensors, expose the temperature information from these sensors
+         to userspace via the normal thermal framework. This means that a wide
+         range of applications and GUI widgets can show this information to
+         the user or use this information for making decisions. For example,
+         the Intel Thermal Daemon can use this information to allow the user
+         to select his laptop to run without turning on the fans.
 
 menu "Texas Instruments thermal drivers"
 source "drivers/thermal/ti-soc-thermal/Kconfig"
index 338a88bf6662d1fd0b963f0f8bc7c02dce55e73b..71b0ec0c370d73aad18d685118c197735c5b2833 100644 (file)
@@ -56,10 +56,15 @@ static LIST_HEAD(thermal_governor_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
 
+static struct thermal_governor *def_governor;
+
 static struct thermal_governor *__find_governor(const char *name)
 {
        struct thermal_governor *pos;
 
+       if (!name || !name[0])
+               return def_governor;
+
        list_for_each_entry(pos, &thermal_governor_list, governor_list)
                if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH))
                        return pos;
@@ -82,17 +87,23 @@ int thermal_register_governor(struct thermal_governor *governor)
        if (__find_governor(governor->name) == NULL) {
                err = 0;
                list_add(&governor->governor_list, &thermal_governor_list);
+               if (!def_governor && !strncmp(governor->name,
+                       DEFAULT_THERMAL_GOVERNOR, THERMAL_NAME_LENGTH))
+                       def_governor = governor;
        }
 
        mutex_lock(&thermal_list_lock);
 
        list_for_each_entry(pos, &thermal_tz_list, node) {
+               /*
+                * only thermal zones with specified tz->tzp->governor_name
+                * may run with tz->govenor unset
+                */
                if (pos->governor)
                        continue;
-               if (pos->tzp)
-                       name = pos->tzp->governor_name;
-               else
-                       name = DEFAULT_THERMAL_GOVERNOR;
+
+               name = pos->tzp->governor_name;
+
                if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH))
                        pos->governor = governor;
        }
@@ -342,8 +353,8 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
 static void handle_non_critical_trips(struct thermal_zone_device *tz,
                        int trip, enum thermal_trip_type trip_type)
 {
-       if (tz->governor)
-               tz->governor->throttle(tz, trip);
+       tz->governor ? tz->governor->throttle(tz, trip) :
+                      def_governor->throttle(tz, trip);
 }
 
 static void handle_critical_trips(struct thermal_zone_device *tz,
@@ -1107,7 +1118,7 @@ __thermal_cooling_device_register(struct device_node *np,
        INIT_LIST_HEAD(&cdev->thermal_instances);
        cdev->np = np;
        cdev->ops = ops;
-       cdev->updated = true;
+       cdev->updated = false;
        cdev->device.class = &thermal_class;
        cdev->devdata = devdata;
        dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
@@ -1533,7 +1544,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
        if (tz->tzp)
                tz->governor = __find_governor(tz->tzp->governor_name);
        else
-               tz->governor = __find_governor(DEFAULT_THERMAL_GOVERNOR);
+               tz->governor = def_governor;
 
        mutex_unlock(&thermal_governor_lock);
 
index 972e1c73722a4c4ec90cd75af32ce99da6438745..081fd7e6a9f070c683deaea799437a2e459b94f4 100644 (file)
@@ -68,6 +68,10 @@ struct phy_dev_entry {
        struct thermal_zone_device *tzone;
 };
 
+static const struct thermal_zone_params pkg_temp_tz_params = {
+       .no_hwmon       = true,
+};
+
 /* List maintaining number of package instances */
 static LIST_HEAD(phy_dev_list);
 static DEFINE_MUTEX(phy_dev_list_mutex);
@@ -394,7 +398,6 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
        int err;
        u32 tj_max;
        struct phy_dev_entry *phy_dev_entry;
-       char buffer[30];
        int thres_count;
        u32 eax, ebx, ecx, edx;
        u8 *temp;
@@ -440,13 +443,11 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
        phy_dev_entry->first_cpu = cpu;
        phy_dev_entry->tj_max = tj_max;
        phy_dev_entry->ref_cnt = 1;
-       snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n",
-                                       phy_dev_entry->phys_proc_id);
-       phy_dev_entry->tzone = thermal_zone_device_register(buffer,
+       phy_dev_entry->tzone = thermal_zone_device_register("x86_pkg_temp",
                        thres_count,
                        (thres_count == MAX_NUMBER_OF_TRIPS) ?
                                0x03 : 0x01,
-                       phy_dev_entry, &tzone_ops, NULL, 0, 0);
+                       phy_dev_entry, &tzone_ops, &pkg_temp_tz_params, 0, 0);
        if (IS_ERR(phy_dev_entry->tzone)) {
                err = PTR_ERR(phy_dev_entry->tzone);
                goto err_ret_free;
index 6496872e2e47c34c29ca75c79ce4d56bf7191146..b01659bd4f7c2163803d64f3fe83cfe063720bf7 100644 (file)
@@ -255,13 +255,7 @@ static int __init hvc_opal_init(void)
        /* Register as a vio device to receive callbacks */
        return platform_driver_register(&hvc_opal_driver);
 }
-module_init(hvc_opal_init);
-
-static void __exit hvc_opal_exit(void)
-{
-       platform_driver_unregister(&hvc_opal_driver);
-}
-module_exit(hvc_opal_exit);
+device_initcall(hvc_opal_init);
 
 static void udbg_opal_putc(char c)
 {
index 0069bb86ba49c5981f9cd1a35229fad37152ab04..08c87920b74a98a02e3fcde902a41a64e79b9caf 100644 (file)
@@ -102,17 +102,7 @@ static int __init hvc_rtas_init(void)
 
        return 0;
 }
-module_init(hvc_rtas_init);
-
-/* This will tear down the tty portion of the driver */
-static void __exit hvc_rtas_exit(void)
-{
-       /* Really the fun isn't over until the worker thread breaks down and
-        * the tty cleans up */
-       if (hvc_rtas_dev)
-               hvc_remove(hvc_rtas_dev);
-}
-module_exit(hvc_rtas_exit);
+device_initcall(hvc_rtas_init);
 
 /* This will happen prior to module init.  There is no tty at this time? */
 static int __init hvc_rtas_console_init(void)
index 72228276fe314b36a1344a1ffef36263a4379c4c..9cf573d06a29bb8f44067d4c2ac70283db20f6db 100644 (file)
@@ -80,14 +80,7 @@ static int __init hvc_udbg_init(void)
 
        return 0;
 }
-module_init(hvc_udbg_init);
-
-static void __exit hvc_udbg_exit(void)
-{
-       if (hvc_udbg_dev)
-               hvc_remove(hvc_udbg_dev);
-}
-module_exit(hvc_udbg_exit);
+device_initcall(hvc_udbg_init);
 
 static int __init hvc_udbg_console_init(void)
 {
index 636c9baad7a58b76fc740bd49794303cfcc472ef..2dc2831840ca1852efb1cec280ced8b2e0afb0ae 100644 (file)
@@ -561,18 +561,7 @@ static int __init xen_hvc_init(void)
 #endif
        return r;
 }
-
-static void __exit xen_hvc_fini(void)
-{
-       struct xencons_info *entry, *next;
-
-       if (list_empty(&xenconsoles))
-                       return;
-
-       list_for_each_entry_safe(entry, next, &xenconsoles, list) {
-               xen_console_remove(entry);
-       }
-}
+device_initcall(xen_hvc_init);
 
 static int xen_cons_init(void)
 {
@@ -598,10 +587,6 @@ static int xen_cons_init(void)
        hvc_instantiate(HVC_COOKIE, 0, ops);
        return 0;
 }
-
-
-module_init(xen_hvc_init);
-module_exit(xen_hvc_fini);
 console_initcall(xen_cons_init);
 
 #ifdef CONFIG_EARLY_PRINTK
index f34461c5f14e102cbf64dba861e46a4a94820ecb..2ebe47b78a3e3ba48093d46164bee6247a32295e 100644 (file)
@@ -1090,6 +1090,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
 {
        unsigned int addr = 0;
        unsigned int modem = 0;
+       unsigned int brk = 0;
        struct gsm_dlci *dlci;
        int len = clen;
        u8 *dp = data;
@@ -1116,6 +1117,16 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
                if (len == 0)
                        return;
        }
+       len--;
+       if (len > 0) {
+               while (gsm_read_ea(&brk, *dp++) == 0) {
+                       len--;
+                       if (len == 0)
+                               return;
+               }
+               modem <<= 7;
+               modem |= (brk & 0x7f);
+       }
        tty = tty_port_tty_get(&dlci->port);
        gsm_process_modem(tty, dlci, modem, clen);
        if (tty) {
index cb8017aa443472f8b67d9ec4eab7403b268d2c0f..d15624c1b75161877e6319e6460981866feb54cb 100644 (file)
@@ -817,8 +817,7 @@ static void process_echoes(struct tty_struct *tty)
        struct n_tty_data *ldata = tty->disc_data;
        size_t echoed;
 
-       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
-           ldata->echo_mark == ldata->echo_tail)
+       if (ldata->echo_mark == ldata->echo_tail)
                return;
 
        mutex_lock(&ldata->output_lock);
@@ -1244,7 +1243,8 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c)
        if (L_ECHO(tty)) {
                echo_char(c, tty);
                commit_echoes(tty);
-       }
+       } else
+               process_echoes(tty);
        isig(signal, tty);
        return;
 }
@@ -1274,7 +1274,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
        if (I_IXON(tty)) {
                if (c == START_CHAR(tty)) {
                        start_tty(tty);
-                       commit_echoes(tty);
+                       process_echoes(tty);
                        return 0;
                }
                if (c == STOP_CHAR(tty)) {
@@ -1820,8 +1820,10 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
         * Fix tty hang when I_IXON(tty) is cleared, but the tty
         * been stopped by STOP_CHAR(tty) before it.
         */
-       if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped)
+       if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
                start_tty(tty);
+               process_echoes(tty);
+       }
 
        /* The termios change make the tty ready for I/O */
        if (waitqueue_active(&tty->write_wait))
@@ -1896,7 +1898,7 @@ err:
 static inline int input_available_p(struct tty_struct *tty, int poll)
 {
        struct n_tty_data *ldata = tty->disc_data;
-       int amt = poll && !TIME_CHAR(tty) ? MIN_CHAR(tty) : 1;
+       int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1;
 
        if (ldata->icanon && !L_EXTPROC(tty)) {
                if (ldata->canon_head != ldata->read_tail)
index 61ecd709a7229aa7d7d6fcc91326a8eda0861fa8..69932b7556cf822194413f2da0278d9bd3f4cb13 100644 (file)
@@ -2432,6 +2432,24 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
 
        serial_dl_write(up, quot);
 
+       /*
+        * XR17V35x UARTs have an extra fractional divisor register (DLD)
+        *
+        * We need to recalculate all of the registers, because DLM and DLL
+        * are already rounded to a whole integer.
+        *
+        * When recalculating we use a 32x clock instead of a 16x clock to
+        * allow 1-bit for rounding in the fractional part.
+        */
+       if (up->port.type == PORT_XR17V35X) {
+               unsigned int baud_x32 = (port->uartclk * 2) / baud;
+               u16 quot = baud_x32 / 32;
+               u8 quot_frac = DIV_ROUND_CLOSEST(baud_x32 % 32, 2);
+
+               serial_dl_write(up, quot);
+               serial_port_out(port, 0x2, quot_frac & 0xf);
+       }
+
        /*
         * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
         * is written without DLAB set, this mode will be disabled.
index faa64e6461002136069e53619ad78c7534a7261d..ed311357674032ad4f53577fe2f8033ba1446941 100644 (file)
@@ -391,7 +391,7 @@ static int dw8250_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int dw8250_suspend(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
@@ -409,7 +409,7 @@ static int dw8250_resume(struct device *dev)
 
        return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_PM_RUNTIME
 static int dw8250_runtime_suspend(struct device *dev)
index 50228eed3b6fa502a3a7bb93d14f9280f1f4e713..0ff3e3624d4c0599623af31535d02502c6da81c5 100644 (file)
@@ -783,7 +783,8 @@ static int pci_netmos_9900_setup(struct serial_private *priv,
 {
        unsigned int bar;
 
-       if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
+       if ((priv->dev->device != PCI_DEVICE_ID_NETMOS_9865) &&
+           (priv->dev->subsystem_device & 0xff00) == 0x3000) {
                /* netmos apparently orders BARs by datasheet layout, so serial
                 * ports get BARs 0 and 3 (or 1 and 4 for memmapped)
                 */
index fa511ebab67c67efda853be187ca670e20db4679..77f035158d6cac1cd7bd5ec094c2a9dfa71cab4e 100644 (file)
@@ -738,9 +738,6 @@ static int serial_omap_startup(struct uart_port *port)
                        return retval;
                }
                disable_irq(up->wakeirq);
-       } else {
-               dev_info(up->port.dev, "no wakeirq for uart%d\n",
-                        up->port.line);
        }
 
        dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
@@ -1604,8 +1601,11 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up,
                                            flags & SER_RS485_RTS_AFTER_SEND);
                if (ret < 0)
                        return ret;
-       } else
+       } else if (up->rts_gpio == -EPROBE_DEFER) {
+               return -EPROBE_DEFER;
+       } else {
                up->rts_gpio = -EINVAL;
+       }
 
        if (of_property_read_u32_array(np, "rs485-rts-delay",
                                    rs485_delay, 2) == 0) {
@@ -1687,6 +1687,9 @@ static int serial_omap_probe(struct platform_device *pdev)
        up->port.iotype = UPIO_MEM;
        up->port.irq = uartirq;
        up->wakeirq = wakeirq;
+       if (!up->wakeirq)
+               dev_info(up->port.dev, "no wakeirq for uart%d\n",
+                        up->port.line);
 
        up->port.regshift = 2;
        up->port.fifosize = 64;
index 49a2ffd101a7145ca1de4a7eccb72d56964037d0..b7bfe24d4ebca6f930bcaa3058b09f017561dfb5 100644 (file)
@@ -542,8 +542,10 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param)
        wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
                        rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
                        SIRFUART_IO_MODE);
-       sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count);
        spin_unlock_irqrestore(&sirfport->rx_lock, flags);
+       spin_lock(&port->lock);
+       sirfsoc_uart_pio_rx_chars(port, 4 - sirfport->rx_io_count);
+       spin_unlock(&port->lock);
        if (sirfport->rx_io_count == 4) {
                spin_lock_irqsave(&sirfport->rx_lock, flags);
                sirfport->rx_io_count = 0;
index cf86e729532b9fc11b768863c94bfb9fe1da7109..dc697cee248ad3dcfa84e2f1d66f8c439b37dd81 100644 (file)
@@ -433,13 +433,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
        unsigned long flags;
        int locked = 1;
 
-       local_irq_save(flags);
-       if (port->sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = spin_trylock(&port->lock);
-       } else
-               spin_lock(&port->lock);
+       if (port->sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&port->lock, flags);
+       else
+               spin_lock_irqsave(&port->lock, flags);
 
        while (n > 0) {
                unsigned long ra = __pa(con_write_page);
@@ -470,8 +467,7 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
        }
 
        if (locked)
-               spin_unlock(&port->lock);
-       local_irq_restore(flags);
+               spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -492,7 +488,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
        unsigned long flags;
        int i, locked = 1;
 
-       local_irq_save(flags);
+       if (port->sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&port->lock, flags);
+       else
+               spin_lock_irqsave(&port->lock, flags);
        if (port->sysrq) {
                locked = 0;
        } else if (oops_in_progress) {
@@ -507,8 +506,7 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
        }
 
        if (locked)
-               spin_unlock(&port->lock);
-       local_irq_restore(flags);
+               spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static struct console sunhv_console = {
index 380fb5355cb26ae68a472a4e6097c57556d0b8e1..5faa8e905e9896e52489a84dd3f6e7925e147dfc 100644 (file)
@@ -844,20 +844,16 @@ static void sunsab_console_write(struct console *con, const char *s, unsigned n)
        unsigned long flags;
        int locked = 1;
 
-       local_irq_save(flags);
-       if (up->port.sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = spin_trylock(&up->port.lock);
-       } else
-               spin_lock(&up->port.lock);
+       if (up->port.sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&up->port.lock, flags);
+       else
+               spin_lock_irqsave(&up->port.lock, flags);
 
        uart_console_write(&up->port, s, n, sunsab_console_putchar);
        sunsab_tec_wait(up);
 
        if (locked)
-               spin_unlock(&up->port.lock);
-       local_irq_restore(flags);
+               spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static int sunsab_console_setup(struct console *con, char *options)
index db79b76f5c8e978e09824b719d585cf470d75d68..9a0f24f837209f2b15f9e11901f350dcb0230a19 100644 (file)
@@ -1295,13 +1295,10 @@ static void sunsu_console_write(struct console *co, const char *s,
        unsigned int ier;
        int locked = 1;
 
-       local_irq_save(flags);
-       if (up->port.sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = spin_trylock(&up->port.lock);
-       } else
-               spin_lock(&up->port.lock);
+       if (up->port.sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&up->port.lock, flags);
+       else
+               spin_lock_irqsave(&up->port.lock, flags);
 
        /*
         *      First save the UER then disable the interrupts
@@ -1319,8 +1316,7 @@ static void sunsu_console_write(struct console *co, const char *s,
        serial_out(up, UART_IER, ier);
 
        if (locked)
-               spin_unlock(&up->port.lock);
-       local_irq_restore(flags);
+               spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 /*
index 45a8c6aa583797ba717ec3da79a24929a6eb425f..a2c40ed287d21b7a7ff545626bba5b0711211149 100644 (file)
@@ -1195,20 +1195,16 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count)
        unsigned long flags;
        int locked = 1;
 
-       local_irq_save(flags);
-       if (up->port.sysrq) {
-               locked = 0;
-       } else if (oops_in_progress) {
-               locked = spin_trylock(&up->port.lock);
-       } else
-               spin_lock(&up->port.lock);
+       if (up->port.sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&up->port.lock, flags);
+       else
+               spin_lock_irqsave(&up->port.lock, flags);
 
        uart_console_write(&up->port, s, count, sunzilog_putchar);
        udelay(2);
 
        if (locked)
-               spin_unlock(&up->port.lock);
-       local_irq_restore(flags);
+               spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static int __init sunzilog_console_setup(struct console *con, char *options)
index d8a55e87877f06f3141602e4f08cdcb668c465b0..0ffb0cbe28237239ffd093877a363c7957c8e328 100644 (file)
                                lock_acquire(&(l)->dep_map, s, t, r, c, n, i)
 # define __rel(l, n, i)                                \
                                lock_release(&(l)->dep_map, n, i)
-# ifdef CONFIG_PROVE_LOCKING
-#  define lockdep_acquire(l, s, t, i)          __acq(l, s, t, 0, 2, NULL, i)
-#  define lockdep_acquire_nest(l, s, t, n, i)  __acq(l, s, t, 0, 2, n, i)
-#  define lockdep_acquire_read(l, s, t, i)     __acq(l, s, t, 1, 2, NULL, i)
-#  define lockdep_release(l, n, i)             __rel(l, n, i)
-# else
-#  define lockdep_acquire(l, s, t, i)          __acq(l, s, t, 0, 1, NULL, i)
-#  define lockdep_acquire_nest(l, s, t, n, i)  __acq(l, s, t, 0, 1, n, i)
-#  define lockdep_acquire_read(l, s, t, i)     __acq(l, s, t, 1, 1, NULL, i)
-#  define lockdep_release(l, n, i)             __rel(l, n, i)
-# endif
+#define lockdep_acquire(l, s, t, i)            __acq(l, s, t, 0, 1, NULL, i)
+#define lockdep_acquire_nest(l, s, t, n, i)    __acq(l, s, t, 0, 1, n, i)
+#define lockdep_acquire_read(l, s, t, i)       __acq(l, s, t, 1, 1, NULL, i)
+#define lockdep_release(l, n, i)               __rel(l, n, i)
 #else
 # define lockdep_acquire(l, s, t, i)           do { } while (0)
 # define lockdep_acquire_nest(l, s, t, n, i)   do { } while (0)
index 61b1137d7e56d877fad8b2339c368cd09a5419e1..23b5d32954bfc9365ec6453d69e331e975ca8d0e 100644 (file)
@@ -1164,6 +1164,8 @@ static void csi_J(struct vc_data *vc, int vpar)
                        scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
                                    vc->vc_screenbuf_size >> 1);
                        set_origin(vc);
+                       if (CON_IS_VISIBLE(vc))
+                               update_screen(vc);
                        /* fall through */
                case 2: /* erase whole display */
                        count = vc->vc_cols * vc->vc_rows;
index 80de2f88ed2c7852fdd38bec785e6d5681cbe310..4ab2cb62dfce4c1b3dfe140ef83f20d4633b9ff0 100644 (file)
@@ -105,7 +105,7 @@ static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir)
 
        do {
                /* flush any pending transfer */
-               hw_write(ci, OP_ENDPTFLUSH, BIT(n), BIT(n));
+               hw_write(ci, OP_ENDPTFLUSH, ~0, BIT(n));
                while (hw_read(ci, OP_ENDPTFLUSH, BIT(n)))
                        cpu_relax();
        } while (hw_read(ci, OP_ENDPTSTAT, BIT(n)));
@@ -205,7 +205,7 @@ static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl)
        if (is_ctrl && dir == RX && hw_read(ci, OP_ENDPTSETUPSTAT, BIT(num)))
                return -EAGAIN;
 
-       hw_write(ci, OP_ENDPTPRIME, BIT(n), BIT(n));
+       hw_write(ci, OP_ENDPTPRIME, ~0, BIT(n));
 
        while (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
                cpu_relax();
index 8d72f0c659377371cc6c481e33458c7d555f3493..062967c90b2a06e66a081f81ab53aabe1a9e37e4 100644 (file)
@@ -717,6 +717,10 @@ int usb_get_configuration(struct usb_device *dev)
                        result = -ENOMEM;
                        goto err;
                }
+
+               if (dev->quirks & USB_QUIRK_DELAY_INIT)
+                       msleep(100);
+
                result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
                    bigbuffer, length);
                if (result < 0) {
index 5d01558cef666233b47f29d569595a1f42dda8b2..ab90a01568283c3c0d2a0a3df9b653bfba65a812 100644 (file)
@@ -63,8 +63,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
        dynid->id.idProduct = idProduct;
        dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
        if (fields > 2 && bInterfaceClass) {
-               if (bInterfaceClass > 255)
-                       return -EINVAL;
+               if (bInterfaceClass > 255) {
+                       retval = -EINVAL;
+                       goto fail;
+               }
 
                dynid->id.bInterfaceClass = (u8)bInterfaceClass;
                dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
@@ -73,17 +75,21 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
        if (fields > 4) {
                const struct usb_device_id *id = id_table;
 
-               if (!id)
-                       return -ENODEV;
+               if (!id) {
+                       retval = -ENODEV;
+                       goto fail;
+               }
 
                for (; id->match_flags; id++)
                        if (id->idVendor == refVendor && id->idProduct == refProduct)
                                break;
 
-               if (id->match_flags)
+               if (id->match_flags) {
                        dynid->id.driver_info = id->driver_info;
-               else
-                       return -ENODEV;
+               } else {
+                       retval = -ENODEV;
+                       goto fail;
+               }
        }
 
        spin_lock(&dynids->lock);
@@ -95,6 +101,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
        if (retval)
                return retval;
        return count;
+
+fail:
+       kfree(dynid);
+       return retval;
 }
 EXPORT_SYMBOL_GPL(usb_store_new_id);
 
index 199aaea6bfe0ad308fd459e0d0eb61daa1cdcb77..2518c325075093a9c26044f2d9dd18483dc7dd60 100644 (file)
@@ -1032,7 +1032,6 @@ static int register_root_hub(struct usb_hcd *hcd)
                                        dev_name(&usb_dev->dev), retval);
                        return retval;
                }
-               usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
        }
 
        retval = usb_new_device (usb_dev);
index babba885978d11e1ba4ece32373ba38a962c3f64..5cbf78d0be2539c868dab16a815b15e4bfe28b99 100644 (file)
@@ -128,7 +128,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
        return usb_get_intfdata(hdev->actconfig->interface[0]);
 }
 
-int usb_device_supports_lpm(struct usb_device *udev)
+static int usb_device_supports_lpm(struct usb_device *udev)
 {
        /* USB 2.1 (and greater) devices indicate LPM support through
         * their USB 2.0 Extended Capabilities BOS descriptor.
@@ -149,11 +149,6 @@ int usb_device_supports_lpm(struct usb_device *udev)
                                "Power management will be impacted.\n");
                return 0;
        }
-
-       /* udev is root hub */
-       if (!udev->parent)
-               return 1;
-
        if (udev->parent->lpm_capable)
                return 1;
 
@@ -1045,7 +1040,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                 */
                if (type == HUB_INIT) {
                        delay = hub_power_on(hub, false);
-                       PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
+                       INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
                        schedule_delayed_work(&hub->init_work,
                                        msecs_to_jiffies(delay));
 
@@ -1199,7 +1194,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 
                /* Don't do a long sleep inside a workqueue routine */
                if (type == HUB_INIT2) {
-                       PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
+                       INIT_DELAYED_WORK(&hub->init_work, hub_init_func3);
                        schedule_delayed_work(&hub->init_work,
                                        msecs_to_jiffies(delay));
                        return;         /* Continues at init3: below */
index 8f37063c0a49eeff7ba2d0902621aaa91800c058..739ee8e8bdfdaf7bc6be98d716255e4f561cc17a 100644 (file)
@@ -47,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Microsoft LifeCam-VX700 v2.0 */
        { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech HD Pro Webcams C920 and C930e */
+       { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
+
        /* Logitech Quickcam Fusion */
        { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
index c49383669cd87ce4dda9b996fd9b3f1caf03bd2b..823857767a16f3384730dcf1f90c42f8eedc3588 100644 (file)
@@ -35,7 +35,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
                unsigned int size);
 extern int usb_get_bos_descriptor(struct usb_device *dev);
 extern void usb_release_bos_descriptor(struct usb_device *dev);
-extern int usb_device_supports_lpm(struct usb_device *udev);
 extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 extern int usb_choose_configuration(struct usb_device *udev);
index 8565d87f94b4872e6f5fb7cb1d813f8e0b4493bc..1d129884cc39ad71e8fddc34b6dc9715ae679f47 100644 (file)
@@ -216,7 +216,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
        int retval = 0;
 
        if (!select_phy)
-               return -ENODEV;
+               return 0;
 
        usbcfg = readl(hsotg->regs + GUSBCFG);
 
index f59484d43b355b15b1297f3341c832a0a395ebb3..4d918ed8d343394bcc92cea19e4e025a9f7c7c5c 100644 (file)
@@ -2565,25 +2565,14 @@ static void _dwc2_hcd_endpoint_reset(struct usb_hcd *hcd,
                                     struct usb_host_endpoint *ep)
 {
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
-       int is_control = usb_endpoint_xfer_control(&ep->desc);
-       int is_out = usb_endpoint_dir_out(&ep->desc);
-       int epnum = usb_endpoint_num(&ep->desc);
-       struct usb_device *udev;
        unsigned long flags;
 
        dev_dbg(hsotg->dev,
                "DWC OTG HCD EP RESET: bEndpointAddress=0x%02x\n",
                ep->desc.bEndpointAddress);
 
-       udev = to_usb_device(hsotg->dev);
-
        spin_lock_irqsave(&hsotg->lock, flags);
-
-       usb_settoggle(udev, epnum, is_out, 0);
-       if (is_control)
-               usb_settoggle(udev, epnum, !is_out, 0);
        dwc2_hcd_endpoint_reset(hsotg, ep);
-
        spin_unlock_irqrestore(&hsotg->lock, flags);
 }
 
index d01d0d3f2cf0981b9e89654cac5697f747ef6d48..eaba547ce26b53699744adb4bcc77fa1627a7c05 100644 (file)
@@ -124,6 +124,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
        int retval;
        int irq;
 
+       if (usb_disabled())
+               return -ENODEV;
+
        match = of_match_device(dwc2_of_match_table, &dev->dev);
        if (match && match->data) {
                params = match->data;
index 888fbb43b338ecebcaf7cf8cb267fb2de35cc240..e969eb809a853dbb38093a0f5d3d39f57f931bb7 100644 (file)
@@ -360,24 +360,30 @@ static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
        bcm_writel(val, udc->iudma_regs + off);
 }
 
-static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off)
+static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan)
 {
-       return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off);
+       return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+                                       int chan)
 {
-       bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off);
+       bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off)
+static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan)
 {
-       return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off);
+       return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
-static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off)
+static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off,
+                                       int chan)
 {
-       bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off);
+       bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off +
+                       (ENETDMA_CHAN_WIDTH * chan));
 }
 
 static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled)
@@ -638,7 +644,7 @@ static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma,
        } while (!last_bd);
 
        usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK,
-                       ENETDMAC_CHANCFG_REG(iudma->ch_idx));
+                       ENETDMAC_CHANCFG_REG, iudma->ch_idx);
 }
 
 /**
@@ -694,9 +700,9 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
                bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num));
 
        /* stop DMA, then wait for the hardware to wrap up */
-       usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx));
+       usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx);
 
-       while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) &
+       while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) &
                                   ENETDMAC_CHANCFG_EN_MASK) {
                udelay(1);
 
@@ -713,10 +719,10 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
                        dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n",
                                 ch_idx);
                        usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK,
-                                       ENETDMAC_CHANCFG_REG(ch_idx));
+                                       ENETDMAC_CHANCFG_REG, ch_idx);
                }
        }
-       usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx));
+       usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx);
 
        /* don't leave "live" HW-owned entries for the next guy to step on */
        for (d = iudma->bd_ring; d <= iudma->end_bd; d++)
@@ -728,11 +734,11 @@ static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma)
 
        /* set up IRQs, UBUS burst size, and BD base for this channel */
        usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-                       ENETDMAC_IRMASK_REG(ch_idx));
-       usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx));
+                       ENETDMAC_IRMASK_REG, ch_idx);
+       usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx);
 
-       usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx));
-       usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx));
+       usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx);
+       usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx);
 }
 
 /**
@@ -2035,7 +2041,7 @@ static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id)
        spin_lock(&udc->lock);
 
        usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK,
-                       ENETDMAC_IR_REG(iudma->ch_idx));
+                       ENETDMAC_IR_REG, iudma->ch_idx);
        bep = iudma->bep;
        rc = iudma_read(udc, iudma);
 
@@ -2175,18 +2181,18 @@ static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p)
                seq_printf(s, " [ep%d]:\n",
                           max_t(int, iudma_defaults[ch_idx].ep_num, 0));
                seq_printf(s, "  cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n",
-                          usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)),
-                          usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)),
-                          usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)),
-                          usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx)));
+                          usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx),
+                          usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx));
 
-               sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx));
-               sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx));
+               sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx);
+               sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx);
                seq_printf(s, "  base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n",
-                          usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)),
+                          usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx),
                           sram2 >> 16, sram2 & 0xffff,
                           sram3 >> 16, sram3 & 0xffff,
-                          usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx)));
+                          usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx));
                seq_printf(s, "  desc: %d/%d used", iudma->n_bds_used,
                           iudma->n_bds);
 
index 306a2b52125c8e7ee2eba91bcf1156e689ae133e..2b43343940766251ee5f274b807b882273f09008 100644 (file)
@@ -585,7 +585,6 @@ static ssize_t ffs_epfile_io(struct file *file,
                             char __user *buf, size_t len, int read)
 {
        struct ffs_epfile *epfile = file->private_data;
-       struct usb_gadget *gadget = epfile->ffs->gadget;
        struct ffs_ep *ep;
        char *data = NULL;
        ssize_t ret, data_len;
@@ -621,6 +620,12 @@ static ssize_t ffs_epfile_io(struct file *file,
 
        /* Allocate & copy */
        if (!halt) {
+               /*
+                * if we _do_ wait above, the epfile->ffs->gadget might be NULL
+                * before the waiting completes, so do not assign to 'gadget' earlier
+                */
+               struct usb_gadget *gadget = epfile->ffs->gadget;
+
                /*
                 * Controller may require buffer size to be aligned to
                 * maxpacketsize of an out endpoint.
index bf7a56b6d48ac2c3ebb3acf8920c70d79900d307..69b76efd11e9bea3f11d9d2effe293c04045f01c 100644 (file)
@@ -1157,7 +1157,7 @@ static int __init printer_bind_config(struct usb_configuration *c)
 
        usb_gadget_set_selfpowered(gadget);
 
-       if (gadget->is_otg) {
+       if (gadget_is_otg(gadget)) {
                otg_descriptor.bmAttributes |= USB_OTG_HNP;
                printer_cfg_driver.descriptors = otg_desc;
                printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
index f04b2c3154dea73b0fa2c1d93322bdbf1c5930bc..dd9678f85c586a591b2a6514ba71034895d1769d 100644 (file)
@@ -1629,7 +1629,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
                ep->ep.desc = NULL;
                ep->halted = 0;
                INIT_LIST_HEAD(&ep->queue);
-               usb_ep_set_maxpacket_limit(&ep->ep, &ep->ep.maxpacket);
+               usb_ep_set_maxpacket_limit(&ep->ep, ep->ep.maxpacket);
        }
 }
 
index 471142725ffe1cd42f92b2ad0883fa925c715a2a..81cda09b47e3127772e51cbc5c57eab7761c4a52 100644 (file)
@@ -685,8 +685,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
        u32                     status, masked_status, pcd_status = 0, cmd;
        int                     bh;
+       unsigned long           flags;
 
-       spin_lock (&ehci->lock);
+       /*
+        * For threadirqs option we use spin_lock_irqsave() variant to prevent
+        * deadlock with ehci hrtimer callback, because hrtimer callbacks run
+        * in interrupt context even when threadirqs is specified. We can go
+        * back to spin_lock() variant when hrtimer callbacks become threaded.
+        */
+       spin_lock_irqsave(&ehci->lock, flags);
 
        status = ehci_readl(ehci, &ehci->regs->status);
 
@@ -704,7 +711,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 
        /* Shared IRQ? */
        if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
-               spin_unlock(&ehci->lock);
+               spin_unlock_irqrestore(&ehci->lock, flags);
                return IRQ_NONE;
        }
 
@@ -815,7 +822,7 @@ dead:
 
        if (bh)
                ehci_work (ehci);
-       spin_unlock (&ehci->lock);
+       spin_unlock_irqrestore(&ehci->lock, flags);
        if (pcd_status)
                usb_hcd_poll_rh_status(hcd);
        return IRQ_HANDLED;
index 47b858fc50b2ee484c035cef8fe8b27c669009b5..7ae0c4d517417d46dbc2dd8f51993728fa839c3a 100644 (file)
@@ -238,6 +238,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        int                     port;
        int                     mask;
        int                     changed;
+       bool                    fs_idle_delay;
 
        ehci_dbg(ehci, "suspend root hub\n");
 
@@ -272,6 +273,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        ehci->bus_suspended = 0;
        ehci->owned_ports = 0;
        changed = 0;
+       fs_idle_delay = false;
        port = HCS_N_PORTS(ehci->hcs_params);
        while (port--) {
                u32 __iomem     *reg = &ehci->regs->port_status [port];
@@ -300,16 +302,32 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
                }
 
                if (t1 != t2) {
+                       /*
+                        * On some controllers, Wake-On-Disconnect will
+                        * generate false wakeup signals until the bus
+                        * switches over to full-speed idle.  For their
+                        * sake, add a delay if we need one.
+                        */
+                       if ((t2 & PORT_WKDISC_E) &&
+                                       ehci_port_speed(ehci, t2) ==
+                                               USB_PORT_STAT_HIGH_SPEED)
+                               fs_idle_delay = true;
                        ehci_writel(ehci, t2, reg);
                        changed = 1;
                }
        }
+       spin_unlock_irq(&ehci->lock);
+
+       if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) {
+               /*
+                * Wait for HCD to enter low-power mode or for the bus
+                * to switch to full-speed idle.
+                */
+               usleep_range(5000, 5500);
+       }
 
        if (changed && ehci->has_tdi_phy_lpm) {
-               spin_unlock_irq(&ehci->lock);
-               msleep(5);      /* 5 ms for HCD to enter low-power mode */
                spin_lock_irq(&ehci->lock);
-
                port = HCS_N_PORTS(ehci->hcs_params);
                while (port--) {
                        u32 __iomem     *hostpc_reg = &ehci->regs->hostpc[port];
@@ -322,8 +340,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
                                        port, (t3 & HOSTPC_PHCD) ?
                                        "succeeded" : "failed");
                }
+               spin_unlock_irq(&ehci->lock);
        }
-       spin_unlock_irq(&ehci->lock);
 
        /* Apparently some devices need a >= 1-uframe delay here */
        if (ehci->bus_suspended)
index b016d38199f2373cab0c789aecbd850b211345ab..eb009a457fb537f6c6674d097e852de0501e98dc 100644 (file)
@@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num)
                                addr, (unsigned int)temp);
 
        addr = &ir_set->erst_base;
-       temp_64 = readq(addr);
+       temp_64 = xhci_read_64(xhci, addr);
        xhci_dbg(xhci, "  %p: ir_set.erst_base = @%08llx\n",
                        addr, temp_64);
 
        addr = &ir_set->erst_dequeue;
-       temp_64 = readq(addr);
+       temp_64 = xhci_read_64(xhci, addr);
        xhci_dbg(xhci, "  %p: ir_set.erst_dequeue = @%08llx\n",
                        addr, temp_64);
 }
@@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
 {
        u64 val;
 
-       val = readq(&xhci->op_regs->cmd_ring);
+       val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
                        lower_32_bits(val));
        xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
index 873c272b3ef572f927504d0aea83b560785e6332..bce4391a0e7d708873180ab40f3ef17737f148a1 100644 (file)
@@ -1958,7 +1958,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
                xhci_warn(xhci, "WARN something wrong with SW event ring "
                                "dequeue ptr.\n");
        /* Update HC event ring dequeue pointer */
-       temp = readq(&xhci->ir_set->erst_dequeue);
+       temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
        temp &= ERST_PTR_MASK;
        /* Don't clear the EHB bit (which is RW1C) because
         * there might be more events to service.
@@ -1967,7 +1967,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Write event ring dequeue pointer, "
                        "preserving EHB bit");
-       writeq(((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+       xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
                        &xhci->ir_set->erst_dequeue);
 }
 
@@ -2269,7 +2269,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Device context base array address = 0x%llx (DMA), %p (virt)",
                        (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
-       writeq(dma, &xhci->op_regs->dcbaa_ptr);
+       xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
 
        /*
         * Initialize the ring segment pool.  The ring must be a contiguous
@@ -2312,13 +2312,13 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
                        (unsigned long long)xhci->cmd_ring->first_seg->dma);
 
        /* Set the address in the Command Ring Control register */
-       val_64 = readq(&xhci->op_regs->cmd_ring);
+       val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
                (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
                xhci->cmd_ring->cycle_state;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Setting command ring address to 0x%x", val);
-       writeq(val_64, &xhci->op_regs->cmd_ring);
+       xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
        xhci_dbg_cmd_ptrs(xhci);
 
        xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags);
@@ -2396,10 +2396,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Set ERST base address for ir_set 0 = 0x%llx",
                        (unsigned long long)xhci->erst.erst_dma_addr);
-       val_64 = readq(&xhci->ir_set->erst_base);
+       val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
        val_64 &= ERST_PTR_MASK;
        val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
-       writeq(val_64, &xhci->ir_set->erst_base);
+       xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
 
        /* Set the event ring dequeue address */
        xhci_set_hc_event_deq(xhci);
index 3c898c12a06b51c8926d85a3d3c5dda5d549a57f..04f986d9234f6de450888fb5178d14e3ea30dda0 100644 (file)
@@ -142,6 +142,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                                "QUIRK: Resetting on resume");
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
+                       pdev->device == 0x0015 &&
+                       pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
+                       pdev->subsystem_device == 0xc0cd)
+               xhci->quirks |= XHCI_RESET_ON_RESUME;
        if (pdev->vendor == PCI_VENDOR_ID_VIA)
                xhci->quirks |= XHCI_RESET_ON_RESUME;
 }
index a0b248c345266e470441bba48247aea00b22fc13..0ed64eb68e48e226c0176c6e8c9c3f5247111c73 100644 (file)
@@ -307,13 +307,14 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
                return 0;
        }
 
-       temp_64 = readq(&xhci->op_regs->cmd_ring);
+       temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        if (!(temp_64 & CMD_RING_RUNNING)) {
                xhci_dbg(xhci, "Command ring had been stopped\n");
                return 0;
        }
        xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
-       writeq(temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
+       xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
+                       &xhci->op_regs->cmd_ring);
 
        /* Section 4.6.1.2 of xHCI 1.0 spec says software should
         * time the completion od all xHCI commands, including
@@ -2864,8 +2865,9 @@ hw_died:
                /* Clear the event handler busy flag (RW1C);
                 * the event ring should be empty.
                 */
-               temp_64 = readq(&xhci->ir_set->erst_dequeue);
-               writeq(temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
+               temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+               xhci_write_64(xhci, temp_64 | ERST_EHB,
+                               &xhci->ir_set->erst_dequeue);
                spin_unlock(&xhci->lock);
 
                return IRQ_HANDLED;
@@ -2877,7 +2879,7 @@ hw_died:
         */
        while (xhci_handle_event(xhci) > 0) {}
 
-       temp_64 = readq(&xhci->ir_set->erst_dequeue);
+       temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
        /* If necessary, update the HW's version of the event ring deq ptr. */
        if (event_ring_deq != xhci->event_ring->dequeue) {
                deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
@@ -2892,7 +2894,7 @@ hw_died:
 
        /* Clear the event handler busy flag (RW1C); event ring is empty. */
        temp_64 |= ERST_EHB;
-       writeq(temp_64, &xhci->ir_set->erst_dequeue);
+       xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
 
        spin_unlock(&xhci->lock);
 
@@ -2965,58 +2967,8 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
        }
 
        while (1) {
-               if (room_on_ring(xhci, ep_ring, num_trbs)) {
-                       union xhci_trb *trb = ep_ring->enqueue;
-                       unsigned int usable = ep_ring->enq_seg->trbs +
-                                       TRBS_PER_SEGMENT - 1 - trb;
-                       u32 nop_cmd;
-
-                       /*
-                        * Section 4.11.7.1 TD Fragments states that a link
-                        * TRB must only occur at the boundary between
-                        * data bursts (eg 512 bytes for 480M).
-                        * While it is possible to split a large fragment
-                        * we don't know the size yet.
-                        * Simplest solution is to fill the trb before the
-                        * LINK with nop commands.
-                        */
-                       if (num_trbs == 1 || num_trbs <= usable || usable == 0)
-                               break;
-
-                       if (ep_ring->type != TYPE_BULK)
-                               /*
-                                * While isoc transfers might have a buffer that
-                                * crosses a 64k boundary it is unlikely.
-                                * Since we can't add NOPs without generating
-                                * gaps in the traffic just hope it never
-                                * happens at the end of the ring.
-                                * This could be fixed by writing a LINK TRB
-                                * instead of the first NOP - however the
-                                * TRB_TYPE_LINK_LE32() calls would all need
-                                * changing to check the ring length.
-                                */
-                               break;
-
-                       if (num_trbs >= TRBS_PER_SEGMENT) {
-                               xhci_err(xhci, "Too many fragments %d, max %d\n",
-                                               num_trbs, TRBS_PER_SEGMENT - 1);
-                               return -EINVAL;
-                       }
-
-                       nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) |
-                                       ep_ring->cycle_state);
-                       ep_ring->num_trbs_free -= usable;
-                       do {
-                               trb->generic.field[0] = 0;
-                               trb->generic.field[1] = 0;
-                               trb->generic.field[2] = 0;
-                               trb->generic.field[3] = nop_cmd;
-                               trb++;
-                       } while (--usable);
-                       ep_ring->enqueue = trb;
-                       if (room_on_ring(xhci, ep_ring, num_trbs))
-                               break;
-               }
+               if (room_on_ring(xhci, ep_ring, num_trbs))
+                       break;
 
                if (ep_ring == xhci->cmd_ring) {
                        xhci_err(xhci, "Do not support expand command ring\n");
index ad364394885a221f8e52b212464ba27573433290..924a6ccdb622777a6fc71b21dfb6a0ee0792f536 100644 (file)
@@ -611,7 +611,7 @@ int xhci_run(struct usb_hcd *hcd)
        xhci_dbg(xhci, "Event ring:\n");
        xhci_debug_ring(xhci, xhci->event_ring);
        xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
-       temp_64 = readq(&xhci->ir_set->erst_dequeue);
+       temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
        temp_64 &= ~ERST_PTR_MASK;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "ERST deq = 64'h%0lx", (long unsigned int) temp_64);
@@ -756,11 +756,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)
 {
        xhci->s3.command = readl(&xhci->op_regs->command);
        xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification);
-       xhci->s3.dcbaa_ptr = readq(&xhci->op_regs->dcbaa_ptr);
+       xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
        xhci->s3.config_reg = readl(&xhci->op_regs->config_reg);
        xhci->s3.erst_size = readl(&xhci->ir_set->erst_size);
-       xhci->s3.erst_base = readq(&xhci->ir_set->erst_base);
-       xhci->s3.erst_dequeue = readq(&xhci->ir_set->erst_dequeue);
+       xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
+       xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
        xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending);
        xhci->s3.irq_control = readl(&xhci->ir_set->irq_control);
 }
@@ -769,11 +769,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
 {
        writel(xhci->s3.command, &xhci->op_regs->command);
        writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
-       writeq(xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
+       xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
        writel(xhci->s3.config_reg, &xhci->op_regs->config_reg);
        writel(xhci->s3.erst_size, &xhci->ir_set->erst_size);
-       writeq(xhci->s3.erst_base, &xhci->ir_set->erst_base);
-       writeq(xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
+       xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+       xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
        writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
        writel(xhci->s3.irq_control, &xhci->ir_set->irq_control);
 }
@@ -783,7 +783,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
        u64     val_64;
 
        /* step 2: initialize command ring buffer */
-       val_64 = readq(&xhci->op_regs->cmd_ring);
+       val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
                (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
                                      xhci->cmd_ring->dequeue) &
@@ -792,7 +792,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "// Setting command ring address to 0x%llx",
                        (long unsigned long) val_64);
-       writeq(val_64, &xhci->op_regs->cmd_ring);
+       xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
 }
 
 /*
@@ -3842,7 +3842,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
        if (ret) {
                return ret;
        }
-       temp_64 = readq(&xhci->op_regs->dcbaa_ptr);
+       temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
        xhci_dbg_trace(xhci, trace_xhci_dbg_address,
                        "Op regs DCBAA ptr = %#016llx", temp_64);
        xhci_dbg_trace(xhci, trace_xhci_dbg_address,
@@ -4730,8 +4730,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        struct device           *dev = hcd->self.controller;
        int                     retval;
 
-       /* Limit the block layer scatter-gather lists to half a segment. */
-       hcd->self.sg_tablesize = TRBS_PER_SEGMENT / 2;
+       /* Accept arbitrarily long scatter-gather lists */
+       hcd->self.sg_tablesize = ~0;
 
        /* support to build packet from discontinuous buffers */
        hcd->self.no_sg_constraint = 1;
index f8416639bf31cf420de82e9f82e35f67ea7c977b..58ed9d088e635c4e7d7ebeaa027da6f126f848eb 100644 (file)
 #include <linux/kernel.h>
 #include <linux/usb/hcd.h>
 
-/*
- * Registers should always be accessed with double word or quad word accesses.
- *
- * Some xHCI implementations may support 64-bit address pointers.  Registers
- * with 64-bit address pointers should be written to with dword accesses by
- * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
- * xHCI implementations that do not support 64-bit address pointers will ignore
- * the high dword, and write order is irrelevant.
- */
-#include <asm-generic/io-64-nonatomic-lo-hi.h>
-
 /* Code sharing between pci-quirks and xhci hcd */
 #include       "xhci-ext-caps.h"
 #include "pci-quirks.h"
@@ -1279,7 +1268,7 @@ union xhci_trb {
  * since the command ring is 64-byte aligned.
  * It must also be greater than 16.
  */
-#define TRBS_PER_SEGMENT       256
+#define TRBS_PER_SEGMENT       64
 /* Allow two commands + a link TRB, along with any reserved command TRBs */
 #define MAX_RSVD_CMD_TRBS      (TRBS_PER_SEGMENT - 3)
 #define TRB_SEGMENT_SIZE       (TRBS_PER_SEGMENT*16)
@@ -1614,6 +1603,34 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
 #define xhci_warn_ratelimited(xhci, fmt, args...) \
        dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
 
+/*
+ * Registers should always be accessed with double word or quad word accesses.
+ *
+ * Some xHCI implementations may support 64-bit address pointers.  Registers
+ * with 64-bit address pointers should be written to with dword accesses by
+ * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
+ * xHCI implementations that do not support 64-bit address pointers will ignore
+ * the high dword, and write order is irrelevant.
+ */
+static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
+               __le64 __iomem *regs)
+{
+       __u32 __iomem *ptr = (__u32 __iomem *) regs;
+       u64 val_lo = readl(ptr);
+       u64 val_hi = readl(ptr + 1);
+       return val_lo + (val_hi << 32);
+}
+static inline void xhci_write_64(struct xhci_hcd *xhci,
+                                const u64 val, __le64 __iomem *regs)
+{
+       __u32 __iomem *ptr = (__u32 __iomem *) regs;
+       u32 val_lo = lower_32_bits(val);
+       u32 val_hi = upper_32_bits(val);
+
+       writel(val_lo, ptr);
+       writel(val_hi, ptr + 1);
+}
+
 static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
 {
        return xhci->quirks & XHCI_LINK_TRB_QUIRK;
index fc192ad9cc6a60eb4a7f00d124eb0a0d1bca73fe..239ad0b1ceb6d15ddff5fa3741ca97796e70e067 100644 (file)
@@ -477,8 +477,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                musb->port1_status |=
                                                (USB_PORT_STAT_C_SUSPEND << 16)
                                                | MUSB_PORT_STAT_RESUME;
+                               musb->rh_timer = jiffies
+                                                + msecs_to_jiffies(20);
                                schedule_delayed_work(
-                                       &musb->finish_resume_work, 20);
+                                       &musb->finish_resume_work,
+                                       msecs_to_jiffies(20));
 
                                musb->xceiv->state = OTG_STATE_A_HOST;
                                musb->is_active = 1;
@@ -2157,11 +2160,19 @@ static void musb_restore_context(struct musb *musb)
        void __iomem *musb_base = musb->mregs;
        void __iomem *ep_target_regs;
        void __iomem *epio;
+       u8 power;
 
        musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
        musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
        musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
-       musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+
+       /* Don't affect SUSPENDM/RESUME bits in POWER reg */
+       power = musb_readb(musb_base, MUSB_POWER);
+       power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME;
+       musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME);
+       power |= musb->context.power;
+       musb_writeb(musb_base, MUSB_POWER, power);
+
        musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
        musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
        musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
index ed455724017b5767f6ad849961946d7ad7af3228..abb38c3833ef46a1f8041c8a5f95fa96138b1796 100644 (file)
@@ -1183,6 +1183,9 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
                                csr = MUSB_CSR0_H_STATUSPKT
                                        | MUSB_CSR0_TXPKTRDY;
 
+                       /* disable ping token in status phase */
+                       csr |= MUSB_CSR0_H_DIS_PING;
+
                        /* flag status stage */
                        musb->ep0_stage = MUSB_EP0_STATUS;
 
index eb634433ef095b631cd7e70df77453334cf48ddc..e2d2d8c9891bc1f7a4cf5f8a16048d58a3d4c630 100644 (file)
@@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
 
                /* later, GetPortStatus will stop RESUME signaling */
                musb->port1_status |= MUSB_PORT_STAT_RESUME;
-               schedule_delayed_work(&musb->finish_resume_work, 20);
+               schedule_delayed_work(&musb->finish_resume_work,
+                                     msecs_to_jiffies(20));
        }
 }
 
@@ -158,7 +159,6 @@ void musb_port_reset(struct musb *musb, bool do_reset)
         */
        power = musb_readb(mbase, MUSB_POWER);
        if (do_reset) {
-
                /*
                 * If RESUME is set, we must make sure it stays minimum 20 ms.
                 * Then we must clear RESUME and wait a bit to let musb start
@@ -167,11 +167,22 @@ void musb_port_reset(struct musb *musb, bool do_reset)
                 * detected".
                 */
                if (power &  MUSB_POWER_RESUME) {
-                       while (time_before(jiffies, musb->rh_timer))
-                               msleep(1);
+                       long remain = (unsigned long) musb->rh_timer - jiffies;
+
+                       if (musb->rh_timer > 0 && remain > 0) {
+                               /* take into account the minimum delay after resume */
+                               schedule_delayed_work(
+                                       &musb->deassert_reset_work, remain);
+                               return;
+                       }
+
                        musb_writeb(mbase, MUSB_POWER,
-                               power & ~MUSB_POWER_RESUME);
-                       msleep(1);
+                                   power & ~MUSB_POWER_RESUME);
+
+                       /* Give the core 1 ms to clear MUSB_POWER_RESUME */
+                       schedule_delayed_work(&musb->deassert_reset_work,
+                                             msecs_to_jiffies(1));
+                       return;
                }
 
                power &= 0xf0;
@@ -180,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset)
 
                musb->port1_status |= USB_PORT_STAT_RESET;
                musb->port1_status &= ~USB_PORT_STAT_ENABLE;
-               schedule_delayed_work(&musb->deassert_reset_work, 50);
+               schedule_delayed_work(&musb->deassert_reset_work,
+                                     msecs_to_jiffies(50));
        } else {
                dev_dbg(musb->controller, "root port reset stopped\n");
                musb_writeb(mbase, MUSB_POWER,
index 2a408cdaf7b2c7102098faac6d29727505f41c91..8aa59a2c5eb2485c823244012cc738ce5df7d127 100644 (file)
@@ -659,7 +659,6 @@ static int omap2430_runtime_suspend(struct device *dev)
                                OTG_INTERFSEL);
 
                omap2430_low_level_exit(musb);
-               phy_power_off(musb->phy);
        }
 
        return 0;
@@ -674,7 +673,6 @@ static int omap2430_runtime_resume(struct device *dev)
                omap2430_low_level_init(musb);
                musb_writel(musb->mregs, OTG_INTERFSEL,
                                musb->context.otg_interfsel);
-               phy_power_on(musb->phy);
        }
 
        return 0;
index 8546c8dccd51b003fc9aba3038184cd2d0eedbea..d204f745ed05e652ef168940dece89e2e16a8269 100644 (file)
@@ -159,32 +159,6 @@ put_3p3:
        return rc;
 }
 
-#ifdef CONFIG_PM_SLEEP
-#define USB_PHY_SUSP_DIG_VOL  500000
-static int msm_hsusb_config_vddcx(int high)
-{
-       int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
-       int min_vol;
-       int ret;
-
-       if (high)
-               min_vol = USB_PHY_VDD_DIG_VOL_MIN;
-       else
-               min_vol = USB_PHY_SUSP_DIG_VOL;
-
-       ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
-       if (ret) {
-               pr_err("%s: unable to set the voltage for regulator "
-                       "HSUSB_VDDCX\n", __func__);
-               return ret;
-       }
-
-       pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
-
-       return ret;
-}
-#endif
-
 static int msm_hsusb_ldo_set_mode(int on)
 {
        int ret = 0;
@@ -440,7 +414,32 @@ static int msm_otg_reset(struct usb_phy *phy)
 #define PHY_SUSPEND_TIMEOUT_USEC       (500 * 1000)
 #define PHY_RESUME_TIMEOUT_USEC        (100 * 1000)
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
+
+#define USB_PHY_SUSP_DIG_VOL  500000
+static int msm_hsusb_config_vddcx(int high)
+{
+       int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
+       int min_vol;
+       int ret;
+
+       if (high)
+               min_vol = USB_PHY_VDD_DIG_VOL_MIN;
+       else
+               min_vol = USB_PHY_SUSP_DIG_VOL;
+
+       ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
+       if (ret) {
+               pr_err("%s: unable to set the voltage for regulator "
+                       "HSUSB_VDDCX\n", __func__);
+               return ret;
+       }
+
+       pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
+
+       return ret;
+}
+
 static int msm_otg_suspend(struct msm_otg *motg)
 {
        struct usb_phy *phy = &motg->phy;
@@ -1733,22 +1732,18 @@ static int msm_otg_pm_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
 static const struct dev_pm_ops msm_otg_dev_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
        SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
                                msm_otg_runtime_idle)
 };
-#endif
 
 static struct platform_driver msm_otg_driver = {
        .remove = msm_otg_remove,
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm = &msm_otg_dev_pm_ops,
-#endif
        },
 };
 
index e6f61e4361df6bcd7f4f63b3124961c5b2be0bc0..8afa813d690bc6f7aa15c9b9c7523cf96b24099a 100644 (file)
@@ -130,7 +130,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
 
        phy = __usb_find_phy(&phy_list, type);
        if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
-               pr_err("unable to find transceiver of type %s\n",
+               pr_debug("PHY: unable to find transceiver of type %s\n",
                        usb_phy_type_string(type));
                goto err0;
        }
@@ -228,7 +228,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
 
        phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
        if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
-               pr_err("unable to find transceiver\n");
+               dev_dbg(dev, "unable to find transceiver\n");
                goto err0;
        }
 
@@ -424,10 +424,8 @@ int usb_bind_phy(const char *dev_name, u8 index,
        unsigned long flags;
 
        phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL);
-       if (!phy_bind) {
-               pr_err("phy_bind(): No memory for phy_bind");
+       if (!phy_bind)
                return -ENOMEM;
-       }
 
        phy_bind->dev_name = dev_name;
        phy_bind->phy_dev_name = phy_dev_name;
index ce0d7b0db012ad9a31b8ea0ad71fd80881f6f8b4..44ab1298680557f840d243056d7fc4812d7adc0d 100644 (file)
@@ -152,6 +152,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
@@ -191,6 +192,8 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
+       { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
@@ -904,6 +907,8 @@ static const struct usb_device_id id_table_combined[] = {
        /* Crucible Devices */
        { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
+       /* Cressi Devices */
+       { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) },
        { }                                     /* Terminating entry */
 };
 
index a7019d1e305814867bb43792ebe55eb00dd7c3fd..e599fbfcde5f8fd5055f29f464fdaea13c130cb5 100644 (file)
@@ -50,6 +50,7 @@
 #define TI_XDS100V2_PID                0xa6d0
 
 #define FTDI_NXTCAM_PID                0xABB8 /* NXTCam for Mindstorms NXT */
+#define FTDI_EV3CON_PID                0xABB9 /* Mindstorms EV3 Console Adapter */
 
 /* US Interface Navigator (http://www.usinterface.com/) */
 #define FTDI_USINT_CAT_PID     0xb810  /* Navigator CAT and 2nd PTT lines */
 /* Sprog II (Andrew Crosland's SprogII DCC interface) */
 #define FTDI_SPROG_II          0xF0C8
 
+/*
+ * Two of the Tagsys RFID Readers
+ */
+#define FTDI_TAGSYS_LP101_PID  0xF0E9  /* Tagsys L-P101 RFID*/
+#define FTDI_TAGSYS_P200X_PID  0xF0EE  /* Tagsys Medio P200x RFID*/
+
 /* an infrared receiver for user access control with IR tags */
 #define FTDI_PIEGROUP_PID      0xF208  /* Product Id */
 
  * Manufacturer: Smart GSM Team
  */
 #define FTDI_Z3X_PID           0x0011
+
+/*
+ * Product: Cressi PC Interface
+ * Manufacturer: Cressi
+ */
+#define FTDI_CRESSI_PID                0x87d0
index 5c86f57e4afad448033baced5dbf4ca29da5a372..68fc9fe65936e712ba08e9f6825de4773b4cc9a9 100644 (file)
@@ -1362,7 +1362,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1267, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1268, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1269, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1271, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) },
@@ -1525,7 +1526,8 @@ static const struct usb_device_id option_ids[] = {
        /* Cinterion */
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
-       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
index c65437cfd4a276a71ffe1e3bede20306c18fe75f..968a40201e5f6e2f2fed8de8e1668977e3f47db4 100644 (file)
@@ -139,6 +139,9 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 0)},       /* Sierra Wireless EM7700 Device Management */
        {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 2)},       /* Sierra Wireless EM7700 NMEA */
        {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 3)},       /* Sierra Wireless EM7700 Modem */
+       {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 0)},       /* Netgear AirCard 340U Device Management */
+       {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 2)},       /* Netgear AirCard 340U NMEA */
+       {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 3)},       /* Netgear AirCard 340U Modem */
 
        { }                             /* Terminating entry */
 };
index f112b079ddfc66895cf47858cfb93ff0e5a5265a..fb79775447b023aa849286856fd85fc0c19ac84e 100644 (file)
@@ -71,7 +71,8 @@ DEVICE(hp4x, HP4X_IDS);
 
 /* Suunto ANT+ USB Driver */
 #define SUUNTO_IDS()                   \
-       { USB_DEVICE(0x0fcf, 0x1008) }
+       { USB_DEVICE(0x0fcf, 0x1008) }, \
+       { USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */
 DEVICE(suunto, SUUNTO_IDS);
 
 /* Siemens USB/MPI adapter */
index 8470e1b114f2bff5538d9f4134e4f6222ab47500..1dd0604d1911d683015bedfe28ab86cdd42e8db4 100644 (file)
@@ -18,7 +18,9 @@ config USB_STORAGE
 
          This option depends on 'SCSI' support being enabled, but you
          probably also need 'SCSI device support: SCSI disk support'
-         (BLK_DEV_SD) for most USB storage devices.
+         (BLK_DEV_SD) for most USB storage devices.  Some devices also
+         will require 'Probe all LUNs on each SCSI device'
+         (SCSI_MULTI_LUN).
 
          To compile this driver as a module, choose M here: the
          module will be called usb-storage.
index 18509e6c21ab84e7d3133f7a0e428ba462d2a24b..9d38ddc8da492178afc8c2bebdbb8cb62cadc85f 100644 (file)
@@ -78,6 +78,8 @@ static const char* host_info(struct Scsi_Host *host)
 
 static int slave_alloc (struct scsi_device *sdev)
 {
+       struct us_data *us = host_to_us(sdev->host);
+
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
         * the extra data and many devices choke if asked for more or
@@ -102,6 +104,10 @@ static int slave_alloc (struct scsi_device *sdev)
         */
        blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
 
+       /* Tell the SCSI layer if we know there is more than one LUN */
+       if (us->protocol == USB_PR_BULK && us->max_lun > 0)
+               sdev->sdev_bflags |= BLIST_FORCELUN;
+
        return 0;
 }
 
index 65a6a75066a81772584d884477dab435434ed19d..82e8ed0324e3c5fe75ed7548d66c2b19f509f200 100644 (file)
@@ -31,7 +31,7 @@ UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
                "Cypress ISD-300LP",
                USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
 
-UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219,
+UNUSUAL_DEV( 0x14cd, 0x6116, 0x0160, 0x0160,
                "Super Top",
                "USB 2.0  SATA BRIDGE",
                USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
index ad06255c2adeb52a185cfcd523973e8f9ecc7f9c..adbeb255616afd32d8dc9dcaa244bdafd6ed46c2 100644 (file)
@@ -1455,6 +1455,13 @@ UNUSUAL_DEV( 0x0f88, 0x042e, 0x0100, 0x0100,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/* Reported by Moritz Moeller-Herrmann <moritz-kernel@moeller-herrmann.de> */
+UNUSUAL_DEV(  0x0fca, 0x8004, 0x0201, 0x0201,
+               "Research In Motion",
+               "BlackBerry Bold 9000",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 ),
+
 /* Reported by Michael Stattmann <michael@stattmann.com> */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
                "Sony Ericsson",
index 4fb7a8f83c8a99ff8d3412a5328b2407c98409a8..54af4e93369583e5629a4bac6d1ecdbd74f885cf 100644 (file)
@@ -186,12 +186,12 @@ static bool is_invalid_reserved_pfn(unsigned long pfn)
        if (pfn_valid(pfn)) {
                bool reserved;
                struct page *tail = pfn_to_page(pfn);
-               struct page *head = compound_trans_head(tail);
+               struct page *head = compound_head(tail);
                reserved = !!(PageReserved(head));
                if (head != tail) {
                        /*
                         * "head" is not a dangling pointer
-                        * (compound_trans_head takes care of that)
+                        * (compound_head takes care of that)
                         * but the hugepage may have been split
                         * from under us (and we may not hold a
                         * reference count on the head page so it can
index 9a68409580d5b76d8d3972e42a33314dc22f16f8..e1e22e0f01e881fe2961dbf1c43cb56f4e22cade 100644 (file)
@@ -70,7 +70,12 @@ enum {
 };
 
 struct vhost_net_ubuf_ref {
-       struct kref kref;
+       /* refcount follows semantics similar to kref:
+        *  0: object is released
+        *  1: no outstanding ubufs
+        * >1: outstanding ubufs
+        */
+       atomic_t refcount;
        wait_queue_head_t wait;
        struct vhost_virtqueue *vq;
 };
@@ -116,14 +121,6 @@ static void vhost_net_enable_zcopy(int vq)
        vhost_net_zcopy_mask |= 0x1 << vq;
 }
 
-static void vhost_net_zerocopy_done_signal(struct kref *kref)
-{
-       struct vhost_net_ubuf_ref *ubufs;
-
-       ubufs = container_of(kref, struct vhost_net_ubuf_ref, kref);
-       wake_up(&ubufs->wait);
-}
-
 static struct vhost_net_ubuf_ref *
 vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy)
 {
@@ -134,21 +131,24 @@ vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy)
        ubufs = kmalloc(sizeof(*ubufs), GFP_KERNEL);
        if (!ubufs)
                return ERR_PTR(-ENOMEM);
-       kref_init(&ubufs->kref);
+       atomic_set(&ubufs->refcount, 1);
        init_waitqueue_head(&ubufs->wait);
        ubufs->vq = vq;
        return ubufs;
 }
 
-static void vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
+static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
 {
-       kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
+       int r = atomic_sub_return(1, &ubufs->refcount);
+       if (unlikely(!r))
+               wake_up(&ubufs->wait);
+       return r;
 }
 
 static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
 {
-       kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
-       wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
+       vhost_net_ubuf_put(ubufs);
+       wait_event(ubufs->wait, !atomic_read(&ubufs->refcount));
 }
 
 static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs)
@@ -306,23 +306,26 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
 {
        struct vhost_net_ubuf_ref *ubufs = ubuf->ctx;
        struct vhost_virtqueue *vq = ubufs->vq;
-       int cnt = atomic_read(&ubufs->kref.refcount);
+       int cnt;
+
+       rcu_read_lock_bh();
 
        /* set len to mark this desc buffers done DMA */
        vq->heads[ubuf->desc].len = success ?
                VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
-       vhost_net_ubuf_put(ubufs);
+       cnt = vhost_net_ubuf_put(ubufs);
 
        /*
         * Trigger polling thread if guest stopped submitting new buffers:
-        * in this case, the refcount after decrement will eventually reach 1
-        * so here it is 2.
+        * in this case, the refcount after decrement will eventually reach 1.
         * We also trigger polling periodically after each 16 packets
         * (the value 16 here is more or less arbitrary, it's tuned to trigger
         * less than 10% of times).
         */
-       if (cnt <= 2 || !(cnt % 16))
+       if (cnt <= 1 || !(cnt % 16))
                vhost_poll_queue(&vq->poll);
+
+       rcu_read_unlock_bh();
 }
 
 /* Expects to be always run from workqueue - which acts as
@@ -420,7 +423,7 @@ static void handle_tx(struct vhost_net *net)
                        msg.msg_control = ubuf;
                        msg.msg_controllen = sizeof(ubuf);
                        ubufs = nvq->ubufs;
-                       kref_get(&ubufs->kref);
+                       atomic_inc(&ubufs->refcount);
                        nvq->upend_idx = (nvq->upend_idx + 1) % UIO_MAXIOV;
                } else {
                        msg.msg_control = NULL;
@@ -502,9 +505,13 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
                        r = -ENOBUFS;
                        goto err;
                }
-               d = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
+               r = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
                                      ARRAY_SIZE(vq->iov) - seg, &out,
                                      &in, log, log_num);
+               if (unlikely(r < 0))
+                       goto err;
+
+               d = r;
                if (d == vq->num) {
                        r = 0;
                        goto err;
@@ -529,6 +536,12 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
        *iovcount = seg;
        if (unlikely(log))
                *log_num = nlogs;
+
+       /* Detect overrun */
+       if (unlikely(datalen > 0)) {
+               r = UIO_MAXIOV + 1;
+               goto err;
+       }
        return headcount;
 err:
        vhost_discard_vq_desc(vq, headcount);
@@ -584,6 +597,14 @@ static void handle_rx(struct vhost_net *net)
                /* On error, stop handling until the next kick. */
                if (unlikely(headcount < 0))
                        break;
+               /* On overrun, truncate and discard */
+               if (unlikely(headcount > UIO_MAXIOV)) {
+                       msg.msg_iovlen = 1;
+                       err = sock->ops->recvmsg(NULL, sock, &msg,
+                                                1, MSG_DONTWAIT | MSG_TRUNC);
+                       pr_debug("Discarded rx packet: len %zd\n", sock_len);
+                       continue;
+               }
                /* OK, now we need to know about added descriptors. */
                if (!headcount) {
                        if (unlikely(vhost_enable_notify(&net->dev, vq))) {
@@ -780,7 +801,7 @@ static void vhost_net_flush(struct vhost_net *n)
                vhost_net_ubuf_put_and_wait(n->vqs[VHOST_NET_VQ_TX].ubufs);
                mutex_lock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex);
                n->tx_flush = false;
-               kref_init(&n->vqs[VHOST_NET_VQ_TX].ubufs->kref);
+               atomic_set(&n->vqs[VHOST_NET_VQ_TX].ubufs->refcount, 1);
                mutex_unlock(&n->vqs[VHOST_NET_VQ_TX].vq.mutex);
        }
 }
@@ -800,6 +821,8 @@ static int vhost_net_release(struct inode *inode, struct file *f)
                fput(tx_sock->file);
        if (rx_sock)
                fput(rx_sock->file);
+       /* Make sure no callbacks are outstanding */
+       synchronize_rcu_bh();
        /* We do an extra flush before freeing memory,
         * since jobs can re-queue themselves. */
        vhost_net_flush(n);
index 0a025b8e2a12efd2f58434b8084a45ad2454b604..e48d4a672580cd5eefaf741946435073a4e58e8c 100644 (file)
@@ -1001,6 +1001,12 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
                        break;
                }
 
+               /* virtio-scsi spec requires byte 0 of the lun to be 1 */
+               if (unlikely(v_req.lun[0] != 1)) {
+                       vhost_scsi_send_bad_target(vs, vq, head, out);
+                       continue;
+               }
+
                /* Extract the tpgt */
                target = v_req.lun[1];
                tpg = ACCESS_ONCE(vs_tpg[target]);
index 22262a3a0e2df673e342fbe800526dab5983bd3a..dade5b7699bc240e81225e8d489136af9e0d71e0 100644 (file)
@@ -364,7 +364,7 @@ config FB_SA1100
 
 config FB_IMX
        tristate "Freescale i.MX1/21/25/27 LCD support"
-       depends on FB && IMX_HAVE_PLATFORM_IMX_FB
+       depends on FB && ARCH_MXC
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 1129d0e9e6403dbb6c68a0478fda17bc2117b7b9..75c8a8e7efc03ad42f2a2f44e60b61d273d62c18 100644 (file)
@@ -22,7 +22,8 @@ config EXYNOS_MIPI_DSI
 
 config EXYNOS_LCD_S6E8AX0
        bool "S6E8AX0 MIPI AMOLED LCD Driver"
-       depends on (EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE)
+       depends on EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE
+       depends on (LCD_CLASS_DEVICE = y)
        default n
        help
          If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
index bbeb8dd7f108fe9f65111337b7d1a30a039c3e2c..77d6221618f4eba677190c9a5c7acf7546b3f55d 100644 (file)
@@ -2160,8 +2160,8 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
        *five_taps = false;
 
        do {
-               in_height = DIV_ROUND_UP(height, *decim_y);
-               in_width = DIV_ROUND_UP(width, *decim_x);
+               in_height = height / *decim_y;
+               in_width = width / *decim_x;
                *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
                                in_height, out_width, out_height, mem_to_mem);
                error = (in_width > maxsinglelinewidth || !*core_clk ||
@@ -2199,8 +2199,8 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
                        dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
 
        do {
-               in_height = DIV_ROUND_UP(height, *decim_y);
-               in_width = DIV_ROUND_UP(width, *decim_x);
+               in_height = height / *decim_y;
+               in_width = width / *decim_x;
                *five_taps = in_height > out_height;
 
                if (in_width > maxsinglelinewidth)
@@ -2268,7 +2268,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
 {
        u16 in_width, in_width_max;
        int decim_x_min = *decim_x;
-       u16 in_height = DIV_ROUND_UP(height, *decim_y);
+       u16 in_height = height / *decim_y;
        const int maxsinglelinewidth =
                                dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
        const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
@@ -2287,7 +2287,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
                return -EINVAL;
 
        do {
-               in_width = DIV_ROUND_UP(width, *decim_x);
+               in_width = width / *decim_x;
        } while (*decim_x <= *x_predecim &&
                        in_width > maxsinglelinewidth && ++*decim_x);
 
@@ -2466,8 +2466,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
        if (r)
                return r;
 
-       in_width = DIV_ROUND_UP(in_width, x_predecim);
-       in_height = DIV_ROUND_UP(in_height, y_predecim);
+       in_width = in_width / x_predecim;
+       in_height = in_height / y_predecim;
 
        if (color_mode == OMAP_DSS_COLOR_YUV2 ||
                        color_mode == OMAP_DSS_COLOR_UYVY ||
index 7411f2674e1682d702c5e3b2af38ffcb8794b24c..23ef21ffc2c4998eee877e956f95c4b6d3166082 100644 (file)
@@ -117,7 +117,7 @@ struct dpi_clk_calc_ctx {
        /* outputs */
 
        struct dsi_clock_info dsi_cinfo;
-       unsigned long long fck;
+       unsigned long fck;
        struct dispc_clock_info dispc_cinfo;
 };
 
index efb9ee9e3c9696996a9be5d752c623ef9c2d7ff4..ba806c9e7f5486ffa40c1e6ba6e38e4dcc993ed7 100644 (file)
@@ -46,7 +46,7 @@ static struct {
 struct sdi_clk_calc_ctx {
        unsigned long pck_min, pck_max;
 
-       unsigned long long fck;
+       unsigned long fck;
        struct dispc_clock_info dispc_cinfo;
 };
 
index a06edbfa95ca6b894ce1ee01ad6ab10241937e5b..1b5d48c578e19208fbb2ef06f9e4788f93a0f5f5 100644 (file)
@@ -884,7 +884,7 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image,
                if (done == count)
                        goto out;
        }
-       if ((uintptr_t)addr & 0x2) {
+       if ((uintptr_t)(addr + done) & 0x2) {
                if ((count - done) < 2) {
                        *(u8 *)(buf + done) = ioread8(addr + done);
                        done += 1;
@@ -938,7 +938,7 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image,
                if (done == count)
                        goto out;
        }
-       if ((uintptr_t)addr & 0x2) {
+       if ((uintptr_t)(addr + done) & 0x2) {
                if ((count - done) < 2) {
                        iowrite8(*(u8 *)(buf + done), addr + done);
                        done += 1;
index 16830d8b777cbd8f68e7751dd37729bc2fd681f5..9911cd5fddb58415b56ad23efadef06504b822f3 100644 (file)
@@ -1289,7 +1289,7 @@ static ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
                if (done == count)
                        goto out;
        }
-       if ((uintptr_t)addr & 0x2) {
+       if ((uintptr_t)(addr + done) & 0x2) {
                if ((count - done) < 2) {
                        *(u8 *)(buf + done) = ioread8(addr + done);
                        done += 1;
@@ -1371,7 +1371,7 @@ static ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
                if (done == count)
                        goto out;
        }
-       if ((uintptr_t)addr & 0x2) {
+       if ((uintptr_t)(addr + done) & 0x2) {
                if ((count - done) < 2) {
                        iowrite8(*(u8 *)(buf + done), addr + done);
                        done += 1;
index 4c4c566c52a35c73e582aa27b35fb7821ae69f8a..79d25894343a0f7d52e8702d05ec4020927d1040 100644 (file)
@@ -223,6 +223,7 @@ config SA1100_WATCHDOG
 
 config DW_WATCHDOG
        tristate "Synopsys DesignWare watchdog"
+       depends on HAS_IOMEM
        help
          Say Y here if to include support for the Synopsys DesignWare
          watchdog timer found in many chips.
index aaf2995d37f4b595d010efa500e89bb1ae5aef5b..68b45fc9ba6a5de684f18128ca337c09e7b3657e 100644 (file)
@@ -402,7 +402,7 @@ static int __init wdt_init(void)
 
        if (!found) {
                pr_err("No W83697HF/HG could be found\n");
-               ret = -EIO;
+               ret = -ENODEV;
                goto out;
        }
 
index d75c811bfa56611a56af01504467781a4f58eccf..45e00afa7f2d70fc20241959edc659e4158847bc 100644 (file)
@@ -16,7 +16,6 @@ xen-pad-$(CONFIG_X86) += xen-acpi-pad.o
 dom0-$(CONFIG_X86) += pcpu.o
 obj-$(CONFIG_XEN_DOM0)                 += $(dom0-y)
 obj-$(CONFIG_BLOCK)                    += biomerge.o
-obj-$(CONFIG_XEN_XENCOMM)              += xencomm.o
 obj-$(CONFIG_XEN_BALLOON)              += xen-balloon.o
 obj-$(CONFIG_XEN_SELFBALLOONING)       += xen-selfballoon.o
 obj-$(CONFIG_XEN_DEV_EVTCHN)           += xen-evtchn.o
index 37d06ea624aa953d40448bcd2a2d4943baf79fa9..61a6ac8fa8fc7ab00dcc7c33cea47981f2509d4b 100644 (file)
@@ -399,11 +399,25 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
                        state = BP_EAGAIN;
                        break;
                }
+               scrub_page(page);
 
-               pfn = page_to_pfn(page);
-               frame_list[i] = pfn_to_mfn(pfn);
+               frame_list[i] = page_to_pfn(page);
+       }
 
-               scrub_page(page);
+       /*
+        * Ensure that ballooned highmem pages don't have kmaps.
+        *
+        * Do this before changing the p2m as kmap_flush_unused()
+        * reads PTEs to obtain pages (and hence needs the original
+        * p2m entry).
+        */
+       kmap_flush_unused();
+
+       /* Update direct mapping, invalidate P2M, and add to balloon. */
+       for (i = 0; i < nr_pages; i++) {
+               pfn = frame_list[i];
+               frame_list[i] = pfn_to_mfn(pfn);
+               page = pfn_to_page(pfn);
 
 #ifdef CONFIG_XEN_HAVE_PVMMU
                /*
@@ -429,11 +443,9 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
                }
 #endif
 
-               balloon_append(pfn_to_page(pfn));
+               balloon_append(page);
        }
 
-       /* Ensure that ballooned highmem pages don't have kmaps. */
-       kmap_flush_unused();
        flush_tlb_all();
 
        set_xen_guest_handle(reservation.extent_start, frame_list);
index 4672e003c0ad03e0a10529fad839a1c799d179a1..f4a9e3311297b7b562f9235dae03e92b9266a9cc 100644 (file)
@@ -862,6 +862,8 @@ int bind_evtchn_to_irq(unsigned int evtchn)
                        irq = ret;
                        goto out;
                }
+               /* New interdomain events are bound to VCPU 0. */
+               bind_evtchn_to_cpu(evtchn, 0);
        } else {
                struct irq_info *info = info_for_irq(irq);
                WARN_ON(info == NULL || info->type != IRQT_EVTCHN);
index 34a2704fbc8856a6a112f9f41392adfd8f04c6bb..073b4a19a8b0796bf320130201ec8e7e98f2cff4 100644 (file)
@@ -284,10 +284,8 @@ static int map_grant_pages(struct grant_map *map)
        }
 
        pr_debug("map %d+%d\n", map->index, map->count);
-       err = gnttab_map_refs_userspace(map->map_ops,
-                                       use_ptemod ? map->kmap_ops : NULL,
-                                       map->pages,
-                                       map->count);
+       err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
+                       map->pages, map->count);
        if (err)
                return err;
 
@@ -317,10 +315,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
                }
        }
 
-       err = gnttab_unmap_refs_userspace(map->unmap_ops + offset,
-                                         use_ptemod ? map->kmap_ops + offset : NULL,
-                                         map->pages + offset,
-                                         pages);
+       err = gnttab_unmap_refs(map->unmap_ops + offset,
+                       use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
+                       pages);
        if (err)
                return err;
 
index 8ee13e2e45e2f8a5a29bb91eba7af714027d254d..b84e3ab839aa06650f98e39da40343f26644532d 100644 (file)
@@ -928,17 +928,15 @@ void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
 }
 EXPORT_SYMBOL_GPL(gnttab_batch_copy);
 
-int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                    struct gnttab_map_grant_ref *kmap_ops,
-                   struct page **pages, unsigned int count,
-                   bool m2p_override)
+                   struct page **pages, unsigned int count)
 {
        int i, ret;
        bool lazy = false;
        pte_t *pte;
-       unsigned long mfn, pfn;
+       unsigned long mfn;
 
-       BUG_ON(kmap_ops && !m2p_override);
        ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
        if (ret)
                return ret;
@@ -957,12 +955,10 @@ int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                        set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
                                        map_ops[i].dev_bus_addr >> PAGE_SHIFT);
                }
-               return 0;
+               return ret;
        }
 
-       if (m2p_override &&
-           !in_interrupt() &&
-           paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
+       if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
                lazy = true;
        }
@@ -979,20 +975,8 @@ int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                } else {
                        mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
                }
-               pfn = page_to_pfn(pages[i]);
-
-               WARN_ON(PagePrivate(pages[i]));
-               SetPagePrivate(pages[i]);
-               set_page_private(pages[i], mfn);
-
-               pages[i]->index = pfn_to_mfn(pfn);
-               if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               if (m2p_override)
-                       ret = m2p_add_override(mfn, pages[i], kmap_ops ?
-                                              &kmap_ops[i] : NULL);
+               ret = m2p_add_override(mfn, pages[i], kmap_ops ?
+                                      &kmap_ops[i] : NULL);
                if (ret)
                        goto out;
        }
@@ -1003,32 +987,15 @@ int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 
        return ret;
 }
-
-int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
-                   struct page **pages, unsigned int count)
-{
-       return __gnttab_map_refs(map_ops, NULL, pages, count, false);
-}
 EXPORT_SYMBOL_GPL(gnttab_map_refs);
 
-int gnttab_map_refs_userspace(struct gnttab_map_grant_ref *map_ops,
-                             struct gnttab_map_grant_ref *kmap_ops,
-                             struct page **pages, unsigned int count)
-{
-       return __gnttab_map_refs(map_ops, kmap_ops, pages, count, true);
-}
-EXPORT_SYMBOL_GPL(gnttab_map_refs_userspace);
-
-int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                      struct gnttab_map_grant_ref *kmap_ops,
-                     struct page **pages, unsigned int count,
-                     bool m2p_override)
+                     struct page **pages, unsigned int count)
 {
        int i, ret;
        bool lazy = false;
-       unsigned long pfn, mfn;
 
-       BUG_ON(kmap_ops && !m2p_override);
        ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
        if (ret)
                return ret;
@@ -1039,33 +1006,17 @@ int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                        set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
                                        INVALID_P2M_ENTRY);
                }
-               return 0;
+               return ret;
        }
 
-       if (m2p_override &&
-           !in_interrupt() &&
-           paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
+       if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
                lazy = true;
        }
 
        for (i = 0; i < count; i++) {
-               pfn = page_to_pfn(pages[i]);
-               mfn = get_phys_to_machine(pfn);
-               if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               set_page_private(pages[i], INVALID_P2M_ENTRY);
-               WARN_ON(!PagePrivate(pages[i]));
-               ClearPagePrivate(pages[i]);
-               set_phys_to_machine(pfn, pages[i]->index);
-               if (m2p_override)
-                       ret = m2p_remove_override(pages[i],
-                                                 kmap_ops ?
-                                                  &kmap_ops[i] : NULL,
-                                                 mfn);
+               ret = m2p_remove_override(pages[i], kmap_ops ?
+                                      &kmap_ops[i] : NULL);
                if (ret)
                        goto out;
        }
@@ -1076,22 +1027,8 @@ int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
 
        return ret;
 }
-
-int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *map_ops,
-                   struct page **pages, unsigned int count)
-{
-       return __gnttab_unmap_refs(map_ops, NULL, pages, count, false);
-}
 EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
 
-int gnttab_unmap_refs_userspace(struct gnttab_unmap_grant_ref *map_ops,
-                               struct gnttab_map_grant_ref *kmap_ops,
-                               struct page **pages, unsigned int count)
-{
-       return __gnttab_unmap_refs(map_ops, kmap_ops, pages, count, true);
-}
-EXPORT_SYMBOL_GPL(gnttab_unmap_refs_userspace);
-
 static unsigned nr_status_frames(unsigned nr_grant_frames)
 {
        BUG_ON(grefs_per_grant_frame == 0);
diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
deleted file mode 100644 (file)
index 4793fc5..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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
- *
- * Copyright (C) IBM Corp. 2006
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <asm/page.h>
-#include <xen/xencomm.h>
-#include <xen/interface/xen.h>
-#include <asm/xen/xencomm.h>   /* for xencomm_is_phys_contiguous() */
-
-static int xencomm_init(struct xencomm_desc *desc,
-                       void *buffer, unsigned long bytes)
-{
-       unsigned long recorded = 0;
-       int i = 0;
-
-       while ((recorded < bytes) && (i < desc->nr_addrs)) {
-               unsigned long vaddr = (unsigned long)buffer + recorded;
-               unsigned long paddr;
-               int offset;
-               int chunksz;
-
-               offset = vaddr % PAGE_SIZE; /* handle partial pages */
-               chunksz = min(PAGE_SIZE - offset, bytes - recorded);
-
-               paddr = xencomm_vtop(vaddr);
-               if (paddr == ~0UL) {
-                       printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
-                              __func__, vaddr);
-                       return -EINVAL;
-               }
-
-               desc->address[i++] = paddr;
-               recorded += chunksz;
-       }
-
-       if (recorded < bytes) {
-               printk(KERN_DEBUG
-                      "%s: could only translate %ld of %ld bytes\n",
-                      __func__, recorded, bytes);
-               return -ENOSPC;
-       }
-
-       /* mark remaining addresses invalid (just for safety) */
-       while (i < desc->nr_addrs)
-               desc->address[i++] = XENCOMM_INVALID;
-
-       desc->magic = XENCOMM_MAGIC;
-
-       return 0;
-}
-
-static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
-                                         void *buffer, unsigned long bytes)
-{
-       struct xencomm_desc *desc;
-       unsigned long buffer_ulong = (unsigned long)buffer;
-       unsigned long start = buffer_ulong & PAGE_MASK;
-       unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
-       unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
-       unsigned long size = sizeof(*desc) +
-               sizeof(desc->address[0]) * nr_addrs;
-
-       /*
-        * slab allocator returns at least sizeof(void*) aligned pointer.
-        * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
-        * cross page boundary.
-        */
-       if (sizeof(*desc) > sizeof(void *)) {
-               unsigned long order = get_order(size);
-               desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
-                                                              order);
-               if (desc == NULL)
-                       return NULL;
-
-               desc->nr_addrs =
-                       ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
-                       sizeof(*desc->address);
-       } else {
-               desc = kmalloc(size, gfp_mask);
-               if (desc == NULL)
-                       return NULL;
-
-               desc->nr_addrs = nr_addrs;
-       }
-       return desc;
-}
-
-void xencomm_free(struct xencomm_handle *desc)
-{
-       if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
-               struct xencomm_desc *desc__ = (struct xencomm_desc *)desc;
-               if (sizeof(*desc__) > sizeof(void *)) {
-                       unsigned long size = sizeof(*desc__) +
-                               sizeof(desc__->address[0]) * desc__->nr_addrs;
-                       unsigned long order = get_order(size);
-                       free_pages((unsigned long)__va(desc), order);
-               } else
-                       kfree(__va(desc));
-       }
-}
-
-static int xencomm_create(void *buffer, unsigned long bytes,
-                         struct xencomm_desc **ret, gfp_t gfp_mask)
-{
-       struct xencomm_desc *desc;
-       int rc;
-
-       pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
-
-       if (bytes == 0) {
-               /* don't create a descriptor; Xen recognizes NULL. */
-               BUG_ON(buffer != NULL);
-               *ret = NULL;
-               return 0;
-       }
-
-       BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
-
-       desc = xencomm_alloc(gfp_mask, buffer, bytes);
-       if (!desc) {
-               printk(KERN_DEBUG "%s failure\n", "xencomm_alloc");
-               return -ENOMEM;
-       }
-
-       rc = xencomm_init(desc, buffer, bytes);
-       if (rc) {
-               printk(KERN_DEBUG "%s failure: %d\n", "xencomm_init", rc);
-               xencomm_free((struct xencomm_handle *)__pa(desc));
-               return rc;
-       }
-
-       *ret = desc;
-       return 0;
-}
-
-static struct xencomm_handle *xencomm_create_inline(void *ptr)
-{
-       unsigned long paddr;
-
-       BUG_ON(!xencomm_is_phys_contiguous((unsigned long)ptr));
-
-       paddr = (unsigned long)xencomm_pa(ptr);
-       BUG_ON(paddr & XENCOMM_INLINE_FLAG);
-       return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
-}
-
-/* "mini" routine, for stack-based communications: */
-static int xencomm_create_mini(void *buffer,
-       unsigned long bytes, struct xencomm_mini *xc_desc,
-       struct xencomm_desc **ret)
-{
-       int rc = 0;
-       struct xencomm_desc *desc;
-       BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
-
-       desc = (void *)xc_desc;
-
-       desc->nr_addrs = XENCOMM_MINI_ADDRS;
-
-       rc = xencomm_init(desc, buffer, bytes);
-       if (!rc)
-               *ret = desc;
-
-       return rc;
-}
-
-struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
-{
-       int rc;
-       struct xencomm_desc *desc;
-
-       if (xencomm_is_phys_contiguous((unsigned long)ptr))
-               return xencomm_create_inline(ptr);
-
-       rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
-
-       if (rc || desc == NULL)
-               return NULL;
-
-       return xencomm_pa(desc);
-}
-
-struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
-                       struct xencomm_mini *xc_desc)
-{
-       int rc;
-       struct xencomm_desc *desc = NULL;
-
-       if (xencomm_is_phys_contiguous((unsigned long)ptr))
-               return xencomm_create_inline(ptr);
-
-       rc = xencomm_create_mini(ptr, bytes, xc_desc,
-                               &desc);
-
-       if (rc)
-               return NULL;
-
-       return xencomm_pa(desc);
-}
index 6621f800812287f6f0fc27cdc7f71a2a32287af2..be75b500005d0d4f68b2d6e3855e71660016353d 100644 (file)
@@ -75,6 +75,7 @@ struct afs_call {
        const struct afs_call_type *type;       /* type of call */
        const struct afs_wait_mode *wait_mode;  /* completion wait mode */
        wait_queue_head_t       waitq;          /* processes awaiting completion */
+       work_func_t             async_workfn;
        struct work_struct      async_work;     /* asynchronous work processor */
        struct work_struct      work;           /* actual work processor */
        struct sk_buff_head     rx_queue;       /* received packets */
index 8ad8c2a0703a120c2dde7f425225f1d515b13f0c..ef943df73b8cdee2c6964439b81417a9c1110b12 100644 (file)
@@ -644,7 +644,7 @@ static void afs_process_async_call(struct work_struct *work)
 
                /* we can't just delete the call because the work item may be
                 * queued */
-               PREPARE_WORK(&call->async_work, afs_delete_async_call);
+               call->async_workfn = afs_delete_async_call;
                queue_work(afs_async_calls, &call->async_work);
        }
 
@@ -663,6 +663,13 @@ void afs_transfer_reply(struct afs_call *call, struct sk_buff *skb)
        call->reply_size += len;
 }
 
+static void afs_async_workfn(struct work_struct *work)
+{
+       struct afs_call *call = container_of(work, struct afs_call, async_work);
+
+       call->async_workfn(work);
+}
+
 /*
  * accept the backlog of incoming calls
  */
@@ -685,7 +692,8 @@ static void afs_collect_incoming_call(struct work_struct *work)
                                return;
                        }
 
-                       INIT_WORK(&call->async_work, afs_process_async_call);
+                       call->async_workfn = afs_process_async_call;
+                       INIT_WORK(&call->async_work, afs_async_workfn);
                        call->wait_mode = &afs_async_incoming_call;
                        call->type = &afs_RXCMxxxx;
                        init_waitqueue_head(&call->waitq);
index 24084732b1d0b264b5c3262796f1ec3dd5fc505f..80ef38c73e5a16af0f9443d94bec3aae700370df 100644 (file)
@@ -41,19 +41,8 @@ static const struct dentry_operations anon_inodefs_dentry_operations = {
 static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type,
                                int flags, const char *dev_name, void *data)
 {
-       struct dentry *root;
-       root = mount_pseudo(fs_type, "anon_inode:", NULL,
+       return mount_pseudo(fs_type, "anon_inode:", NULL,
                        &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC);
-       if (!IS_ERR(root)) {
-               struct super_block *s = root->d_sb;
-               anon_inode_inode = alloc_anon_inode(s);
-               if (IS_ERR(anon_inode_inode)) {
-                       dput(root);
-                       deactivate_locked_super(s);
-                       root = ERR_CAST(anon_inode_inode);
-               }
-       }
-       return root;
 }
 
 static struct file_system_type anon_inode_fs_type = {
@@ -175,22 +164,15 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd);
 
 static int __init anon_inode_init(void)
 {
-       int error;
-
-       error = register_filesystem(&anon_inode_fs_type);
-       if (error)
-               goto err_exit;
        anon_inode_mnt = kern_mount(&anon_inode_fs_type);
-       if (IS_ERR(anon_inode_mnt)) {
-               error = PTR_ERR(anon_inode_mnt);
-               goto err_unregister_filesystem;
-       }
-       return 0;
+       if (IS_ERR(anon_inode_mnt))
+               panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt));
 
-err_unregister_filesystem:
-       unregister_filesystem(&anon_inode_fs_type);
-err_exit:
-       panic(KERN_ERR "anon_inode_init() failed (%d)\n", error);
+       anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
+       if (IS_ERR(anon_inode_inode))
+               panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));
+
+       return 0;
 }
 
 fs_initcall(anon_inode_init);
index 0bad24ddc2e7a39abf29547f24173cc050017d15..4f70f383132cc9dfe143c570fbb9759967fefc6f 100644 (file)
@@ -114,6 +114,14 @@ void bio_integrity_free(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_integrity_free);
 
+static inline unsigned int bip_integrity_vecs(struct bio_integrity_payload *bip)
+{
+       if (bip->bip_slab == BIO_POOL_NONE)
+               return BIP_INLINE_VECS;
+
+       return bvec_nr_vecs(bip->bip_slab);
+}
+
 /**
  * bio_integrity_add_page - Attach integrity metadata
  * @bio:       bio to update
@@ -129,7 +137,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
        struct bio_integrity_payload *bip = bio->bi_integrity;
        struct bio_vec *iv;
 
-       if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_slab)) {
+       if (bip->bip_vcnt >= bip_integrity_vecs(bip)) {
                printk(KERN_ERR "%s: bip_vec full\n", __func__);
                return 0;
        }
@@ -226,7 +234,8 @@ unsigned int bio_integrity_tag_size(struct bio *bio)
 }
 EXPORT_SYMBOL(bio_integrity_tag_size);
 
-int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set)
+static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len,
+                            int set)
 {
        struct bio_integrity_payload *bip = bio->bi_integrity;
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
@@ -449,11 +458,10 @@ static int bio_integrity_verify(struct bio *bio)
        struct blk_integrity_exchg bix;
        struct bio_vec *bv;
        sector_t sector = bio->bi_integrity->bip_iter.bi_sector;
-       unsigned int sectors, total, ret;
+       unsigned int sectors, ret = 0;
        void *prot_buf = bio->bi_integrity->bip_buf;
        int i;
 
-       ret = total = 0;
        bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
        bix.sector_size = bi->sector_size;
 
@@ -475,8 +483,6 @@ static int bio_integrity_verify(struct bio *bio)
                sectors = bv->bv_len / bi->sector_size;
                sector += sectors;
                prot_buf += sectors * bi->tuple_size;
-               total += sectors * bi->tuple_size;
-               BUG_ON(total > bio->bi_integrity->bip_iter.bi_size);
 
                kunmap_atomic(kaddr);
        }
index 75c49a38223969c1f7256868cb3b09fc7d3bd286..8754e7b6eb49330055a1efc69e86451fa9c65ff8 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -611,7 +611,6 @@ EXPORT_SYMBOL(bio_clone_fast);
 struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
                             struct bio_set *bs)
 {
-       unsigned nr_iovecs = 0;
        struct bvec_iter iter;
        struct bio_vec bv;
        struct bio *bio;
@@ -638,10 +637,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
         *    __bio_clone_fast() anyways.
         */
 
-       bio_for_each_segment(bv, bio_src, iter)
-               nr_iovecs++;
-
-       bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs);
+       bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs);
        if (!bio)
                return NULL;
 
@@ -650,9 +646,18 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
        bio->bi_iter.bi_sector  = bio_src->bi_iter.bi_sector;
        bio->bi_iter.bi_size    = bio_src->bi_iter.bi_size;
 
+       if (bio->bi_rw & REQ_DISCARD)
+               goto integrity_clone;
+
+       if (bio->bi_rw & REQ_WRITE_SAME) {
+               bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
+               goto integrity_clone;
+       }
+
        bio_for_each_segment(bv, bio_src, iter)
                bio->bi_io_vec[bio->bi_vcnt++] = bv;
 
+integrity_clone:
        if (bio_integrity(bio_src)) {
                int ret;
 
index 49a62b4dda3b0184ccd30880b8449b967eda5f27..0e8388e72d8d0c7dd3884a0d0ff7e8cabf120fbb 100644 (file)
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
-#include <linux/crc32c.h>
 #include <linux/genhd.h>
 #include <linux/blkdev.h>
 #include "ctree.h"
 #include "disk-io.h"
+#include "hash.h"
 #include "transaction.h"
 #include "extent_io.h"
 #include "volumes.h"
@@ -1823,7 +1823,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state,
                size_t sublen = i ? PAGE_CACHE_SIZE :
                                    (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE);
 
-               crc = crc32c(crc, data, sublen);
+               crc = btrfs_crc32c(crc, data, sublen);
        }
        btrfs_csum_final(crc, csum);
        if (memcmp(csum, h->csum, state->csum_size))
index e2600cdb6c257e366b873445c396a917249e76f3..b01fb6c527e32e7443cc5d461138222d5b538b9d 100644 (file)
@@ -1010,6 +1010,8 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
                bytes = min(bytes, working_bytes);
                kaddr = kmap_atomic(page_out);
                memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
+               if (*pg_index == (vcnt - 1) && *pg_offset == 0)
+                       memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
                kunmap_atomic(kaddr);
                flush_dcache_page(page_out);
 
index 0e69295d0031e558eb3ebb257ff2d4bb2f79772f..81ea55314b1ff0f61d2691f786a481889cd831ac 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <linux/crc32c.h>
 #include <linux/slab.h>
 #include <linux/migrate.h>
 #include <linux/ratelimit.h>
@@ -35,6 +34,7 @@
 #include <asm/unaligned.h>
 #include "ctree.h"
 #include "disk-io.h"
+#include "hash.h"
 #include "transaction.h"
 #include "btrfs_inode.h"
 #include "volumes.h"
@@ -244,7 +244,7 @@ out:
 
 u32 btrfs_csum_data(char *data, u32 seed, size_t len)
 {
-       return crc32c(seed, data, len);
+       return btrfs_crc32c(seed, data, len);
 }
 
 void btrfs_csum_final(u32 crc, char *result)
@@ -3839,7 +3839,6 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                        rb_erase(&ref->rb_node, &head->ref_root);
                        atomic_dec(&delayed_refs->num_entries);
                        btrfs_put_delayed_ref(ref);
-                       cond_resched_lock(&head->lock);
                }
                if (head->must_insert_reserved)
                        pin_bytes = true;
index 9c9ecc93ae2c3152d85cb2e15eeabd7bec95160f..32312e09f0f5999d05aaabafceebcce62b685568 100644 (file)
@@ -2385,6 +2385,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                        spin_unlock(&delayed_refs->lock);
                        locked_ref = NULL;
                        cond_resched();
+                       count++;
                        continue;
                }
 
index 5c4ab9c18940cc7827a75df6e02a84370cae3edd..d3d44486290bf6c8dce015ec24f440874ceb6d67 100644 (file)
@@ -2629,7 +2629,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                        EXTENT_DEFRAG, 1, cached_state);
        if (ret) {
                u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item);
-               if (last_snapshot >= BTRFS_I(inode)->generation)
+               if (0 && last_snapshot >= BTRFS_I(inode)->generation)
                        /* the inode is shared */
                        new = record_old_file_extents(inode, ordered_extent);
 
@@ -5154,7 +5154,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
                        return ERR_CAST(inode);
        }
 
-       return d_splice_alias(inode, dentry);
+       return d_materialise_unique(dentry, inode);
 }
 
 unsigned char btrfs_filetype_table[] = {
index b0134892dc70cdf69be04ad44e3e52183a86fcb0..a6d8efa46bfe50129b54ef11e4a854adad3b56ac 100644 (file)
@@ -3537,20 +3537,6 @@ out:
        return ret;
 }
 
-static long btrfs_ioctl_global_rsv(struct btrfs_root *root, void __user *arg)
-{
-       struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv;
-       u64 reserved;
-
-       spin_lock(&block_rsv->lock);
-       reserved = block_rsv->reserved;
-       spin_unlock(&block_rsv->lock);
-
-       if (arg && copy_to_user(arg, &reserved, sizeof(reserved)))
-               return -EFAULT;
-       return 0;
-}
-
 /*
  * there are many ways the trans_start and trans_end ioctls can lead
  * to deadlocks.  They should only be used by applications that
@@ -4525,7 +4511,7 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
        spin_lock(&root->fs_info->super_lock);
        strcpy(super_block->label, label);
        spin_unlock(&root->fs_info->super_lock);
-       ret = btrfs_end_transaction(trans, root);
+       ret = btrfs_commit_transaction(trans, root);
 
 out_unlock:
        mnt_drop_write_file(file);
@@ -4668,7 +4654,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
        if (ret)
                return ret;
 
-       trans = btrfs_start_transaction(root, 1);
+       trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
@@ -4689,7 +4675,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
        btrfs_set_super_incompat_flags(super_block, newflags);
        spin_unlock(&root->fs_info->super_lock);
 
-       return btrfs_end_transaction(trans, root);
+       return btrfs_commit_transaction(trans, root);
 }
 
 long btrfs_ioctl(struct file *file, unsigned int
@@ -4757,8 +4743,6 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_logical_to_ino(root, argp);
        case BTRFS_IOC_SPACE_INFO:
                return btrfs_ioctl_space_info(root, argp);
-       case BTRFS_IOC_GLOBAL_RSV:
-               return btrfs_ioctl_global_rsv(root, argp);
        case BTRFS_IOC_SYNC: {
                int ret;
 
index 730dce395858a6e4c86a43b4a8fa41779d719e0d..9dde9717c1b9264124d007184bc4c4d60276d99c 100644 (file)
 #include <linux/xattr.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/radix-tree.h>
-#include <linux/crc32c.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 
 #include "send.h"
 #include "backref.h"
+#include "hash.h"
 #include "locking.h"
 #include "disk-io.h"
 #include "btrfs_inode.h"
@@ -620,7 +620,7 @@ static int send_cmd(struct send_ctx *sctx)
        hdr->len = cpu_to_le32(sctx->send_size - sizeof(*hdr));
        hdr->crc = 0;
 
-       crc = crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size);
+       crc = btrfs_crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size);
        hdr->crc = cpu_to_le32(crc);
 
        ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size,
@@ -1332,6 +1332,16 @@ verbose_printk(KERN_DEBUG "btrfs: find_extent_clone: data_offset=%llu, "
        }
 
        if (cur_clone_root) {
+               if (compressed != BTRFS_COMPRESS_NONE) {
+                       /*
+                        * Offsets given by iterate_extent_inodes() are relative
+                        * to the start of the extent, we need to add logical
+                        * offset from the file extent item.
+                        * (See why at backref.c:check_extent_in_eb())
+                        */
+                       cur_clone_root->offset += btrfs_file_extent_offset(eb,
+                                                                          fi);
+               }
                *found = cur_clone_root;
                ret = 0;
        } else {
@@ -2774,8 +2784,6 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino)
        return 0;
 }
 
-#ifdef CONFIG_BTRFS_ASSERT
-
 static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino)
 {
        struct rb_node *n = sctx->waiting_dir_moves.rb_node;
@@ -2796,8 +2804,6 @@ static int del_waiting_dir_move(struct send_ctx *sctx, u64 ino)
        return -ENOENT;
 }
 
-#endif
-
 static int add_pending_dir_move(struct send_ctx *sctx, u64 parent_ino)
 {
        struct rb_node **p = &sctx->pending_dir_moves.rb_node;
@@ -2902,7 +2908,9 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
        }
 
        sctx->send_progress = sctx->cur_ino + 1;
-       ASSERT(del_waiting_dir_move(sctx, pm->ino) == 0);
+       ret = del_waiting_dir_move(sctx, pm->ino);
+       ASSERT(ret == 0);
+
        ret = get_cur_path(sctx, pm->ino, pm->gen, to_path);
        if (ret < 0)
                goto out;
index c02f63356895ff7fc5b59f36748e7aeb36840e04..d04db817be5c8271f531d87d0ee9a4a950f616f8 100644 (file)
@@ -566,7 +566,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                kfree(num);
 
                                if (info->max_inline) {
-                                       info->max_inline = max_t(u64,
+                                       info->max_inline = min_t(u64,
                                                info->max_inline,
                                                root->sectorsize);
                                }
@@ -855,6 +855,7 @@ static struct dentry *get_default_root(struct super_block *sb,
        struct btrfs_path *path;
        struct btrfs_key location;
        struct inode *inode;
+       struct dentry *dentry;
        u64 dir_id;
        int new = 0;
 
@@ -925,7 +926,13 @@ setup_root:
                return dget(sb->s_root);
        }
 
-       return d_obtain_alias(inode);
+       dentry = d_obtain_alias(inode);
+       if (!IS_ERR(dentry)) {
+               spin_lock(&dentry->d_lock);
+               dentry->d_flags &= ~DCACHE_DISCONNECTED;
+               spin_unlock(&dentry->d_lock);
+       }
+       return dentry;
 }
 
 static int btrfs_fill_super(struct super_block *sb,
@@ -1996,7 +2003,7 @@ static void __exit exit_btrfs_fs(void)
        btrfs_hash_exit();
 }
 
-module_init(init_btrfs_fs)
+late_initcall(init_btrfs_fs);
 module_exit(exit_btrfs_fs)
 
 MODULE_LICENSE("GPL");
index 782374d8fd1970ee9d6b4742fc2e213dc4d2e637..865f4cf9a7695899c18d368f6ab2629340994dce 100644 (file)
@@ -578,8 +578,14 @@ static int add_device_membership(struct btrfs_fs_info *fs_info)
                return -ENOMEM;
 
        list_for_each_entry(dev, &fs_devices->devices, dev_list) {
-               struct hd_struct *disk = dev->bdev->bd_part;
-               struct kobject *disk_kobj = &part_to_dev(disk)->kobj;
+               struct hd_struct *disk;
+               struct kobject *disk_kobj;
+
+               if (!dev->bdev)
+                       continue;
+
+               disk = dev->bdev->bd_part;
+               disk_kobj = &part_to_dev(disk)->kobj;
 
                error = sysfs_create_link(fs_info->device_dir_kobj,
                                          disk_kobj, disk_kobj->name);
index 651dba10b9c2b5468af528ad3114166b90d8c067..27265a8b43c1661f85d02b6fb931e8311ea7fe02 100644 (file)
@@ -654,14 +654,16 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode);
 static void __set_page_dirty(struct page *page,
                struct address_space *mapping, int warn)
 {
-       spin_lock_irq(&mapping->tree_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&mapping->tree_lock, flags);
        if (page->mapping) {    /* Race with truncate? */
                WARN_ON_ONCE(warn && !PageUptodate(page));
                account_page_dirtied(page, mapping);
                radix_tree_tag_set(&mapping->page_tree,
                                page_index(page), PAGECACHE_TAG_DIRTY);
        }
-       spin_unlock_irq(&mapping->tree_lock);
+       spin_unlock_irqrestore(&mapping->tree_lock, flags);
        __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
 }
 
index 4c2d452c4bfc0abad11cf3e3b0577d62ed3ef240..21887d63dad589a53e3da21fccb00c45a5c28ab6 100644 (file)
@@ -54,11 +54,6 @@ static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode,
        return acl;
 }
 
-void ceph_forget_all_cached_acls(struct inode *inode)
-{
-       forget_all_cached_acls(inode);
-}
-
 struct posix_acl *ceph_get_acl(struct inode *inode, int type)
 {
        int size;
@@ -160,11 +155,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
                        goto out_dput;
        }
 
-       if (value)
-               ret = __ceph_setxattr(dentry, name, value, size, 0);
-       else
-               ret = __ceph_removexattr(dentry, name);
-
+       ret = __ceph_setxattr(dentry, name, value, size, 0);
        if (ret) {
                if (new_mode != old_mode) {
                        newattrs.ia_mode = old_mode;
index 6da4df84ba300824a8a6afdea9f2a20121600765..45eda6d7a40c2030db42fc06fa2d741f180c254f 100644 (file)
@@ -100,6 +100,14 @@ static unsigned fpos_off(loff_t p)
        return p & 0xffffffff;
 }
 
+static int fpos_cmp(loff_t l, loff_t r)
+{
+       int v = ceph_frag_compare(fpos_frag(l), fpos_frag(r));
+       if (v)
+               return v;
+       return (int)(fpos_off(l) - fpos_off(r));
+}
+
 /*
  * When possible, we try to satisfy a readdir by peeking at the
  * dcache.  We make this work by carefully ordering dentries on
@@ -156,7 +164,7 @@ more:
                if (!d_unhashed(dentry) && dentry->d_inode &&
                    ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
                    ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
-                   ctx->pos <= di->offset)
+                   fpos_cmp(ctx->pos, di->offset) <= 0)
                        break;
                dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
                     dentry->d_name.len, dentry->d_name.name, di->offset,
@@ -695,9 +703,8 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
        ceph_mdsc_put_request(req);
 
        if (!err)
-               err = ceph_init_acl(dentry, dentry->d_inode, dir);
-
-       if (err)
+               ceph_init_acl(dentry, dentry->d_inode, dir);
+       else
                d_drop(dentry);
        return err;
 }
@@ -735,7 +742,9 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
        if (!err && !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
        ceph_mdsc_put_request(req);
-       if (err)
+       if (!err)
+               ceph_init_acl(dentry, dentry->d_inode, dir);
+       else
                d_drop(dentry);
        return err;
 }
@@ -776,7 +785,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
                err = ceph_handle_notrace_create(dir, dentry);
        ceph_mdsc_put_request(req);
 out:
-       if (err < 0)
+       if (!err)
+               ceph_init_acl(dentry, dentry->d_inode, dir);
+       else
                d_drop(dentry);
        return err;
 }
index dfd2ce3419f812f71769406023d0ff33cea3a35b..09c7afe32e496c7dfe20d527106c7a184248c3ca 100644 (file)
@@ -286,6 +286,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
        } else {
                dout("atomic_open finish_open on dn %p\n", dn);
                if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
+                       ceph_init_acl(dentry, dentry->d_inode, dir);
                        *opened |= FILE_CREATED;
                }
                err = finish_open(file, dentry, ceph_open, opened);
index 2df963f1cf5a3b84615772e793cd45eeddec801f..10a4ccbf38dab2c6f26407e7383815986f337bc0 100644 (file)
@@ -144,7 +144,11 @@ enum {
        Opt_ino32,
        Opt_noino32,
        Opt_fscache,
-       Opt_nofscache
+       Opt_nofscache,
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       Opt_acl,
+#endif
+       Opt_noacl
 };
 
 static match_table_t fsopt_tokens = {
@@ -172,6 +176,10 @@ static match_table_t fsopt_tokens = {
        {Opt_noino32, "noino32"},
        {Opt_fscache, "fsc"},
        {Opt_nofscache, "nofsc"},
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       {Opt_acl, "acl"},
+#endif
+       {Opt_noacl, "noacl"},
        {-1, NULL}
 };
 
@@ -271,6 +279,14 @@ static int parse_fsopt_token(char *c, void *private)
        case Opt_nofscache:
                fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
                break;
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       case Opt_acl:
+               fsopt->sb_flags |= MS_POSIXACL;
+               break;
+#endif
+       case Opt_noacl:
+               fsopt->sb_flags &= ~MS_POSIXACL;
+               break;
        default:
                BUG_ON(token);
        }
@@ -438,6 +454,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
        else
                seq_puts(m, ",nofsc");
 
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       if (fsopt->sb_flags & MS_POSIXACL)
+               seq_puts(m, ",acl");
+       else
+               seq_puts(m, ",noacl");
+#endif
+
        if (fsopt->wsize)
                seq_printf(m, ",wsize=%d", fsopt->wsize);
        if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
@@ -819,9 +842,6 @@ static int ceph_set_super(struct super_block *s, void *data)
 
        s->s_flags = fsc->mount_options->sb_flags;
        s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
-#ifdef CONFIG_CEPH_FS_POSIX_ACL
-       s->s_flags |= MS_POSIXACL;
-#endif
 
        s->s_xattr = ceph_xattr_handlers;
        s->s_fs_info = fsc;
@@ -911,6 +931,10 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
        struct ceph_options *opt = NULL;
 
        dout("ceph_mount\n");
+
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       flags |= MS_POSIXACL;
+#endif
        err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
        if (err < 0) {
                res = ERR_PTR(err);
index 19793b56d0a7d3a90330c36a218312728b42e45e..d8801a95b6857d514fc27e440af8d476513cae3e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/wait.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
+#include <linux/posix_acl.h>
 
 #include <linux/ceph/libceph.h>
 
@@ -743,7 +744,11 @@ extern const struct xattr_handler *ceph_xattr_handlers[];
 struct posix_acl *ceph_get_acl(struct inode *, int);
 int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int ceph_init_acl(struct dentry *, struct inode *, struct inode *);
-void ceph_forget_all_cached_acls(struct inode *inode);
+
+static inline void ceph_forget_all_cached_acls(struct inode *inode)
+{
+       forget_all_cached_acls(inode);
+}
 
 #else
 
index 898b6565ad3e2c114baca0282fafea6a5643071a..a55ec37378c6730efa476d3d6a923e37ba10ec72 100644 (file)
@@ -12,6 +12,9 @@
 #define XATTR_CEPH_PREFIX "ceph."
 #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
 
+static int __remove_xattr(struct ceph_inode_info *ci,
+                         struct ceph_inode_xattr *xattr);
+
 /*
  * List of handlers for synthetic system.* attributes. Other
  * attributes are handled directly.
@@ -319,8 +322,7 @@ static struct ceph_vxattr *ceph_match_vxattr(struct inode *inode,
 static int __set_xattr(struct ceph_inode_info *ci,
                           const char *name, int name_len,
                           const char *val, int val_len,
-                          int dirty,
-                          int should_free_name, int should_free_val,
+                          int flags, int update_xattr,
                           struct ceph_inode_xattr **newxattr)
 {
        struct rb_node **p;
@@ -349,12 +351,31 @@ static int __set_xattr(struct ceph_inode_info *ci,
                xattr = NULL;
        }
 
+       if (update_xattr) {
+               int err = 0;
+               if (xattr && (flags & XATTR_CREATE))
+                       err = -EEXIST;
+               else if (!xattr && (flags & XATTR_REPLACE))
+                       err = -ENODATA;
+               if (err) {
+                       kfree(name);
+                       kfree(val);
+                       return err;
+               }
+               if (update_xattr < 0) {
+                       if (xattr)
+                               __remove_xattr(ci, xattr);
+                       kfree(name);
+                       return 0;
+               }
+       }
+
        if (!xattr) {
                new = 1;
                xattr = *newxattr;
                xattr->name = name;
                xattr->name_len = name_len;
-               xattr->should_free_name = should_free_name;
+               xattr->should_free_name = update_xattr;
 
                ci->i_xattrs.count++;
                dout("__set_xattr count=%d\n", ci->i_xattrs.count);
@@ -364,7 +385,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
                if (xattr->should_free_val)
                        kfree((void *)xattr->val);
 
-               if (should_free_name) {
+               if (update_xattr) {
                        kfree((void *)name);
                        name = xattr->name;
                }
@@ -379,8 +400,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
                xattr->val = "";
 
        xattr->val_len = val_len;
-       xattr->dirty = dirty;
-       xattr->should_free_val = (val && should_free_val);
+       xattr->dirty = update_xattr;
+       xattr->should_free_val = (val && update_xattr);
 
        if (new) {
                rb_link_node(&xattr->node, parent, p);
@@ -442,7 +463,7 @@ static int __remove_xattr(struct ceph_inode_info *ci,
                          struct ceph_inode_xattr *xattr)
 {
        if (!xattr)
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        rb_erase(&xattr->node, &ci->i_xattrs.index);
 
@@ -588,7 +609,7 @@ start:
                        p += len;
 
                        err = __set_xattr(ci, name, namelen, val, len,
-                                         0, 0, 0, &xattrs[numattr]);
+                                         0, 0, &xattrs[numattr]);
 
                        if (err < 0)
                                goto bad;
@@ -850,6 +871,9 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
 
        dout("setxattr value=%.*s\n", (int)size, value);
 
+       if (!value)
+               flags |= CEPH_XATTR_REMOVE;
+
        /* do request */
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
                                       USE_AUTH_MDS);
@@ -892,7 +916,7 @@ int __ceph_setxattr(struct dentry *dentry, const char *name,
        struct ceph_inode_info *ci = ceph_inode(inode);
        int issued;
        int err;
-       int dirty;
+       int dirty = 0;
        int name_len = strlen(name);
        int val_len = size;
        char *newname = NULL;
@@ -953,12 +977,14 @@ retry:
                goto retry;
        }
 
-       err = __set_xattr(ci, newname, name_len, newval,
-                         val_len, 1, 1, 1, &xattr);
+       err = __set_xattr(ci, newname, name_len, newval, val_len,
+                         flags, value ? 1 : -1, &xattr);
 
-       dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
-       ci->i_xattrs.dirty = true;
-       inode->i_ctime = CURRENT_TIME;
+       if (!err) {
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+               ci->i_xattrs.dirty = true;
+               inode->i_ctime = CURRENT_TIME;
+       }
 
        spin_unlock(&ci->i_ceph_lock);
        if (dirty)
index 8f9b4f710d4a31ea651f64586fa2469edd92c2fa..7ff866dbb89eb7b31033ce1e99f7b56f664fbdf6 100644 (file)
@@ -865,8 +865,8 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
        return rc;
 }
 
-static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
-               __u16 fid, u32 *pacllen)
+struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
+               const struct cifs_fid *cifsfid, u32 *pacllen)
 {
        struct cifs_ntsd *pntsd = NULL;
        unsigned int xid;
@@ -877,7 +877,8 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
                return ERR_CAST(tlink);
 
        xid = get_xid();
-       rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
+       rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
+                               pacllen);
        free_xid(xid);
 
        cifs_put_tlink(tlink);
@@ -946,7 +947,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
        if (!open_file)
                return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 
-       pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
+       pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
        cifsFileInfo_put(open_file);
        return pntsd;
 }
@@ -1006,19 +1007,31 @@ out:
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
 int
 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
-                 struct inode *inode, const char *path, const __u16 *pfid)
+                 struct inode *inode, const char *path,
+                 const struct cifs_fid *pfid)
 {
        struct cifs_ntsd *pntsd = NULL;
        u32 acllen = 0;
        int rc = 0;
+       struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+       struct cifs_tcon *tcon;
 
        cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
-       if (pfid)
-               pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
-       else
-               pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
+       if (IS_ERR(tlink))
+               return PTR_ERR(tlink);
+       tcon = tlink_tcon(tlink);
 
+       if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
+               pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
+                                                         &acllen);
+       else if (tcon->ses->server->ops->get_acl)
+               pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
+                                                       &acllen);
+       else {
+               cifs_put_tlink(tlink);
+               return -EOPNOTSUPP;
+       }
        /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
@@ -1030,6 +1043,8 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
                        cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
        }
 
+       cifs_put_tlink(tlink);
+
        return rc;
 }
 
@@ -1043,15 +1058,30 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
        __u32 secdesclen = 0;
        struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+       struct cifs_tcon *tcon;
+
+       if (IS_ERR(tlink))
+               return PTR_ERR(tlink);
+       tcon = tlink_tcon(tlink);
 
        cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
 
        /* Get the security descriptor */
-       pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
+
+       if (tcon->ses->server->ops->get_acl == NULL) {
+               cifs_put_tlink(tlink);
+               return -EOPNOTSUPP;
+       }
+
+       pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
+                                               &secdesclen);
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
-               goto out;
+               cifs_put_tlink(tlink);
+               return rc;
        }
 
        /*
@@ -1064,6 +1094,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
        pnntsd = kmalloc(secdesclen, GFP_KERNEL);
        if (!pnntsd) {
                kfree(pntsd);
+               cifs_put_tlink(tlink);
                return -ENOMEM;
        }
 
@@ -1072,14 +1103,18 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
        cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
 
+       if (tcon->ses->server->ops->set_acl == NULL)
+               rc = -EOPNOTSUPP;
+
        if (!rc) {
                /* Set the security descriptor */
-               rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
+               rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
+                                                    path, aclflag);
                cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
        }
+       cifs_put_tlink(tlink);
 
        kfree(pnntsd);
        kfree(pntsd);
-out:
        return rc;
 }
index a245d1809ed8d63dc7ee5cbc5320bb117a12c71e..c0f3718b77a83e7e0e010b089e436356e83a1eb7 100644 (file)
@@ -323,7 +323,8 @@ struct smb_version_operations {
        /* async read from the server */
        int (*async_readv)(struct cifs_readdata *);
        /* async write to the server */
-       int (*async_writev)(struct cifs_writedata *);
+       int (*async_writev)(struct cifs_writedata *,
+                           void (*release)(struct kref *));
        /* sync read from the server */
        int (*sync_read)(const unsigned int, struct cifsFileInfo *,
                         struct cifs_io_parms *, unsigned int *, char **,
@@ -395,6 +396,12 @@ struct smb_version_operations {
        int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
                        const char *, const void *, const __u16,
                        const struct nls_table *, int);
+       struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
+                       const char *, u32 *);
+       struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
+                       const struct cifs_fid *, u32 *);
+       int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
+                       int);
 };
 
 struct smb_version_values {
@@ -506,7 +513,7 @@ struct cifs_mnt_data {
 static inline unsigned int
 get_rfc1002_length(void *buf)
 {
-       return be32_to_cpu(*((__be32 *)buf));
+       return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
 }
 
 static inline void
@@ -1064,7 +1071,7 @@ struct cifs_writedata {
        unsigned int                    pagesz;
        unsigned int                    tailsz;
        unsigned int                    nr_pages;
-       struct page                     *pages[1];
+       struct page                     *pages[];
 };
 
 /*
index 79e6e9a93a8ce984420ef8dc68fa3d941ff1f045..acc4ee8ed0759a7e786709ea61d5077970b3ef3e 100644 (file)
@@ -151,7 +151,7 @@ extern struct inode *cifs_iget(struct super_block *sb,
 
 extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
                               FILE_ALL_INFO *data, struct super_block *sb,
-                              int xid, const __u16 *fid);
+                              int xid, const struct cifs_fid *fid);
 extern int cifs_get_inode_info_unix(struct inode **pinode,
                        const unsigned char *search_path,
                        struct super_block *sb, unsigned int xid);
@@ -162,11 +162,13 @@ extern int cifs_rename_pending_delete(const char *full_path,
                                      const unsigned int xid);
 extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
                              struct cifs_fattr *fattr, struct inode *inode,
-                             const char *path, const __u16 *pfid);
+                             const char *path, const struct cifs_fid *pfid);
 extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64,
                                        kuid_t, kgid_t);
 extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
                                        const char *, u32 *);
+extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
+                                               const struct cifs_fid *, u32 *);
 extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
                                const char *, int);
 
@@ -488,7 +490,8 @@ void cifs_readdata_release(struct kref *refcount);
 int cifs_async_readv(struct cifs_readdata *rdata);
 int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
 
-int cifs_async_writev(struct cifs_writedata *wdata);
+int cifs_async_writev(struct cifs_writedata *wdata,
+                     void (*release)(struct kref *kref));
 void cifs_writev_complete(struct work_struct *work);
 struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
                                                work_func_t complete);
index 4d881c35eecaa035717b52d9c19b9dac00dd9dae..f3264bd7a83d9427a158130a7d4a842443bd8b53 100644 (file)
@@ -1910,7 +1910,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
 
        do {
                server = tlink_tcon(wdata->cfile->tlink)->ses->server;
-               rc = server->ops->async_writev(wdata);
+               rc = server->ops->async_writev(wdata, cifs_writedata_release);
        } while (rc == -EAGAIN);
 
        for (i = 0; i < wdata->nr_pages; i++) {
@@ -1962,15 +1962,9 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
 {
        struct cifs_writedata *wdata;
 
-       /* this would overflow */
-       if (nr_pages == 0) {
-               cifs_dbg(VFS, "%s: called with nr_pages == 0!\n", __func__);
-               return NULL;
-       }
-
        /* writedata + number of page pointers */
        wdata = kzalloc(sizeof(*wdata) +
-                       sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
+                       sizeof(struct page *) * nr_pages, GFP_NOFS);
        if (wdata != NULL) {
                kref_init(&wdata->refcount);
                INIT_LIST_HEAD(&wdata->list);
@@ -2031,7 +2025,8 @@ cifs_writev_callback(struct mid_q_entry *mid)
 
 /* cifs_async_writev - send an async write, and set up mid to handle result */
 int
-cifs_async_writev(struct cifs_writedata *wdata)
+cifs_async_writev(struct cifs_writedata *wdata,
+                 void (*release)(struct kref *kref))
 {
        int rc = -EACCES;
        WRITE_REQ *smb = NULL;
@@ -2105,7 +2100,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
        if (rc == 0)
                cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
        else
-               kref_put(&wdata->refcount, cifs_writedata_release);
+               kref_put(&wdata->refcount, release);
 
 async_writev_out:
        cifs_small_buf_release(smb);
index d3a6796caa5a3fce527584ae6437b2a446663da4..3db0c5fd9a1109629764cf5f2b759dd9ddd8cd8a 100644 (file)
@@ -378,7 +378,7 @@ cifs_create_get_file_info:
                                              xid);
        else {
                rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
-                                        xid, &fid->netfid);
+                                        xid, fid);
                if (newinode) {
                        if (server->ops->set_lease_key)
                                server->ops->set_lease_key(newinode, fid);
index 853d6d1cc822280a0deb1e5106aff7d84323e869..834fce759d8075313261dfa0a01c76ba9c2cb5b3 100644 (file)
@@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
                                              xid);
        else
                rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
-                                        xid, &fid->netfid);
+                                        xid, fid);
 
 out:
        kfree(buf);
@@ -2043,7 +2043,8 @@ retry:
                        }
                        wdata->pid = wdata->cfile->pid;
                        server = tlink_tcon(wdata->cfile->tlink)->ses->server;
-                       rc = server->ops->async_writev(wdata);
+                       rc = server->ops->async_writev(wdata,
+                                                       cifs_writedata_release);
                } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
 
                for (i = 0; i < nr_pages; ++i)
@@ -2331,9 +2332,20 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
 }
 
 static void
-cifs_uncached_writev_complete(struct work_struct *work)
+cifs_uncached_writedata_release(struct kref *refcount)
 {
        int i;
+       struct cifs_writedata *wdata = container_of(refcount,
+                                       struct cifs_writedata, refcount);
+
+       for (i = 0; i < wdata->nr_pages; i++)
+               put_page(wdata->pages[i]);
+       cifs_writedata_release(refcount);
+}
+
+static void
+cifs_uncached_writev_complete(struct work_struct *work)
+{
        struct cifs_writedata *wdata = container_of(work,
                                        struct cifs_writedata, work);
        struct inode *inode = wdata->cfile->dentry->d_inode;
@@ -2347,12 +2359,7 @@ cifs_uncached_writev_complete(struct work_struct *work)
 
        complete(&wdata->done);
 
-       if (wdata->result != -EAGAIN) {
-               for (i = 0; i < wdata->nr_pages; i++)
-                       put_page(wdata->pages[i]);
-       }
-
-       kref_put(&wdata->refcount, cifs_writedata_release);
+       kref_put(&wdata->refcount, cifs_uncached_writedata_release);
 }
 
 /* attempt to send write to server, retry on any -EAGAIN errors */
@@ -2370,7 +2377,8 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata)
                        if (rc != 0)
                                continue;
                }
-               rc = server->ops->async_writev(wdata);
+               rc = server->ops->async_writev(wdata,
+                                              cifs_uncached_writedata_release);
        } while (rc == -EAGAIN);
 
        return rc;
@@ -2381,7 +2389,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
                 unsigned long nr_segs, loff_t *poffset)
 {
        unsigned long nr_pages, i;
-       size_t copied, len, cur_len;
+       size_t bytes, copied, len, cur_len;
        ssize_t total_written = 0;
        loff_t offset;
        struct iov_iter it;
@@ -2436,14 +2444,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
 
                save_len = cur_len;
                for (i = 0; i < nr_pages; i++) {
-                       copied = min_t(const size_t, cur_len, PAGE_SIZE);
+                       bytes = min_t(const size_t, cur_len, PAGE_SIZE);
                        copied = iov_iter_copy_from_user(wdata->pages[i], &it,
-                                                        0, copied);
+                                                        0, bytes);
                        cur_len -= copied;
                        iov_iter_advance(&it, copied);
+                       /*
+                        * If we didn't copy as much as we expected, then that
+                        * may mean we trod into an unmapped area. Stop copying
+                        * at that point. On the next pass through the big
+                        * loop, we'll likely end up getting a zero-length
+                        * write and bailing out of it.
+                        */
+                       if (copied < bytes)
+                               break;
                }
                cur_len = save_len - cur_len;
 
+               /*
+                * If we have no data to send, then that probably means that
+                * the copy above failed altogether. That's most likely because
+                * the address in the iovec was bogus. Set the rc to -EFAULT,
+                * free anything we allocated and bail out.
+                */
+               if (!cur_len) {
+                       for (i = 0; i < nr_pages; i++)
+                               put_page(wdata->pages[i]);
+                       kfree(wdata);
+                       rc = -EFAULT;
+                       break;
+               }
+
+               /*
+                * i + 1 now represents the number of pages we actually used in
+                * the copy phase above. Bring nr_pages down to that, and free
+                * any pages that we didn't use.
+                */
+               for ( ; nr_pages > i + 1; nr_pages--)
+                       put_page(wdata->pages[nr_pages - 1]);
+
                wdata->sync_mode = WB_SYNC_ALL;
                wdata->nr_pages = nr_pages;
                wdata->offset = (__u64)offset;
@@ -2454,7 +2493,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
                wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
                rc = cifs_uncached_retry_writev(wdata);
                if (rc) {
-                       kref_put(&wdata->refcount, cifs_writedata_release);
+                       kref_put(&wdata->refcount,
+                                cifs_uncached_writedata_release);
                        break;
                }
 
@@ -2496,7 +2536,7 @@ restart_loop:
                        }
                }
                list_del_init(&wdata->list);
-               kref_put(&wdata->refcount, cifs_writedata_release);
+               kref_put(&wdata->refcount, cifs_uncached_writedata_release);
        }
 
        if (total_written > 0)
@@ -2539,31 +2579,19 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
        struct cifsInodeInfo *cinode = CIFS_I(inode);
        struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
        ssize_t rc = -EACCES;
+       loff_t lock_pos = pos;
 
-       BUG_ON(iocb->ki_pos != pos);
-
+       if (file->f_flags & O_APPEND)
+               lock_pos = i_size_read(inode);
        /*
         * We need to hold the sem to be sure nobody modifies lock list
         * with a brlock that prevents writing.
         */
        down_read(&cinode->lock_sem);
-       if (!cifs_find_lock_conflict(cfile, pos, iov_length(iov, nr_segs),
+       if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs),
                                     server->vals->exclusive_lock_type, NULL,
-                                    CIFS_WRITE_OP)) {
-               mutex_lock(&inode->i_mutex);
-               rc = __generic_file_aio_write(iocb, iov, nr_segs,
-                                              &iocb->ki_pos);
-               mutex_unlock(&inode->i_mutex);
-       }
-
-       if (rc > 0) {
-               ssize_t err;
-
-               err = generic_write_sync(file, pos, rc);
-               if (err < 0 && rc > 0)
-                       rc = err;
-       }
-
+                                    CIFS_WRITE_OP))
+               rc = generic_file_aio_write(iocb, iov, nr_segs, pos);
        up_read(&cinode->lock_sem);
        return rc;
 }
index 9cb9679d735719b42f83b89e39b9c0bbd56fdd65..aadc2b68678b7d70c0381d10c847c86624589c4c 100644 (file)
@@ -527,10 +527,15 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
                return PTR_ERR(tlink);
        tcon = tlink_tcon(tlink);
 
-       rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
-                           ea_value, 4 /* size of buf */, cifs_sb->local_nls,
-                           cifs_sb->mnt_cifs_flags &
-                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+       if (tcon->ses->server->ops->query_all_EAs == NULL) {
+               cifs_put_tlink(tlink);
+               return -EOPNOTSUPP;
+       }
+
+       rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
+                       "SETFILEBITS", ea_value, 4 /* size of buf */,
+                       cifs_sb->local_nls,
+                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        cifs_put_tlink(tlink);
        if (rc < 0)
                return (int)rc;
@@ -672,7 +677,7 @@ cgfi_exit:
 int
 cifs_get_inode_info(struct inode **inode, const char *full_path,
                    FILE_ALL_INFO *data, struct super_block *sb, int xid,
-                   const __u16 *fid)
+                   const struct cifs_fid *fid)
 {
        bool validinum = false;
        __u16 srchflgs;
index 9ac5bfc9cc56af6ee74f9f3d2e15e66ab2dd2e54..526fb89f92305b9e85d1f62f65a6e48c04555e83 100644 (file)
@@ -1067,6 +1067,15 @@ struct smb_version_operations smb1_operations = {
        .query_mf_symlink = cifs_query_mf_symlink,
        .create_mf_symlink = cifs_create_mf_symlink,
        .is_read_op = cifs_is_read_op,
+#ifdef CONFIG_CIFS_XATTR
+       .query_all_EAs = CIFSSMBQAllEAs,
+       .set_EA = CIFSSMBSetEA,
+#endif /* CIFS_XATTR */
+#ifdef CONFIG_CIFS_ACL
+       .get_acl = get_cifs_acl,
+       .get_acl_by_fid = get_cifs_acl_by_fid,
+       .set_acl = set_cifs_acl,
+#endif /* CIFS_ACL */
 };
 
 struct smb_version_values smb1_values = {
index c38350851b0883cd6074b04f5aa36398b2528e3c..bc0bb9c34f72aaef62383760a06fa55c72d5b70b 100644 (file)
@@ -57,4 +57,7 @@
 #define SMB2_CMACAES_SIZE (16)
 #define SMB3_SIGNKEY_SIZE (16)
 
+/* Maximum buffer size value we can send with 1 credit */
+#define SMB2_MAX_BUFFER_SIZE 65536
+
 #endif /* _SMB2_GLOB_H */
index 757da3e54d3dce601b71b97883f3430556040107..192f51a12cf1c63fb6eee3359b2350747343a76c 100644 (file)
@@ -182,11 +182,8 @@ smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
        /* start with specified wsize, or default */
        wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
        wsize = min_t(unsigned int, wsize, server->max_write);
-       /*
-        * limit write size to 2 ** 16, because we don't support multicredit
-        * requests now.
-        */
-       wsize = min_t(unsigned int, wsize, 2 << 15);
+       /* set it to the maximum buffer size value we can send with 1 credit */
+       wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
 
        return wsize;
 }
@@ -200,11 +197,8 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
        /* start with specified rsize, or default */
        rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
        rsize = min_t(unsigned int, rsize, server->max_read);
-       /*
-        * limit write size to 2 ** 16, because we don't support multicredit
-        * requests now.
-        */
-       rsize = min_t(unsigned int, rsize, 2 << 15);
+       /* set it to the maximum buffer size value we can send with 1 credit */
+       rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
 
        return rsize;
 }
index 2013234b73adc47a5a34cb907ce0b818f65a16f5..860344701067f49169e20a8a41df55145fa5f023 100644 (file)
@@ -413,7 +413,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 
        /* SMB2 only has an extended negflavor */
        server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
-       server->maxBuf = le32_to_cpu(rsp->MaxTransactSize);
+       /* set it to the maximum buffer size value we can send with 1 credit */
+       server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize),
+                              SMB2_MAX_BUFFER_SIZE);
        server->max_read = le32_to_cpu(rsp->MaxReadSize);
        server->max_write = le32_to_cpu(rsp->MaxWriteSize);
        /* BB Do we need to validate the SecurityMode? */
@@ -1890,7 +1892,8 @@ smb2_writev_callback(struct mid_q_entry *mid)
 
 /* smb2_async_writev - send an async write, and set up mid to handle result */
 int
-smb2_async_writev(struct cifs_writedata *wdata)
+smb2_async_writev(struct cifs_writedata *wdata,
+                 void (*release)(struct kref *kref))
 {
        int rc = -EACCES;
        struct smb2_write_req *req = NULL;
@@ -1938,7 +1941,7 @@ smb2_async_writev(struct cifs_writedata *wdata)
                                smb2_writev_callback, wdata, 0);
 
        if (rc) {
-               kref_put(&wdata->refcount, cifs_writedata_release);
+               kref_put(&wdata->refcount, release);
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
        }
 
index 93adc64666f310345b4c6d76bba628741aa4e634..0ce48db20a6511add52f9b44f5cbf664a178e41f 100644 (file)
@@ -123,7 +123,8 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
 extern int smb2_async_readv(struct cifs_readdata *rdata);
 extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                     unsigned int *nbytes, char **buf, int *buf_type);
-extern int smb2_async_writev(struct cifs_writedata *wdata);
+extern int smb2_async_writev(struct cifs_writedata *wdata,
+                            void (*release)(struct kref *kref));
 extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
                      unsigned int *nbytes, struct kvec *iov, int n_vec);
 extern int SMB2_echo(struct TCP_Server_Info *server);
index b375709528467b5a1a74e078fae2aeb7813e1a1e..18cd5650a5fc6106394691f6ee5baf37f5d8d49b 100644 (file)
@@ -270,6 +270,26 @@ cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
                iov->iov_len = rqst->rq_pagesz;
 }
 
+static unsigned long
+rqst_len(struct smb_rqst *rqst)
+{
+       unsigned int i;
+       struct kvec *iov = rqst->rq_iov;
+       unsigned long buflen = 0;
+
+       /* total up iov array first */
+       for (i = 0; i < rqst->rq_nvec; i++)
+               buflen += iov[i].iov_len;
+
+       /* add in the page array if there is one */
+       if (rqst->rq_npages) {
+               buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
+               buflen += rqst->rq_tailsz;
+       }
+
+       return buflen;
+}
+
 static int
 smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
 {
@@ -277,6 +297,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
        struct kvec *iov = rqst->rq_iov;
        int n_vec = rqst->rq_nvec;
        unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
+       unsigned long send_length;
        unsigned int i;
        size_t total_len = 0, sent;
        struct socket *ssocket = server->ssocket;
@@ -285,6 +306,14 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
        if (ssocket == NULL)
                return -ENOTSOCK;
 
+       /* sanity check send length */
+       send_length = rqst_len(rqst);
+       if (send_length != smb_buf_length + 4) {
+               WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
+                       send_length, smb_buf_length);
+               return -EIO;
+       }
+
        cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
        dump_smb(iov[0].iov_base, iov[0].iov_len);
 
index 95c43bb203353a65974a6cf5b24a0fe02c3c5c86..5ac836a86b1885d4e1766e831a1b56d3a263e277 100644 (file)
@@ -176,8 +176,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
                        rc = -ENOMEM;
                } else {
                        memcpy(pacl, ea_value, value_size);
-                       rc = set_cifs_acl(pacl, value_size,
-                               direntry->d_inode, full_path, CIFS_ACL_DACL);
+                       if (pTcon->ses->server->ops->set_acl)
+                               rc = pTcon->ses->server->ops->set_acl(pacl,
+                                               value_size, direntry->d_inode,
+                                               full_path, CIFS_ACL_DACL);
+                       else
+                               rc = -EOPNOTSUPP;
                        if (rc == 0) /* force revalidate of the inode */
                                CIFS_I(direntry->d_inode)->time = 0;
                        kfree(pacl);
@@ -323,8 +327,11 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                        u32 acllen;
                        struct cifs_ntsd *pacl;
 
-                       pacl = get_cifs_acl(cifs_sb, direntry->d_inode,
-                                               full_path, &acllen);
+                       if (pTcon->ses->server->ops->get_acl == NULL)
+                               goto get_ea_exit; /* rc already EOPNOTSUPP */
+
+                       pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
+                                       direntry->d_inode, full_path, &acllen);
                        if (IS_ERR(pacl)) {
                                rc = PTR_ERR(pacl);
                                cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
index 6af20de2c1a3c29d5cc7c251d8fb3fa2182de445..19252b97f0cc9662940c2782c76e6782c7fa787a 100644 (file)
@@ -72,8 +72,8 @@ int compat_printk(const char *fmt, ...)
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
  */
-asmlinkage long compat_sys_utime(const char __user *filename,
-                                struct compat_utimbuf __user *t)
+COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
+                      struct compat_utimbuf __user *, t)
 {
        struct timespec tv[2];
 
@@ -87,7 +87,7 @@ asmlinkage long compat_sys_utime(const char __user *filename,
        return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
 }
 
-asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filename, struct compat_timespec __user *t, int flags)
+COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
 {
        struct timespec tv[2];
 
@@ -102,7 +102,7 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, const char __user *filena
        return do_utimes(dfd, filename, t ? tv : NULL, flags);
 }
 
-asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filename, struct compat_timeval __user *t)
+COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
 {
        struct timespec tv[2];
 
@@ -121,7 +121,7 @@ asmlinkage long compat_sys_futimesat(unsigned int dfd, const char __user *filena
        return do_utimes(dfd, filename, t ? tv : NULL, 0);
 }
 
-asmlinkage long compat_sys_utimes(const char __user *filename, struct compat_timeval __user *t)
+COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t)
 {
        return compat_sys_futimesat(AT_FDCWD, filename, t);
 }
@@ -159,8 +159,8 @@ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
        return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
-asmlinkage long compat_sys_newstat(const char __user * filename,
-               struct compat_stat __user *statbuf)
+COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
+                      struct compat_stat __user *, statbuf)
 {
        struct kstat stat;
        int error;
@@ -171,8 +171,8 @@ asmlinkage long compat_sys_newstat(const char __user * filename,
        return cp_compat_stat(&stat, statbuf);
 }
 
-asmlinkage long compat_sys_newlstat(const char __user * filename,
-               struct compat_stat __user *statbuf)
+COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
+                      struct compat_stat __user *, statbuf)
 {
        struct kstat stat;
        int error;
@@ -184,9 +184,9 @@ asmlinkage long compat_sys_newlstat(const char __user * filename,
 }
 
 #ifndef __ARCH_WANT_STAT64
-asmlinkage long compat_sys_newfstatat(unsigned int dfd,
-               const char __user *filename,
-               struct compat_stat __user *statbuf, int flag)
+COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
+                      const char __user *, filename,
+                      struct compat_stat __user *, statbuf, int, flag)
 {
        struct kstat stat;
        int error;
@@ -198,8 +198,8 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd,
 }
 #endif
 
-asmlinkage long compat_sys_newfstat(unsigned int fd,
-               struct compat_stat __user * statbuf)
+COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
+                      struct compat_stat __user *, statbuf)
 {
        struct kstat stat;
        int error = vfs_fstat(fd, &stat);
@@ -247,7 +247,7 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
  * The following statfs calls are copies of code from fs/statfs.c and
  * should be checked against those from time to time
  */
-asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
+COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
 {
        struct kstatfs tmp;
        int error = user_statfs(pathname, &tmp);
@@ -256,7 +256,7 @@ asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_sta
        return error;
 }
 
-asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf)
+COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
 {
        struct kstatfs tmp;
        int error = fd_statfs(fd, &tmp);
@@ -298,7 +298,7 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
        return 0;
 }
 
-asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
+COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
 {
        struct kstatfs tmp;
        int error;
@@ -312,7 +312,7 @@ asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t s
        return error;
 }
 
-asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
+COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
 {
        struct kstatfs tmp;
        int error;
@@ -331,7 +331,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c
  * Given how simple this syscall is that apporach is more maintainable
  * than the various conversion hacks.
  */
-asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u)
+COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
 {
        struct compat_ustat tmp;
        struct kstatfs sbuf;
@@ -399,8 +399,8 @@ static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *u
 }
 #endif
 
-asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
-               unsigned long arg)
+COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
+                      compat_ulong_t, arg)
 {
        mm_segment_t old_fs;
        struct flock f;
@@ -468,16 +468,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
        return ret;
 }
 
-asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
-               unsigned long arg)
+COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
+                      compat_ulong_t, arg)
 {
        if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
                return -EINVAL;
        return compat_sys_fcntl64(fd, cmd, arg);
 }
 
-asmlinkage long
-compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p)
+COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_reqs, u32 __user *, ctx32p)
 {
        long ret;
        aio_context_t ctx64;
@@ -496,32 +495,24 @@ compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p)
        return ret;
 }
 
-asmlinkage long
-compat_sys_io_getevents(aio_context_t ctx_id,
-                                unsigned long min_nr,
-                                unsigned long nr,
-                                struct io_event __user *events,
-                                struct compat_timespec __user *timeout)
+COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
+                      compat_long_t, min_nr,
+                      compat_long_t, nr,
+                      struct io_event __user *, events,
+                      struct compat_timespec __user *, timeout)
 {
-       long ret;
        struct timespec t;
        struct timespec __user *ut = NULL;
 
-       ret = -EFAULT;
-       if (unlikely(!access_ok(VERIFY_WRITE, events, 
-                               nr * sizeof(struct io_event))))
-               goto out;
        if (timeout) {
                if (get_compat_timespec(&t, timeout))
-                       goto out;
+                       return -EFAULT;
 
                ut = compat_alloc_user_space(sizeof(*ut));
                if (copy_to_user(ut, &t, sizeof(t)) )
-                       goto out;
+                       return -EFAULT;
        } 
-       ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut);
-out:
-       return ret;
+       return sys_io_getevents(ctx_id, min_nr, nr, events, ut);
 }
 
 /* A write operation does a read from user space and vice versa */
@@ -617,8 +608,8 @@ copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64)
 
 #define MAX_AIO_SUBMITS        (PAGE_SIZE/sizeof(struct iocb *))
 
-asmlinkage long
-compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb)
+COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
+                      int, nr, u32 __user *, iocb)
 {
        struct iocb __user * __user *iocb64; 
        long ret;
@@ -770,10 +761,10 @@ static int do_nfs4_super_data_conv(void *raw_data)
 #define NCPFS_NAME      "ncpfs"
 #define NFS4_NAME      "nfs4"
 
-asmlinkage long compat_sys_mount(const char __user * dev_name,
-                                const char __user * dir_name,
-                                const char __user * type, unsigned long flags,
-                                const void __user * data)
+COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
+                      const char __user *, dir_name,
+                      const char __user *, type, compat_ulong_t, flags,
+                      const void __user *, data)
 {
        char *kernel_type;
        unsigned long data_page;
@@ -869,8 +860,8 @@ efault:
        return -EFAULT;
 }
 
-asmlinkage long compat_sys_old_readdir(unsigned int fd,
-       struct compat_old_linux_dirent __user *dirent, unsigned int count)
+COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
+               struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
 {
        int error;
        struct fd f = fdget(fd);
@@ -948,8 +939,8 @@ efault:
        return -EFAULT;
 }
 
-asmlinkage long compat_sys_getdents(unsigned int fd,
-               struct compat_linux_dirent __user *dirent, unsigned int count)
+COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
+               struct compat_linux_dirent __user *, dirent, unsigned int, count)
 {
        struct fd f;
        struct compat_linux_dirent __user * lastdirent;
@@ -981,7 +972,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
        return error;
 }
 
-#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
+#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
 
 struct compat_getdents_callback64 {
        struct dir_context ctx;
@@ -1033,8 +1024,8 @@ efault:
        return -EFAULT;
 }
 
-asmlinkage long compat_sys_getdents64(unsigned int fd,
-               struct linux_dirent64 __user * dirent, unsigned int count)
+COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd,
+               struct linux_dirent64 __user *, dirent, unsigned int, count)
 {
        struct fd f;
        struct linux_dirent64 __user * lastdirent;
@@ -1066,7 +1057,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
        fdput(f);
        return error;
 }
-#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
+#endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */
 
 /*
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
@@ -1287,9 +1278,9 @@ out_nofds:
        return ret;
 }
 
-asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
-       compat_ulong_t __user *outp, compat_ulong_t __user *exp,
-       struct compat_timeval __user *tvp)
+COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
+       compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
+       struct compat_timeval __user *tvp)
 {
        struct timespec end_time, *to = NULL;
        struct compat_timeval tv;
@@ -1320,7 +1311,7 @@ struct compat_sel_arg_struct {
        compat_uptr_t tvp;
 };
 
-asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg)
+COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
 {
        struct compat_sel_arg_struct a;
 
@@ -1381,9 +1372,9 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
        return ret;
 }
 
-asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
-       compat_ulong_t __user *outp, compat_ulong_t __user *exp,
-       struct compat_timespec __user *tsp, void __user *sig)
+COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
+       compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
+       struct compat_timespec __user *, tsp, void __user *, sig)
 {
        compat_size_t sigsetsize = 0;
        compat_uptr_t up = 0;
@@ -1400,9 +1391,9 @@ asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
                                 sigsetsize);
 }
 
-asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
-       unsigned int nfds, struct compat_timespec __user *tsp,
-       const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
+COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
+       unsigned int,  nfds, struct compat_timespec __user *, tsp,
+       const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
 {
        compat_sigset_t ss32;
        sigset_t ksigmask, sigsaved;
index a81147e2e4ef2eef2c2fb330a0f9ce464e2c67f6..4d24d17bcfc1dc3ecd917f12f2a889da1a506e24 100644 (file)
@@ -88,6 +88,11 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
 #define        ELF_HWCAP               COMPAT_ELF_HWCAP
 #endif
 
+#ifdef COMPAT_ELF_HWCAP2
+#undef ELF_HWCAP2
+#define        ELF_HWCAP2              COMPAT_ELF_HWCAP2
+#endif
+
 #ifdef COMPAT_ARCH_DLINFO
 #undef ARCH_DLINFO
 #define        ARCH_DLINFO             COMPAT_ARCH_DLINFO
index 3881610b64384cee634367c3c35d237a4fa2f2aa..e82289047272d6e636583e20969f59450987da05 100644 (file)
@@ -1538,9 +1538,10 @@ static int compat_ioctl_check_table(unsigned int xcmd)
        return ioctl_pointer[i] == xcmd;
 }
 
-asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
-                               unsigned long arg)
+COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
+                      compat_ulong_t, arg32)
 {
+       unsigned long arg = arg32;
        struct fd f = fdget(fd);
        int error = -EBADF;
        if (!f.file)
index 265e0ce9769c70db65d5f9df11c4365f44c6dd29..ca02c13a84aa24d55b18bbced577ece923605665 100644 (file)
@@ -2833,9 +2833,9 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
        u32 dlen = ACCESS_ONCE(name->len);
        char *p;
 
-       if (*buflen < dlen + 1)
-               return -ENAMETOOLONG;
        *buflen -= dlen + 1;
+       if (*buflen < 0)
+               return -ENAMETOOLONG;
        p = *buffer -= dlen + 1;
        *p++ = '/';
        while (dlen--) {
index 8dd524f322847b346e119c6d5c5b3693de6fb8bc..cdb2971192a53fbfe2e340feb9819b7454f8ffa2 100644 (file)
@@ -21,7 +21,7 @@ static ssize_t efivarfs_file_write(struct file *file,
        u32 attributes;
        struct inode *inode = file->f_mapping->host;
        unsigned long datasize = count - sizeof(attributes);
-       ssize_t bytes = 0;
+       ssize_t bytes;
        bool set = false;
 
        if (count < sizeof(attributes))
@@ -33,14 +33,9 @@ static ssize_t efivarfs_file_write(struct file *file,
        if (attributes & ~(EFI_VARIABLE_MASK))
                return -EINVAL;
 
-       data = kmalloc(datasize, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
-               bytes = -EFAULT;
-               goto out;
-       }
+       data = memdup_user(userbuf + sizeof(attributes), datasize);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
 
        bytes = efivar_entry_set_get_size(var, attributes, &datasize,
                                          data, &set);
index e1529b4c79b1c29b300ab6519a94d7b748069e33..4f59402fdda541bd22349aad786a95d12cc6d089 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -748,11 +748,10 @@ EXPORT_SYMBOL(setup_arg_pages);
 
 #endif /* CONFIG_MMU */
 
-struct file *open_exec(const char *name)
+static struct file *do_open_exec(struct filename *name)
 {
        struct file *file;
        int err;
-       struct filename tmp = { .name = name };
        static const struct open_flags open_exec_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
                .acc_mode = MAY_EXEC | MAY_OPEN,
@@ -760,7 +759,7 @@ struct file *open_exec(const char *name)
                .lookup_flags = LOOKUP_FOLLOW,
        };
 
-       file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags);
+       file = do_filp_open(AT_FDCWD, name, &open_exec_flags);
        if (IS_ERR(file))
                goto out;
 
@@ -784,6 +783,12 @@ exit:
        fput(file);
        return ERR_PTR(err);
 }
+
+struct file *open_exec(const char *name)
+{
+       struct filename tmp = { .name = name };
+       return do_open_exec(&tmp);
+}
 EXPORT_SYMBOL(open_exec);
 
 int kernel_read(struct file *file, loff_t offset,
@@ -1162,7 +1167,7 @@ int prepare_bprm_creds(struct linux_binprm *bprm)
        return -ENOMEM;
 }
 
-void free_bprm(struct linux_binprm *bprm)
+static void free_bprm(struct linux_binprm *bprm)
 {
        free_arg_pages(bprm);
        if (bprm->cred) {
@@ -1432,7 +1437,7 @@ static int exec_binprm(struct linux_binprm *bprm)
 /*
  * sys_execve() executes a new program.
  */
-static int do_execve_common(const char *filename,
+static int do_execve_common(struct filename *filename,
                                struct user_arg_ptr argv,
                                struct user_arg_ptr envp)
 {
@@ -1441,6 +1446,9 @@ static int do_execve_common(const char *filename,
        struct files_struct *displaced;
        int retval;
 
+       if (IS_ERR(filename))
+               return PTR_ERR(filename);
+
        /*
         * We move the actual failure in case of RLIMIT_NPROC excess from
         * set*uid() to execve() because too many poorly written programs
@@ -1473,7 +1481,7 @@ static int do_execve_common(const char *filename,
        check_unsafe_exec(bprm);
        current->in_execve = 1;
 
-       file = open_exec(filename);
+       file = do_open_exec(filename);
        retval = PTR_ERR(file);
        if (IS_ERR(file))
                goto out_unmark;
@@ -1481,8 +1489,7 @@ static int do_execve_common(const char *filename,
        sched_exec();
 
        bprm->file = file;
-       bprm->filename = filename;
-       bprm->interp = filename;
+       bprm->filename = bprm->interp = filename->name;
 
        retval = bprm_mm_init(bprm);
        if (retval)
@@ -1523,6 +1530,7 @@ static int do_execve_common(const char *filename,
        acct_update_integrals(current);
        task_numa_free(current);
        free_bprm(bprm);
+       putname(filename);
        if (displaced)
                put_files_struct(displaced);
        return retval;
@@ -1544,10 +1552,11 @@ out_files:
        if (displaced)
                reset_files_struct(displaced);
 out_ret:
+       putname(filename);
        return retval;
 }
 
-int do_execve(const char *filename,
+int do_execve(struct filename *filename,
        const char __user *const __user *__argv,
        const char __user *const __user *__envp)
 {
@@ -1557,7 +1566,7 @@ int do_execve(const char *filename,
 }
 
 #ifdef CONFIG_COMPAT
-static int compat_do_execve(const char *filename,
+static int compat_do_execve(struct filename *filename,
        const compat_uptr_t __user *__argv,
        const compat_uptr_t __user *__envp)
 {
@@ -1607,25 +1616,13 @@ SYSCALL_DEFINE3(execve,
                const char __user *const __user *, argv,
                const char __user *const __user *, envp)
 {
-       struct filename *path = getname(filename);
-       int error = PTR_ERR(path);
-       if (!IS_ERR(path)) {
-               error = do_execve(path->name, argv, envp);
-               putname(path);
-       }
-       return error;
+       return do_execve(getname(filename), argv, envp);
 }
 #ifdef CONFIG_COMPAT
-asmlinkage long compat_sys_execve(const char __user * filename,
-       const compat_uptr_t __user * argv,
-       const compat_uptr_t __user * envp)
+COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
+       const compat_uptr_t __user *, argv,
+       const compat_uptr_t __user *, envp)
 {
-       struct filename *path = getname(filename);
-       int error = PTR_ERR(path);
-       if (!IS_ERR(path)) {
-               error = compat_do_execve(path->name, argv, envp);
-               putname(path);
-       }
-       return error;
+       return compat_do_execve(getname(filename), argv, envp);
 }
 #endif
index ece55565b9cd35575c454d44656c63321d89e0f9..d3a534fdc5ff6c766131e5d843591149736cc4d8 100644 (file)
@@ -771,6 +771,8 @@ do {                                                                               \
        if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime))                      \
                (einode)->xtime.tv_sec =                                       \
                        (signed)le32_to_cpu((raw_inode)->xtime);               \
+       else                                                                   \
+               (einode)->xtime.tv_sec = 0;                                    \
        if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))            \
                ext4_decode_extra_time(&(einode)->xtime,                       \
                                       raw_inode->xtime ## _extra);            \
index 10cff4736b116185f9d0a2cea73dca9423c6fb92..74bc2d549c58bd57d60ebcb0a143a3fdf4e95997 100644 (file)
@@ -3906,6 +3906,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
                } else
                        err = ret;
                map->m_flags |= EXT4_MAP_MAPPED;
+               map->m_pblk = newblock;
                if (allocated > map->m_len)
                        allocated = map->m_len;
                map->m_len = allocated;
index 43e64f6022eb4af22e7ac95eb6aaa34e7e6735a9..1a5073959f322655b93ade8189107b9148d244ed 100644 (file)
@@ -152,7 +152,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
        if (ret > 0) {
                ssize_t err;
 
-               err = generic_write_sync(file, pos, ret);
+               err = generic_write_sync(file, iocb->ki_pos - ret, ret);
                if (err < 0 && ret > 0)
                        ret = err;
        }
index 6e39895a91b80aaae3914cc3a51756b3fa48a4c8..24bfd7ff30491457283b22821eb5a9b93b2adec4 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 #include <linux/aio.h>
+#include <linux/bitops.h>
 
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -3921,18 +3922,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc)
 void ext4_set_inode_flags(struct inode *inode)
 {
        unsigned int flags = EXT4_I(inode)->i_flags;
+       unsigned int new_fl = 0;
 
-       inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
        if (flags & EXT4_SYNC_FL)
-               inode->i_flags |= S_SYNC;
+               new_fl |= S_SYNC;
        if (flags & EXT4_APPEND_FL)
-               inode->i_flags |= S_APPEND;
+               new_fl |= S_APPEND;
        if (flags & EXT4_IMMUTABLE_FL)
-               inode->i_flags |= S_IMMUTABLE;
+               new_fl |= S_IMMUTABLE;
        if (flags & EXT4_NOATIME_FL)
-               inode->i_flags |= S_NOATIME;
+               new_fl |= S_NOATIME;
        if (flags & EXT4_DIRSYNC_FL)
-               inode->i_flags |= S_DIRSYNC;
+               new_fl |= S_DIRSYNC;
+       set_mask_bits(&inode->i_flags,
+                     S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl);
 }
 
 /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
index 6bea80614d77c19c6ca7b1ac9160d64f1115b36e..a2a837f0040743d9e76608904c5b2cb429aaadd2 100644 (file)
@@ -140,7 +140,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
        handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2);
        if (IS_ERR(handle)) {
                err = -EINVAL;
-               goto swap_boot_out;
+               goto journal_err_out;
        }
 
        /* Protect extent tree against block allocations via delalloc */
@@ -198,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
 
        ext4_double_up_write_data_sem(inode, inode_bl);
 
+journal_err_out:
        ext4_inode_resume_unlocked_dio(inode);
        ext4_inode_resume_unlocked_dio(inode_bl);
 
index c5adbb318a90c8c612c97dab1a47c0143b19ef77..f3b84cd9de566ff7b1ffb5d16e75483e9b9d06f2 100644 (file)
@@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb,
        ext4_group_t group;
        ext4_group_t last_group;
        unsigned overhead;
+       __u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0;
 
        BUG_ON(flex_gd->count == 0 || group_data == NULL);
 
@@ -266,7 +267,7 @@ next_group:
        src_group++;
        for (; src_group <= last_group; src_group++) {
                overhead = ext4_group_overhead_blocks(sb, src_group);
-               if (overhead != 0)
+               if (overhead == 0)
                        last_blk += group_data[src_group - group].blocks_count;
                else
                        break;
@@ -280,8 +281,7 @@ next_group:
                group = ext4_get_group_number(sb, start_blk - 1);
                group -= group_data[0].group;
                group_data[group].free_blocks_count--;
-               if (flexbg_size > 1)
-                       flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+               flex_gd->bg_flags[group] &= uninit_mask;
        }
 
        /* Allocate inode bitmaps */
@@ -292,22 +292,30 @@ next_group:
                group = ext4_get_group_number(sb, start_blk - 1);
                group -= group_data[0].group;
                group_data[group].free_blocks_count--;
-               if (flexbg_size > 1)
-                       flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
+               flex_gd->bg_flags[group] &= uninit_mask;
        }
 
        /* Allocate inode tables */
        for (; it_index < flex_gd->count; it_index++) {
-               if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk)
+               unsigned int itb = EXT4_SB(sb)->s_itb_per_group;
+               ext4_fsblk_t next_group_start;
+
+               if (start_blk + itb > last_blk)
                        goto next_group;
                group_data[it_index].inode_table = start_blk;
-               group = ext4_get_group_number(sb, start_blk - 1);
+               group = ext4_get_group_number(sb, start_blk);
+               next_group_start = ext4_group_first_block_no(sb, group + 1);
                group -= group_data[0].group;
-               group_data[group].free_blocks_count -=
-                                       EXT4_SB(sb)->s_itb_per_group;
-               if (flexbg_size > 1)
-                       flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT;
 
+               if (start_blk + itb > next_group_start) {
+                       flex_gd->bg_flags[group + 1] &= uninit_mask;
+                       overhead = start_blk + itb - next_group_start;
+                       group_data[group + 1].free_blocks_count -= overhead;
+                       itb -= overhead;
+               }
+
+               group_data[group].free_blocks_count -= itb;
+               flex_gd->bg_flags[group] &= uninit_mask;
                start_blk += EXT4_SB(sb)->s_itb_per_group;
        }
 
@@ -401,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
                start = ext4_group_first_block_no(sb, group);
                group -= flex_gd->groups[0].group;
 
-               count2 = sb->s_blocksize * 8 - (block - start);
+               count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start);
                if (count2 > count)
                        count2 = count;
 
@@ -620,7 +628,7 @@ handle_ib:
                        if (err)
                                goto out;
                        count = group_table_count[j];
-                       start = group_data[i].block_bitmap;
+                       start = (&group_data[i].block_bitmap)[j];
                        block = start;
                }
 
index 1f7784de05b6c6afad4d7437202ceb6efeec3399..710fed2377d415a32b0658faabde9960ff639b84 100644 (file)
@@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        for (i = 0; i < 4; i++)
                sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
        sbi->s_def_hash_version = es->s_def_hash_version;
-       i = le32_to_cpu(es->s_flags);
-       if (i & EXT2_FLAGS_UNSIGNED_HASH)
-               sbi->s_hash_unsigned = 3;
-       else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
+       if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+               i = le32_to_cpu(es->s_flags);
+               if (i & EXT2_FLAGS_UNSIGNED_HASH)
+                       sbi->s_hash_unsigned = 3;
+               else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
 #ifdef __CHAR_UNSIGNED__
-               es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
-               sbi->s_hash_unsigned = 3;
+                       if (!(sb->s_flags & MS_RDONLY))
+                               es->s_flags |=
+                                       cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
+                       sbi->s_hash_unsigned = 3;
 #else
-               es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
+                       if (!(sb->s_flags & MS_RDONLY))
+                               es->s_flags |=
+                                       cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
 #endif
+               }
        }
 
        /* Handle clustersize */
index 771578b33fb6c7fee9a7c28d01138e4670e07e59..b61293badfb1a9c98742a5bcc790751979251741 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -34,7 +34,7 @@ static void *alloc_fdmem(size_t size)
         * vmalloc() if the allocation size will be considered "large" by the VM.
         */
        if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
-               void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
+               void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY);
                if (data != NULL)
                        return data;
        }
@@ -497,7 +497,7 @@ repeat:
        error = fd;
 #if 1
        /* Sanity check */
-       if (rcu_dereference_raw(fdt->fd[fd]) != NULL) {
+       if (rcu_access_pointer(fdt->fd[fd]) != NULL) {
                printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
                rcu_assign_pointer(fdt->fd[fd], NULL);
        }
@@ -683,35 +683,54 @@ EXPORT_SYMBOL(fget_raw);
  * The fput_needed flag returned by fget_light should be passed to the
  * corresponding fput_light.
  */
-struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed)
+static unsigned long __fget_light(unsigned int fd, fmode_t mask)
 {
        struct files_struct *files = current->files;
        struct file *file;
 
-       *fput_needed = 0;
        if (atomic_read(&files->count) == 1) {
                file = __fcheck_files(files, fd);
-               if (file && (file->f_mode & mask))
-                       file = NULL;
+               if (!file || unlikely(file->f_mode & mask))
+                       return 0;
+               return (unsigned long)file;
        } else {
                file = __fget(fd, mask);
-               if (file)
-                       *fput_needed = 1;
+               if (!file)
+                       return 0;
+               return FDPUT_FPUT | (unsigned long)file;
        }
-
-       return file;
 }
-struct file *fget_light(unsigned int fd, int *fput_needed)
+unsigned long __fdget(unsigned int fd)
 {
-       return __fget_light(fd, FMODE_PATH, fput_needed);
+       return __fget_light(fd, FMODE_PATH);
 }
-EXPORT_SYMBOL(fget_light);
+EXPORT_SYMBOL(__fdget);
 
-struct file *fget_raw_light(unsigned int fd, int *fput_needed)
+unsigned long __fdget_raw(unsigned int fd)
 {
-       return __fget_light(fd, 0, fput_needed);
+       return __fget_light(fd, 0);
 }
 
+unsigned long __fdget_pos(unsigned int fd)
+{
+       unsigned long v = __fdget(fd);
+       struct file *file = (struct file *)(v & ~3);
+
+       if (file && (file->f_mode & FMODE_ATOMIC_POS)) {
+               if (file_count(file) > 1) {
+                       v |= FDPUT_POS_UNLOCK;
+                       mutex_lock(&file->f_pos_lock);
+               }
+       }
+       return v;
+}
+
+/*
+ * We only lock f_pos if we have threads or if the file might be
+ * shared with another process. In both cases we'll have an elevated
+ * file count (done either by fdget() or by fork()).
+ */
+
 void set_close_on_exec(unsigned int fd, int flag)
 {
        struct files_struct *files = current->files;
index 5fff9030be34df26aff0c0ed56081aee1306bf02..5b24008ea4f678b668ff2a52fa41f1812b579645 100644 (file)
@@ -135,6 +135,7 @@ struct file *get_empty_filp(void)
        atomic_long_set(&f->f_count, 1);
        rwlock_init(&f->f_owner.lock);
        spin_lock_init(&f->f_lock);
+       mutex_init(&f->f_pos_lock);
        eventpoll_init_file(f);
        /* f->f_version: 0 */
        return f;
index e0259a163f98e69000c28bdb78fcf2b77c2bed2d..d754e3cf99a85af0c433e71846db6ee051751ebd 100644 (file)
 struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
-       /*
-        * Write only inodes dirtied before this time. Don't forget to set
-        * older_than_this_is_set when you set this.
-        */
-       unsigned long older_than_this;
+       unsigned long *older_than_this;
        enum writeback_sync_modes sync_mode;
        unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
        unsigned int for_sync:1;        /* sync(2) WB_SYNC_ALL writeback */
-       unsigned int older_than_this_is_set:1;
        enum wb_reason reason;          /* why was writeback initiated? */
 
        struct list_head list;          /* pending work list */
@@ -252,10 +247,10 @@ static int move_expired_inodes(struct list_head *delaying_queue,
        int do_sb_sort = 0;
        int moved = 0;
 
-       WARN_ON_ONCE(!work->older_than_this_is_set);
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
-               if (inode_dirtied_after(inode, work->older_than_this))
+               if (work->older_than_this &&
+                   inode_dirtied_after(inode, *work->older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
@@ -742,8 +737,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
                .sync_mode      = WB_SYNC_NONE,
                .range_cyclic   = 1,
                .reason         = reason,
-               .older_than_this = jiffies,
-               .older_than_this_is_set = 1,
        };
 
        spin_lock(&wb->list_lock);
@@ -802,13 +795,12 @@ static long wb_writeback(struct bdi_writeback *wb,
 {
        unsigned long wb_start = jiffies;
        long nr_pages = work->nr_pages;
+       unsigned long oldest_jif;
        struct inode *inode;
        long progress;
 
-       if (!work->older_than_this_is_set) {
-               work->older_than_this = jiffies;
-               work->older_than_this_is_set = 1;
-       }
+       oldest_jif = jiffies;
+       work->older_than_this = &oldest_jif;
 
        spin_lock(&wb->list_lock);
        for (;;) {
@@ -842,10 +834,10 @@ static long wb_writeback(struct bdi_writeback *wb,
                 * safe.
                 */
                if (work->for_kupdate) {
-                       work->older_than_this = jiffies -
+                       oldest_jif = jiffies -
                                msecs_to_jiffies(dirty_expire_interval * 10);
                } else if (work->for_background)
-                       work->older_than_this = jiffies;
+                       oldest_jif = jiffies;
 
                trace_writeback_start(wb->bdi, work);
                if (list_empty(&wb->b_io))
@@ -1357,21 +1349,18 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb);
 
 /**
  * sync_inodes_sb      -       sync sb inode pages
- * @sb:                        the superblock
- * @older_than_this:   timestamp
+ * @sb: the superblock
  *
  * This function writes and waits on any dirty inode belonging to this
- * superblock that has been dirtied before given timestamp.
+ * super_block.
  */
-void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
+void sync_inodes_sb(struct super_block *sb)
 {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
                .sb             = sb,
                .sync_mode      = WB_SYNC_ALL,
                .nr_pages       = LONG_MAX,
-               .older_than_this = older_than_this,
-               .older_than_this_is_set = 1,
                .range_cyclic   = 0,
                .done           = &done,
                .reason         = WB_REASON_SYNC,
index e1959efad64fa0f4101541683e8c422d27a37aa7..b5ebc2d7d80d30d39b21243561e1f7d26c300329 100644 (file)
@@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj)
        struct fscache_object *xobj;
        struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL;
 
+       ASSERT(RB_EMPTY_NODE(&obj->objlist_link));
+
        write_lock(&fscache_object_list_lock);
 
        while (*p) {
@@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj)
  */
 void fscache_objlist_remove(struct fscache_object *obj)
 {
+       if (RB_EMPTY_NODE(&obj->objlist_link))
+               return;
+
        write_lock(&fscache_object_list_lock);
 
        BUG_ON(RB_EMPTY_ROOT(&fscache_object_list));
index 53d35c5042404738c213233220500feaf7686ae8..d3b4539f16515451cdd691fd853927d00fa3f8a8 100644 (file)
@@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object,
        object->cache = cache;
        object->cookie = cookie;
        object->parent = NULL;
+#ifdef CONFIG_FSCACHE_OBJECT_LIST
+       RB_CLEAR_NODE(&object->objlist_link);
+#endif
 
        object->oob_event_mask = 0;
        for (t = object->oob_table; t->events; t++)
index 968ce411db53e807b6f3b0fd216cd6730f226b5d..32602c667b4aaf697c97b7f7e709d808328a5468 100644 (file)
@@ -103,6 +103,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry,
                folder = &entry->folder;
                memset(folder, 0, sizeof(*folder));
                folder->type = cpu_to_be16(HFSPLUS_FOLDER);
+               if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags))
+                       folder->flags |= cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT);
                folder->id = cpu_to_be32(inode->i_ino);
                HFSPLUS_I(inode)->create_date =
                        folder->create_date =
@@ -203,6 +205,36 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
        return hfs_brec_find(fd, hfs_find_rec_by_key);
 }
 
+static void hfsplus_subfolders_inc(struct inode *dir)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+
+       if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
+               /*
+                * Increment subfolder count. Note, the value is only meaningful
+                * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set.
+                */
+               HFSPLUS_I(dir)->subfolders++;
+       }
+}
+
+static void hfsplus_subfolders_dec(struct inode *dir)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
+
+       if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) {
+               /*
+                * Decrement subfolder count. Note, the value is only meaningful
+                * for folders with HFSPLUS_HAS_FOLDER_COUNT flag set.
+                *
+                * Check for zero. Some subfolders may have been created
+                * by an implementation ignorant of this counter.
+                */
+               if (HFSPLUS_I(dir)->subfolders)
+                       HFSPLUS_I(dir)->subfolders--;
+       }
+}
+
 int hfsplus_create_cat(u32 cnid, struct inode *dir,
                struct qstr *str, struct inode *inode)
 {
@@ -247,6 +279,8 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir,
                goto err1;
 
        dir->i_size++;
+       if (S_ISDIR(inode->i_mode))
+               hfsplus_subfolders_inc(dir);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
        hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
 
@@ -336,6 +370,8 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
                goto out;
 
        dir->i_size--;
+       if (type == HFSPLUS_FOLDER)
+               hfsplus_subfolders_dec(dir);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
        hfsplus_mark_inode_dirty(dir, HFSPLUS_I_CAT_DIRTY);
 
@@ -380,6 +416,7 @@ int hfsplus_rename_cat(u32 cnid,
 
        hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
                                src_fd.entrylength);
+       type = be16_to_cpu(entry.type);
 
        /* create new dir entry with the data from the old entry */
        hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
@@ -394,6 +431,8 @@ int hfsplus_rename_cat(u32 cnid,
        if (err)
                goto out;
        dst_dir->i_size++;
+       if (type == HFSPLUS_FOLDER)
+               hfsplus_subfolders_inc(dst_dir);
        dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC;
 
        /* finally remove the old entry */
@@ -405,6 +444,8 @@ int hfsplus_rename_cat(u32 cnid,
        if (err)
                goto out;
        src_dir->i_size--;
+       if (type == HFSPLUS_FOLDER)
+               hfsplus_subfolders_dec(src_dir);
        src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC;
 
        /* remove old thread entry */
index 08846425b67ffa112b7978650e1521b74955a1dc..62d571eb69bae9c7d04b5c27238b9fa2a1d4a633 100644 (file)
@@ -242,6 +242,7 @@ struct hfsplus_inode_info {
         */
        sector_t fs_blocks;
        u8 userflags;           /* BSD user file flags */
+       u32 subfolders;         /* Subfolder count (HFSX only) */
        struct list_head open_dir_list;
        loff_t phys_size;
 
index 8ffb3a8ffe75b9d6374cb9198d83d5dce5553457..5a126828d85eb011714b067976f0a14981103c7c 100644 (file)
@@ -261,7 +261,7 @@ struct hfsplus_cat_folder {
        struct DInfo user_info;
        struct DXInfo finder_info;
        __be32 text_encoding;
-       u32 reserved;
+       __be32 subfolders;      /* Subfolder count in HFSX. Reserved in HFS+. */
 } __packed;
 
 /* HFS file info (stolen from hfs.h) */
@@ -301,11 +301,13 @@ struct hfsplus_cat_file {
        struct hfsplus_fork_raw rsrc_fork;
 } __packed;
 
-/* File attribute bits */
+/* File and folder flag bits */
 #define HFSPLUS_FILE_LOCKED            0x0001
 #define HFSPLUS_FILE_THREAD_EXISTS     0x0002
 #define HFSPLUS_XATTR_EXISTS           0x0004
 #define HFSPLUS_ACL_EXISTS             0x0008
+#define HFSPLUS_HAS_FOLDER_COUNT       0x0010  /* Folder has subfolder count
+                                                * (HFSX only) */
 
 /* HFS+ catalog thread (part of a cat_entry) */
 struct hfsplus_cat_thread {
index fa929f325f87502074d66e208c1a57feba089c82..a4f45bd88a631ad5a153a8f45fdd1044a3637c1c 100644 (file)
@@ -375,6 +375,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
        hip->extent_state = 0;
        hip->flags = 0;
        hip->userflags = 0;
+       hip->subfolders = 0;
        memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
        memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
        hip->alloc_blocks = 0;
@@ -494,6 +495,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
                HFSPLUS_I(inode)->create_date = folder->create_date;
                HFSPLUS_I(inode)->fs_blocks = 0;
+               if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
+                       HFSPLUS_I(inode)->subfolders =
+                               be32_to_cpu(folder->subfolders);
+               }
                inode->i_op = &hfsplus_dir_inode_operations;
                inode->i_fop = &hfsplus_dir_operations;
        } else if (type == HFSPLUS_FILE) {
@@ -566,6 +571,10 @@ int hfsplus_cat_write_inode(struct inode *inode)
                folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
                folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
                folder->valence = cpu_to_be32(inode->i_size - 2);
+               if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
+                       folder->subfolders =
+                               cpu_to_be32(HFSPLUS_I(inode)->subfolders);
+               }
                hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
                                         sizeof(struct hfsplus_cat_folder));
        } else if (HFSPLUS_IS_RSRC(inode)) {
index 968eab5bc1f5623f09169c65f178518dbd87ee2b..68537e8b7a0934859048ecd4cfb0e67cdcb6b819 100644 (file)
@@ -75,7 +75,7 @@ int hfsplus_parse_options_remount(char *input, int *force)
        int token;
 
        if (!input)
-               return 0;
+               return 1;
 
        while ((p = strsep(&input, ",")) != NULL) {
                if (!*p)
index 8360674c85bcb98af88d6aaff3ee4c46fe6f31bf..60bb365f54a52efb8ff859ff746ac1af201bb7d2 100644 (file)
@@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type,
         * similarly constrained call sites
         */
        ret = start_this_handle(journal, handle, GFP_NOFS);
-       if (ret < 0)
+       if (ret < 0) {
                jbd2_journal_free_reserved(handle);
+               return ret;
+       }
        handle->h_type = type;
        handle->h_line_no = line_no;
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(jbd2_journal_start_reserved);
 
index e973b85d6afd9f136bcae002cbe70432000e5a15..5a8ea16eedbcd1d634feedce069637a717c49c19 100644 (file)
@@ -86,6 +86,8 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
                rc = posix_acl_equiv_mode(acl, &inode->i_mode);
                if (rc < 0)
                        return rc;
+               inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(inode);
                if (rc == 0)
                        acl = NULL;
                break;
index 3bd5ee45f7b3a13cf3dcc65f824fd8dad5ac6960..46325d5c34fc37f1e2861c959e875886bfef124c 100644 (file)
@@ -854,9 +854,6 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        int rc;
        tid_t tid;
 
-       if ((rc = can_set_xattr(inode, name, value, value_len)))
-               return rc;
-
        /*
         * If this is a request for a synthetic attribute in the system.*
         * namespace use the generic infrastructure to resolve a handler
@@ -865,6 +862,9 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_setxattr(dentry, name, value, value_len, flags);
 
+       if ((rc = can_set_xattr(inode, name, value, value_len)))
+               return rc;
+
        if (value == NULL) {    /* empty EA, do not remove */
                value = "";
                value_len = 0;
@@ -1034,9 +1034,6 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
        int rc;
        tid_t tid;
 
-       if ((rc = can_set_xattr(inode, name, NULL, 0)))
-               return rc;
-
        /*
         * If this is a request for a synthetic attribute in the system.*
         * namespace use the generic infrastructure to resolve a handler
@@ -1045,6 +1042,9 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_removexattr(dentry, name);
 
+       if ((rc = can_set_xattr(inode, name, NULL, 0)))
+               return rc;
+
        tid = txBegin(inode->i_sb, 0);
        mutex_lock(&ji->commit_mutex);
        rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
@@ -1061,7 +1061,7 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
  * attributes are handled directly.
  */
 const struct xattr_handler *jfs_xattr_handlers[] = {
-#ifdef JFS_POSIX_ACL
+#ifdef CONFIG_JFS_POSIX_ACL
        &posix_acl_access_xattr_handler,
        &posix_acl_default_xattr_handler,
 #endif
index 5104cf5d25c5af6d28996bbe9b4a00700bf4479c..bd6e18be6e1a231c10867bc8f4e292e49353d03f 100644 (file)
@@ -187,19 +187,23 @@ static void kernfs_deactivate(struct kernfs_node *kn)
 
        kn->u.completion = (void *)&wait;
 
-       rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_);
+       if (kn->flags & KERNFS_LOCKDEP)
+               rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_);
        /* atomic_add_return() is a mb(), put_active() will always see
         * the updated kn->u.completion.
         */
        v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active);
 
        if (v != KN_DEACTIVATED_BIAS) {
-               lock_contended(&kn->dep_map, _RET_IP_);
+               if (kn->flags & KERNFS_LOCKDEP)
+                       lock_contended(&kn->dep_map, _RET_IP_);
                wait_for_completion(&wait);
        }
 
-       lock_acquired(&kn->dep_map, _RET_IP_);
-       rwsem_release(&kn->dep_map, 1, _RET_IP_);
+       if (kn->flags & KERNFS_LOCKDEP) {
+               lock_acquired(&kn->dep_map, _RET_IP_);
+               rwsem_release(&kn->dep_map, 1, _RET_IP_);
+       }
 }
 
 /**
index 0d6ce895a9eec0ce3b3329d1353b594d353aeacb..0f4152defe7b6f96afa752acdbc075a512bc8c5d 100644 (file)
@@ -94,6 +94,7 @@ const void *kernfs_super_ns(struct super_block *sb)
  * @fs_type: file_system_type of the fs being mounted
  * @flags: mount flags specified for the mount
  * @root: kernfs_root of the hierarchy being mounted
+ * @new_sb_created: tell the caller if we allocated a new superblock
  * @ns: optional namespace tag of the mount
  *
  * This is to be called from each kernfs user's file_system_type->mount()
@@ -104,7 +105,8 @@ const void *kernfs_super_ns(struct super_block *sb)
  * The return value can be passed to the vfs layer verbatim.
  */
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-                              struct kernfs_root *root, const void *ns)
+                              struct kernfs_root *root, bool *new_sb_created,
+                              const void *ns)
 {
        struct super_block *sb;
        struct kernfs_super_info *info;
@@ -122,6 +124,10 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
                kfree(info);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
+
+       if (new_sb_created)
+               *new_sb_created = !sb->s_root;
+
        if (!sb->s_root) {
                error = kernfs_fill_super(sb);
                if (error) {
index e066a3902973640ae3d75dc0c768ceb8f15eb9d8..ab798a88ec1d52347afe05d4b8ed2eff13151de1 100644 (file)
@@ -779,6 +779,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
        struct nlm_file         *file = block->b_file;
        struct nlm_lock         *lock = &block->b_call->a_args.lock;
        int                     error;
+       loff_t                  fl_start, fl_end;
 
        dprintk("lockd: grant blocked lock %p\n", block);
 
@@ -796,9 +797,16 @@ nlmsvc_grant_blocked(struct nlm_block *block)
        }
 
        /* Try the lock operation again */
+       /* vfs_lock_file() can mangle fl_start and fl_end, but we need
+        * them unchanged for the GRANT_MSG
+        */
        lock->fl.fl_flags |= FL_SLEEP;
+       fl_start = lock->fl.fl_start;
+       fl_end = lock->fl.fl_end;
        error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
        lock->fl.fl_flags &= ~FL_SLEEP;
+       lock->fl.fl_start = fl_start;
+       lock->fl.fl_end = fl_end;
 
        switch (error) {
        case 0:
index a17458ca6f29e4dbf1f1a1b8bb9e97949b279d29..b29e42f05f3442b887e58ca1972a9333ec474bd7 100644 (file)
@@ -19,13 +19,13 @@ struct mnt_pcp {
 };
 
 struct mountpoint {
-       struct list_head m_hash;
+       struct hlist_node m_hash;
        struct dentry *m_dentry;
        int m_count;
 };
 
 struct mount {
-       struct list_head mnt_hash;
+       struct hlist_node mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
index d580df2e6804d0863d555234388a34397387c3e6..4b491b4319905b2dd6698d3f58aae1d0d0141499 100644 (file)
@@ -196,6 +196,7 @@ recopy:
                goto error;
 
        result->uptr = filename;
+       result->aname = NULL;
        audit_getname(result);
        return result;
 
@@ -210,6 +211,35 @@ getname(const char __user * filename)
        return getname_flags(filename, 0, NULL);
 }
 
+/*
+ * The "getname_kernel()" interface doesn't do pathnames longer
+ * than EMBEDDED_NAME_MAX. Deal with it - you're a kernel user.
+ */
+struct filename *
+getname_kernel(const char * filename)
+{
+       struct filename *result;
+       char *kname;
+       int len;
+
+       len = strlen(filename);
+       if (len >= EMBEDDED_NAME_MAX)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       result = __getname();
+       if (unlikely(!result))
+               return ERR_PTR(-ENOMEM);
+
+       kname = (char *)result + sizeof(*result);
+       result->name = kname;
+       result->uptr = NULL;
+       result->aname = NULL;
+       result->separate = false;
+
+       strlcpy(kname, filename, EMBEDDED_NAME_MAX);
+       return result;
+}
+
 #ifdef CONFIG_AUDITSYSCALL
 void putname(struct filename *name)
 {
@@ -1079,7 +1109,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                        return false;
 
                if (!d_mountpoint(path->dentry))
-                       break;
+                       return true;
 
                mounted = __lookup_mnt(path->mnt, path->dentry);
                if (!mounted)
@@ -1095,20 +1125,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                 */
                *inode = path->dentry->d_inode;
        }
-       return true;
-}
-
-static void follow_mount_rcu(struct nameidata *nd)
-{
-       while (d_mountpoint(nd->path.dentry)) {
-               struct mount *mounted;
-               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
-               if (!mounted)
-                       break;
-               nd->path.mnt = &mounted->mnt;
-               nd->path.dentry = mounted->mnt.mnt_root;
-               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
-       }
+       return read_seqretry(&mount_lock, nd->m_seq);
 }
 
 static int follow_dotdot_rcu(struct nameidata *nd)
@@ -1136,7 +1153,17 @@ static int follow_dotdot_rcu(struct nameidata *nd)
                        break;
                nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
        }
-       follow_mount_rcu(nd);
+       while (d_mountpoint(nd->path.dentry)) {
+               struct mount *mounted;
+               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
+               if (!mounted)
+                       break;
+               nd->path.mnt = &mounted->mnt;
+               nd->path.dentry = mounted->mnt.mnt_root;
+               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
+               if (!read_seqretry(&mount_lock, nd->m_seq))
+                       goto failed;
+       }
        nd->inode = nd->path.dentry->d_inode;
        return 0;
 
@@ -1854,7 +1881,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 
                nd->path = f.file->f_path;
                if (flags & LOOKUP_RCU) {
-                       if (f.need_put)
+                       if (f.flags & FDPUT_FPUT)
                                *fp = f.file;
                        nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
                        rcu_read_lock();
index 22e536705c45d128ab8651759cea74d83f481ab1..2ffc5a2905d463e828c387fbfb92a31f219f98bc 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/proc_ns.h>
 #include <linux/magic.h>
+#include <linux/bootmem.h>
 #include "pnode.h"
 #include "internal.h"
 
-#define HASH_SHIFT ilog2(PAGE_SIZE / sizeof(struct list_head))
-#define HASH_SIZE (1UL << HASH_SHIFT)
+static unsigned int m_hash_mask __read_mostly;
+static unsigned int m_hash_shift __read_mostly;
+static unsigned int mp_hash_mask __read_mostly;
+static unsigned int mp_hash_shift __read_mostly;
+
+static __initdata unsigned long mhash_entries;
+static int __init set_mhash_entries(char *str)
+{
+       if (!str)
+               return 0;
+       mhash_entries = simple_strtoul(str, &str, 0);
+       return 1;
+}
+__setup("mhash_entries=", set_mhash_entries);
+
+static __initdata unsigned long mphash_entries;
+static int __init set_mphash_entries(char *str)
+{
+       if (!str)
+               return 0;
+       mphash_entries = simple_strtoul(str, &str, 0);
+       return 1;
+}
+__setup("mphash_entries=", set_mphash_entries);
 
 static int event;
 static DEFINE_IDA(mnt_id_ida);
@@ -36,8 +59,8 @@ static DEFINE_SPINLOCK(mnt_id_lock);
 static int mnt_id_start = 0;
 static int mnt_group_start = 1;
 
-static struct list_head *mount_hashtable __read_mostly;
-static struct list_head *mountpoint_hashtable __read_mostly;
+static struct hlist_head *mount_hashtable __read_mostly;
+static struct hlist_head *mountpoint_hashtable __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
 static DECLARE_RWSEM(namespace_sem);
 
@@ -55,12 +78,19 @@ EXPORT_SYMBOL_GPL(fs_kobj);
  */
 __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
 
-static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
+static inline struct hlist_head *m_hash(struct vfsmount *mnt, struct dentry *dentry)
 {
        unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES);
        tmp += ((unsigned long)dentry / L1_CACHE_BYTES);
-       tmp = tmp + (tmp >> HASH_SHIFT);
-       return tmp & (HASH_SIZE - 1);
+       tmp = tmp + (tmp >> m_hash_shift);
+       return &mount_hashtable[tmp & m_hash_mask];
+}
+
+static inline struct hlist_head *mp_hash(struct dentry *dentry)
+{
+       unsigned long tmp = ((unsigned long)dentry / L1_CACHE_BYTES);
+       tmp = tmp + (tmp >> mp_hash_shift);
+       return &mountpoint_hashtable[tmp & mp_hash_mask];
 }
 
 /*
@@ -187,7 +217,7 @@ static struct mount *alloc_vfsmnt(const char *name)
                mnt->mnt_writers = 0;
 #endif
 
-               INIT_LIST_HEAD(&mnt->mnt_hash);
+               INIT_HLIST_NODE(&mnt->mnt_hash);
                INIT_LIST_HEAD(&mnt->mnt_child);
                INIT_LIST_HEAD(&mnt->mnt_mounts);
                INIT_LIST_HEAD(&mnt->mnt_list);
@@ -575,10 +605,10 @@ bool legitimize_mnt(struct vfsmount *bastard, unsigned seq)
  */
 struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
 {
-       struct list_head *head = mount_hashtable + hash(mnt, dentry);
+       struct hlist_head *head = m_hash(mnt, dentry);
        struct mount *p;
 
-       list_for_each_entry_rcu(p, head, mnt_hash)
+       hlist_for_each_entry_rcu(p, head, mnt_hash)
                if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
                        return p;
        return NULL;
@@ -590,13 +620,17 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
  */
 struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
 {
-       struct list_head *head = mount_hashtable + hash(mnt, dentry);
-       struct mount *p;
-
-       list_for_each_entry_reverse(p, head, mnt_hash)
-               if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
-                       return p;
-       return NULL;
+       struct mount *p, *res;
+       res = p = __lookup_mnt(mnt, dentry);
+       if (!p)
+               goto out;
+       hlist_for_each_entry_continue(p, mnt_hash) {
+               if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry)
+                       break;
+               res = p;
+       }
+out:
+       return res;
 }
 
 /*
@@ -633,11 +667,11 @@ struct vfsmount *lookup_mnt(struct path *path)
 
 static struct mountpoint *new_mountpoint(struct dentry *dentry)
 {
-       struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
+       struct hlist_head *chain = mp_hash(dentry);
        struct mountpoint *mp;
        int ret;
 
-       list_for_each_entry(mp, chain, m_hash) {
+       hlist_for_each_entry(mp, chain, m_hash) {
                if (mp->m_dentry == dentry) {
                        /* might be worth a WARN_ON() */
                        if (d_unlinked(dentry))
@@ -659,7 +693,7 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry)
 
        mp->m_dentry = dentry;
        mp->m_count = 1;
-       list_add(&mp->m_hash, chain);
+       hlist_add_head(&mp->m_hash, chain);
        return mp;
 }
 
@@ -670,7 +704,7 @@ static void put_mountpoint(struct mountpoint *mp)
                spin_lock(&dentry->d_lock);
                dentry->d_flags &= ~DCACHE_MOUNTED;
                spin_unlock(&dentry->d_lock);
-               list_del(&mp->m_hash);
+               hlist_del(&mp->m_hash);
                kfree(mp);
        }
 }
@@ -712,7 +746,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path)
        mnt->mnt_parent = mnt;
        mnt->mnt_mountpoint = mnt->mnt.mnt_root;
        list_del_init(&mnt->mnt_child);
-       list_del_init(&mnt->mnt_hash);
+       hlist_del_init_rcu(&mnt->mnt_hash);
        put_mountpoint(mnt->mnt_mp);
        mnt->mnt_mp = NULL;
 }
@@ -739,15 +773,14 @@ static void attach_mnt(struct mount *mnt,
                        struct mountpoint *mp)
 {
        mnt_set_mountpoint(parent, mp, mnt);
-       list_add_tail(&mnt->mnt_hash, mount_hashtable +
-                       hash(&parent->mnt, mp->m_dentry));
+       hlist_add_head_rcu(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry));
        list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
 }
 
 /*
  * vfsmount lock must be held for write
  */
-static void commit_tree(struct mount *mnt)
+static void commit_tree(struct mount *mnt, struct mount *shadows)
 {
        struct mount *parent = mnt->mnt_parent;
        struct mount *m;
@@ -762,8 +795,11 @@ static void commit_tree(struct mount *mnt)
 
        list_splice(&head, n->list.prev);
 
-       list_add_tail(&mnt->mnt_hash, mount_hashtable +
-                               hash(&parent->mnt, mnt->mnt_mountpoint));
+       if (shadows)
+               hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash);
+       else
+               hlist_add_head_rcu(&mnt->mnt_hash,
+                               m_hash(&parent->mnt, mnt->mnt_mountpoint));
        list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
        touch_mnt_namespace(n);
 }
@@ -1153,26 +1189,28 @@ int may_umount(struct vfsmount *mnt)
 
 EXPORT_SYMBOL(may_umount);
 
-static LIST_HEAD(unmounted);   /* protected by namespace_sem */
+static HLIST_HEAD(unmounted);  /* protected by namespace_sem */
 
 static void namespace_unlock(void)
 {
        struct mount *mnt;
-       LIST_HEAD(head);
+       struct hlist_head head = unmounted;
 
-       if (likely(list_empty(&unmounted))) {
+       if (likely(hlist_empty(&head))) {
                up_write(&namespace_sem);
                return;
        }
 
-       list_splice_init(&unmounted, &head);
+       head.first->pprev = &head.first;
+       INIT_HLIST_HEAD(&unmounted);
+
        up_write(&namespace_sem);
 
        synchronize_rcu();
 
-       while (!list_empty(&head)) {
-               mnt = list_first_entry(&head, struct mount, mnt_hash);
-               list_del_init(&mnt->mnt_hash);
+       while (!hlist_empty(&head)) {
+               mnt = hlist_entry(head.first, struct mount, mnt_hash);
+               hlist_del_init(&mnt->mnt_hash);
                if (mnt->mnt_ex_mountpoint.mnt)
                        path_put(&mnt->mnt_ex_mountpoint);
                mntput(&mnt->mnt);
@@ -1193,16 +1231,19 @@ static inline void namespace_lock(void)
  */
 void umount_tree(struct mount *mnt, int how)
 {
-       LIST_HEAD(tmp_list);
+       HLIST_HEAD(tmp_list);
        struct mount *p;
+       struct mount *last = NULL;
 
-       for (p = mnt; p; p = next_mnt(p, mnt))
-               list_move(&p->mnt_hash, &tmp_list);
+       for (p = mnt; p; p = next_mnt(p, mnt)) {
+               hlist_del_init_rcu(&p->mnt_hash);
+               hlist_add_head(&p->mnt_hash, &tmp_list);
+       }
 
        if (how)
                propagate_umount(&tmp_list);
 
-       list_for_each_entry(p, &tmp_list, mnt_hash) {
+       hlist_for_each_entry(p, &tmp_list, mnt_hash) {
                list_del_init(&p->mnt_expire);
                list_del_init(&p->mnt_list);
                __touch_mnt_namespace(p->mnt_ns);
@@ -1220,8 +1261,13 @@ void umount_tree(struct mount *mnt, int how)
                        p->mnt_mp = NULL;
                }
                change_mnt_propagation(p, MS_PRIVATE);
+               last = p;
+       }
+       if (last) {
+               last->mnt_hash.next = unmounted.first;
+               unmounted.first = tmp_list.first;
+               unmounted.first->pprev = &unmounted.first;
        }
-       list_splice(&tmp_list, &unmounted);
 }
 
 static void shrink_submounts(struct mount *mnt);
@@ -1605,24 +1651,23 @@ static int attach_recursive_mnt(struct mount *source_mnt,
                        struct mountpoint *dest_mp,
                        struct path *parent_path)
 {
-       LIST_HEAD(tree_list);
+       HLIST_HEAD(tree_list);
        struct mount *child, *p;
+       struct hlist_node *n;
        int err;
 
        if (IS_MNT_SHARED(dest_mnt)) {
                err = invent_group_ids(source_mnt, true);
                if (err)
                        goto out;
-       }
-       err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
-       if (err)
-               goto out_cleanup_ids;
-
-       lock_mount_hash();
-
-       if (IS_MNT_SHARED(dest_mnt)) {
+               err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
+               if (err)
+                       goto out_cleanup_ids;
+               lock_mount_hash();
                for (p = source_mnt; p; p = next_mnt(p, source_mnt))
                        set_mnt_shared(p);
+       } else {
+               lock_mount_hash();
        }
        if (parent_path) {
                detach_mnt(source_mnt, parent_path);
@@ -1630,20 +1675,22 @@ static int attach_recursive_mnt(struct mount *source_mnt,
                touch_mnt_namespace(source_mnt->mnt_ns);
        } else {
                mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
-               commit_tree(source_mnt);
+               commit_tree(source_mnt, NULL);
        }
 
-       list_for_each_entry_safe(child, p, &tree_list, mnt_hash) {
-               list_del_init(&child->mnt_hash);
-               commit_tree(child);
+       hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
+               struct mount *q;
+               hlist_del_init(&child->mnt_hash);
+               q = __lookup_mnt_last(&child->mnt_parent->mnt,
+                                     child->mnt_mountpoint);
+               commit_tree(child, q);
        }
        unlock_mount_hash();
 
        return 0;
 
  out_cleanup_ids:
-       if (IS_MNT_SHARED(dest_mnt))
-               cleanup_group_ids(source_mnt, NULL);
+       cleanup_group_ids(source_mnt, NULL);
  out:
        return err;
 }
@@ -2777,18 +2824,24 @@ void __init mnt_init(void)
        mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
                        0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
 
-       mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
-       mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
+       mount_hashtable = alloc_large_system_hash("Mount-cache",
+                               sizeof(struct hlist_head),
+                               mhash_entries, 19,
+                               0,
+                               &m_hash_shift, &m_hash_mask, 0, 0);
+       mountpoint_hashtable = alloc_large_system_hash("Mountpoint-cache",
+                               sizeof(struct hlist_head),
+                               mphash_entries, 19,
+                               0,
+                               &mp_hash_shift, &mp_hash_mask, 0, 0);
 
        if (!mount_hashtable || !mountpoint_hashtable)
                panic("Failed to allocate mount hash table\n");
 
-       printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE);
-
-       for (u = 0; u < HASH_SIZE; u++)
-               INIT_LIST_HEAD(&mount_hashtable[u]);
-       for (u = 0; u < HASH_SIZE; u++)
-               INIT_LIST_HEAD(&mountpoint_hashtable[u]);
+       for (u = 0; u <= m_hash_mask; u++)
+               INIT_HLIST_HEAD(&mount_hashtable[u]);
+       for (u = 0; u <= mp_hash_mask; u++)
+               INIT_HLIST_HEAD(&mountpoint_hashtable[u]);
 
        kernfs_init();
 
index ef792f29f831c4c72e3e4edd7db9257165aca2fe..5d8ccecf5f5caada2de94bf30689ecd9e725a15a 100644 (file)
@@ -659,16 +659,19 @@ int nfs_async_inode_return_delegation(struct inode *inode,
 
        rcu_read_lock();
        delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (delegation == NULL)
+               goto out_enoent;
 
-       if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) {
-               rcu_read_unlock();
-               return -ENOENT;
-       }
+       if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid))
+               goto out_enoent;
        nfs_mark_return_delegation(server, delegation);
        rcu_read_unlock();
 
        nfs_delegation_run_state_manager(clp);
        return 0;
+out_enoent:
+       rcu_read_unlock();
+       return -ENOENT;
 }
 
 static struct inode *
index be38b573495a78ddf281629da6e5f85f98eed17b..4a48fe4b84b68c4e704aea84ea761e101a5ad0df 100644 (file)
@@ -1846,6 +1846,11 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
                                                        GFP_KERNEL)) {
                SetPageUptodate(page);
                unlock_page(page);
+               /*
+                * add_to_page_cache_lru() grabs an extra page refcount.
+                * Drop it here to avoid leaking this page later.
+                */
+               page_cache_release(page);
        } else
                __free_page(page);
 
index 28a0a3cbd3b7818ee255f3a3c57b738d098e48c3..360114ae8b829bf705eaf4feda49b8fe484de2c0 100644 (file)
@@ -164,17 +164,16 @@ static void nfs_zap_caches_locked(struct inode *inode)
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) {
                nfs_fscache_invalidate(inode);
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR
-                                       | NFS_INO_INVALID_LABEL
                                        | NFS_INO_INVALID_DATA
                                        | NFS_INO_INVALID_ACCESS
                                        | NFS_INO_INVALID_ACL
                                        | NFS_INO_REVAL_PAGECACHE;
        } else
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR
-                                       | NFS_INO_INVALID_LABEL
                                        | NFS_INO_INVALID_ACCESS
                                        | NFS_INO_INVALID_ACL
                                        | NFS_INO_REVAL_PAGECACHE;
+       nfs_zap_label_cache_locked(nfsi);
 }
 
 void nfs_zap_caches(struct inode *inode)
@@ -266,6 +265,13 @@ nfs_init_locked(struct inode *inode, void *opaque)
 }
 
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
+static void nfs_clear_label_invalid(struct inode *inode)
+{
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL;
+       spin_unlock(&inode->i_lock);
+}
+
 void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        struct nfs4_label *label)
 {
@@ -283,6 +289,7 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        __func__,
                                        (char *)label->label,
                                        label->len, error);
+               nfs_clear_label_invalid(inode);
        }
 }
 
@@ -1648,7 +1655,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                inode->i_blocks = fattr->du.nfs2.blocks;
 
        /* Update attrtimeo value if we're out of the unstable period */
-       if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) {
+       if (invalid & NFS_INO_INVALID_ATTR) {
                nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
                nfsi->attrtimeo_timestamp = now;
@@ -1661,7 +1668,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                }
        }
        invalid &= ~NFS_INO_INVALID_ATTR;
-       invalid &= ~NFS_INO_INVALID_LABEL;
        /* Don't invalidate the data if we were to blame */
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
                                || S_ISLNK(inode->i_mode)))
index 8b5cc04a86115e05f0a2e98e9b02a0b307b1b910..b46cf5a6732952460c68f6faeeb5479f355868d7 100644 (file)
@@ -176,7 +176,8 @@ extern struct nfs_server *nfs4_create_server(
 extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
                                                      struct nfs_fh *);
 extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
-                                       struct sockaddr *sap, size_t salen);
+                                       struct sockaddr *sap, size_t salen,
+                                       struct net *net);
 extern void nfs_free_server(struct nfs_server *server);
 extern struct nfs_server *nfs_clone_server(struct nfs_server *,
                                           struct nfs_fh *,
@@ -279,9 +280,18 @@ static inline void nfs4_label_free(struct nfs4_label *label)
        }
        return;
 }
+
+static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
+{
+       if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL))
+               nfsi->cache_validity |= NFS_INO_INVALID_LABEL;
+}
 #else
 static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
 static inline void nfs4_label_free(void *label) {}
+static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
+{
+}
 #endif /* CONFIG_NFS_V4_SECURITY_LABEL */
 
 /* proc.c */
index 9a5ca03fa539fc5fb61ea4516b0ce0b6f4ae10ea..871d6eda8dba1247e882919aff0cc20e9d0e3392 100644 (file)
@@ -80,7 +80,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
        }
 
        if (res.acl_access != NULL) {
-               if (posix_acl_equiv_mode(res.acl_access, NULL) ||
+               if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) ||
                    res.acl_access->a_count == 0) {
                        posix_acl_release(res.acl_access);
                        res.acl_access = NULL;
@@ -113,7 +113,7 @@ getout:
        return ERR_PTR(status);
 }
 
-int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
                struct posix_acl *dfacl)
 {
        struct nfs_server *server = NFS_SERVER(inode);
@@ -198,6 +198,15 @@ out:
        return status;
 }
 
+int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+               struct posix_acl *dfacl)
+{
+       int ret;
+       ret = __nfs3_proc_setacls(inode, acl, dfacl);
+       return (ret == -EOPNOTSUPP) ? 0 : ret;
+
+}
+
 int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        struct posix_acl *alloc = NULL, *dfacl = NULL;
@@ -225,7 +234,7 @@ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
                if (IS_ERR(alloc))
                        goto fail;
        }
-       status = nfs3_proc_setacls(inode, acl, dfacl);
+       status = __nfs3_proc_setacls(inode, acl, dfacl);
        posix_acl_release(alloc);
        return status;
 
@@ -233,25 +242,6 @@ fail:
        return PTR_ERR(alloc);
 }
 
-int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               umode_t mode)
-{
-       struct posix_acl *default_acl, *acl;
-       int error;
-
-       error = posix_acl_create(dir, &mode, &default_acl, &acl);
-       if (error)
-               return (error == -EOPNOTSUPP) ? 0 : error;
-
-       error = nfs3_proc_setacls(inode, acl, default_acl);
-
-       if (acl)
-               posix_acl_release(acl);
-       if (default_acl)
-               posix_acl_release(default_acl);
-       return error;
-}
-
 const struct xattr_handler *nfs3_xattr_handlers[] = {
        &posix_acl_access_xattr_handler,
        &posix_acl_default_xattr_handler,
index aa9bc973f36a31eacbca297c71f2cd9bb5fb81e9..a462ef0fb5d6dcda8bab6f211e8122d7d972b070 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/nfs_mount.h>
 #include <linux/freezer.h>
+#include <linux/xattr.h>
 
 #include "iostat.h"
 #include "internal.h"
index dbb3e1f30c68e25ea5a7905ffeb552fd8954cb81..0e46d3d1b6cc6c06854517c66ab4aa5f783cfb9e 100644 (file)
@@ -170,7 +170,7 @@ void nfs41_shutdown_client(struct nfs_client *clp)
 void nfs40_shutdown_client(struct nfs_client *clp)
 {
        if (clp->cl_slot_tbl) {
-               nfs4_release_slot_table(clp->cl_slot_tbl);
+               nfs4_shutdown_slot_table(clp->cl_slot_tbl);
                kfree(clp->cl_slot_tbl);
        }
 }
@@ -1135,6 +1135,7 @@ static int nfs_probe_destination(struct nfs_server *server)
  * @hostname: new end-point's hostname
  * @sap: new end-point's socket address
  * @salen: size of "sap"
+ * @net: net namespace
  *
  * The nfs_server must be quiescent before this function is invoked.
  * Either its session is drained (NFSv4.1+), or its transport is
@@ -1143,13 +1144,13 @@ static int nfs_probe_destination(struct nfs_server *server)
  * Returns zero on success, or a negative errno value.
  */
 int nfs4_update_server(struct nfs_server *server, const char *hostname,
-                      struct sockaddr *sap, size_t salen)
+                      struct sockaddr *sap, size_t salen, struct net *net)
 {
        struct nfs_client *clp = server->nfs_client;
        struct rpc_clnt *clnt = server->client;
        struct xprt_create xargs = {
                .ident          = clp->cl_proto,
-               .net            = &init_net,
+               .net            = net,
                .dstaddr        = sap,
                .addrlen        = salen,
                .servername     = hostname,
@@ -1189,7 +1190,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
        error = nfs4_set_client(server, hostname, sap, salen, buf,
                                clp->cl_rpcclient->cl_auth->au_flavor,
                                clp->cl_proto, clnt->cl_timeout,
-                               clp->cl_minorversion, clp->cl_net);
+                               clp->cl_minorversion, net);
        nfs_put_client(clp);
        if (error != 0) {
                nfs_server_insert_lists(server);
index 12c8132ad4081a3937c12ceebc991d1f61048093..b9a35c05b60f7f418ce91443d46dab88c690ca69 100644 (file)
@@ -324,8 +324,9 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
                        &rdata->res.seq_res,
                        task))
                return;
-       nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context,
-                       rdata->args.lock_context, FMODE_READ);
+       if (nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context,
+                       rdata->args.lock_context, FMODE_READ) == -EIO)
+               rpc_exit(task, -EIO); /* lost lock, terminate I/O */
 }
 
 static void filelayout_read_call_done(struct rpc_task *task, void *data)
@@ -435,8 +436,9 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data)
                        &wdata->res.seq_res,
                        task))
                return;
-       nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context,
-                       wdata->args.lock_context, FMODE_WRITE);
+       if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context,
+                       wdata->args.lock_context, FMODE_WRITE) == -EIO)
+               rpc_exit(task, -EIO); /* lost lock, terminate I/O */
 }
 
 static void filelayout_write_call_done(struct rpc_task *task, void *data)
index 4e7f05d3e9db77d1fe96533424362c4171201014..3d5dbf80d46a8c844bf7fd96c6db6935bb76d48b 100644 (file)
@@ -121,9 +121,8 @@ static int nfs4_validate_fspath(struct dentry *dentry,
 }
 
 static size_t nfs_parse_server_name(char *string, size_t len,
-               struct sockaddr *sa, size_t salen, struct nfs_server *server)
+               struct sockaddr *sa, size_t salen, struct net *net)
 {
-       struct net *net = rpc_net_ns(server->client);
        ssize_t ret;
 
        ret = rpc_pton(net, string, len, sa, salen);
@@ -223,6 +222,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
                                     const struct nfs4_fs_location *location)
 {
        const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+       struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client);
        struct vfsmount *mnt = ERR_PTR(-ENOENT);
        char *mnt_path;
        unsigned int maxbuflen;
@@ -248,8 +248,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
                        continue;
 
                mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len,
-                               mountdata->addr, addr_bufsize,
-                               NFS_SB(mountdata->sb));
+                               mountdata->addr, addr_bufsize, net);
                if (mountdata->addrlen == 0)
                        continue;
 
@@ -419,6 +418,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
                const struct nfs4_fs_location *location)
 {
        const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+       struct net *net = rpc_net_ns(server->client);
        struct sockaddr *sap;
        unsigned int s;
        size_t salen;
@@ -440,7 +440,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
                        continue;
 
                salen = nfs_parse_server_name(buf->data, buf->len,
-                                               sap, addr_bufsize, server);
+                                               sap, addr_bufsize, net);
                if (salen == 0)
                        continue;
                rpc_set_port(sap, NFS_PORT);
@@ -450,7 +450,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server,
                if (hostname == NULL)
                        break;
 
-               error = nfs4_update_server(server, hostname, sap, salen);
+               error = nfs4_update_server(server, hostname, sap, salen, net);
                kfree(hostname);
                if (error == 0)
                        break;
index 42da6af77587bef4972ef8a84fc005b07aa4136f..450bfedbe2f4c0f88cacc44ec504872487279faa 100644 (file)
@@ -1620,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
 
-       nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args,
-                               &data->o_res.seq_res, task);
+       nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args,
+                               &data->c_res.seq_res, task);
 }
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
 
-       nfs40_sequence_done(task, &data->o_res.seq_res);
+       nfs40_sequence_done(task, &data->c_res.seq_res);
 
        data->rpc_status = task->tk_status;
        if (data->rpc_status == 0) {
@@ -1686,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
        };
        int status;
 
-       nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1);
+       nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
        kref_get(&data->kref);
        data->rpc_done = 0;
        data->rpc_status = 0;
@@ -2398,13 +2398,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 
        if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) {
                /* Use that stateid */
-       } else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) {
+       } else if (truncate && state != NULL) {
                struct nfs_lockowner lockowner = {
                        .l_owner = current->files,
                        .l_pid = current->tgid,
                };
-               nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
-                               &lockowner);
+               if (!nfs4_valid_open_stateid(state))
+                       return -EBADF;
+               if (nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
+                               &lockowner) == -EIO)
+                       return -EBADF;
        } else
                nfs4_stateid_copy(&arg.stateid, &zero_stateid);
 
@@ -4011,8 +4014,9 @@ static bool nfs4_stateid_is_current(nfs4_stateid *stateid,
 {
        nfs4_stateid current_stateid;
 
-       if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode))
-               return false;
+       /* If the current stateid represents a lost lock, then exit */
+       if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode) == -EIO)
+               return true;
        return nfs4_stateid_match(stateid, &current_stateid);
 }
 
@@ -5828,8 +5832,7 @@ struct nfs_release_lockowner_data {
        struct nfs4_lock_state *lsp;
        struct nfs_server *server;
        struct nfs_release_lockowner_args args;
-       struct nfs4_sequence_args seq_args;
-       struct nfs4_sequence_res seq_res;
+       struct nfs_release_lockowner_res res;
        unsigned long timestamp;
 };
 
@@ -5837,7 +5840,7 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata
 {
        struct nfs_release_lockowner_data *data = calldata;
        nfs40_setup_sequence(data->server,
-                               &data->seq_args, &data->seq_res, task);
+                               &data->args.seq_args, &data->res.seq_res, task);
        data->timestamp = jiffies;
 }
 
@@ -5846,7 +5849,7 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
        struct nfs_release_lockowner_data *data = calldata;
        struct nfs_server *server = data->server;
 
-       nfs40_sequence_done(task, &data->seq_res);
+       nfs40_sequence_done(task, &data->res.seq_res);
 
        switch (task->tk_status) {
        case 0:
@@ -5887,7 +5890,6 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
        data = kmalloc(sizeof(*data), GFP_NOFS);
        if (!data)
                return -ENOMEM;
-       nfs4_init_sequence(&data->seq_args, &data->seq_res, 0);
        data->lsp = lsp;
        data->server = server;
        data->args.lock_owner.clientid = server->nfs_client->cl_clientid;
@@ -5895,6 +5897,8 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st
        data->args.lock_owner.s_dev = server->s_dev;
 
        msg.rpc_argp = &data->args;
+       msg.rpc_resp = &data->res;
+       nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
        rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
        return 0;
 }
index cf883c7ae053322626b8aa3c5b18861cd81f0085..e799dc3c3b1db9f7681199907bff5e7bffb3f853 100644 (file)
@@ -231,14 +231,23 @@ out:
        return ret;
 }
 
+/*
+ * nfs4_release_slot_table - release all slot table entries
+ */
+static void nfs4_release_slot_table(struct nfs4_slot_table *tbl)
+{
+       nfs4_shrink_slot_table(tbl, 0);
+}
+
 /**
- * nfs4_release_slot_table - release resources attached to a slot table
+ * nfs4_shutdown_slot_table - release resources attached to a slot table
  * @tbl: slot table to shut down
  *
  */
-void nfs4_release_slot_table(struct nfs4_slot_table *tbl)
+void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl)
 {
-       nfs4_shrink_slot_table(tbl, 0);
+       nfs4_release_slot_table(tbl);
+       rpc_destroy_wait_queue(&tbl->slot_tbl_waitq);
 }
 
 /**
@@ -422,7 +431,7 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
        spin_unlock(&tbl->slot_tbl_lock);
 }
 
-static void nfs4_destroy_session_slot_tables(struct nfs4_session *session)
+static void nfs4_release_session_slot_tables(struct nfs4_session *session)
 {
        nfs4_release_slot_table(&session->fc_slot_table);
        nfs4_release_slot_table(&session->bc_slot_table);
@@ -450,7 +459,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
        if (status && tbl->slots == NULL)
                /* Fore and back channel share a connection so get
                 * both slot tables or neither */
-               nfs4_destroy_session_slot_tables(ses);
+               nfs4_release_session_slot_tables(ses);
        return status;
 }
 
@@ -470,6 +479,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
        return session;
 }
 
+static void nfs4_destroy_session_slot_tables(struct nfs4_session *session)
+{
+       nfs4_shutdown_slot_table(&session->fc_slot_table);
+       nfs4_shutdown_slot_table(&session->bc_slot_table);
+}
+
 void nfs4_destroy_session(struct nfs4_session *session)
 {
        struct rpc_xprt *xprt;
index 2323061006512c37b2189a79ddf41441d0aafff9..b34ada9bc6a2d03a677e46cc5ab8c4eb7c1fd838 100644 (file)
@@ -74,7 +74,7 @@ enum nfs4_session_state {
 
 extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
                unsigned int max_reqs, const char *queue);
-extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl);
+extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
 extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
 extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
 extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
index e5be72518bd7ebe813522b1c24f7fa16b539421e..0deb32105ccf3cb8b40fe95365f91f8b4b9c4da4 100644 (file)
@@ -974,9 +974,6 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst,
        else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
                nfs4_stateid_copy(dst, &lsp->ls_stateid);
                ret = 0;
-               smp_rmb();
-               if (!list_empty(&lsp->ls_seqid.list))
-                       ret = -EWOULDBLOCK;
        }
        spin_unlock(&state->state_lock);
        nfs4_put_lock_state(lsp);
@@ -984,10 +981,9 @@ out:
        return ret;
 }
 
-static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
+static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
 {
        const nfs4_stateid *src;
-       int ret;
        int seq;
 
        do {
@@ -996,12 +992,7 @@ static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
                if (test_bit(NFS_OPEN_STATE, &state->flags))
                        src = &state->open_stateid;
                nfs4_stateid_copy(dst, src);
-               ret = 0;
-               smp_rmb();
-               if (!list_empty(&state->owner->so_seqid.list))
-                       ret = -EWOULDBLOCK;
        } while (read_seqretry(&state->seqlock, seq));
-       return ret;
 }
 
 /*
@@ -1015,15 +1006,19 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
        if (ret == -EIO)
                /* A lost lock - don't even consider delegations */
                goto out;
-       if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
+       /* returns true if delegation stateid found and copied */
+       if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) {
+               ret = 0;
                goto out;
+       }
        if (ret != -ENOENT)
                /* nfs4_copy_delegation_stateid() didn't over-write
                 * dst, so it still has the lock stateid which we now
                 * choose to use.
                 */
                goto out;
-       ret = nfs4_copy_open_stateid(dst, state);
+       nfs4_copy_open_stateid(dst, state);
+       ret = 0;
 out:
        if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41))
                dst->seqid = 0;
index d3a587144222b56becd0ce82597fb95bc8767592..d190e33d0ec2fdeb845eec70ab3c610ab551758d 100644 (file)
@@ -151,17 +151,15 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
                pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
                if (IS_ERR(pacl))
                        return PTR_ERR(pacl);
-               /* allocate for worst case: one (deny, allow) pair each: */
-               size += 2 * pacl->a_count;
        }
+       /* allocate for worst case: one (deny, allow) pair each: */
+       size += 2 * pacl->a_count;
 
        if (S_ISDIR(inode->i_mode)) {
                flags = NFS4_ACL_DIR;
                dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
                if (dpacl)
                        size += 2 * dpacl->a_count;
-       } else {
-               dpacl = NULL;
        }
 
        *acl = nfs4_acl_new(size);
@@ -170,8 +168,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
                goto out;
        }
 
-       if (pacl)
-               _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
+       _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
 
        if (dpacl)
                _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
index 017d3cb5e99b4391027fe37b7c56c23966754e2d..6d7be3f8035631cb207a5733c71dbfc2f800fa4c 100644 (file)
@@ -449,6 +449,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        fh_lock(fhp);
        host_err = notify_change(dentry, iap, NULL);
        fh_unlock(fhp);
+       err = nfserrno(host_err);
 
 out_put_write_access:
        if (size_change)
index 0b9ff4395e6ac320f6108f7c3cabb2d57d5a426f..abc8cbcfe90e0fca9f67471740c0b41c9055b7c6 100644 (file)
@@ -86,7 +86,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
                                struct fsnotify_mark *inode_mark,
                                struct fsnotify_mark *vfsmount_mark,
                                u32 mask, void *data, int data_type,
-                               const unsigned char *file_name)
+                               const unsigned char *file_name, u32 cookie)
 {
        struct dnotify_mark *dn_mark;
        struct dnotify_struct *dn;
index 0e792f5e3147c3cfcf38a980716075ea509b0e46..dc638f786d5c762373288942dc04cc5c5cee0750 100644 (file)
@@ -147,7 +147,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
                                 struct fsnotify_mark *inode_mark,
                                 struct fsnotify_mark *fanotify_mark,
                                 u32 mask, void *data, int data_type,
-                                const unsigned char *file_name)
+                                const unsigned char *file_name, u32 cookie)
 {
        int ret = 0;
        struct fanotify_event_info *event;
@@ -192,10 +192,12 @@ static int fanotify_handle_event(struct fsnotify_group *group,
 
        ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
        if (ret) {
-               BUG_ON(mask & FAN_ALL_PERM_EVENTS);
+               /* Permission events shouldn't be merged */
+               BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS);
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               ret = 0;
+
+               return 0;
        }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
index b6175fa11bf856809d1ee6a43ee9b861980e9160..287a22c041496a206d94daa299be55a20b4786a2 100644 (file)
@@ -698,6 +698,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        struct fsnotify_group *group;
        int f_flags, fd;
        struct user_struct *user;
+       struct fanotify_event_info *oevent;
 
        pr_debug("%s: flags=%d event_f_flags=%d\n",
                __func__, flags, event_f_flags);
@@ -730,8 +731,20 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        group->fanotify_data.user = user;
        atomic_inc(&user->fanotify_listeners);
 
+       oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
+       if (unlikely(!oevent)) {
+               fd = -ENOMEM;
+               goto out_destroy_group;
+       }
+       group->overflow_event = &oevent->fse;
+       fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+       oevent->tgid = get_pid(task_tgid(current));
+       oevent->path.mnt = NULL;
+       oevent->path.dentry = NULL;
+
        group->fanotify_data.f_flags = event_f_flags;
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       oevent->response = 0;
        mutex_init(&group->fanotify_data.access_mutex);
        init_waitqueue_head(&group->fanotify_data.access_waitq);
        INIT_LIST_HEAD(&group->fanotify_data.access_list);
index 1d4e1ea2f37ca4995db3f16db9bd00bbf862ca93..9d3e9c50066aaf5856350cf3bc85576a79bab900 100644 (file)
@@ -179,7 +179,7 @@ static int send_to_group(struct inode *to_tell,
 
        return group->ops->handle_event(group, to_tell, inode_mark,
                                        vfsmount_mark, mask, data, data_is,
-                                       file_name);
+                                       file_name, cookie);
 }
 
 /*
index ee674fe2cec7f3f7b99ad09363b6a425ff4d6dbd..ad199598045655105e7ba4db0ed639357bf3fc6f 100644 (file)
@@ -55,6 +55,13 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
        /* clear the notification queue of all events */
        fsnotify_flush_notify(group);
 
+       /*
+        * Destroy overflow event (we cannot use fsnotify_destroy_event() as
+        * that deliberately ignores overflow events.
+        */
+       if (group->overflow_event)
+               group->ops->free_event(group->overflow_event);
+
        fsnotify_put_group(group);
 }
 
@@ -99,7 +106,6 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
        INIT_LIST_HEAD(&group->marks_list);
 
        group->ops = ops;
-       fsnotify_init_event(&group->overflow_event, NULL, FS_Q_OVERFLOW);
 
        return group;
 }
index 485eef3f4407a0371d903c08a75c9f262dfde82e..ed855ef6f0775e447489e7dd43e00ff3891c850e 100644 (file)
@@ -27,6 +27,6 @@ extern int inotify_handle_event(struct fsnotify_group *group,
                                struct fsnotify_mark *inode_mark,
                                struct fsnotify_mark *vfsmount_mark,
                                u32 mask, void *data, int data_type,
-                               const unsigned char *file_name);
+                               const unsigned char *file_name, u32 cookie);
 
 extern const struct fsnotify_ops inotify_fsnotify_ops;
index d5ee56348bb803fd0ddff46d4f3da7d0fa7016d1..43ab1e1a07a20acaca5a4741487ac5121e00bbd4 100644 (file)
@@ -67,7 +67,7 @@ int inotify_handle_event(struct fsnotify_group *group,
                         struct fsnotify_mark *inode_mark,
                         struct fsnotify_mark *vfsmount_mark,
                         u32 mask, void *data, int data_type,
-                        const unsigned char *file_name)
+                        const unsigned char *file_name, u32 cookie)
 {
        struct inotify_inode_mark *i_mark;
        struct inotify_event_info *event;
@@ -103,6 +103,7 @@ int inotify_handle_event(struct fsnotify_group *group,
        fsn_event = &event->fse;
        fsnotify_init_event(fsn_event, inode, mask);
        event->wd = i_mark->wd;
+       event->sync_cookie = cookie;
        event->name_len = len;
        if (len)
                strcpy(event->name, file_name);
index 497395c8274bc62cd0fab6c2cf89ce4950fafffc..78a2ca3966c3857a8f4a5bf5369b63ad10ef3380 100644 (file)
@@ -495,7 +495,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
 
        /* Queue ignore event for the watch */
        inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
-                            NULL, FSNOTIFY_EVENT_NONE, NULL);
+                            NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
 
        i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
        /* remove this mark from the idr */
@@ -633,11 +633,23 @@ static int inotify_update_watch(struct fsnotify_group *group, struct inode *inod
 static struct fsnotify_group *inotify_new_group(unsigned int max_events)
 {
        struct fsnotify_group *group;
+       struct inotify_event_info *oevent;
 
        group = fsnotify_alloc_group(&inotify_fsnotify_ops);
        if (IS_ERR(group))
                return group;
 
+       oevent = kmalloc(sizeof(struct inotify_event_info), GFP_KERNEL);
+       if (unlikely(!oevent)) {
+               fsnotify_destroy_group(group);
+               return ERR_PTR(-ENOMEM);
+       }
+       group->overflow_event = &oevent->fse;
+       fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
+       oevent->wd = -1;
+       oevent->sync_cookie = 0;
+       oevent->name_len = 0;
+
        group->max_events = max_events;
 
        spin_lock_init(&group->inotify_data.idr_lock);
index 18b3c4427dcac0f2c9125581cc171be3f1eb3a9f..1e58402171a56cd9d078ab62307951689a5630df 100644 (file)
@@ -80,7 +80,8 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
 /*
  * Add an event to the group notification queue.  The group can later pull this
  * event off the queue to deal with.  The function returns 0 if the event was
- * added to the queue, 1 if the event was merged with some other queued event.
+ * added to the queue, 1 if the event was merged with some other queued event,
+ * 2 if the queue of events has overflown.
  */
 int fsnotify_add_notify_event(struct fsnotify_group *group,
                              struct fsnotify_event *event,
@@ -95,10 +96,14 @@ int fsnotify_add_notify_event(struct fsnotify_group *group,
        mutex_lock(&group->notification_mutex);
 
        if (group->q_len >= group->max_events) {
+               ret = 2;
                /* Queue overflow event only if it isn't already queued */
-               if (list_empty(&group->overflow_event.list))
-                       event = &group->overflow_event;
-               ret = 1;
+               if (!list_empty(&group->overflow_event->list)) {
+                       mutex_unlock(&group->notification_mutex);
+                       return ret;
+               }
+               event = group->overflow_event;
+               goto queue;
        }
 
        if (!list_empty(list) && merge) {
@@ -109,6 +114,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group,
                }
        }
 
+queue:
        group->q_len++;
        list_add_tail(&event->list, list);
        mutex_unlock(&group->notification_mutex);
@@ -132,7 +138,11 @@ struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group
 
        event = list_first_entry(&group->notification_list,
                                 struct fsnotify_event, list);
-       list_del(&event->list);
+       /*
+        * We need to init list head for the case of overflow event so that
+        * check in fsnotify_add_notify_events() works
+        */
+       list_del_init(&event->list);
        group->q_len--;
 
        return event;
index ea4ba9daeb472069cd9d8664b58ff363806ab4e4..db9bd8a31725477eb9130bb6868d25bda510aa4a 100644 (file)
@@ -2134,7 +2134,7 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        ret = ntfs_file_aio_write_nolock(iocb, iov, nr_segs, &iocb->ki_pos);
        mutex_unlock(&inode->i_mutex);
        if (ret > 0) {
-               int err = generic_write_sync(file, pos, ret);
+               int err = generic_write_sync(file, iocb->ki_pos - ret, ret);
                if (err < 0)
                        ret = err;
        }
index 8750ae1b8636f5904bdc921ea657c8aba69406b0..e2edff38be52b6963c32962604b26adfbe682dd4 100644 (file)
@@ -4742,6 +4742,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
                                enum ocfs2_alloc_restarted *reason_ret)
 {
        int status = 0, err = 0;
+       int need_free = 0;
        int free_extents;
        enum ocfs2_alloc_restarted reason = RESTART_NONE;
        u32 bit_off, num_bits;
@@ -4796,7 +4797,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
                                              OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
-               goto leave;
+               need_free = 1;
+               goto bail;
        }
 
        block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
@@ -4807,7 +4809,8 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
                                     num_bits, flags, meta_ac);
        if (status < 0) {
                mlog_errno(status);
-               goto leave;
+               need_free = 1;
+               goto bail;
        }
 
        ocfs2_journal_dirty(handle, et->et_root_bh);
@@ -4821,6 +4824,19 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
                reason = RESTART_TRANS;
        }
 
+bail:
+       if (need_free) {
+               if (data_ac->ac_which == OCFS2_AC_USE_LOCAL)
+                       ocfs2_free_local_alloc_bits(osb, handle, data_ac,
+                                       bit_off, num_bits);
+               else
+                       ocfs2_free_clusters(handle,
+                                       data_ac->ac_inode,
+                                       data_ac->ac_bh,
+                                       ocfs2_clusters_to_blocks(osb->sb, bit_off),
+                                       num_bits);
+       }
+
 leave:
        if (reason_ret)
                *reason_ret = reason;
@@ -6805,6 +6821,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                                         struct buffer_head *di_bh)
 {
        int ret, i, has_data, num_pages = 0;
+       int need_free = 0;
+       u32 bit_off, num;
        handle_t *handle;
        u64 uninitialized_var(block);
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
@@ -6850,7 +6868,6 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
        }
 
        if (has_data) {
-               u32 bit_off, num;
                unsigned int page_end;
                u64 phys;
 
@@ -6886,6 +6903,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages);
                if (ret) {
                        mlog_errno(ret);
+                       need_free = 1;
                        goto out_commit;
                }
 
@@ -6896,6 +6914,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                ret = ocfs2_read_inline_data(inode, pages[0], di_bh);
                if (ret) {
                        mlog_errno(ret);
+                       need_free = 1;
                        goto out_commit;
                }
 
@@ -6927,6 +6946,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                ret = ocfs2_insert_extent(handle, &et, 0, block, 1, 0, NULL);
                if (ret) {
                        mlog_errno(ret);
+                       need_free = 1;
                        goto out_commit;
                }
 
@@ -6938,6 +6958,18 @@ out_commit:
                dquot_free_space_nodirty(inode,
                                          ocfs2_clusters_to_bytes(osb->sb, 1));
 
+       if (need_free) {
+               if (data_ac->ac_which == OCFS2_AC_USE_LOCAL)
+                       ocfs2_free_local_alloc_bits(osb, handle, data_ac,
+                                       bit_off, num);
+               else
+                       ocfs2_free_clusters(handle,
+                                       data_ac->ac_inode,
+                                       data_ac->ac_bh,
+                                       ocfs2_clusters_to_blocks(osb->sb, bit_off),
+                                       num);
+       }
+
        ocfs2_commit_trans(osb, handle);
 
 out_unlock:
@@ -7126,7 +7158,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh,
        if (end > i_size_read(inode))
                end = i_size_read(inode);
 
-       BUG_ON(start >= end);
+       BUG_ON(start > end);
 
        if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) ||
            !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) ||
index d77d71ead8d12071a52b1f0f63c66f1077c93f84..51632c40e896fd0b7c4e4c87b2afc5dc4f418aca 100644 (file)
@@ -185,6 +185,9 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
                              file->f_path.dentry->d_name.name,
                              (unsigned long long)datasync);
 
+       if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+               return -EROFS;
+
        err = filemap_write_and_wait_range(inode->i_mapping, start, end);
        if (err)
                return err;
@@ -474,11 +477,6 @@ static int ocfs2_truncate_file(struct inode *inode,
                goto bail;
        }
 
-       /* lets handle the simple truncate cases before doing any more
-        * cluster locking. */
-       if (new_i_size == le64_to_cpu(fe->i_size))
-               goto bail;
-
        down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
        ocfs2_resv_discard(&osb->osb_la_resmap,
@@ -718,7 +716,8 @@ leave:
  * While a write will already be ordering the data, a truncate will not.
  * Thus, we need to explicitly order the zeroed pages.
  */
-static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode)
+static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode,
+                                               struct buffer_head *di_bh)
 {
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        handle_t *handle = NULL;
@@ -735,7 +734,14 @@ static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode)
        }
 
        ret = ocfs2_jbd2_file_inode(handle, inode);
-       if (ret < 0)
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret)
                mlog_errno(ret);
 
 out:
@@ -751,7 +757,7 @@ out:
  * to be too fragile to do exactly what we need without us having to
  * worry about recursive locking in ->write_begin() and ->write_end(). */
 static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
-                                u64 abs_to)
+                                u64 abs_to, struct buffer_head *di_bh)
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page;
@@ -759,6 +765,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
        handle_t *handle = NULL;
        int ret = 0;
        unsigned zero_from, zero_to, block_start, block_end;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
 
        BUG_ON(abs_from >= abs_to);
        BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT));
@@ -801,7 +808,8 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
                }
 
                if (!handle) {
-                       handle = ocfs2_zero_start_ordered_transaction(inode);
+                       handle = ocfs2_zero_start_ordered_transaction(inode,
+                                                                     di_bh);
                        if (IS_ERR(handle)) {
                                ret = PTR_ERR(handle);
                                handle = NULL;
@@ -818,8 +826,22 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from,
                        ret = 0;
        }
 
-       if (handle)
+       if (handle) {
+               /*
+                * fs-writeback will release the dirty pages without page lock
+                * whose offset are over inode size, the release happens at
+                * block_write_full_page_endio().
+                */
+               i_size_write(inode, abs_to);
+               inode->i_blocks = ocfs2_inode_sector_count(inode);
+               di->i_size = cpu_to_le64((u64)i_size_read(inode));
+               inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
+               di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+               di->i_mtime_nsec = di->i_ctime_nsec;
+               ocfs2_journal_dirty(handle, di_bh);
                ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+       }
 
 out_unlock:
        unlock_page(page);
@@ -915,7 +937,7 @@ out:
  * has made sure that the entire range needs zeroing.
  */
 static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start,
-                                  u64 range_end)
+                                  u64 range_end, struct buffer_head *di_bh)
 {
        int rc = 0;
        u64 next_pos;
@@ -931,7 +953,7 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start,
                next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE;
                if (next_pos > range_end)
                        next_pos = range_end;
-               rc = ocfs2_write_zero_page(inode, zero_pos, next_pos);
+               rc = ocfs2_write_zero_page(inode, zero_pos, next_pos, di_bh);
                if (rc < 0) {
                        mlog_errno(rc);
                        break;
@@ -977,7 +999,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh,
                        range_end = zero_to_size;
 
                ret = ocfs2_zero_extend_range(inode, range_start,
-                                             range_end);
+                                             range_end, di_bh);
                if (ret) {
                        mlog_errno(ret);
                        break;
@@ -1145,14 +1167,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                goto bail_unlock_rw;
        }
 
-       if (size_change && attr->ia_size != i_size_read(inode)) {
+       if (size_change) {
                status = inode_newsize_ok(inode, attr->ia_size);
                if (status)
                        goto bail_unlock;
 
                inode_dio_wait(inode);
 
-               if (i_size_read(inode) > attr->ia_size) {
+               if (i_size_read(inode) >= attr->ia_size) {
                        if (ocfs2_should_order_data(inode)) {
                                status = ocfs2_begin_ordered_truncate(inode,
                                                                      attr->ia_size);
@@ -2371,8 +2393,8 @@ out_dio:
 
        if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
            ((file->f_flags & O_DIRECT) && !direct_io)) {
-               ret = filemap_fdatawrite_range(file->f_mapping, pos,
-                                              pos + count - 1);
+               ret = filemap_fdatawrite_range(file->f_mapping, *ppos,
+                                              *ppos + count - 1);
                if (ret < 0)
                        written = ret;
 
@@ -2385,8 +2407,8 @@ out_dio:
                }
 
                if (!ret)
-                       ret = filemap_fdatawait_range(file->f_mapping, pos,
-                                                     pos + count - 1);
+                       ret = filemap_fdatawait_range(file->f_mapping, *ppos,
+                                                     *ppos + count - 1);
        }
 
        /*
index cd5496b7a0a39d4ab7658b59a8480a1bb5d6d1eb..0440134556216d4b12a00168253b9b9446ff7312 100644 (file)
@@ -781,6 +781,48 @@ bail:
        return status;
 }
 
+int ocfs2_free_local_alloc_bits(struct ocfs2_super *osb,
+                               handle_t *handle,
+                               struct ocfs2_alloc_context *ac,
+                               u32 bit_off,
+                               u32 num_bits)
+{
+       int status, start;
+       u32 clear_bits;
+       struct inode *local_alloc_inode;
+       void *bitmap;
+       struct ocfs2_dinode *alloc;
+       struct ocfs2_local_alloc *la;
+
+       BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);
+
+       local_alloc_inode = ac->ac_inode;
+       alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+       la = OCFS2_LOCAL_ALLOC(alloc);
+
+       bitmap = la->la_bitmap;
+       start = bit_off - le32_to_cpu(la->la_bm_off);
+       clear_bits = num_bits;
+
+       status = ocfs2_journal_access_di(handle,
+                       INODE_CACHE(local_alloc_inode),
+                       osb->local_alloc_bh,
+                       OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto bail;
+       }
+
+       while (clear_bits--)
+               ocfs2_clear_bit(start++, bitmap);
+
+       le32_add_cpu(&alloc->id1.bitmap1.i_used, -num_bits);
+       ocfs2_journal_dirty(handle, osb->local_alloc_bh);
+
+bail:
+       return status;
+}
+
 static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc)
 {
        u32 count;
index 1be9b586446086bb9ea81499a10283cedaa5c6f2..44a7d1fb2decc79c108082668432dfe1f641b3b3 100644 (file)
@@ -55,6 +55,12 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 u32 *bit_off,
                                 u32 *num_bits);
 
+int ocfs2_free_local_alloc_bits(struct ocfs2_super *osb,
+                               handle_t *handle,
+                               struct ocfs2_alloc_context *ac,
+                               u32 bit_off,
+                               u32 num_bits);
+
 void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb,
                                      unsigned int num_clusters);
 void ocfs2_la_enable_worker(struct work_struct *work);
index f4d609be940086794ff8e64b1ed7cd832ba517f5..3683643f3f0ecf4410e0d85549ca4494f60af7fb 100644 (file)
@@ -664,6 +664,7 @@ static int ocfs2_link(struct dentry *old_dentry,
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        struct ocfs2_dir_lookup_result lookup = { NULL, };
        sigset_t oldset;
+       u64 old_de_ino;
 
        trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno,
                         old_dentry->d_name.len, old_dentry->d_name.name,
@@ -686,6 +687,22 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out;
        }
 
+       err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name,
+                       old_dentry->d_name.len, &old_de_ino);
+       if (err) {
+               err = -ENOENT;
+               goto out;
+       }
+
+       /*
+        * Check whether another node removed the source inode while we
+        * were in the vfs.
+        */
+       if (old_de_ino != OCFS2_I(inode)->ip_blkno) {
+               err = -ENOENT;
+               goto out;
+       }
+
        err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
                                        dentry->d_name.len);
        if (err)
index aaa50611ec66c27f2b6cd9a67a039a05e0253787..d7b5108789e2e7d8a26049b7dc6a01f8a0ff2d6f 100644 (file)
@@ -717,6 +717,12 @@ static int ocfs2_release_dquot(struct dquot *dquot)
         */
        if (status < 0)
                mlog_errno(status);
+       /*
+        * Clear dq_off so that we search for the structure in quota file next
+        * time we acquire it. The structure might be deleted and reallocated
+        * elsewhere by another node while our dquot structure is on freelist.
+        */
+       dquot->dq_off = 0;
        clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
 out_trans:
        ocfs2_commit_trans(osb, handle);
@@ -756,16 +762,17 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
        status = ocfs2_lock_global_qf(info, 1);
        if (status < 0)
                goto out;
-       if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
-               status = ocfs2_qinfo_lock(info, 0);
-               if (status < 0)
-                       goto out_dq;
-               status = qtree_read_dquot(&info->dqi_gi, dquot);
-               ocfs2_qinfo_unlock(info, 0);
-               if (status < 0)
-                       goto out_dq;
-       }
-       set_bit(DQ_READ_B, &dquot->dq_flags);
+       status = ocfs2_qinfo_lock(info, 0);
+       if (status < 0)
+               goto out_dq;
+       /*
+        * We always want to read dquot structure from disk because we don't
+        * know what happened with it while it was on freelist.
+        */
+       status = qtree_read_dquot(&info->dqi_gi, dquot);
+       ocfs2_qinfo_unlock(info, 0);
+       if (status < 0)
+               goto out_dq;
 
        OCFS2_DQUOT(dquot)->dq_use_count++;
        OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
index 2e4344be3b962b40a6cd4e5743a87f088b7abe63..2001862bf2b1cfbb20ed78bd9febeacbc96b42a4 100644 (file)
@@ -1303,10 +1303,6 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot)
        ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
 
 out:
-       /* Clear the read bit so that next time someone uses this
-        * dquot he reads fresh info from disk and allocates local
-        * dquot structure */
-       clear_bit(DQ_READ_B, &dquot->dq_flags);
        return status;
 }
 
index 1324e6600e57378b8e4d1624dc1366af57fde7b2..ca5ce14cbddcef81498305f8ccbccc978750faed 100644 (file)
@@ -346,7 +346,9 @@ int ocfs2_cluster_connect(const char *stack_name,
 
        strlcpy(new_conn->cc_name, group, GROUP_NAME_MAX + 1);
        new_conn->cc_namelen = grouplen;
-       strlcpy(new_conn->cc_cluster_name, cluster_name, CLUSTER_NAME_MAX + 1);
+       if (cluster_name_len)
+               strlcpy(new_conn->cc_cluster_name, cluster_name,
+                       CLUSTER_NAME_MAX + 1);
        new_conn->cc_cluster_name_len = cluster_name_len;
        new_conn->cc_recovery_handler = recovery_handler;
        new_conn->cc_recovery_data = recovery_data;
index 4b3e1edf2fe4d917e69e56b3e268e32f2ae7301a..b9ed8b25c108c69d68889b5b6eadac9878eb7bd9 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -705,6 +705,10 @@ static int do_dentry_open(struct file *f,
                return 0;
        }
 
+       /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
+       if (S_ISREG(inode->i_mode))
+               f->f_mode |= FMODE_ATOMIC_POS;
+
        f->f_op = fops_get(inode->i_fop);
        if (unlikely(WARN_ON(!f->f_op))) {
                error = -ENODEV;
index c7221bb19801e6b6251ad1ed3cea6f4f79dcf876..88396df725b4bbe84dc7d57eaf7a259877e5d87c 100644 (file)
@@ -220,14 +220,14 @@ static struct mount *get_source(struct mount *dest,
  * @tree_list : list of heads of trees to be attached.
  */
 int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
-                   struct mount *source_mnt, struct list_head *tree_list)
+                   struct mount *source_mnt, struct hlist_head *tree_list)
 {
        struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
        struct mount *m, *child;
        int ret = 0;
        struct mount *prev_dest_mnt = dest_mnt;
        struct mount *prev_src_mnt  = source_mnt;
-       LIST_HEAD(tmp_list);
+       HLIST_HEAD(tmp_list);
 
        for (m = propagation_next(dest_mnt, dest_mnt); m;
                        m = propagation_next(m, dest_mnt)) {
@@ -246,27 +246,29 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
                child = copy_tree(source, source->mnt.mnt_root, type);
                if (IS_ERR(child)) {
                        ret = PTR_ERR(child);
-                       list_splice(tree_list, tmp_list.prev);
+                       tmp_list = *tree_list;
+                       tmp_list.first->pprev = &tmp_list.first;
+                       INIT_HLIST_HEAD(tree_list);
                        goto out;
                }
 
                if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
                        mnt_set_mountpoint(m, dest_mp, child);
-                       list_add_tail(&child->mnt_hash, tree_list);
+                       hlist_add_head(&child->mnt_hash, tree_list);
                } else {
                        /*
                         * This can happen if the parent mount was bind mounted
                         * on some subdirectory of a shared/slave mount.
                         */
-                       list_add_tail(&child->mnt_hash, &tmp_list);
+                       hlist_add_head(&child->mnt_hash, &tmp_list);
                }
                prev_dest_mnt = m;
                prev_src_mnt  = child;
        }
 out:
        lock_mount_hash();
-       while (!list_empty(&tmp_list)) {
-               child = list_first_entry(&tmp_list, struct mount, mnt_hash);
+       while (!hlist_empty(&tmp_list)) {
+               child = hlist_entry(tmp_list.first, struct mount, mnt_hash);
                umount_tree(child, 0);
        }
        unlock_mount_hash();
@@ -338,8 +340,10 @@ static void __propagate_umount(struct mount *mnt)
                 * umount the child only if the child has no
                 * other children
                 */
-               if (child && list_empty(&child->mnt_mounts))
-                       list_move_tail(&child->mnt_hash, &mnt->mnt_hash);
+               if (child && list_empty(&child->mnt_mounts)) {
+                       hlist_del_init_rcu(&child->mnt_hash);
+                       hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash);
+               }
        }
 }
 
@@ -350,11 +354,11 @@ static void __propagate_umount(struct mount *mnt)
  *
  * vfsmount lock must be held for write
  */
-int propagate_umount(struct list_head *list)
+int propagate_umount(struct hlist_head *list)
 {
        struct mount *mnt;
 
-       list_for_each_entry(mnt, list, mnt_hash)
+       hlist_for_each_entry(mnt, list, mnt_hash)
                __propagate_umount(mnt);
        return 0;
 }
index 59e7eda1851ec447d705a02866c19a07d91d2c99..fc28a27fa89233d24b90bdd748477994b8713ecd 100644 (file)
@@ -36,8 +36,8 @@ static inline void set_mnt_shared(struct mount *mnt)
 
 void change_mnt_propagation(struct mount *, int);
 int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
-               struct list_head *);
-int propagate_umount(struct list_head *);
+               struct hlist_head *);
+int propagate_umount(struct hlist_head *);
 int propagate_mount_busy(struct mount *, int);
 void mnt_release_group_id(struct mount *);
 int get_dominating_id(struct mount *mnt, const struct path *root);
index 38bae5a0ea257ebc414aef89727f3a652d904c96..11c54fd51e16d6248926287c407b06da39495231 100644 (file)
@@ -521,8 +521,11 @@ posix_acl_chmod(struct inode *inode, umode_t mode)
                return -EOPNOTSUPP;
 
        acl = get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR_OR_NULL(acl))
+       if (IS_ERR_OR_NULL(acl)) {
+               if (acl == ERR_PTR(-EOPNOTSUPP))
+                       return 0;
                return PTR_ERR(acl);
+       }
 
        ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
        if (ret)
@@ -544,14 +547,15 @@ posix_acl_create(struct inode *dir, umode_t *mode,
                goto no_acl;
 
        p = get_acl(dir, ACL_TYPE_DEFAULT);
-       if (IS_ERR(p))
+       if (IS_ERR(p)) {
+               if (p == ERR_PTR(-EOPNOTSUPP))
+                       goto apply_umask;
                return PTR_ERR(p);
-
-       if (!p) {
-               *mode &= ~current_umask();
-               goto no_acl;
        }
 
+       if (!p)
+               goto apply_umask;
+
        *acl = posix_acl_clone(p, GFP_NOFS);
        if (!*acl)
                return -ENOMEM;
@@ -575,6 +579,8 @@ posix_acl_create(struct inode *dir, umode_t *mode,
        }
        return 0;
 
+apply_umask:
+       *mode &= ~current_umask();
 no_acl:
        *default_acl = NULL;
        *acl = NULL;
index 51507065263b29e3b915a6aa2238630fe3f7ac67..b9760628e1fde7b9a5c681798a65185144abeb92 100644 (file)
@@ -1824,6 +1824,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
        if (rc)
                goto out_mmput;
 
+       rc = -ENOENT;
        down_read(&mm->mmap_sem);
        vma = find_exact_vma(mm, vm_start, vm_end);
        if (vma && vma->vm_file) {
index 02174a610315ebb218880a8744e05b2244b6d26f..e647c55275d9ff9f96b92ac859e65c10fc03d318 100644 (file)
@@ -121,9 +121,8 @@ u64 stable_page_flags(struct page *page)
         * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon
         * to make sure a given page is a thp, not a non-huge compound page.
         */
-       else if (PageTransCompound(page) &&
-                (PageLRU(compound_trans_head(page)) ||
-                 PageAnon(compound_trans_head(page))))
+       else if (PageTransCompound(page) && (PageLRU(compound_head(page)) ||
+                                            PageAnon(compound_head(page))))
                u |= 1 << KPF_THP;
 
        /*
index 6f599c62f0cc939ce2b68a75dbcd38d366ee7fa9..9d231e9e5f0ef48cd7ef372437d85fbf9b8cbc2e 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/irqnr.h>
-#include <asm/cputime.h>
+#include <linux/cputime.h>
 #include <linux/tick.h>
 
 #ifndef arch_irq_stat_cpu
index 7141b8d0ca9ed9800afb1ae87def5f8aa06b8f46..33de567c25af4b04a6ba283caaf5e4f6d9b4ecdb 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/seq_file.h>
 #include <linux/time.h>
 #include <linux/kernel_stat.h>
-#include <asm/cputime.h>
+#include <linux/cputime.h>
 
 static int uptime_proc_show(struct seq_file *m, void *v)
 {
index 2ca7ba047f04b658028e1e8c9cd9f5ba746d9946..88d4585b30f1531b6e609825315d0868cc2edbe6 100644 (file)
@@ -468,17 +468,24 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr)
                        return rc;
                }
                nhdr_ptr = notes_section;
-               while (real_sz < max_sz) {
-                       if (nhdr_ptr->n_namesz == 0)
-                               break;
+               while (nhdr_ptr->n_namesz != 0) {
                        sz = sizeof(Elf64_Nhdr) +
                                ((nhdr_ptr->n_namesz + 3) & ~3) +
                                ((nhdr_ptr->n_descsz + 3) & ~3);
+                       if ((real_sz + sz) > max_sz) {
+                               pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n",
+                                       nhdr_ptr->n_namesz, nhdr_ptr->n_descsz);
+                               break;
+                       }
                        real_sz += sz;
                        nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
                }
                kfree(notes_section);
                phdr_ptr->p_memsz = real_sz;
+               if (real_sz == 0) {
+                       pr_warn("Warning: Zero PT_NOTE entries found\n");
+                       return -EINVAL;
+               }
        }
 
        return 0;
@@ -648,17 +655,24 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr)
                        return rc;
                }
                nhdr_ptr = notes_section;
-               while (real_sz < max_sz) {
-                       if (nhdr_ptr->n_namesz == 0)
-                               break;
+               while (nhdr_ptr->n_namesz != 0) {
                        sz = sizeof(Elf32_Nhdr) +
                                ((nhdr_ptr->n_namesz + 3) & ~3) +
                                ((nhdr_ptr->n_descsz + 3) & ~3);
+                       if ((real_sz + sz) > max_sz) {
+                               pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n",
+                                       nhdr_ptr->n_namesz, nhdr_ptr->n_descsz);
+                               break;
+                       }
                        real_sz += sz;
                        nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
                }
                kfree(notes_section);
                phdr_ptr->p_memsz = real_sz;
+               if (real_sz == 0) {
+                       pr_warn("Warning: Zero PT_NOTE entries found\n");
+                       return -EINVAL;
+               }
        }
 
        return 0;
index 831d49a4111f8405716d96ff6a451fc9ebd59e91..cfc8dcc160437c0daacd234f43d29faeb9b2fd33 100644 (file)
@@ -581,9 +581,17 @@ int dquot_scan_active(struct super_block *sb,
                dqstats_inc(DQST_LOOKUPS);
                dqput(old_dquot);
                old_dquot = dquot;
-               ret = fn(dquot, priv);
-               if (ret < 0)
-                       goto out;
+               /*
+                * ->release_dquot() can be racing with us. Our reference
+                * protects us from new calls to it so just wait for any
+                * outstanding call and recheck the DQ_ACTIVE_B after that.
+                */
+               wait_on_dquot(dquot);
+               if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
+                       ret = fn(dquot, priv);
+                       if (ret < 0)
+                               goto out;
+               }
                spin_lock(&dq_list_lock);
                /* We are safe to continue now because our dquot could not
                 * be moved out of the inuse list while we hold the reference */
index edc5746a902a090ce4dbda6b8b1205e729dff5b3..31c6efa431839e41f4b39b314cb640dd89b68ecc 100644 (file)
@@ -264,10 +264,22 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
 }
 EXPORT_SYMBOL(vfs_llseek);
 
+static inline struct fd fdget_pos(int fd)
+{
+       return __to_fd(__fdget_pos(fd));
+}
+
+static inline void fdput_pos(struct fd f)
+{
+       if (f.flags & FDPUT_POS_UNLOCK)
+               mutex_unlock(&f.file->f_pos_lock);
+       fdput(f);
+}
+
 SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
 {
        off_t retval;
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        if (!f.file)
                return -EBADF;
 
@@ -278,7 +290,7 @@ SYSCALL_DEFINE3(lseek, unsigned int, fd, off_t, offset, unsigned int, whence)
                if (res != (loff_t)retval)
                        retval = -EOVERFLOW;    /* LFS: should only happen on 32 bit platforms */
        }
-       fdput(f);
+       fdput_pos(f);
        return retval;
 }
 
@@ -295,7 +307,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
                unsigned int, whence)
 {
        int retval;
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        loff_t offset;
 
        if (!f.file)
@@ -315,7 +327,7 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high,
                        retval = 0;
        }
 out_putf:
-       fdput(f);
+       fdput_pos(f);
        return retval;
 }
 #endif
@@ -498,7 +510,7 @@ static inline void file_pos_write(struct file *file, loff_t pos)
 
 SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
 {
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        ssize_t ret = -EBADF;
 
        if (f.file) {
@@ -506,7 +518,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
                ret = vfs_read(f.file, buf, count, &pos);
                if (ret >= 0)
                        file_pos_write(f.file, pos);
-               fdput(f);
+               fdput_pos(f);
        }
        return ret;
 }
@@ -514,7 +526,7 @@ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
 SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
                size_t, count)
 {
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        ssize_t ret = -EBADF;
 
        if (f.file) {
@@ -522,7 +534,7 @@ SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
                ret = vfs_write(f.file, buf, count, &pos);
                if (ret >= 0)
                        file_pos_write(f.file, pos);
-               fdput(f);
+               fdput_pos(f);
        }
 
        return ret;
@@ -797,7 +809,7 @@ EXPORT_SYMBOL(vfs_writev);
 SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
                unsigned long, vlen)
 {
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        ssize_t ret = -EBADF;
 
        if (f.file) {
@@ -805,7 +817,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
                ret = vfs_readv(f.file, vec, vlen, &pos);
                if (ret >= 0)
                        file_pos_write(f.file, pos);
-               fdput(f);
+               fdput_pos(f);
        }
 
        if (ret > 0)
@@ -817,7 +829,7 @@ SYSCALL_DEFINE3(readv, unsigned long, fd, const struct iovec __user *, vec,
 SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
                unsigned long, vlen)
 {
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        ssize_t ret = -EBADF;
 
        if (f.file) {
@@ -825,7 +837,7 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec,
                ret = vfs_writev(f.file, vec, vlen, &pos);
                if (ret >= 0)
                        file_pos_write(f.file, pos);
-               fdput(f);
+               fdput_pos(f);
        }
 
        if (ret > 0)
@@ -968,7 +980,7 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
                const struct compat_iovec __user *,vec,
                compat_ulong_t, vlen)
 {
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        ssize_t ret;
        loff_t pos;
 
@@ -978,13 +990,13 @@ COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
        ret = compat_readv(f.file, vec, vlen, &pos);
        if (ret >= 0)
                f.file->f_pos = pos;
-       fdput(f);
+       fdput_pos(f);
        return ret;
 }
 
-COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
-               const struct compat_iovec __user *,vec,
-               unsigned long, vlen, loff_t, pos)
+static long __compat_sys_preadv64(unsigned long fd,
+                                 const struct compat_iovec __user *vec,
+                                 unsigned long vlen, loff_t pos)
 {
        struct fd f;
        ssize_t ret;
@@ -1001,12 +1013,22 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
        return ret;
 }
 
+#ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
+COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, loff_t, pos)
+{
+       return __compat_sys_preadv64(fd, vec, vlen, pos);
+}
+#endif
+
 COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
                const struct compat_iovec __user *,vec,
                compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
 {
        loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       return compat_sys_preadv64(fd, vec, vlen, pos);
+
+       return __compat_sys_preadv64(fd, vec, vlen, pos);
 }
 
 static size_t compat_writev(struct file *file,
@@ -1035,7 +1057,7 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
                const struct compat_iovec __user *, vec,
                compat_ulong_t, vlen)
 {
-       struct fd f = fdget(fd);
+       struct fd f = fdget_pos(fd);
        ssize_t ret;
        loff_t pos;
 
@@ -1045,13 +1067,13 @@ COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
        ret = compat_writev(f.file, vec, vlen, &pos);
        if (ret >= 0)
                f.file->f_pos = pos;
-       fdput(f);
+       fdput_pos(f);
        return ret;
 }
 
-COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
-               const struct compat_iovec __user *,vec,
-               unsigned long, vlen, loff_t, pos)
+static long __compat_sys_pwritev64(unsigned long fd,
+                                  const struct compat_iovec __user *vec,
+                                  unsigned long vlen, loff_t pos)
 {
        struct fd f;
        ssize_t ret;
@@ -1068,12 +1090,22 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
        return ret;
 }
 
+#ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
+COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
+               const struct compat_iovec __user *,vec,
+               unsigned long, vlen, loff_t, pos)
+{
+       return __compat_sys_pwritev64(fd, vec, vlen, pos);
+}
+#endif
+
 COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
                const struct compat_iovec __user *,vec,
                compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
 {
        loff_t pos = ((loff_t)pos_high << 32) | pos_low;
-       return compat_sys_pwritev64(fd, vec, vlen, pos);
+
+       return __compat_sys_pwritev64(fd, vec, vlen, pos);
 }
 #endif
 
index 2b7882b508db4ce66486455d22f812e83809e77f..9a3c68cf6026ae0405ef91c07f3ec9ef02854f1a 100644 (file)
@@ -324,23 +324,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                        switch (flag) {
                        case M_INSERT:  /* insert item into L[0] */
 
-                               if (item_pos == tb->lnum[0] - 1
-                                   && tb->lbytes != -1) {
+                               if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
                                        /* part of new item falls into L[0] */
                                        int new_item_len;
                                        int version;
 
-                                       ret_val =
-                                           leaf_shift_left(tb, tb->lnum[0] - 1,
-                                                           -1);
+                                       ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, -1);
 
                                        /* Calculate item length to insert to S[0] */
-                                       new_item_len =
-                                           ih_item_len(ih) - tb->lbytes;
+                                       new_item_len = ih_item_len(ih) - tb->lbytes;
                                        /* Calculate and check item length to insert to L[0] */
-                                       put_ih_item_len(ih,
-                                                       ih_item_len(ih) -
-                                                       new_item_len);
+                                       put_ih_item_len(ih, ih_item_len(ih) - new_item_len);
 
                                        RFALSE(ih_item_len(ih) <= 0,
                                               "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d",
@@ -349,30 +343,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        /* Insert new item into L[0] */
                                        buffer_info_init_left(tb, &bi);
                                        leaf_insert_into_buf(&bi,
-                                                            n + item_pos -
-                                                            ret_val, ih, body,
-                                                            zeros_num >
-                                                            ih_item_len(ih) ?
-                                                            ih_item_len(ih) :
-                                                            zeros_num);
+                                                       n + item_pos - ret_val, ih, body,
+                                                       zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num);
 
                                        version = ih_version(ih);
 
                                        /* Calculate key component, item length and body to insert into S[0] */
-                                       set_le_ih_k_offset(ih,
-                                                          le_ih_k_offset(ih) +
-                                                          (tb->
-                                                           lbytes <<
-                                                           (is_indirect_le_ih
-                                                            (ih) ? tb->tb_sb->
-                                                            s_blocksize_bits -
-                                                            UNFM_P_SHIFT :
-                                                            0)));
+                                       set_le_ih_k_offset(ih, le_ih_k_offset(ih) +
+                                                       (tb-> lbytes << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0)));
 
                                        put_ih_item_len(ih, new_item_len);
                                        if (tb->lbytes > zeros_num) {
-                                               body +=
-                                                   (tb->lbytes - zeros_num);
+                                               body += (tb->lbytes - zeros_num);
                                                zeros_num = 0;
                                        } else
                                                zeros_num -= tb->lbytes;
@@ -383,15 +365,10 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                } else {
                                        /* new item in whole falls into L[0] */
                                        /* Shift lnum[0]-1 items to L[0] */
-                                       ret_val =
-                                           leaf_shift_left(tb, tb->lnum[0] - 1,
-                                                           tb->lbytes);
+                                       ret_val = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes);
                                        /* Insert new item into L[0] */
                                        buffer_info_init_left(tb, &bi);
-                                       leaf_insert_into_buf(&bi,
-                                                            n + item_pos -
-                                                            ret_val, ih, body,
-                                                            zeros_num);
+                                       leaf_insert_into_buf(&bi, n + item_pos - ret_val, ih, body, zeros_num);
                                        tb->insert_size[0] = 0;
                                        zeros_num = 0;
                                }
@@ -399,264 +376,117 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,  /* item h
 
                        case M_PASTE:   /* append item in L[0] */
 
-                               if (item_pos == tb->lnum[0] - 1
-                                   && tb->lbytes != -1) {
+                               if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
                                        /* we must shift the part of the appended item */
-                                       if (is_direntry_le_ih
-                                           (B_N_PITEM_HEAD(tbS0, item_pos))) {
+                                       if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) {
 
                                                RFALSE(zeros_num,
                                                       "PAP-12090: invalid parameter in case of a directory");
                                                /* directory item */
                                                if (tb->lbytes > pos_in_item) {
                                                        /* new directory entry falls into L[0] */
-                                                       struct item_head
-                                                           *pasted;
-                                                       int l_pos_in_item =
-                                                           pos_in_item;
+                                                       struct item_head *pasted;
+                                                       int l_pos_in_item = pos_in_item;
 
                                                        /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */
-                                                       ret_val =
-                                                           leaf_shift_left(tb,
-                                                                           tb->
-                                                                           lnum
-                                                                           [0],
-                                                                           tb->
-                                                                           lbytes
-                                                                           -
-                                                                           1);
-                                                       if (ret_val
-                                                           && !item_pos) {
-                                                               pasted =
-                                                                   B_N_PITEM_HEAD
-                                                                   (tb->L[0],
-                                                                    B_NR_ITEMS
-                                                                    (tb->
-                                                                     L[0]) -
-                                                                    1);
-                                                               l_pos_in_item +=
-                                                                   I_ENTRY_COUNT
-                                                                   (pasted) -
-                                                                   (tb->
-                                                                    lbytes -
-                                                                    1);
+                                                       ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1);
+                                                       if (ret_val && !item_pos) {
+                                                               pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1);
+                                                               l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes -1);
                                                        }
 
                                                        /* Append given directory entry to directory item */
                                                        buffer_info_init_left(tb, &bi);
-                                                       leaf_paste_in_buffer
-                                                           (&bi,
-                                                            n + item_pos -
-                                                            ret_val,
-                                                            l_pos_in_item,
-                                                            tb->insert_size[0],
-                                                            body, zeros_num);
+                                                       leaf_paste_in_buffer(&bi, n + item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, zeros_num);
 
                                                        /* previous string prepared space for pasting new entry, following string pastes this entry */
 
                                                        /* when we have merge directory item, pos_in_item has been changed too */
 
                                                        /* paste new directory entry. 1 is entry number */
-                                                       leaf_paste_entries(&bi,
-                                                                          n +
-                                                                          item_pos
-                                                                          -
-                                                                          ret_val,
-                                                                          l_pos_in_item,
-                                                                          1,
-                                                                          (struct
-                                                                           reiserfs_de_head
-                                                                           *)
-                                                                          body,
-                                                                          body
-                                                                          +
-                                                                          DEH_SIZE,
-                                                                          tb->
-                                                                          insert_size
-                                                                          [0]
-                                                           );
+                                                       leaf_paste_entries(&bi, n + item_pos - ret_val, l_pos_in_item,
+                                                                          1, (struct reiserfs_de_head *) body,
+                                                                          body + DEH_SIZE, tb->insert_size[0]);
                                                        tb->insert_size[0] = 0;
                                                } else {
                                                        /* new directory item doesn't fall into L[0] */
                                                        /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */
-                                                       leaf_shift_left(tb,
-                                                                       tb->
-                                                                       lnum[0],
-                                                                       tb->
-                                                                       lbytes);
+                                                       leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
                                                }
                                                /* Calculate new position to append in item body */
                                                pos_in_item -= tb->lbytes;
                                        } else {
                                                /* regular object */
-                                               RFALSE(tb->lbytes <= 0,
-                                                      "PAP-12095: there is nothing to shift to L[0]. lbytes=%d",
-                                                      tb->lbytes);
-                                               RFALSE(pos_in_item !=
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)),
+                                               RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes);
+                                               RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),
                                                       "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d",
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)),
-                                                      pos_in_item);
+                                                      ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)),pos_in_item);
 
                                                if (tb->lbytes >= pos_in_item) {
                                                        /* appended item will be in L[0] in whole */
                                                        int l_n;
 
                                                        /* this bytes number must be appended to the last item of L[h] */
-                                                       l_n =
-                                                           tb->lbytes -
-                                                           pos_in_item;
+                                                       l_n = tb->lbytes - pos_in_item;
 
                                                        /* Calculate new insert_size[0] */
-                                                       tb->insert_size[0] -=
-                                                           l_n;
+                                                       tb->insert_size[0] -= l_n;
 
-                                                       RFALSE(tb->
-                                                              insert_size[0] <=
-                                                              0,
+                                                       RFALSE(tb->insert_size[0] <= 0,
                                                               "PAP-12105: there is nothing to paste into L[0]. insert_size=%d",
-                                                              tb->
-                                                              insert_size[0]);
-                                                       ret_val =
-                                                           leaf_shift_left(tb,
-                                                                           tb->
-                                                                           lnum
-                                                                           [0],
-                                                                           ih_item_len
-                                                                           (B_N_PITEM_HEAD
-                                                                            (tbS0,
-                                                                             item_pos)));
+                                                              tb->insert_size[0]);
+                                                       ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len
+                                                                           (B_N_PITEM_HEAD(tbS0, item_pos)));
                                                        /* Append to body of item in L[0] */
                                                        buffer_info_init_left(tb, &bi);
                                                        leaf_paste_in_buffer
-                                                           (&bi,
-                                                            n + item_pos -
-                                                            ret_val,
-                                                            ih_item_len
-                                                            (B_N_PITEM_HEAD
-                                                             (tb->L[0],
-                                                              n + item_pos -
-                                                              ret_val)), l_n,
-                                                            body,
-                                                            zeros_num >
-                                                            l_n ? l_n :
-                                                            zeros_num);
+                                                           (&bi, n + item_pos - ret_val, ih_item_len
+                                                            (B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val)),
+                                                            l_n, body,
+                                                            zeros_num > l_n ? l_n : zeros_num);
                                                        /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */
                                                        {
                                                                int version;
-                                                               int temp_l =
-                                                                   l_n;
-
-                                                               RFALSE
-                                                                   (ih_item_len
-                                                                    (B_N_PITEM_HEAD
-                                                                     (tbS0,
-                                                                      0)),
+                                                               int temp_l = l_n;
+
+                                                               RFALSE(ih_item_len(B_N_PITEM_HEAD(tbS0, 0)),
                                                                     "PAP-12106: item length must be 0");
-                                                               RFALSE
-                                                                   (comp_short_le_keys
-                                                                    (B_N_PKEY
-                                                                     (tbS0, 0),
-                                                                     B_N_PKEY
-                                                                     (tb->L[0],
-                                                                      n +
-                                                                      item_pos
-                                                                      -
-                                                                      ret_val)),
+                                                               RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY
+                                                                     (tb->L[0], n + item_pos - ret_val)),
                                                                     "PAP-12107: items must be of the same file");
                                                                if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) {
-                                                                       temp_l =
-                                                                           l_n
-                                                                           <<
-                                                                           (tb->
-                                                                            tb_sb->
-                                                                            s_blocksize_bits
-                                                                            -
-                                                                            UNFM_P_SHIFT);
+                                                                       temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT);
                                                                }
                                                                /* update key of first item in S0 */
-                                                               version =
-                                                                   ih_version
-                                                                   (B_N_PITEM_HEAD
-                                                                    (tbS0, 0));
-                                                               set_le_key_k_offset
-                                                                   (version,
-                                                                    B_N_PKEY
-                                                                    (tbS0, 0),
-                                                                    le_key_k_offset
-                                                                    (version,
-                                                                     B_N_PKEY
-                                                                     (tbS0,
-                                                                      0)) +
-                                                                    temp_l);
+                                                               version = ih_version(B_N_PITEM_HEAD(tbS0, 0));
+                                                               set_le_key_k_offset(version, B_N_PKEY(tbS0, 0),
+                                                                    le_key_k_offset(version,B_N_PKEY(tbS0, 0)) + temp_l);
                                                                /* update left delimiting key */
-                                                               set_le_key_k_offset
-                                                                   (version,
-                                                                    B_N_PDELIM_KEY
-                                                                    (tb->
-                                                                     CFL[0],
-                                                                     tb->
-                                                                     lkey[0]),
-                                                                    le_key_k_offset
-                                                                    (version,
-                                                                     B_N_PDELIM_KEY
-                                                                     (tb->
-                                                                      CFL[0],
-                                                                      tb->
-                                                                      lkey[0]))
-                                                                    + temp_l);
+                                                               set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]),
+                                                                    le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l);
                                                        }
 
                                                        /* Calculate new body, position in item and insert_size[0] */
                                                        if (l_n > zeros_num) {
-                                                               body +=
-                                                                   (l_n -
-                                                                    zeros_num);
+                                                               body += (l_n - zeros_num);
                                                                zeros_num = 0;
                                                        } else
-                                                               zeros_num -=
-                                                                   l_n;
+                                                               zeros_num -= l_n;
                                                        pos_in_item = 0;
 
-                                                       RFALSE
-                                                           (comp_short_le_keys
-                                                            (B_N_PKEY(tbS0, 0),
-                                                             B_N_PKEY(tb->L[0],
-                                                                      B_NR_ITEMS
-                                                                      (tb->
-                                                                       L[0]) -
-                                                                      1))
-                                                            ||
-                                                            !op_is_left_mergeable
-                                                            (B_N_PKEY(tbS0, 0),
-                                                             tbS0->b_size)
-                                                            ||
-                                                            !op_is_left_mergeable
-                                                            (B_N_PDELIM_KEY
-                                                             (tb->CFL[0],
-                                                              tb->lkey[0]),
-                                                             tbS0->b_size),
+                                                       RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1))
+                                                            || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)
+                                                            || !op_is_left_mergeable(B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), tbS0->b_size),
                                                             "PAP-12120: item must be merge-able with left neighboring item");
                                                } else {        /* only part of the appended item will be in L[0] */
 
                                                        /* Calculate position in item for append in S[0] */
-                                                       pos_in_item -=
-                                                           tb->lbytes;
+                                                       pos_in_item -= tb->lbytes;
 
-                                                       RFALSE(pos_in_item <= 0,
-                                                              "PAP-12125: no place for paste. pos_in_item=%d",
-                                                              pos_in_item);
+                                                       RFALSE(pos_in_item <= 0, "PAP-12125: no place for paste. pos_in_item=%d", pos_in_item);
 
                                                        /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
-                                                       leaf_shift_left(tb,
-                                                                       tb->
-                                                                       lnum[0],
-                                                                       tb->
-                                                                       lbytes);
+                                                       leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
                                                }
                                        }
                                } else {        /* appended item will be in L[0] in whole */
@@ -665,52 +495,30 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
 
                                        if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) {       /* if we paste into first item of S[0] and it is left mergable */
                                                /* then increment pos_in_item by the size of the last item in L[0] */
-                                               pasted =
-                                                   B_N_PITEM_HEAD(tb->L[0],
-                                                                  n - 1);
+                                               pasted = B_N_PITEM_HEAD(tb->L[0], n - 1);
                                                if (is_direntry_le_ih(pasted))
-                                                       pos_in_item +=
-                                                           ih_entry_count
-                                                           (pasted);
+                                                       pos_in_item += ih_entry_count(pasted);
                                                else
-                                                       pos_in_item +=
-                                                           ih_item_len(pasted);
+                                                       pos_in_item += ih_item_len(pasted);
                                        }
 
                                        /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
-                                       ret_val =
-                                           leaf_shift_left(tb, tb->lnum[0],
-                                                           tb->lbytes);
+                                       ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
                                        /* Append to body of item in L[0] */
                                        buffer_info_init_left(tb, &bi);
-                                       leaf_paste_in_buffer(&bi,
-                                                            n + item_pos -
-                                                            ret_val,
+                                       leaf_paste_in_buffer(&bi, n + item_pos - ret_val,
                                                             pos_in_item,
                                                             tb->insert_size[0],
                                                             body, zeros_num);
 
                                        /* if appended item is directory, paste entry */
-                                       pasted =
-                                           B_N_PITEM_HEAD(tb->L[0],
-                                                          n + item_pos -
-                                                          ret_val);
+                                       pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val);
                                        if (is_direntry_le_ih(pasted))
-                                               leaf_paste_entries(&bi,
-                                                                  n +
-                                                                  item_pos -
-                                                                  ret_val,
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
-                                                   );
+                                               leaf_paste_entries(&bi, n + item_pos - ret_val,
+                                                                  pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *) body,
+                                                                  body + DEH_SIZE,
+                                                                  tb->insert_size[0]);
                                        /* if appended item is indirect item, put unformatted node into un list */
                                        if (is_indirect_le_ih(pasted))
                                                set_ih_free_space(pasted, 0);
@@ -722,13 +530,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
                                reiserfs_panic(tb->tb_sb, "PAP-12130",
                                               "lnum > 0: unexpected mode: "
                                               " %s(%d)",
-                                              (flag ==
-                                               M_DELETE) ? "DELETE" : ((flag ==
-                                                                        M_CUT)
-                                                                       ? "CUT"
-                                                                       :
-                                                                       "UNKNOWN"),
-                                              flag);
+                                              (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                        }
                } else {
                        /* new item doesn't fall into L[0] */
@@ -748,14 +550,12 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                case M_INSERT:  /* insert item */
                        if (n - tb->rnum[0] < item_pos) {       /* new item or its part falls to R[0] */
                                if (item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) {      /* part of new item falls into R[0] */
-                                       loff_t old_key_comp, old_len,
-                                           r_zeros_number;
+                                       loff_t old_key_comp, old_len, r_zeros_number;
                                        const char *r_body;
                                        int version;
                                        loff_t offset;
 
-                                       leaf_shift_right(tb, tb->rnum[0] - 1,
-                                                        -1);
+                                       leaf_shift_right(tb, tb->rnum[0] - 1, -1);
 
                                        version = ih_version(ih);
                                        /* Remember key component and item length */
@@ -763,29 +563,17 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        old_len = ih_item_len(ih);
 
                                        /* Calculate key component and item length to insert into R[0] */
-                                       offset =
-                                           le_ih_k_offset(ih) +
-                                           ((old_len -
-                                             tb->
-                                             rbytes) << (is_indirect_le_ih(ih)
-                                                         ? tb->tb_sb->
-                                                         s_blocksize_bits -
-                                                         UNFM_P_SHIFT : 0));
+                                       offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0));
                                        set_le_ih_k_offset(ih, offset);
                                        put_ih_item_len(ih, tb->rbytes);
                                        /* Insert part of the item into R[0] */
                                        buffer_info_init_right(tb, &bi);
                                        if ((old_len - tb->rbytes) > zeros_num) {
                                                r_zeros_number = 0;
-                                               r_body =
-                                                   body + (old_len -
-                                                           tb->rbytes) -
-                                                   zeros_num;
+                                               r_body = body + (old_len - tb->rbytes) - zeros_num;
                                        } else {
                                                r_body = body;
-                                               r_zeros_number =
-                                                   zeros_num - (old_len -
-                                                                tb->rbytes);
+                                               r_zeros_number = zeros_num - (old_len - tb->rbytes);
                                                zeros_num -= r_zeros_number;
                                        }
 
@@ -798,25 +586,18 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
 
                                        /* Calculate key component and item length to insert into S[0] */
                                        set_le_ih_k_offset(ih, old_key_comp);
-                                       put_ih_item_len(ih,
-                                                       old_len - tb->rbytes);
+                                       put_ih_item_len(ih, old_len - tb->rbytes);
 
                                        tb->insert_size[0] -= tb->rbytes;
 
                                } else {        /* whole new item falls into R[0] */
 
                                        /* Shift rnum[0]-1 items to R[0] */
-                                       ret_val =
-                                           leaf_shift_right(tb,
-                                                            tb->rnum[0] - 1,
-                                                            tb->rbytes);
+                                       ret_val = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes);
                                        /* Insert new item into R[0] */
                                        buffer_info_init_right(tb, &bi);
-                                       leaf_insert_into_buf(&bi,
-                                                            item_pos - n +
-                                                            tb->rnum[0] - 1,
-                                                            ih, body,
-                                                            zeros_num);
+                                       leaf_insert_into_buf(&bi, item_pos - n + tb->rnum[0] - 1,
+                                                            ih, body, zeros_num);
 
                                        if (item_pos - n + tb->rnum[0] - 1 == 0) {
                                                replace_key(tb, tb->CFR[0],
@@ -841,200 +622,97 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
 
                                                RFALSE(zeros_num,
                                                       "PAP-12145: invalid parameter in case of a directory");
-                                               entry_count =
-                                                   I_ENTRY_COUNT(B_N_PITEM_HEAD
-                                                                 (tbS0,
-                                                                  item_pos));
+                                               entry_count = I_ENTRY_COUNT(B_N_PITEM_HEAD
+                                                                 (tbS0, item_pos));
                                                if (entry_count - tb->rbytes <
                                                    pos_in_item)
                                                        /* new directory entry falls into R[0] */
                                                {
                                                        int paste_entry_position;
 
-                                                       RFALSE(tb->rbytes - 1 >=
-                                                              entry_count
-                                                              || !tb->
-                                                              insert_size[0],
+                                                       RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0],
                                                               "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d",
-                                                              tb->rbytes,
-                                                              entry_count);
+                                                              tb->rbytes, entry_count);
                                                        /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */
-                                                       leaf_shift_right(tb,
-                                                                        tb->
-                                                                        rnum
-                                                                        [0],
-                                                                        tb->
-                                                                        rbytes
-                                                                        - 1);
+                                                       leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1);
                                                        /* Paste given directory entry to directory item */
-                                                       paste_entry_position =
-                                                           pos_in_item -
-                                                           entry_count +
-                                                           tb->rbytes - 1;
+                                                       paste_entry_position = pos_in_item - entry_count + tb->rbytes - 1;
                                                        buffer_info_init_right(tb, &bi);
-                                                       leaf_paste_in_buffer
-                                                           (&bi, 0,
-                                                            paste_entry_position,
-                                                            tb->insert_size[0],
-                                                            body, zeros_num);
+                                                       leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, zeros_num);
                                                        /* paste entry */
-                                                       leaf_paste_entries(&bi,
-                                                                          0,
-                                                                          paste_entry_position,
-                                                                          1,
-                                                                          (struct
-                                                                           reiserfs_de_head
-                                                                           *)
-                                                                          body,
-                                                                          body
-                                                                          +
-                                                                          DEH_SIZE,
-                                                                          tb->
-                                                                          insert_size
-                                                                          [0]
-                                                           );
-
-                                                       if (paste_entry_position
-                                                           == 0) {
+                                                       leaf_paste_entries(&bi, 0, paste_entry_position, 1,
+                                                                          (struct reiserfs_de_head *) body,
+                                                                          body + DEH_SIZE, tb->insert_size[0]);
+
+                                                       if (paste_entry_position == 0) {
                                                                /* change delimiting keys */
-                                                               replace_key(tb,
-                                                                           tb->
-                                                                           CFR
-                                                                           [0],
-                                                                           tb->
-                                                                           rkey
-                                                                           [0],
-                                                                           tb->
-                                                                           R
-                                                                           [0],
-                                                                           0);
+                                                               replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0);
                                                        }
 
                                                        tb->insert_size[0] = 0;
                                                        pos_in_item++;
                                                } else {        /* new directory entry doesn't fall into R[0] */
 
-                                                       leaf_shift_right(tb,
-                                                                        tb->
-                                                                        rnum
-                                                                        [0],
-                                                                        tb->
-                                                                        rbytes);
+                                                       leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                                                }
                                        } else {        /* regular object */
 
-                                               int n_shift, n_rem,
-                                                   r_zeros_number;
+                                               int n_shift, n_rem, r_zeros_number;
                                                const char *r_body;
 
                                                /* Calculate number of bytes which must be shifted from appended item */
-                                               if ((n_shift =
-                                                    tb->rbytes -
-                                                    tb->insert_size[0]) < 0)
+                                               if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0)
                                                        n_shift = 0;
 
-                                               RFALSE(pos_in_item !=
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)),
+                                               RFALSE(pos_in_item != ih_item_len
+                                                      (B_N_PITEM_HEAD(tbS0, item_pos)),
                                                       "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d",
-                                                      pos_in_item,
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos)));
-
-                                               leaf_shift_right(tb,
-                                                                tb->rnum[0],
-                                                                n_shift);
+                                                      pos_in_item, ih_item_len
+                                                      (B_N_PITEM_HEAD(tbS0, item_pos)));
+
+                                               leaf_shift_right(tb, tb->rnum[0], n_shift);
                                                /* Calculate number of bytes which must remain in body after appending to R[0] */
-                                               if ((n_rem =
-                                                    tb->insert_size[0] -
-                                                    tb->rbytes) < 0)
+                                               if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0)
                                                        n_rem = 0;
 
                                                {
                                                        int version;
-                                                       unsigned long temp_rem =
-                                                           n_rem;
-
-                                                       version =
-                                                           ih_version
-                                                           (B_N_PITEM_HEAD
-                                                            (tb->R[0], 0));
-                                                       if (is_indirect_le_key
-                                                           (version,
-                                                            B_N_PKEY(tb->R[0],
-                                                                     0))) {
-                                                               temp_rem =
-                                                                   n_rem <<
-                                                                   (tb->tb_sb->
-                                                                    s_blocksize_bits
-                                                                    -
-                                                                    UNFM_P_SHIFT);
+                                                       unsigned long temp_rem = n_rem;
+
+                                                       version = ih_version(B_N_PITEM_HEAD(tb->R[0], 0));
+                                                       if (is_indirect_le_key(version, B_N_PKEY(tb->R[0], 0))) {
+                                                               temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT);
                                                        }
-                                                       set_le_key_k_offset
-                                                           (version,
-                                                            B_N_PKEY(tb->R[0],
-                                                                     0),
-                                                            le_key_k_offset
-                                                            (version,
-                                                             B_N_PKEY(tb->R[0],
-                                                                      0)) +
-                                                            temp_rem);
-                                                       set_le_key_k_offset
-                                                           (version,
-                                                            B_N_PDELIM_KEY(tb->
-                                                                           CFR
-                                                                           [0],
-                                                                           tb->
-                                                                           rkey
-                                                                           [0]),
-                                                            le_key_k_offset
-                                                            (version,
-                                                             B_N_PDELIM_KEY
-                                                             (tb->CFR[0],
-                                                              tb->rkey[0])) +
-                                                            temp_rem);
+                                                       set_le_key_k_offset(version, B_N_PKEY(tb->R[0], 0),
+                                                            le_key_k_offset(version, B_N_PKEY(tb->R[0], 0)) + temp_rem);
+                                                       set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0]),
+                                                            le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFR[0], tb->rkey[0])) + temp_rem);
                                                }
 /*               k_offset (B_N_PKEY(tb->R[0],0)) += n_rem;
                  k_offset (B_N_PDELIM_KEY(tb->CFR[0],tb->rkey[0])) += n_rem;*/
-                                               do_balance_mark_internal_dirty
-                                                   (tb, tb->CFR[0], 0);
+                                               do_balance_mark_internal_dirty(tb, tb->CFR[0], 0);
 
                                                /* Append part of body into R[0] */
                                                buffer_info_init_right(tb, &bi);
                                                if (n_rem > zeros_num) {
                                                        r_zeros_number = 0;
-                                                       r_body =
-                                                           body + n_rem -
-                                                           zeros_num;
+                                                       r_body = body + n_rem - zeros_num;
                                                } else {
                                                        r_body = body;
-                                                       r_zeros_number =
-                                                           zeros_num - n_rem;
-                                                       zeros_num -=
-                                                           r_zeros_number;
+                                                       r_zeros_number = zeros_num - n_rem;
+                                                       zeros_num -= r_zeros_number;
                                                }
 
-                                               leaf_paste_in_buffer(&bi, 0,
-                                                                    n_shift,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0] -
-                                                                    n_rem,
-                                                                    r_body,
-                                                                    r_zeros_number);
-
-                                               if (is_indirect_le_ih
-                                                   (B_N_PITEM_HEAD
-                                                    (tb->R[0], 0))) {
+                                               leaf_paste_in_buffer(&bi, 0, n_shift,
+                                                                    tb->insert_size[0] - n_rem,
+                                                                    r_body, r_zeros_number);
+
+                                               if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->R[0], 0))) {
 #if 0
                                                        RFALSE(n_rem,
                                                               "PAP-12160: paste more than one unformatted node pointer");
 #endif
-                                                       set_ih_free_space
-                                                           (B_N_PITEM_HEAD
-                                                            (tb->R[0], 0), 0);
+                                                       set_ih_free_space(B_N_PITEM_HEAD(tb->R[0], 0), 0);
                                                }
                                                tb->insert_size[0] = n_rem;
                                                if (!n_rem)
@@ -1044,58 +722,28 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
 
                                        struct item_head *pasted;
 
-                                       ret_val =
-                                           leaf_shift_right(tb, tb->rnum[0],
-                                                            tb->rbytes);
+                                       ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
                                        /* append item in R[0] */
                                        if (pos_in_item >= 0) {
                                                buffer_info_init_right(tb, &bi);
-                                               leaf_paste_in_buffer(&bi,
-                                                                    item_pos -
-                                                                    n +
-                                                                    tb->
-                                                                    rnum[0],
-                                                                    pos_in_item,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0], body,
-                                                                    zeros_num);
+                                               leaf_paste_in_buffer(&bi, item_pos - n + tb->rnum[0], pos_in_item,
+                                                                    tb->insert_size[0], body, zeros_num);
                                        }
 
                                        /* paste new entry, if item is directory item */
-                                       pasted =
-                                           B_N_PITEM_HEAD(tb->R[0],
-                                                          item_pos - n +
-                                                          tb->rnum[0]);
-                                       if (is_direntry_le_ih(pasted)
-                                           && pos_in_item >= 0) {
-                                               leaf_paste_entries(&bi,
-                                                                  item_pos -
-                                                                  n +
-                                                                  tb->rnum[0],
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
-                                                   );
+                                       pasted = B_N_PITEM_HEAD(tb->R[0], item_pos - n + tb->rnum[0]);
+                                       if (is_direntry_le_ih(pasted) && pos_in_item >= 0) {
+                                               leaf_paste_entries(&bi, item_pos - n + tb->rnum[0],
+                                                                  pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *) body,
+                                                                  body + DEH_SIZE, tb->insert_size[0]);
                                                if (!pos_in_item) {
 
-                                                       RFALSE(item_pos - n +
-                                                              tb->rnum[0],
+                                                       RFALSE(item_pos - n + tb->rnum[0],
                                                               "PAP-12165: directory item must be first item of node when pasting is in 0th position");
 
                                                        /* update delimiting keys */
-                                                       replace_key(tb,
-                                                                   tb->CFR[0],
-                                                                   tb->rkey[0],
-                                                                   tb->R[0],
-                                                                   0);
+                                                       replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
                                                }
                                        }
 
@@ -1111,22 +759,16 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                default:        /* cases d and t */
                        reiserfs_panic(tb->tb_sb, "PAP-12175",
                                       "rnum > 0: unexpected mode: %s(%d)",
-                                      (flag ==
-                                       M_DELETE) ? "DELETE" : ((flag ==
-                                                                M_CUT) ? "CUT"
-                                                               : "UNKNOWN"),
-                                      flag);
+                                      (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                }
 
        }
 
        /* tb->rnum[0] > 0 */
        RFALSE(tb->blknum[0] > 3,
-              "PAP-12180: blknum can not be %d. It must be <= 3",
-              tb->blknum[0]);
+              "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]);
        RFALSE(tb->blknum[0] < 0,
-              "PAP-12185: blknum can not be %d. It must be >= 0",
-              tb->blknum[0]);
+              "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]);
 
        /* if while adding to a node we discover that it is possible to split
           it in two, and merge the left part into the left neighbor and the
@@ -1177,8 +819,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
 
                        if (n - snum[i] < item_pos) {   /* new item or it's part falls to first new node S_new[i] */
                                if (item_pos == n - snum[i] + 1 && sbytes[i] != -1) {   /* part of new item falls into S_new[i] */
-                                       int old_key_comp, old_len,
-                                           r_zeros_number;
+                                       int old_key_comp, old_len, r_zeros_number;
                                        const char *r_body;
                                        int version;
 
@@ -1192,15 +833,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        old_len = ih_item_len(ih);
 
                                        /* Calculate key component and item length to insert into S_new[i] */
-                                       set_le_ih_k_offset(ih,
-                                                          le_ih_k_offset(ih) +
-                                                          ((old_len -
-                                                            sbytes[i]) <<
-                                                           (is_indirect_le_ih
-                                                            (ih) ? tb->tb_sb->
-                                                            s_blocksize_bits -
-                                                            UNFM_P_SHIFT :
-                                                            0)));
+                                       set_le_ih_k_offset(ih, le_ih_k_offset(ih) +
+                                                          ((old_len - sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT : 0)));
 
                                        put_ih_item_len(ih, sbytes[i]);
 
@@ -1209,39 +843,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
 
                                        if ((old_len - sbytes[i]) > zeros_num) {
                                                r_zeros_number = 0;
-                                               r_body =
-                                                   body + (old_len -
-                                                           sbytes[i]) -
-                                                   zeros_num;
+                                               r_body = body + (old_len - sbytes[i]) - zeros_num;
                                        } else {
                                                r_body = body;
-                                               r_zeros_number =
-                                                   zeros_num - (old_len -
-                                                                sbytes[i]);
+                                               r_zeros_number = zeros_num - (old_len - sbytes[i]);
                                                zeros_num -= r_zeros_number;
                                        }
 
-                                       leaf_insert_into_buf(&bi, 0, ih, r_body,
-                                                            r_zeros_number);
+                                       leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeros_number);
 
                                        /* Calculate key component and item length to insert into S[i] */
                                        set_le_ih_k_offset(ih, old_key_comp);
-                                       put_ih_item_len(ih,
-                                                       old_len - sbytes[i]);
+                                       put_ih_item_len(ih, old_len - sbytes[i]);
                                        tb->insert_size[0] -= sbytes[i];
                                } else {        /* whole new item falls into S_new[i] */
 
                                        /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */
                                        leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
-                                                       snum[i] - 1, sbytes[i],
-                                                       S_new[i]);
+                                                       snum[i] - 1, sbytes[i], S_new[i]);
 
                                        /* Insert new item into S_new[i] */
                                        buffer_info_init_bh(tb, &bi, S_new[i]);
-                                       leaf_insert_into_buf(&bi,
-                                                            item_pos - n +
-                                                            snum[i] - 1, ih,
-                                                            body, zeros_num);
+                                       leaf_insert_into_buf(&bi, item_pos - n + snum[i] - 1,
+                                                            ih, body, zeros_num);
 
                                        zeros_num = tb->insert_size[0] = 0;
                                }
@@ -1268,150 +892,73 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,  /* item h
 
                                                int entry_count;
 
-                                               entry_count =
-                                                   ih_entry_count(aux_ih);
+                                               entry_count = ih_entry_count(aux_ih);
 
-                                               if (entry_count - sbytes[i] <
-                                                   pos_in_item
-                                                   && pos_in_item <=
-                                                   entry_count) {
+                                               if (entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count) {
                                                        /* new directory entry falls into S_new[i] */
 
-                                                       RFALSE(!tb->
-                                                              insert_size[0],
-                                                              "PAP-12215: insert_size is already 0");
-                                                       RFALSE(sbytes[i] - 1 >=
-                                                              entry_count,
+                                                       RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0");
+                                                       RFALSE(sbytes[i] - 1 >= entry_count,
                                                               "PAP-12220: there are no so much entries (%d), only %d",
-                                                              sbytes[i] - 1,
-                                                              entry_count);
+                                                              sbytes[i] - 1, entry_count);
 
                                                        /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */
-                                                       leaf_move_items
-                                                           (LEAF_FROM_S_TO_SNEW,
-                                                            tb, snum[i],
-                                                            sbytes[i] - 1,
-                                                            S_new[i]);
+                                                       leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i] - 1, S_new[i]);
                                                        /* Paste given directory entry to directory item */
                                                        buffer_info_init_bh(tb, &bi, S_new[i]);
-                                                       leaf_paste_in_buffer
-                                                           (&bi, 0,
-                                                            pos_in_item -
-                                                            entry_count +
-                                                            sbytes[i] - 1,
-                                                            tb->insert_size[0],
-                                                            body, zeros_num);
+                                                       leaf_paste_in_buffer(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1,
+                                                            tb->insert_size[0], body, zeros_num);
                                                        /* paste new directory entry */
-                                                       leaf_paste_entries(&bi,
-                                                                          0,
-                                                                          pos_in_item
-                                                                          -
-                                                                          entry_count
-                                                                          +
-                                                                          sbytes
-                                                                          [i] -
-                                                                          1, 1,
-                                                                          (struct
-                                                                           reiserfs_de_head
-                                                                           *)
-                                                                          body,
-                                                                          body
-                                                                          +
-                                                                          DEH_SIZE,
-                                                                          tb->
-                                                                          insert_size
-                                                                          [0]
-                                                           );
+                                                       leaf_paste_entries(&bi, 0, pos_in_item - entry_count + sbytes[i] - 1, 1,
+                                                                          (struct reiserfs_de_head *) body,
+                                                                          body + DEH_SIZE, tb->insert_size[0]);
                                                        tb->insert_size[0] = 0;
                                                        pos_in_item++;
                                                } else {        /* new directory entry doesn't fall into S_new[i] */
-                                                       leaf_move_items
-                                                           (LEAF_FROM_S_TO_SNEW,
-                                                            tb, snum[i],
-                                                            sbytes[i],
-                                                            S_new[i]);
+                                                       leaf_move_items(LEAF_FROM_S_TO_SNEW,tb, snum[i], sbytes[i], S_new[i]);
                                                }
                                        } else {        /* regular object */
 
-                                               int n_shift, n_rem,
-                                                   r_zeros_number;
+                                               int n_shift, n_rem, r_zeros_number;
                                                const char *r_body;
 
-                                               RFALSE(pos_in_item !=
-                                                      ih_item_len
-                                                      (B_N_PITEM_HEAD
-                                                       (tbS0, item_pos))
-                                                      || tb->insert_size[0] <=
-                                                      0,
+                                               RFALSE(pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)) || tb->insert_size[0] <= 0,
                                                       "PAP-12225: item too short or insert_size <= 0");
 
                                                /* Calculate number of bytes which must be shifted from appended item */
-                                               n_shift =
-                                                   sbytes[i] -
-                                                   tb->insert_size[0];
+                                               n_shift = sbytes[i] - tb->insert_size[0];
                                                if (n_shift < 0)
                                                        n_shift = 0;
-                                               leaf_move_items
-                                                   (LEAF_FROM_S_TO_SNEW, tb,
-                                                    snum[i], n_shift,
-                                                    S_new[i]);
+                                               leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], n_shift, S_new[i]);
 
                                                /* Calculate number of bytes which must remain in body after append to S_new[i] */
-                                               n_rem =
-                                                   tb->insert_size[0] -
-                                                   sbytes[i];
+                                               n_rem = tb->insert_size[0] - sbytes[i];
                                                if (n_rem < 0)
                                                        n_rem = 0;
                                                /* Append part of body into S_new[0] */
                                                buffer_info_init_bh(tb, &bi, S_new[i]);
                                                if (n_rem > zeros_num) {
                                                        r_zeros_number = 0;
-                                                       r_body =
-                                                           body + n_rem -
-                                                           zeros_num;
+                                                       r_body = body + n_rem - zeros_num;
                                                } else {
                                                        r_body = body;
-                                                       r_zeros_number =
-                                                           zeros_num - n_rem;
-                                                       zeros_num -=
-                                                           r_zeros_number;
+                                                       r_zeros_number = zeros_num - n_rem;
+                                                       zeros_num -= r_zeros_number;
                                                }
 
-                                               leaf_paste_in_buffer(&bi, 0,
-                                                                    n_shift,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0] -
-                                                                    n_rem,
-                                                                    r_body,
-                                                                    r_zeros_number);
+                                               leaf_paste_in_buffer(&bi, 0, n_shift,
+                                                                    tb->insert_size[0] - n_rem,
+                                                                    r_body, r_zeros_number);
                                                {
                                                        struct item_head *tmp;
 
-                                                       tmp =
-                                                           B_N_PITEM_HEAD(S_new
-                                                                          [i],
-                                                                          0);
+                                                       tmp = B_N_PITEM_HEAD(S_new[i], 0);
                                                        if (is_indirect_le_ih
                                                            (tmp)) {
-                                                               set_ih_free_space
-                                                                   (tmp, 0);
-                                                               set_le_ih_k_offset
-                                                                   (tmp,
-                                                                    le_ih_k_offset
-                                                                    (tmp) +
-                                                                    (n_rem <<
-                                                                     (tb->
-                                                                      tb_sb->
-                                                                      s_blocksize_bits
-                                                                      -
-                                                                      UNFM_P_SHIFT)));
+                                                               set_ih_free_space(tmp, 0);
+                                                               set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT)));
                                                        } else {
-                                                               set_le_ih_k_offset
-                                                                   (tmp,
-                                                                    le_ih_k_offset
-                                                                    (tmp) +
-                                                                    n_rem);
+                                                               set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem);
                                                        }
                                                }
 
@@ -1426,8 +973,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
                                        struct item_head *pasted;
 
 #ifdef CONFIG_REISERFS_CHECK
-                                       struct item_head *ih_check =
-                                           B_N_PITEM_HEAD(tbS0, item_pos);
+                                       struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos);
 
                                        if (!is_direntry_le_ih(ih_check)
                                            && (pos_in_item != ih_item_len(ih_check)
@@ -1439,8 +985,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,     /* item h
                                                             "to ih_item_len");
 #endif                         /* CONFIG_REISERFS_CHECK */
 
-                                       leaf_mi =
-                                           leaf_move_items(LEAF_FROM_S_TO_SNEW,
+                                       leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW,
                                                            tb, snum[i],
                                                            sbytes[i],
                                                            S_new[i]);
@@ -1452,30 +997,19 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                                        /* paste into item */
                                        buffer_info_init_bh(tb, &bi, S_new[i]);
                                        leaf_paste_in_buffer(&bi,
-                                                            item_pos - n +
-                                                            snum[i],
+                                                            item_pos - n + snum[i],
                                                             pos_in_item,
                                                             tb->insert_size[0],
                                                             body, zeros_num);
 
-                                       pasted =
-                                           B_N_PITEM_HEAD(S_new[i],
-                                                          item_pos - n +
-                                                          snum[i]);
+                                       pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]);
                                        if (is_direntry_le_ih(pasted)) {
                                                leaf_paste_entries(&bi,
-                                                                  item_pos -
-                                                                  n + snum[i],
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
+                                                                  item_pos - n + snum[i],
+                                                                  pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *)body,
+                                                                  body + DEH_SIZE,
+                                                                  tb->insert_size[0]
                                                    );
                                        }
 
@@ -1495,11 +1029,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                default:        /* cases d and t */
                        reiserfs_panic(tb->tb_sb, "PAP-12245",
                                       "blknum > 2: unexpected mode: %s(%d)",
-                                      (flag ==
-                                       M_DELETE) ? "DELETE" : ((flag ==
-                                                                M_CUT) ? "CUT"
-                                                               : "UNKNOWN"),
-                                      flag);
+                                      (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag);
                }
 
                memcpy(insert_key + i, B_N_PKEY(S_new[i], 0), KEY_SIZE);
@@ -1524,9 +1054,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                        /* If we insert the first key change the delimiting key */
                        if (item_pos == 0) {
                                if (tb->CFL[0]) /* can be 0 in reiserfsck */
-                                       replace_key(tb, tb->CFL[0], tb->lkey[0],
-                                                   tbS0, 0);
-
+                                       replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
                        }
                        break;
 
@@ -1536,53 +1064,27 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,  /* item h
                                pasted = B_N_PITEM_HEAD(tbS0, item_pos);
                                /* when directory, may be new entry already pasted */
                                if (is_direntry_le_ih(pasted)) {
-                                       if (pos_in_item >= 0 &&
-                                           pos_in_item <=
-                                           ih_entry_count(pasted)) {
+                                       if (pos_in_item >= 0 && pos_in_item <= ih_entry_count(pasted)) {
 
                                                RFALSE(!tb->insert_size[0],
                                                       "PAP-12260: insert_size is 0 already");
 
                                                /* prepare space */
                                                buffer_info_init_tbS0(tb, &bi);
-                                               leaf_paste_in_buffer(&bi,
-                                                                    item_pos,
-                                                                    pos_in_item,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0], body,
+                                               leaf_paste_in_buffer(&bi, item_pos, pos_in_item,
+                                                                    tb->insert_size[0], body,
                                                                     zeros_num);
 
                                                /* paste entry */
-                                               leaf_paste_entries(&bi,
-                                                                  item_pos,
-                                                                  pos_in_item,
-                                                                  1,
-                                                                  (struct
-                                                                   reiserfs_de_head
-                                                                   *)body,
-                                                                  body +
-                                                                  DEH_SIZE,
-                                                                  tb->
-                                                                  insert_size
-                                                                  [0]
-                                                   );
+                                               leaf_paste_entries(&bi, item_pos, pos_in_item, 1,
+                                                                  (struct reiserfs_de_head *)body,
+                                                                  body + DEH_SIZE,
+                                                                  tb->insert_size[0]);
                                                if (!item_pos && !pos_in_item) {
-                                                       RFALSE(!tb->CFL[0]
-                                                              || !tb->L[0],
+                                                       RFALSE(!tb->CFL[0] || !tb->L[0],
                                                               "PAP-12270: CFL[0]/L[0] must be specified");
-                                                       if (tb->CFL[0]) {
-                                                               replace_key(tb,
-                                                                           tb->
-                                                                           CFL
-                                                                           [0],
-                                                                           tb->
-                                                                           lkey
-                                                                           [0],
-                                                                           tbS0,
-                                                                           0);
-
-                                                       }
+                                                       if (tb->CFL[0])
+                                                               replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
                                                }
                                                tb->insert_size[0] = 0;
                                        }
@@ -1593,13 +1095,8 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,   /* item h
                                                       "PAP-12275: insert size must not be %d",
                                                       tb->insert_size[0]);
                                                buffer_info_init_tbS0(tb, &bi);
-                                               leaf_paste_in_buffer(&bi,
-                                                                    item_pos,
-                                                                    pos_in_item,
-                                                                    tb->
-                                                                    insert_size
-                                                                    [0], body,
-                                                                    zeros_num);
+                                               leaf_paste_in_buffer(&bi, item_pos, pos_in_item,
+                                                                    tb->insert_size[0], body, zeros_num);
 
                                                if (is_indirect_le_ih(pasted)) {
 #if 0
@@ -1611,8 +1108,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                                               tb->
                                                               insert_size[0]);
 #endif
-                                                       set_ih_free_space
-                                                           (pasted, 0);
+                                                       set_ih_free_space(pasted, 0);
                                                }
                                                tb->insert_size[0] = 0;
                                        }
@@ -1620,8 +1116,7 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih,    /* item h
                                        else {
                                                if (tb->insert_size[0]) {
                                                        print_cur_tb("12285");
-                                                       reiserfs_panic(tb->
-                                                                      tb_sb,
+                                                       reiserfs_panic(tb->tb_sb,
                                                            "PAP-12285",
                                                            "insert_size "
                                                            "must be 0 "
index f15537452231d003a05f99b6b28d3c63b85dc8f0..b28d1dd10e8b70194a604a1fca654237edd817be 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
  * wait == 1 case since in that case write_inode() functions do
  * sync_dirty_buffer() and thus effectively write one block at a time.
  */
-static int __sync_filesystem(struct super_block *sb, int wait,
-                            unsigned long start)
+static int __sync_filesystem(struct super_block *sb, int wait)
 {
        if (wait)
-               sync_inodes_sb(sb, start);
+               sync_inodes_sb(sb);
        else
                writeback_inodes_sb(sb, WB_REASON_SYNC);
 
@@ -48,7 +47,6 @@ static int __sync_filesystem(struct super_block *sb, int wait,
 int sync_filesystem(struct super_block *sb)
 {
        int ret;
-       unsigned long start = jiffies;
 
        /*
         * We need to be protected against the filesystem going from
@@ -62,17 +60,17 @@ int sync_filesystem(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
-       ret = __sync_filesystem(sb, 0, start);
+       ret = __sync_filesystem(sb, 0);
        if (ret < 0)
                return ret;
-       return __sync_filesystem(sb, 1, start);
+       return __sync_filesystem(sb, 1);
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
 static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
        if (!(sb->s_flags & MS_RDONLY))
-               sync_inodes_sb(sb, *((unsigned long *)arg));
+               sync_inodes_sb(sb);
 }
 
 static void sync_fs_one_sb(struct super_block *sb, void *arg)
@@ -104,10 +102,9 @@ static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
 SYSCALL_DEFINE0(sync)
 {
        int nowait = 0, wait = 1;
-       unsigned long start = jiffies;
 
        wakeup_flusher_threads(0, WB_REASON_SYNC);
-       iterate_supers(sync_inodes_one_sb, &start);
+       iterate_supers(sync_inodes_one_sb, NULL);
        iterate_supers(sync_fs_one_sb, &nowait);
        iterate_supers(sync_fs_one_sb, &wait);
        iterate_bdevs(fdatawrite_one_bdev, NULL);
@@ -222,23 +219,6 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
        return do_fsync(fd, 1);
 }
 
-/**
- * generic_write_sync - perform syncing after a write if file / inode is sync
- * @file:      file to which the write happened
- * @pos:       offset where the write started
- * @count:     length of the write
- *
- * This is just a simple wrapper about our general syncing function.
- */
-int generic_write_sync(struct file *file, loff_t pos, loff_t count)
-{
-       if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
-               return 0;
-       return vfs_fsync_range(file, pos, pos + count - 1,
-                              (file->f_flags & __O_SYNC) ? 0 : 1);
-}
-EXPORT_SYMBOL(generic_write_sync);
-
 /*
  * sys_sync_file_range() permits finely controlled syncing over a segment of
  * a file in the range offset .. (offset+nbytes-1) inclusive.  If nbytes is
index 6211230814fd89dcc1a0a4b0acbabe000428e5b8..3eaf5c6622eb4fafc82137bc501aac803d7952f4 100644 (file)
@@ -27,6 +27,7 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
 {
        struct dentry *root;
        void *ns;
+       bool new_sb;
 
        if (!(flags & MS_KERNMOUNT)) {
                if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
@@ -37,8 +38,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        }
 
        ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
-       root = kernfs_mount_ns(fs_type, flags, sysfs_root, ns);
-       if (IS_ERR(root))
+       root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns);
+       if (IS_ERR(root) || !new_sb)
                kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
        return root;
 }
index c02a27a19c6df0984eb3ea13fc5a06c5e251aaa5..1037637957c7670e1a66e6bf1a8e51c80fbcc49d 100644 (file)
@@ -144,6 +144,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        size_t count = iocb->ki_nbytes;
        struct udf_inode_info *iinfo = UDF_I(inode);
 
+       mutex_lock(&inode->i_mutex);
        down_write(&iinfo->i_data_sem);
        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
                if (file->f_flags & O_APPEND)
@@ -156,6 +157,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                                pos + count)) {
                        err = udf_expand_file_adinicb(inode);
                        if (err) {
+                               mutex_unlock(&inode->i_mutex);
                                udf_debug("udf_expand_adinicb: err=%d\n", err);
                                return err;
                        }
@@ -169,9 +171,17 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        } else
                up_write(&iinfo->i_data_sem);
 
-       retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
-       if (retval > 0)
+       retval = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
+       mutex_unlock(&inode->i_mutex);
+
+       if (retval > 0) {
+               ssize_t err;
+
                mark_inode_dirty(inode);
+               err = generic_write_sync(file, iocb->ki_pos - retval, retval);
+               if (err < 0)
+                       retval = err;
+       }
 
        return retval;
 }
index 062b7925bca04c02949919ac37aab790d7b982a2..982ce05c87ed61c86dfc9200731a28f2db44b70b 100644 (file)
@@ -265,6 +265,7 @@ int udf_expand_file_adinicb(struct inode *inode)
                .nr_to_write = 1,
        };
 
+       WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
        if (!iinfo->i_lenAlloc) {
                if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
                        iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
index 2e7989e3a2d67374d17e5086ec3b15bfbcb32e2d..64b48eade91d14c79408b6863f199e9181350f81 100644 (file)
@@ -799,7 +799,7 @@ xfs_file_aio_write(
                XFS_STATS_ADD(xs_write_bytes, ret);
 
                /* Handle various SYNC-type writes */
-               err = generic_write_sync(file, pos, ret);
+               err = generic_write_sync(file, iocb->ki_pos - ret, ret);
                if (err < 0)
                        ret = err;
        }
index f35d5c953ff953dcde133c4b55568d1920db3589..9ddfb8190ca1cd56b5f1cd2247e9f54925fce68f 100644 (file)
@@ -705,7 +705,6 @@ xfs_setattr_size(
 {
        struct xfs_mount        *mp = ip->i_mount;
        struct inode            *inode = VFS_I(ip);
-       int                     mask = iattr->ia_valid;
        xfs_off_t               oldsize, newsize;
        struct xfs_trans        *tp;
        int                     error;
@@ -726,8 +725,8 @@ xfs_setattr_size(
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        ASSERT(S_ISREG(ip->i_d.di_mode));
-       ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
-                       ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
+       ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
+               ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
 
        oldsize = inode->i_size;
        newsize = iattr->ia_size;
@@ -736,7 +735,7 @@ xfs_setattr_size(
         * Short circuit the truncate case for zero length files.
         */
        if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
-               if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
+               if (!(iattr->ia_valid & (ATTR_CTIME|ATTR_MTIME)))
                        return 0;
 
                /*
@@ -824,10 +823,11 @@ xfs_setattr_size(
         * these flags set.  For all other operations the VFS set these flags
         * explicitly if it wants a timestamp update.
         */
-       if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+       if (newsize != oldsize &&
+           !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) {
                iattr->ia_ctime = iattr->ia_mtime =
                        current_fs_time(inode->i_sb);
-               mask |= ATTR_CTIME | ATTR_MTIME;
+               iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
        }
 
        /*
@@ -863,9 +863,9 @@ xfs_setattr_size(
                xfs_inode_clear_eofblocks_tag(ip);
        }
 
-       if (mask & ATTR_MODE)
+       if (iattr->ia_valid & ATTR_MODE)
                xfs_setattr_mode(ip, iattr);
-       if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+       if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
                xfs_setattr_time(ip, iattr);
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
index cdebd832c3dba1fcd937869d1cedcebe09113c25..4ef6fdbced78b7e99680f9e4e8afbb502a7bce92 100644 (file)
@@ -205,16 +205,25 @@ xlog_cil_insert_format_items(
                /*
                 * We 64-bit align the length of each iovec so that the start
                 * of the next one is naturally aligned.  We'll need to
-                * account for that slack space here.
+                * account for that slack space here. Then round nbytes up
+                * to 64-bit alignment so that the initial buffer alignment is
+                * easy to calculate and verify.
                 */
                nbytes += niovecs * sizeof(uint64_t);
+               nbytes = round_up(nbytes, sizeof(uint64_t));
 
                /* grab the old item if it exists for reservation accounting */
                old_lv = lip->li_lv;
 
-               /* calc buffer size */
-               buf_size = sizeof(struct xfs_log_vec) + nbytes +
-                               niovecs * sizeof(struct xfs_log_iovec);
+               /*
+                * The data buffer needs to start 64-bit aligned, so round up
+                * that space to ensure we can align it appropriately and not
+                * overrun the buffer.
+                */
+               buf_size = nbytes +
+                          round_up((sizeof(struct xfs_log_vec) +
+                                    niovecs * sizeof(struct xfs_log_iovec)),
+                                   sizeof(uint64_t));
 
                /* compare to existing item size */
                if (lip->li_lv && buf_size <= lip->li_lv->lv_size) {
@@ -251,6 +260,8 @@ xlog_cil_insert_format_items(
                /* The allocated data region lies beyond the iovec region */
                lv->lv_buf_len = 0;
                lv->lv_buf = (char *)lv + buf_size - nbytes;
+               ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t)));
+
                lip->li_ops->iop_format(lip, lv);
 insert:
                ASSERT(lv->lv_buf_len <= nbytes);
index 02df7b408a2623d6a32e7a2bc8285be9348ca646..f96c05669a9e06298980bd14e377e34536d0119b 100644 (file)
@@ -282,22 +282,29 @@ xfs_readsb(
        struct xfs_sb   *sbp = &mp->m_sb;
        int             error;
        int             loud = !(flags & XFS_MFSI_QUIET);
+       const struct xfs_buf_ops *buf_ops;
 
        ASSERT(mp->m_sb_bp == NULL);
        ASSERT(mp->m_ddev_targp != NULL);
 
+       /*
+        * For the initial read, we must guess at the sector
+        * size based on the block device.  It's enough to
+        * get the sb_sectsize out of the superblock and
+        * then reread with the proper length.
+        * We don't verify it yet, because it may not be complete.
+        */
+       sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
+       buf_ops = NULL;
+
        /*
         * Allocate a (locked) buffer to hold the superblock.
         * This will be kept around at all times to optimize
         * access to the superblock.
         */
-       sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
-
 reread:
        bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
-                                  BTOBB(sector_size), 0,
-                                  loud ? &xfs_sb_buf_ops
-                                       : &xfs_sb_quiet_buf_ops);
+                                  BTOBB(sector_size), 0, buf_ops);
        if (!bp) {
                if (loud)
                        xfs_warn(mp, "SB buffer read failed");
@@ -328,12 +335,13 @@ reread:
        }
 
        /*
-        * If device sector size is smaller than the superblock size,
-        * re-read the superblock so the buffer is correctly sized.
+        * Re-read the superblock so the buffer is correctly sized,
+        * and properly verified.
         */
-       if (sector_size < sbp->sb_sectsize) {
+       if (buf_ops == NULL) {
                xfs_buf_relse(bp);
                sector_size = sbp->sb_sectsize;
+               buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops;
                goto reread;
        }
 
index b7c9aea77f8fd2e7ca88537df77536eca8148418..1e116794bb6622d686487f36a461f8f644fd27c2 100644 (file)
@@ -295,8 +295,7 @@ xfs_mount_validate_sb(
            sbp->sb_dblocks == 0                                        ||
            sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)                      ||
            sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
-               XFS_CORRUPTION_ERROR("SB sanity check failed",
-                               XFS_ERRLEVEL_LOW, mp, sbp);
+               xfs_notice(mp, "SB sanity check failed");
                return XFS_ERROR(EFSCORRUPTED);
        }
 
@@ -611,10 +610,10 @@ xfs_sb_read_verify(
                                                XFS_SB_VERSION_5) ||
             dsb->sb_crc != 0)) {
 
-               if (!xfs_verify_cksum(bp->b_addr, be16_to_cpu(dsb->sb_sectsize),
+               if (!xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
                                      offsetof(struct xfs_sb, sb_crc))) {
                        /* Only fail bad secondaries on a known V5 filesystem */
-                       if (bp->b_bn != XFS_SB_DADDR &&
+                       if (bp->b_bn == XFS_SB_DADDR ||
                            xfs_sb_version_hascrc(&mp->m_sb)) {
                                error = EFSCORRUPTED;
                                goto out_error;
@@ -625,7 +624,7 @@ xfs_sb_read_verify(
 
 out_error:
        if (error) {
-               if (error != EWRONGFS)
+               if (error == EFSCORRUPTED)
                        XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
                                             mp, bp->b_addr);
                xfs_buf_ioerror(bp, error);
@@ -644,7 +643,6 @@ xfs_sb_quiet_read_verify(
 {
        struct xfs_dsb  *dsb = XFS_BUF_TO_SBP(bp);
 
-
        if (dsb->sb_magicnum == cpu_to_be32(XFS_SB_MAGIC)) {
                /* XFS filesystem, verify noisily! */
                xfs_sb_read_verify(bp);
index f317488263dd975eb85eb44d9746abfb974ef46f..d971f4932b5d8bb92d5efe645f372462abfbbe81 100644 (file)
@@ -913,7 +913,7 @@ xfs_flush_inodes(
        struct super_block      *sb = mp->m_super;
 
        if (down_read_trylock(&sb->s_umount)) {
-               sync_inodes_sb(sb, jiffies);
+               sync_inodes_sb(sb);
                up_read(&sb->s_umount);
        }
 }
index fa2a50b7ee660c774313e20f0027302bfb0b495c..0a7e06623470586b0509ef99410dbc54aa572f9e 100644 (file)
@@ -5,14 +5,15 @@
  * Compile time versions of __arch_hweightN()
  */
 #define __const_hweight8(w)            \
-      (        (!!((w) & (1ULL << 0))) +       \
-       (!!((w) & (1ULL << 1))) +       \
-       (!!((w) & (1ULL << 2))) +       \
-       (!!((w) & (1ULL << 3))) +       \
-       (!!((w) & (1ULL << 4))) +       \
-       (!!((w) & (1ULL << 5))) +       \
-       (!!((w) & (1ULL << 6))) +       \
-       (!!((w) & (1ULL << 7))) )
+       ((unsigned int)                 \
+        ((!!((w) & (1ULL << 0))) +     \
+         (!!((w) & (1ULL << 1))) +     \
+         (!!((w) & (1ULL << 2))) +     \
+         (!!((w) & (1ULL << 3))) +     \
+         (!!((w) & (1ULL << 4))) +     \
+         (!!((w) & (1ULL << 5))) +     \
+         (!!((w) & (1ULL << 6))) +     \
+         (!!((w) & (1ULL << 7)))))
 
 #define __const_hweight16(w) (__const_hweight8(w)  + __const_hweight8((w)  >> 8 ))
 #define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
index 272ecba9f5889672b4b4e555c3208946a8c5e002..d5cb78f539861afdc82eae345ee4c8148fb2448e 100644 (file)
@@ -15,8 +15,10 @@ typedef u64 __nocast cputime64_t;
 
 
 /*
- * Convert nanoseconds to cputime
+ * Convert nanoseconds <-> cputime
  */
+#define cputime_to_nsecs(__ct)         \
+       jiffies_to_nsecs(cputime_to_jiffies(__ct))
 #define nsecs_to_cputime64(__nsec)     \
        jiffies64_to_cputime64(nsecs_to_jiffies64(__nsec))
 #define nsecs_to_cputime(__nsec)       \
index 2c9e62c2bfd03cce685243832d5db4c8e71ec04c..4e817606c5494126a31ae50e58a6e76242d89f07 100644 (file)
@@ -44,7 +44,10 @@ typedef u64 __nocast cputime64_t;
 /*
  * Convert cputime <-> nanoseconds
  */
-#define nsecs_to_cputime(__nsecs)      ((__force u64)(__nsecs))
+#define cputime_to_nsecs(__ct)         \
+       (__force u64)(__ct)
+#define nsecs_to_cputime(__nsecs)      \
+       (__force cputime_t)(__nsecs)
 
 
 /*
diff --git a/include/asm-generic/mcs_spinlock.h b/include/asm-generic/mcs_spinlock.h
new file mode 100644 (file)
index 0000000..10cd4ff
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ASM_MCS_SPINLOCK_H
+#define __ASM_MCS_SPINLOCK_H
+
+/*
+ * Architectures can define their own:
+ *
+ *   arch_mcs_spin_lock_contended(l)
+ *   arch_mcs_spin_unlock_contended(l)
+ *
+ * See kernel/locking/mcs_spinlock.c.
+ */
+
+#endif /* __ASM_MCS_SPINLOCK_H */
index 8e4f41d9af4d47279e13a33edd317ce5de32e451..1ec08c198b66a8ed7203b63d4cec3af7dc6424df 100644 (file)
@@ -193,6 +193,19 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
 }
 #endif
 
+#ifndef __HAVE_ARCH_PTE_UNUSED
+/*
+ * Some architectures provide facilities to virtualization guests
+ * so that they can flag allocated pages as unused. This allows the
+ * host to transparently reclaim unused pages. This function returns
+ * whether the pte's page is unused.
+ */
+static inline int pte_unused(pte_t pte)
+{
+       return 0;
+}
+#endif
+
 #ifndef __HAVE_ARCH_PMD_SAME
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
@@ -701,6 +714,18 @@ static inline pte_t pte_mknuma(pte_t pte)
 }
 #endif
 
+#ifndef ptep_set_numa
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pte_t *ptep)
+{
+       pte_t ptent = *ptep;
+
+       ptent = pte_mknuma(ptent);
+       set_pte_at(mm, addr, ptep, ptent);
+       return;
+}
+#endif
+
 #ifndef pmd_mknuma
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
@@ -708,6 +733,18 @@ static inline pmd_t pmd_mknuma(pmd_t pmd)
        return pmd_clear_flags(pmd, _PAGE_PRESENT);
 }
 #endif
+
+#ifndef pmdp_set_numa
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pmd_t *pmdp)
+{
+       pmd_t pmd = *pmdp;
+
+       pmd = pmd_mknuma(pmd);
+       set_pmd_at(mm, addr, pmdp, pmd);
+       return;
+}
+#endif
 #else
 extern int pte_numa(pte_t pte);
 extern int pmd_numa(pmd_t pmd);
@@ -715,6 +752,8 @@ extern pte_t pte_mknonnuma(pte_t pte);
 extern pmd_t pmd_mknonnuma(pmd_t pmd);
 extern pte_t pte_mknuma(pte_t pte);
 extern pmd_t pmd_mknuma(pmd_t pmd);
+extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp);
 #endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
 #else
 static inline int pmd_numa(pmd_t pmd)
@@ -742,10 +781,23 @@ static inline pte_t pte_mknuma(pte_t pte)
        return pte;
 }
 
+static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pte_t *ptep)
+{
+       return;
+}
+
+
 static inline pmd_t pmd_mknuma(pmd_t pmd)
 {
        return pmd;
 }
+
+static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
+                                pmd_t *pmdp)
+{
+       return ;
+}
 #endif /* CONFIG_NUMA_BALANCING */
 
 #endif /* CONFIG_MMU */
index bb1e2cdeb9bff0ec6322680196c11e5e676b2ca6..d48bf5a95cc1bd6e2a3f93ebbe6f3022202c1b98 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_POWERPC_RWSEM_H
-#define _ASM_POWERPC_RWSEM_H
+#ifndef _ASM_GENERIC_RWSEM_H
+#define _ASM_GENERIC_RWSEM_H
 
 #ifndef _LINUX_RWSEM_H
 #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
@@ -8,7 +8,7 @@
 #ifdef __KERNEL__
 
 /*
- * R/W semaphores for PPC using the stuff in lib/rwsem.c.
+ * R/W semaphores originally for PPC using the stuff in lib/rwsem.c.
  * Adapted largely from include/asm-i386/rwsem.h
  * by Paul Mackerras <paulus@samba.org>.
  */
@@ -16,7 +16,7 @@
 /*
  * the semaphore definition
  */
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_64BIT
 # define RWSEM_ACTIVE_MASK             0xffffffffL
 #else
 # define RWSEM_ACTIVE_MASK             0x0000ffffL
@@ -129,4 +129,4 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 }
 
 #endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_RWSEM_H */
+#endif /* _ASM_GENERIC_RWSEM_H */
index 04086c5be930e2941f8be91cb0a47107da73ad08..04a7f31301f8fda61ab05cf42a3bea5c28431178 100644 (file)
@@ -199,6 +199,9 @@ int drm_err(const char *func, const char *format, ...);
 #define DRM_INFO(fmt, ...)                             \
        printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
 
+#define DRM_INFO_ONCE(fmt, ...)                                \
+       printk_once(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
+
 /**
  * Debug output.
  *
index 71727b6210ae57d5b064be1cab19a4dc660df6f8..8f3dee09757999c7c959e284250142c143d37d7d 100644 (file)
@@ -907,6 +907,9 @@ struct drm_mode_config {
 
        /* whether async page flip is supported or not */
        bool async_page_flip;
+
+       /* cursor size */
+       uint32_t cursor_width, cursor_height;
 };
 
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
index d1f61bfe0ebe49841cc5f249c8307b75973b98a7..49a828425fa2d984615b6352812681a455d7d99b 100644 (file)
@@ -29,6 +29,8 @@
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_memory.h>
 
+struct device;
+
 /**
  * Initialize pool allocator.
  */
index a1116a3b54ef106b610e74cc54ac0326b76805f6..8c1603b10665d141a2b0cb67e2643c0db7452146 100644 (file)
 #define TEGRA124_CLK_PWM 17
 #define TEGRA124_CLK_I2S2 18
 /* 20 (register bit affects vi and vi_sensor) */
-#define TEGRA124_CLK_GR_2D 21
+/* 21 */
 #define TEGRA124_CLK_USBD 22
 #define TEGRA124_CLK_ISP 23
-#define TEGRA124_CLK_GR_3D 24
+/* 26 */
 /* 25 */
 #define TEGRA124_CLK_DISP2 26
 #define TEGRA124_CLK_DISP1 27
index be85127bfed3a2da2a58a3284a48b7e72094ca91..f27000f55a83d6a27921372f9890520e492a747b 100644 (file)
@@ -171,6 +171,11 @@ static inline int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 add
        return 0;
 }
 
+static inline int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
+{
+       return -ENXIO;
+}
+
 static inline int kvm_vgic_init(struct kvm *kvm)
 {
        return 0;
index 73a25005d88aa7cc76f7e8049b9697be18955c39..1f16d502600c5d887dbb54fea12440bd7bf9692a 100644 (file)
 
 struct device;
 struct ata_port_info;
+struct ahci_host_priv;
+struct platform_device;
 
+/*
+ * Note ahci_platform_data is deprecated, it is only kept around for use
+ * by the old da850 and spear13xx ahci code.
+ * New drivers should instead declare their own platform_driver struct, and
+ * use ahci_platform* functions in their own probe, suspend and resume methods.
+ */
 struct ahci_platform_data {
        int (*init)(struct device *dev, void __iomem *addr);
        void (*exit)(struct device *dev);
        int (*suspend)(struct device *dev);
        int (*resume)(struct device *dev);
-       const struct ata_port_info *ata_port_info;
-       unsigned int force_port_map;
-       unsigned int mask_port_map;
 };
 
+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
+struct ahci_host_priv *ahci_platform_get_resources(
+       struct platform_device *pdev);
+int ahci_platform_init_host(struct platform_device *pdev,
+                           struct ahci_host_priv *hpriv,
+                           const struct ata_port_info *pi_template,
+                           unsigned int force_port_map,
+                           unsigned int mask_port_map);
+
+int ahci_platform_suspend_host(struct device *dev);
+int ahci_platform_resume_host(struct device *dev);
+int ahci_platform_suspend(struct device *dev);
+int ahci_platform_resume(struct device *dev);
+
 #endif /* _AHCI_PLATFORM_H */
index aa865a9a4c4f862b4aa693ed9918399b338e7696..ec1464df4c60930a7fde38f1bc6f35a35b7f79d3 100644 (file)
@@ -43,6 +43,7 @@ struct mq_attr;
 struct mqstat;
 struct audit_watch;
 struct audit_tree;
+struct sk_buff;
 
 struct audit_krule {
        int                     vers_ops;
@@ -463,7 +464,7 @@ extern int audit_filter_user(int type);
 extern int audit_filter_type(int type);
 extern int audit_rule_change(int type, __u32 portid, int seq,
                                void *data, size_t datasz);
-extern int audit_list_rules_send(__u32 portid, int seq);
+extern int audit_list_rules_send(struct sk_buff *request_skb, int seq);
 
 extern u32 audit_enabled;
 #else /* CONFIG_AUDIT */
index fd8bf3219ef7bbc9af53a05e391215a978de1a19..b4a745d7d9a9005b99970afc0ad595fb0efe8e85 100644 (file)
@@ -115,7 +115,6 @@ extern int copy_strings_kernel(int argc, const char *const *argv,
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
 extern void install_exec_creds(struct linux_binprm *bprm);
 extern void set_binfmt(struct linux_binfmt *new);
-extern void free_bprm(struct linux_binprm *);
 extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t);
 
 #endif /* _LINUX_BINFMTS_H */
index 70654521dab69fb03443723550e9b9f8c64a6533..5a4d39b4686be4fb1f78c06442f29d4d955297d7 100644 (file)
@@ -250,6 +250,17 @@ static inline unsigned bio_segments(struct bio *bio)
        struct bio_vec bv;
        struct bvec_iter iter;
 
+       /*
+        * We special case discard/write same, because they interpret bi_size
+        * differently:
+        */
+
+       if (bio->bi_rw & REQ_DISCARD)
+               return 1;
+
+       if (bio->bi_rw & REQ_WRITE_SAME)
+               return 1;
+
        bio_for_each_segment(bv, bio, iter)
                segs++;
 
@@ -332,6 +343,7 @@ extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *);
 extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
 
 extern struct bio_set *fs_bio_set;
+unsigned int bio_integrity_tag_size(struct bio *bio);
 
 static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
index abc9ca7784568ba5737add4fce84577348428eac..be5fd38bd5a05d83eaac250055defcccacafe054 100644 (file)
@@ -196,6 +196,21 @@ static inline unsigned long __ffs64(u64 word)
 
 #ifdef __KERNEL__
 
+#ifndef set_mask_bits
+#define set_mask_bits(ptr, _mask, _bits)       \
+({                                                             \
+       const typeof(*ptr) mask = (_mask), bits = (_bits);      \
+       typeof(*ptr) old, new;                                  \
+                                                               \
+       do {                                                    \
+               old = ACCESS_ONCE(*ptr);                        \
+               new = (old & ~mask) | bits;                     \
+       } while (cmpxchg(ptr, old, new) != old);                \
+                                                               \
+       new;                                                    \
+})
+#endif
+
 #ifndef find_last_bit
 /**
  * find_last_bit - find the last set bit in a memory region
index 161b23105b1ec9d90f3520f08fb66d0d9be66358..2ff2e8d982bea9b689050a2802fba5ec29e44b81 100644 (file)
@@ -83,6 +83,8 @@ struct blk_mq_ops {
         */
        rq_timed_out_fn         *timeout;
 
+       softirq_done_fn         *complete;
+
        /*
         * Override for hctx allocations (should probably go)
         */
@@ -119,11 +121,11 @@ void blk_mq_init_commands(struct request_queue *, void (*init)(void *data, struc
 
 void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule);
 
-void blk_mq_insert_request(struct request_queue *, struct request *, bool);
+void blk_mq_insert_request(struct request *, bool, bool, bool);
 void blk_mq_run_queues(struct request_queue *q, bool async);
 void blk_mq_free_request(struct request *rq);
 bool blk_mq_can_queue(struct blk_mq_hw_ctx *);
-struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp, bool reserved);
+struct request *blk_mq_alloc_request(struct request_queue *q, int rw, gfp_t gfp);
 struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw, gfp_t gfp);
 struct request *blk_mq_rq_from_tag(struct request_queue *q, unsigned int tag);
 
@@ -131,7 +133,15 @@ struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_ind
 struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_reg *, unsigned int);
 void blk_mq_free_single_hw_queue(struct blk_mq_hw_ctx *, unsigned int);
 
-void blk_mq_end_io(struct request *rq, int error);
+bool blk_mq_end_io_partial(struct request *rq, int error,
+               unsigned int nr_bytes);
+static inline void blk_mq_end_io(struct request *rq, int error)
+{
+       bool done = !blk_mq_end_io_partial(rq, error, blk_rq_bytes(rq));
+       BUG_ON(!done);
+}
+
+void blk_mq_complete_request(struct request *rq);
 
 void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx);
 void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx);
index 8678c4322b4462357266397c5455bc9c6be04fd6..4afa4f8f60909f6e53416c60682c02b35408c66e 100644 (file)
@@ -98,7 +98,7 @@ struct request {
        struct list_head queuelist;
        union {
                struct call_single_data csd;
-               struct work_struct mq_flush_data;
+               struct work_struct mq_flush_work;
        };
 
        struct request_queue *q;
@@ -448,13 +448,8 @@ struct request_queue {
        unsigned long           flush_pending_since;
        struct list_head        flush_queue[2];
        struct list_head        flush_data_in_flight;
-       union {
-               struct request  flush_rq;
-               struct {
-                       spinlock_t mq_flush_lock;
-                       struct work_struct mq_flush_work;
-               };
-       };
+       struct request          *flush_rq;
+       spinlock_t              mq_flush_lock;
 
        struct mutex            sysfs_lock;
 
index 2f0543f7510c65aa71c5b5de43315da8d64c51aa..f9bbbb472663af08aef78ac152e8293f36736ea4 100644 (file)
@@ -11,7 +11,9 @@
 #define CAN_SKB_H
 
 #include <linux/types.h>
+#include <linux/skbuff.h>
 #include <linux/can.h>
+#include <net/sock.h>
 
 /*
  * The struct can_skb_priv is used to transport additional information along
@@ -42,4 +44,40 @@ static inline void can_skb_reserve(struct sk_buff *skb)
        skb_reserve(skb, sizeof(struct can_skb_priv));
 }
 
+static inline void can_skb_destructor(struct sk_buff *skb)
+{
+       sock_put(skb->sk);
+}
+
+static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
+{
+       if (sk) {
+               sock_hold(sk);
+               skb->destructor = can_skb_destructor;
+               skb->sk = sk;
+       }
+}
+
+/*
+ * returns an unshared skb owned by the original sock to be echo'ed back
+ */
+static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
+{
+       if (skb_shared(skb)) {
+               struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
+
+               if (likely(nskb)) {
+                       can_skb_set_owner(nskb, skb->sk);
+                       consume_skb(skb);
+                       return nskb;
+               } else {
+                       kfree_skb(skb);
+                       return NULL;
+               }
+       }
+
+       /* we can assume to have an unshared skb with proper owner */
+       return skb;
+}
+
 #endif /* CAN_SKB_H */
index 2623cffc73a17b32cf9660bf67cf05bd9ae4b45f..25bfb0eff7720b459ffefa45ec035ec0229c8b1c 100644 (file)
@@ -373,8 +373,9 @@ extern const char *ceph_mds_op_name(int op);
 /*
  * Ceph setxattr request flags.
  */
-#define CEPH_XATTR_CREATE  1
-#define CEPH_XATTR_REPLACE 2
+#define CEPH_XATTR_CREATE  (1 << 0)
+#define CEPH_XATTR_REPLACE (1 << 1)
+#define CEPH_XATTR_REMOVE  (1 << 31)
 
 union ceph_mds_request_args {
        struct {
index 5c097596104b80535a0a00bdd45b4a2441fac889..9450f025fe0c01ac52bf78caccf114c30312a2e4 100644 (file)
@@ -166,6 +166,8 @@ struct cgroup {
         *
         * The ID of the root cgroup is always 0, and a new cgroup
         * will be assigned with a smallest available ID.
+        *
+        * Allocating/Removing ID must be protected by cgroup_mutex.
         */
        int id;
 
index 092b64168d7fa6935dfe476f1657af9dda620a7a..4a21a872dbbd6423025f1a9253832f228cfe1c48 100644 (file)
@@ -245,6 +245,10 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 void omap2_init_clk_clkdm(struct clk_hw *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
+int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long parent_rate);
+long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *prate);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 int omap2_clk_disable_autoidle_all(void);
index 3f448c65511b525ae9d92c38d7201f087b568334..01c0aa57ccecf39420b3fd30f830614e613fbe58 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/if.h>
 #include <linux/fs.h>
 #include <linux/aio_abi.h>     /* for aio_context_t */
+#include <linux/unistd.h>
 
 #include <asm/compat.h>
 #include <asm/siginfo.h>
@@ -27,6 +28,9 @@
 #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v))
 #endif
 
+#define COMPAT_SYSCALL_DEFINE0(name) \
+       asmlinkage long compat_sys_##name(void)
+
 #define COMPAT_SYSCALL_DEFINE1(name, ...) \
         COMPAT_SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
 #define COMPAT_SYSCALL_DEFINE2(name, ...) \
@@ -68,6 +72,8 @@ typedef struct compat_sigaltstack {
 typedef __compat_uid32_t       compat_uid_t;
 typedef __compat_gid32_t       compat_gid_t;
 
+typedef        compat_ulong_t          compat_aio_context_t;
+
 struct compat_sel_arg_struct;
 struct rusage;
 
@@ -318,7 +324,7 @@ asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg);
 asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp,
                compat_ssize_t msgsz, int msgflg);
 asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp,
-               compat_ssize_t msgsz, long msgtyp, int msgflg);
+               compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg);
 long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmctl(int first, int second, void __user *uptr);
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
@@ -337,6 +343,19 @@ asmlinkage ssize_t compat_sys_preadv(compat_ulong_t fd,
 asmlinkage ssize_t compat_sys_pwritev(compat_ulong_t fd,
                const struct compat_iovec __user *vec,
                compat_ulong_t vlen, u32 pos_low, u32 pos_high);
+
+#ifdef __ARCH_WANT_COMPAT_SYS_PREADV64
+asmlinkage long compat_sys_preadv64(unsigned long fd,
+               const struct compat_iovec __user *vec,
+               unsigned long vlen, loff_t pos);
+#endif
+
+#ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64
+asmlinkage long compat_sys_pwritev64(unsigned long fd,
+               const struct compat_iovec __user *vec,
+               unsigned long vlen, loff_t pos);
+#endif
+
 asmlinkage long compat_sys_lseek(unsigned int, compat_off_t, unsigned int);
 
 asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
@@ -451,7 +470,7 @@ asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
 asmlinkage long compat_sys_timerfd_gettime(int ufd,
                                   struct compat_itimerspec __user *otmr);
 
-asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page,
+asmlinkage long compat_sys_move_pages(pid_t pid, compat_ulong_t nr_pages,
                                      __u32 __user *pages,
                                      const int __user *nodes,
                                      int __user *status,
@@ -481,20 +500,20 @@ asmlinkage long compat_sys_statfs64(const char __user *pathname,
 asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz,
                                     struct compat_statfs64 __user *buf);
 asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
-                                  unsigned long arg);
+                                  compat_ulong_t arg);
 asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
-                                unsigned long arg);
+                                compat_ulong_t arg);
 asmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p);
-asmlinkage long compat_sys_io_getevents(aio_context_t ctx_id,
-                                       unsigned long min_nr,
-                                       unsigned long nr,
+asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id,
+                                       compat_long_t min_nr,
+                                       compat_long_t nr,
                                        struct io_event __user *events,
                                        struct compat_timespec __user *timeout);
-asmlinkage long compat_sys_io_submit(aio_context_t ctx_id, int nr,
+asmlinkage long compat_sys_io_submit(compat_aio_context_t ctx_id, int nr,
                                     u32 __user *iocb);
 asmlinkage long compat_sys_mount(const char __user *dev_name,
                                 const char __user *dir_name,
-                                const char __user *type, unsigned long flags,
+                                const char __user *type, compat_ulong_t flags,
                                 const void __user *data);
 asmlinkage long compat_sys_old_readdir(unsigned int fd,
                                       struct compat_old_linux_dirent __user *,
@@ -502,9 +521,11 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
 asmlinkage long compat_sys_getdents(unsigned int fd,
                                    struct compat_linux_dirent __user *dirent,
                                    unsigned int count);
+#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
 asmlinkage long compat_sys_getdents64(unsigned int fd,
                                      struct linux_dirent64 __user *dirent,
                                      unsigned int count);
+#endif
 asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *,
                                    unsigned int nr_segs, unsigned int flags);
 asmlinkage long compat_sys_open(const char __user *filename, int flags,
@@ -549,9 +570,9 @@ asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
                                    unsigned vlen, unsigned int flags);
 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg,
                                   unsigned int flags);
-asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len,
+asmlinkage long compat_sys_recv(int fd, void __user *buf, compat_size_t len,
                                unsigned flags);
-asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len,
+asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, compat_size_t len,
                            unsigned flags, struct sockaddr __user *addr,
                            int __user *addrlen);
 asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
@@ -615,16 +636,16 @@ asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig,
                                struct compat_siginfo __user *uinfo);
 asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info);
 asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
-                                unsigned long arg);
+                                compat_ulong_t arg);
 asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
                struct compat_timespec __user *utime, u32 __user *uaddr2,
                u32 val3);
 asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
                                      char __user *optval, int __user *optlen);
-asmlinkage long compat_sys_kexec_load(unsigned long entry,
-                                     unsigned long nr_segments,
+asmlinkage long compat_sys_kexec_load(compat_ulong_t entry,
+                                     compat_ulong_t nr_segments,
                                      struct compat_kexec_segment __user *,
-                                     unsigned long flags);
+                                     compat_ulong_t flags);
 asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes,
                        const struct compat_mq_attr __user *u_mqstat,
                        struct compat_mq_attr __user *u_omqstat);
@@ -635,11 +656,11 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name,
                        struct compat_mq_attr __user *u_attr);
 asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
                        const char __user *u_msg_ptr,
-                       size_t msg_len, unsigned int msg_prio,
+                       compat_size_t msg_len, unsigned int msg_prio,
                        const struct compat_timespec __user *u_abs_timeout);
 asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
                        char __user *u_msg_ptr,
-                       size_t msg_len, unsigned int __user *u_msg_prio,
+                       compat_size_t msg_len, unsigned int __user *u_msg_prio,
                        const struct compat_timespec __user *u_abs_timeout);
 asmlinkage long compat_sys_socketcall(int call, u32 __user *args);
 asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args);
@@ -654,12 +675,12 @@ extern void __user *compat_alloc_user_space(unsigned long len);
 
 asmlinkage ssize_t compat_sys_process_vm_readv(compat_pid_t pid,
                const struct compat_iovec __user *lvec,
-               unsigned long liovcnt, const struct compat_iovec __user *rvec,
-               unsigned long riovcnt, unsigned long flags);
+               compat_ulong_t liovcnt, const struct compat_iovec __user *rvec,
+               compat_ulong_t riovcnt, compat_ulong_t flags);
 asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
                const struct compat_iovec __user *lvec,
-               unsigned long liovcnt, const struct compat_iovec __user *rvec,
-               unsigned long riovcnt, unsigned long flags);
+               compat_ulong_t liovcnt, const struct compat_iovec __user *rvec,
+               compat_ulong_t riovcnt, compat_ulong_t flags);
 
 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
                                    compat_off_t __user *offset, compat_size_t count);
index ded429966c1f447db9106359b174fb742fd3fe54..2507fd2a1eb4f9d4971b9de5344e8f250570c012 100644 (file)
  *
  * (asm goto is automatically volatile - the naming reflects this.)
  */
-#if GCC_VERSION <= 40801
-# define asm_volatile_goto(x...)       do { asm goto(x); asm (""); } while (0)
-#else
-# define asm_volatile_goto(x...)       do { asm goto(x); } while (0)
-#endif
+#define asm_volatile_goto(x...)        do { asm goto(x); asm (""); } while (0)
 
 #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
 #if GCC_VERSION >= 40400
diff --git a/include/linux/cputime.h b/include/linux/cputime.h
new file mode 100644 (file)
index 0000000..f2eb2ee
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __LINUX_CPUTIME_H
+#define __LINUX_CPUTIME_H
+
+#include <asm/cputime.h>
+
+#ifndef cputime_to_nsecs
+# define cputime_to_nsecs(__ct)        \
+       (cputime_to_usecs(__ct) * NSEC_PER_USEC)
+#endif
+
+#ifndef nsecs_to_cputime
+# define nsecs_to_cputime(__nsecs)     \
+       usecs_to_cputime((__nsecs) / NSEC_PER_USEC)
+#endif
+
+#endif /* __LINUX_CPUTIME_H */
index dfac5ed311205d2469628273b161e4008fcfcbfb..f886985a28b2d5c0db1f1a798817eb167d2cb23c 100644 (file)
@@ -171,7 +171,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
                               size_t size, int flags, const char *);
 
 #define dma_buf_export(priv, ops, size, flags) \
-       dma_buf_export_named(priv, ops, size, flags, __FILE__)
+       dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME)
 
 int dma_buf_fd(struct dma_buf *dmabuf, int flags);
 struct dma_buf *dma_buf_get(int fd);
index 0a819e7a60c961246c529570fedf7717dd6c3c7c..6c100ff0cae4b6eb886e48530c9f48c858b0f257 100644 (file)
@@ -153,6 +153,102 @@ typedef struct {
        u8 sets_to_zero;
 } efi_time_cap_t;
 
+typedef struct {
+       efi_table_hdr_t hdr;
+       u32 raise_tpl;
+       u32 restore_tpl;
+       u32 allocate_pages;
+       u32 free_pages;
+       u32 get_memory_map;
+       u32 allocate_pool;
+       u32 free_pool;
+       u32 create_event;
+       u32 set_timer;
+       u32 wait_for_event;
+       u32 signal_event;
+       u32 close_event;
+       u32 check_event;
+       u32 install_protocol_interface;
+       u32 reinstall_protocol_interface;
+       u32 uninstall_protocol_interface;
+       u32 handle_protocol;
+       u32 __reserved;
+       u32 register_protocol_notify;
+       u32 locate_handle;
+       u32 locate_device_path;
+       u32 install_configuration_table;
+       u32 load_image;
+       u32 start_image;
+       u32 exit;
+       u32 unload_image;
+       u32 exit_boot_services;
+       u32 get_next_monotonic_count;
+       u32 stall;
+       u32 set_watchdog_timer;
+       u32 connect_controller;
+       u32 disconnect_controller;
+       u32 open_protocol;
+       u32 close_protocol;
+       u32 open_protocol_information;
+       u32 protocols_per_handle;
+       u32 locate_handle_buffer;
+       u32 locate_protocol;
+       u32 install_multiple_protocol_interfaces;
+       u32 uninstall_multiple_protocol_interfaces;
+       u32 calculate_crc32;
+       u32 copy_mem;
+       u32 set_mem;
+       u32 create_event_ex;
+} __packed efi_boot_services_32_t;
+
+typedef struct {
+       efi_table_hdr_t hdr;
+       u64 raise_tpl;
+       u64 restore_tpl;
+       u64 allocate_pages;
+       u64 free_pages;
+       u64 get_memory_map;
+       u64 allocate_pool;
+       u64 free_pool;
+       u64 create_event;
+       u64 set_timer;
+       u64 wait_for_event;
+       u64 signal_event;
+       u64 close_event;
+       u64 check_event;
+       u64 install_protocol_interface;
+       u64 reinstall_protocol_interface;
+       u64 uninstall_protocol_interface;
+       u64 handle_protocol;
+       u64 __reserved;
+       u64 register_protocol_notify;
+       u64 locate_handle;
+       u64 locate_device_path;
+       u64 install_configuration_table;
+       u64 load_image;
+       u64 start_image;
+       u64 exit;
+       u64 unload_image;
+       u64 exit_boot_services;
+       u64 get_next_monotonic_count;
+       u64 stall;
+       u64 set_watchdog_timer;
+       u64 connect_controller;
+       u64 disconnect_controller;
+       u64 open_protocol;
+       u64 close_protocol;
+       u64 open_protocol_information;
+       u64 protocols_per_handle;
+       u64 locate_handle_buffer;
+       u64 locate_protocol;
+       u64 install_multiple_protocol_interfaces;
+       u64 uninstall_multiple_protocol_interfaces;
+       u64 calculate_crc32;
+       u64 copy_mem;
+       u64 set_mem;
+       u64 create_event_ex;
+} __packed efi_boot_services_64_t;
+
 /*
  * EFI Boot Services table
  */
@@ -231,12 +327,61 @@ typedef enum {
     EfiPciIoAttributeOperationMaximum
 } EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
 
+typedef struct {
+       u32 read;
+       u32 write;
+} efi_pci_io_protocol_access_32_t;
+
+typedef struct {
+       u64 read;
+       u64 write;
+} efi_pci_io_protocol_access_64_t;
 
 typedef struct {
        void *read;
        void *write;
 } efi_pci_io_protocol_access_t;
 
+typedef struct {
+       u32 poll_mem;
+       u32 poll_io;
+       efi_pci_io_protocol_access_32_t mem;
+       efi_pci_io_protocol_access_32_t io;
+       efi_pci_io_protocol_access_32_t pci;
+       u32 copy_mem;
+       u32 map;
+       u32 unmap;
+       u32 allocate_buffer;
+       u32 free_buffer;
+       u32 flush;
+       u32 get_location;
+       u32 attributes;
+       u32 get_bar_attributes;
+       u32 set_bar_attributes;
+       uint64_t romsize;
+       void *romimage;
+} efi_pci_io_protocol_32;
+
+typedef struct {
+       u64 poll_mem;
+       u64 poll_io;
+       efi_pci_io_protocol_access_64_t mem;
+       efi_pci_io_protocol_access_64_t io;
+       efi_pci_io_protocol_access_64_t pci;
+       u64 copy_mem;
+       u64 map;
+       u64 unmap;
+       u64 allocate_buffer;
+       u64 free_buffer;
+       u64 flush;
+       u64 get_location;
+       u64 attributes;
+       u64 get_bar_attributes;
+       u64 set_bar_attributes;
+       uint64_t romsize;
+       void *romimage;
+} efi_pci_io_protocol_64;
+
 typedef struct {
        void *poll_mem;
        void *poll_io;
@@ -290,6 +435,42 @@ typedef struct {
 #define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
 #define EFI_RUNTIME_SERVICES_REVISION  0x00010000
 
+typedef struct {
+       efi_table_hdr_t hdr;
+       u32 get_time;
+       u32 set_time;
+       u32 get_wakeup_time;
+       u32 set_wakeup_time;
+       u32 set_virtual_address_map;
+       u32 convert_pointer;
+       u32 get_variable;
+       u32 get_next_variable;
+       u32 set_variable;
+       u32 get_next_high_mono_count;
+       u32 reset_system;
+       u32 update_capsule;
+       u32 query_capsule_caps;
+       u32 query_variable_info;
+} efi_runtime_services_32_t;
+
+typedef struct {
+       efi_table_hdr_t hdr;
+       u64 get_time;
+       u64 set_time;
+       u64 get_wakeup_time;
+       u64 set_wakeup_time;
+       u64 set_virtual_address_map;
+       u64 convert_pointer;
+       u64 get_variable;
+       u64 get_next_variable;
+       u64 set_variable;
+       u64 get_next_high_mono_count;
+       u64 reset_system;
+       u64 update_capsule;
+       u64 query_capsule_caps;
+       u64 query_variable_info;
+} efi_runtime_services_64_t;
+
 typedef struct {
        efi_table_hdr_t hdr;
        void *get_time;
@@ -483,6 +664,38 @@ struct efi_memory_map {
        unsigned long desc_size;
 };
 
+typedef struct {
+       u32 revision;
+       u32 parent_handle;
+       u32 system_table;
+       u32 device_handle;
+       u32 file_path;
+       u32 reserved;
+       u32 load_options_size;
+       u32 load_options;
+       u32 image_base;
+       __aligned_u64 image_size;
+       unsigned int image_code_type;
+       unsigned int image_data_type;
+       unsigned long unload;
+} efi_loaded_image_32_t;
+
+typedef struct {
+       u32 revision;
+       u64 parent_handle;
+       u64 system_table;
+       u64 device_handle;
+       u64 file_path;
+       u64 reserved;
+       u32 load_options_size;
+       u64 load_options;
+       u64 image_base;
+       __aligned_u64 image_size;
+       unsigned int image_code_type;
+       unsigned int image_data_type;
+       unsigned long unload;
+} efi_loaded_image_64_t;
+
 typedef struct {
        u32 revision;
        void *parent_handle;
@@ -511,6 +724,34 @@ typedef struct {
        efi_char16_t filename[1];
 } efi_file_info_t;
 
+typedef struct {
+       u64 revision;
+       u32 open;
+       u32 close;
+       u32 delete;
+       u32 read;
+       u32 write;
+       u32 get_position;
+       u32 set_position;
+       u32 get_info;
+       u32 set_info;
+       u32 flush;
+} efi_file_handle_32_t;
+
+typedef struct {
+       u64 revision;
+       u64 open;
+       u64 close;
+       u64 delete;
+       u64 read;
+       u64 write;
+       u64 get_position;
+       u64 set_position;
+       u64 get_info;
+       u64 set_info;
+       u64 flush;
+} efi_file_handle_64_t;
+
 typedef struct _efi_file_handle {
        u64 revision;
        efi_status_t (*open)(struct _efi_file_handle *,
@@ -573,6 +814,7 @@ extern struct efi {
        efi_reset_system_t *reset_system;
        efi_set_virtual_address_map_t *set_virtual_address_map;
        struct efi_memory_map *memmap;
+       unsigned long flags;
 } efi;
 
 static inline int
@@ -659,18 +901,17 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_ARCH_1             6       /* First arch-specific bit */
 
 #ifdef CONFIG_EFI
-# ifdef CONFIG_X86
-extern int efi_enabled(int facility);
-# else
-static inline int efi_enabled(int facility)
+/*
+ * Test whether the above EFI_* bits are enabled.
+ */
+static inline bool efi_enabled(int feature)
 {
-       return 1;
+       return test_bit(feature, &efi.flags) != 0;
 }
-# endif
 #else
-static inline int efi_enabled(int facility)
+static inline bool efi_enabled(int feature)
 {
-       return 0;
+       return false;
 }
 #endif
 
@@ -809,6 +1050,17 @@ struct efivar_entry {
        bool deleting;
 };
 
+struct efi_simple_text_output_protocol_32 {
+       u32 reset;
+       u32 output_string;
+       u32 test_string;
+};
+
+struct efi_simple_text_output_protocol_64 {
+       u64 reset;
+       u64 output_string;
+       u64 test_string;
+};
 
 struct efi_simple_text_output_protocol {
        void *reset;
index cbacf4faf447a9dd2b3fd50d3dc2e4f86a120e67..4d69123377a2b4e0a7869ba38cc91ceb4fd1c7b7 100644 (file)
@@ -28,33 +28,36 @@ static inline void fput_light(struct file *file, int fput_needed)
 
 struct fd {
        struct file *file;
-       int need_put;
+       unsigned int flags;
 };
+#define FDPUT_FPUT       1
+#define FDPUT_POS_UNLOCK 2
 
 static inline void fdput(struct fd fd)
 {
-       if (fd.need_put)
+       if (fd.flags & FDPUT_FPUT)
                fput(fd.file);
 }
 
 extern struct file *fget(unsigned int fd);
-extern struct file *fget_light(unsigned int fd, int *fput_needed);
+extern struct file *fget_raw(unsigned int fd);
+extern unsigned long __fdget(unsigned int fd);
+extern unsigned long __fdget_raw(unsigned int fd);
+extern unsigned long __fdget_pos(unsigned int fd);
 
-static inline struct fd fdget(unsigned int fd)
+static inline struct fd __to_fd(unsigned long v)
 {
-       int b;
-       struct file *f = fget_light(fd, &b);
-       return (struct fd){f,b};
+       return (struct fd){(struct file *)(v & ~3),v & 3};
 }
 
-extern struct file *fget_raw(unsigned int fd);
-extern struct file *fget_raw_light(unsigned int fd, int *fput_needed);
+static inline struct fd fdget(unsigned int fd)
+{
+       return __to_fd(__fdget(fd));
+}
 
 static inline struct fd fdget_raw(unsigned int fd)
 {
-       int b;
-       struct file *f = fget_raw_light(fd, &b);
-       return (struct fd){f,b};
+       return __to_fd(__fdget_raw(fd));
 }
 
 extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
index 5d7782e42b8f22f81df12652348ff9a21aebc7e4..c3683bdf28fe4e677959f33d524bd724a9a1d59d 100644 (file)
@@ -200,6 +200,7 @@ struct fw_device {
        unsigned irmc:1;
        unsigned bc_implemented:2;
 
+       work_func_t workfn;
        struct delayed_work work;
        struct fw_attribute_group attribute_group;
 };
index 09f553c59813a2b2f88991ab0ab854880e07e574..23b2a35d712efbec3e31df0cae70b69a17b81616 100644 (file)
@@ -123,6 +123,9 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* File is opened with O_PATH; almost nothing can be done with it */
 #define FMODE_PATH             ((__force fmode_t)0x4000)
 
+/* File needs atomic accesses to f_pos */
+#define FMODE_ATOMIC_POS       ((__force fmode_t)0x8000)
+
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)
 
@@ -780,13 +783,14 @@ struct file {
        const struct file_operations    *f_op;
 
        /*
-        * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR.
+        * Protects f_ep_links, f_flags.
         * Must not be taken from IRQ context.
         */
        spinlock_t              f_lock;
        atomic_long_t           f_count;
        unsigned int            f_flags;
        fmode_t                 f_mode;
+       struct mutex            f_pos_lock;
        loff_t                  f_pos;
        struct fown_struct      f_owner;
        const struct cred       *f_cred;
@@ -808,7 +812,7 @@ struct file {
 #ifdef CONFIG_DEBUG_WRITECOUNT
        unsigned long f_mnt_write_state;
 #endif
-};
+} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
 
 struct file_handle {
        __u32 handle_bytes;
@@ -2079,6 +2083,7 @@ extern struct file * dentry_open(const struct path *, int, const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
 
 extern struct filename *getname(const char __user *);
+extern struct filename *getname_kernel(const char *);
 
 enum {
        FILE_CREATED = 1,
@@ -2273,7 +2278,13 @@ extern int filemap_fdatawrite_range(struct address_space *mapping,
 extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,
                           int datasync);
 extern int vfs_fsync(struct file *file, int datasync);
-extern int generic_write_sync(struct file *file, loff_t pos, loff_t count);
+static inline int generic_write_sync(struct file *file, loff_t pos, loff_t count)
+{
+       if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
+               return 0;
+       return vfs_fsync_range(file, pos, pos + count - 1,
+                              (file->f_flags & __O_SYNC) ? 0 : 1);
+}
 extern void emergency_sync(void);
 extern void emergency_remount(void);
 #ifdef CONFIG_BLOCK
index 3d286ff49ab0c82309ec3499bf27cc77f75f3670..64cf3ef50696c7bf50b3c3a3e211cfa9d3accb0d 100644 (file)
@@ -99,7 +99,7 @@ struct fsnotify_ops {
                            struct fsnotify_mark *inode_mark,
                            struct fsnotify_mark *vfsmount_mark,
                            u32 mask, void *data, int data_type,
-                           const unsigned char *file_name);
+                           const unsigned char *file_name, u32 cookie);
        void (*free_group_priv)(struct fsnotify_group *group);
        void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group);
        void (*free_event)(struct fsnotify_event *event);
@@ -160,7 +160,7 @@ struct fsnotify_group {
 
        struct fasync_struct *fsn_fa;    /* async notification */
 
-       struct fsnotify_event overflow_event;   /* Event we queue when the
+       struct fsnotify_event *overflow_event;  /* Event we queue when the
                                                 * notification list is too
                                                 * full */
 
index 4e4cc28623adff33d7f33bc2f7ceda7269397c62..4cdb3a17bcb5932113020955cf8aa46b7b592f14 100644 (file)
@@ -495,10 +495,6 @@ enum {
        FILTER_TRACE_FN,
 };
 
-#define EVENT_STORAGE_SIZE 128
-extern struct mutex event_storage_mutex;
-extern char event_storage[EVENT_STORAGE_SIZE];
-
 extern int trace_event_raw_init(struct ftrace_event_call *call);
 extern int trace_define_field(struct ftrace_event_call *call, const char *type,
                              const char *name, int offset, int size,
index b0d95cac826e8f310aee6dfa999c69ee56727bfb..6435f46d6e1319b71f52050144f3e871986196df 100644 (file)
@@ -55,7 +55,11 @@ union futex_key {
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
 extern void exit_pi_state_list(struct task_struct *curr);
+#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
+#define futex_cmpxchg_enabled 1
+#else
 extern int futex_cmpxchg_enabled;
+#endif
 #else
 static inline void exit_robust_list(struct task_struct *curr)
 {
index 0437439bc047bd4a99d7465132b1d9417667934e..39b81dc7d01acdb28e6e888fea3399f7866057f8 100644 (file)
@@ -123,6 +123,10 @@ struct vm_area_struct;
                         __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \
                         __GFP_NO_KSWAPD)
 
+/*
+ * GFP_THISNODE does not perform any reclaim, you most likely want to
+ * use __GFP_THISNODE to allocate from a given node without fallback!
+ */
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE   (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
 #else
index 4d34dbbbad4dde2ce2c1cd820320537661575450..7a8144fef4065fab8505ffcfe2482cc0b60f3cbb 100644 (file)
@@ -4,8 +4,6 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 
-#ifdef CONFIG_GPIOLIB
-
 struct device;
 struct gpio_chip;
 
@@ -18,6 +16,8 @@ struct gpio_chip;
  */
 struct gpio_desc;
 
+#ifdef CONFIG_GPIOLIB
+
 /* Acquire and dispose GPIOs */
 struct gpio_desc *__must_check gpiod_get(struct device *dev,
                                         const char *con_id);
index db512014e061b27abae7d689175e82d74348683b..b826239bdce0b26a614ae0802782860348dd6fc6 100644 (file)
@@ -157,46 +157,6 @@ static inline int hpage_nr_pages(struct page *page)
                return HPAGE_PMD_NR;
        return 1;
 }
-/*
- * compound_trans_head() should be used instead of compound_head(),
- * whenever the "page" passed as parameter could be the tail of a
- * transparent hugepage that could be undergoing a
- * __split_huge_page_refcount(). The page structure layout often
- * changes across releases and it makes extensive use of unions. So if
- * the page structure layout will change in a way that
- * page->first_page gets clobbered by __split_huge_page_refcount, the
- * implementation making use of smp_rmb() will be required.
- *
- * Currently we define compound_trans_head as compound_head, because
- * page->private is in the same union with page->first_page, and
- * page->private isn't clobbered. However this also means we're
- * currently leaving dirt into the page->private field of anonymous
- * pages resulting from a THP split, instead of setting page->private
- * to zero like for every other page that has PG_private not set. But
- * anonymous pages don't use page->private so this is not a problem.
- */
-#if 0
-/* This will be needed if page->private will be clobbered in split_huge_page */
-static inline struct page *compound_trans_head(struct page *page)
-{
-       if (PageTail(page)) {
-               struct page *head;
-               head = page->first_page;
-               smp_rmb();
-               /*
-                * head may be a dangling pointer.
-                * __split_huge_page_refcount clears PageTail before
-                * overwriting first_page, so if PageTail is still
-                * there it means the head pointer isn't dangling.
-                */
-               if (PageTail(page))
-                       return head;
-       }
-       return page;
-}
-#else
-#define compound_trans_head(page) compound_head(page)
-#endif
 
 extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                                unsigned long addr, pmd_t pmd, pmd_t *pmdp);
@@ -226,7 +186,6 @@ static inline int split_huge_page(struct page *page)
        do { } while (0)
 #define split_huge_page_pmd_mm(__mm, __address, __pmd) \
        do { } while (0)
-#define compound_trans_head(page) compound_head(page)
 static inline int hugepage_madvise(struct vm_area_struct *vma,
                                   unsigned long *vm_flags, int advice)
 {
index 15da677478ddc353b151d81362043bcbdfc3d089..344883dce5849b62e8f6c0e59e1daed09b5a0f80 100644 (file)
@@ -875,7 +875,7 @@ struct vmbus_channel_relid_released {
 struct vmbus_channel_initiate_contact {
        struct vmbus_channel_message_header header;
        u32 vmbus_version_requested;
-       u32 padding2;
+       u32 target_vcpu; /* The VCPU the host should respond to */
        u64 interrupt_page;
        u64 monitor_page1;
        u64 monitor_page2;
index e1688802964f3ccb6aebc0738a98f9b838a6d02d..a3ba270763426bd7dfd9f0633e0abb4476d2dc50 100644 (file)
@@ -163,6 +163,23 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
+#ifdef CONFIG_LTO
+/* Work around a LTO gcc problem: when there is no reference to a variable
+ * in a module it will be moved to the end of the program. This causes
+ * reordering of initcalls which the kernel does not like.
+ * Add a dummy reference function to avoid this. The function is
+ * deleted by the linker.
+ */
+#define LTO_REFERENCE_INITCALL(x) \
+       ; /* yes this is needed */                      \
+       static __used __exit void *reference_##x(void)  \
+       {                                               \
+               return &x;                              \
+       }
+#else
+#define LTO_REFERENCE_INITCALL(x)
+#endif
+
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -175,7 +192,8 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
        static initcall_t __initcall_##fn##id __used \
-       __attribute__((__section__(".initcall" #id ".init"))) = fn
+       __attribute__((__section__(".initcall" #id ".init"))) = fn; \
+       LTO_REFERENCE_INITCALL(__initcall_##fn##id)
 
 /*
  * Early initcalls run before initializing SMP.
index 0053adde0ed9a37111ffd273c17f6d19956a6a77..a2678d35b5a2e8fc8f840d91f1ac5c7ec0c97bec 100644 (file)
@@ -158,6 +158,11 @@ devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
                                         devname, dev_id);
 }
 
+extern int __must_check
+devm_request_any_context_irq(struct device *dev, unsigned int irq,
+                irq_handler_t handler, unsigned long irqflags,
+                const char *devname, void *dev_id);
+
 extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
 
 /*
index f4f42faec68677a6fb032e7ccdf07b8b0bb130cb..8a18e75600ccb25b47f17decfacdef673de89713 100644 (file)
@@ -24,7 +24,7 @@
 
 struct device;
 
-void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
+__visible void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
 void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
 
 #ifdef CONFIG_MMU
index e7831d20373776f5c3dc80c5a04147e8aa611c85..35e7eca4e33b1fbbde3029b5f3cb2be350d0dafc 100644 (file)
@@ -118,9 +118,7 @@ extern int mq_init_ns(struct ipc_namespace *ns);
  *     the new maximum will handle anyone else.  I may have to revisit this
  *     in the future.
  */
-#define MIN_QUEUESMAX                  1
 #define DFLT_QUEUESMAX               256
-#define HARD_QUEUESMAX              1024
 #define MIN_MSGMAX                     1
 #define DFLT_MSG                      10U
 #define DFLT_MSGMAX                   10
index 66017028dcb3d0aebf70aa7281e7758a42bcb3bf..19ae05d4b8ec26b6dc6fa5f568d2b25b698e3417 100644 (file)
@@ -30,7 +30,9 @@ void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
        work->func = func;
 }
 
-void irq_work_queue(struct irq_work *work);
+#define DEFINE_IRQ_WORK(name, _f) struct irq_work name = { .func = (_f), }
+
+bool irq_work_queue(struct irq_work *work);
 void irq_work_run(void);
 void irq_work_sync(struct irq_work *work);
 
index 196d1ea86df081a5224928b4d75117aec85cd822..08fb0247764177a8b96f83f5181a17c9d33b099c 100644 (file)
@@ -458,7 +458,7 @@ extern enum system_states {
 
 #define TAINT_PROPRIETARY_MODULE       0
 #define TAINT_FORCED_MODULE            1
-#define TAINT_UNSAFE_SMP               2
+#define TAINT_CPU_OUT_OF_SPEC          2
 #define TAINT_FORCED_RMMOD             3
 #define TAINT_MACHINE_CHECK            4
 #define TAINT_BAD_PAGE                 5
index 51c72be4a7c3f1782a5d5f21801b06bea1720f57..d7c61317db8640546f18174209b1f1ac7ec4f219 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/vtime.h>
 #include <asm/irq.h>
-#include <asm/cputime.h>
+#include <linux/cputime.h>
 
 /*
  * 'kernel_stat.h' contains the definitions needed for doing
index 5be9f0228a3bbc8ddfad7a2fc245f6601cfc1f17..d267623c28cfdaa385ab5f288683c0157f9e8ef4 100644 (file)
@@ -249,7 +249,8 @@ void kernfs_notify(struct kernfs_node *kn);
 
 const void *kernfs_super_ns(struct super_block *sb);
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-                              struct kernfs_root *root, const void *ns);
+                              struct kernfs_root *root, bool *new_sb_created,
+                              const void *ns);
 void kernfs_kill_sb(struct super_block *sb);
 
 void kernfs_init(void);
@@ -317,7 +318,7 @@ static inline const void *kernfs_super_ns(struct super_block *sb)
 
 static inline struct dentry *
 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-               struct kernfs_root *root, const void *ns)
+               struct kernfs_root *root, bool *new_sb_created, const void *ns)
 { return ERR_PTR(-ENOSYS); }
 
 static inline void kernfs_kill_sb(struct super_block *sb) { }
@@ -368,9 +369,9 @@ static inline int kernfs_remove_by_name(struct kernfs_node *parent,
 
 static inline struct dentry *
 kernfs_mount(struct file_system_type *fs_type, int flags,
-            struct kernfs_root *root)
+            struct kernfs_root *root, bool *new_sb_created)
 {
-       return kernfs_mount_ns(fs_type, flags, root, NULL);
+       return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL);
 }
 
 #endif /* __LINUX_KERNFS_H */
index 6d4066cdb5b5b8508be5347e50f1c16c1fddf493..a7564193004959ba12bc28361a4c32d76b8297c2 100644 (file)
@@ -127,12 +127,6 @@ extern asmlinkage long sys_kexec_load(unsigned long entry,
                                        struct kexec_segment __user *segments,
                                        unsigned long flags);
 extern int kernel_kexec(void);
-#ifdef CONFIG_COMPAT
-extern asmlinkage long compat_sys_kexec_load(unsigned long entry,
-                               unsigned long nr_segments,
-                               struct compat_kexec_segment __user *segments,
-                               unsigned long flags);
-#endif
 extern struct page *kimage_alloc_control_pages(struct kimage *image,
                                                unsigned int order);
 extern void crash_kexec(struct pt_regs *);
index bec6dbe939a0267def1f73864d07c5025cb687f1..1de36be64df4d1516a2a451901733d36fd32ec4e 100644 (file)
@@ -848,7 +848,6 @@ struct ata_port {
        struct completion       park_req_pending;
 
        pm_message_t            pm_mesg;
-       int                     *pm_result;
        enum ata_lpm_policy     target_lpm_policy;
 
        struct timer_list       fastdrain_timer;
@@ -1140,16 +1139,14 @@ extern bool ata_link_offline(struct ata_link *link);
 #ifdef CONFIG_PM
 extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
 extern void ata_host_resume(struct ata_host *host);
-extern int ata_sas_port_async_suspend(struct ata_port *ap, int *async);
-extern int ata_sas_port_async_resume(struct ata_port *ap, int *async);
+extern void ata_sas_port_suspend(struct ata_port *ap);
+extern void ata_sas_port_resume(struct ata_port *ap);
 #else
-static inline int ata_sas_port_async_suspend(struct ata_port *ap, int *async)
+static inline void ata_sas_port_suspend(struct ata_port *ap)
 {
-       return 0;
 }
-static inline int ata_sas_port_async_resume(struct ata_port *ap, int *async)
+static inline void ata_sas_port_resume(struct ata_port *ap)
 {
-       return 0;
 }
 #endif
 extern int ata_ratelimit(void);
index a6a42dd024661324dbeed5b9cfaa028744bae154..34a513a2727bbe83adff047613a1ad3458684ac2 100644 (file)
@@ -12,9 +12,9 @@
 #endif
 
 #ifdef __cplusplus
-#define CPP_ASMLINKAGE extern "C"
+#define CPP_ASMLINKAGE extern "C" __visible
 #else
-#define CPP_ASMLINKAGE
+#define CPP_ASMLINKAGE __visible
 #endif
 
 #ifndef asmlinkage
index 92b1bfc5da6087850e43015ebdaf7d3de455f522..008388f920d7e93e32ba388dd4b497f33d7bd49d 100644 (file)
@@ -252,9 +252,9 @@ struct held_lock {
        unsigned int trylock:1;                                         /* 16 bits */
 
        unsigned int read:2;        /* see lock_acquire() comment */
-       unsigned int check:2;       /* see lock_acquire() comment */
+       unsigned int check:1;       /* see lock_acquire() comment */
        unsigned int hardirqs_off:1;
-       unsigned int references:11;                                     /* 32 bits */
+       unsigned int references:12;                                     /* 32 bits */
 };
 
 /*
@@ -265,7 +265,7 @@ extern void lockdep_info(void);
 extern void lockdep_reset(void);
 extern void lockdep_reset_lock(struct lockdep_map *lock);
 extern void lockdep_free_key_range(void *start, unsigned long size);
-extern void lockdep_sys_exit(void);
+extern asmlinkage void lockdep_sys_exit(void);
 
 extern void lockdep_off(void);
 extern void lockdep_on(void);
@@ -303,7 +303,7 @@ extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
                                 (lock)->dep_map.key, sub)
 
 #define lockdep_set_novalidate_class(lock) \
-       lockdep_set_class(lock, &__lockdep_no_validate__)
+       lockdep_set_class_and_name(lock, &__lockdep_no_validate__, #lock)
 /*
  * Compare locking classes
  */
@@ -326,9 +326,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
  *
  * Values for check:
  *
- *   0: disabled
- *   1: simple checks (freeing, held-at-exit-time, etc.)
- *   2: full validation
+ *   0: simple checks (freeing, held-at-exit-time, etc.)
+ *   1: full validation
  */
 extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
                         int trylock, int read, int check,
@@ -479,15 +478,9 @@ static inline void print_irqtrace_events(struct task_struct *curr)
  * on the per lock-class debug mode:
  */
 
-#ifdef CONFIG_PROVE_LOCKING
- #define lock_acquire_exclusive(l, s, t, n, i)         lock_acquire(l, s, t, 0, 2, n, i)
- #define lock_acquire_shared(l, s, t, n, i)            lock_acquire(l, s, t, 1, 2, n, i)
- #define lock_acquire_shared_recursive(l, s, t, n, i)  lock_acquire(l, s, t, 2, 2, n, i)
-#else
- #define lock_acquire_exclusive(l, s, t, n, i)         lock_acquire(l, s, t, 0, 1, n, i)
- #define lock_acquire_shared(l, s, t, n, i)            lock_acquire(l, s, t, 1, 1, n, i)
- #define lock_acquire_shared_recursive(l, s, t, n, i)  lock_acquire(l, s, t, 2, 1, n, i)
-#endif
+#define lock_acquire_exclusive(l, s, t, n, i)          lock_acquire(l, s, t, 0, 1, n, i)
+#define lock_acquire_shared(l, s, t, n, i)             lock_acquire(l, s, t, 1, 1, n, i)
+#define lock_acquire_shared_recursive(l, s, t, n, i)   lock_acquire(l, s, t, 2, 1, n, i)
 
 #define spin_acquire(l, s, t, i)               lock_acquire_exclusive(l, s, t, NULL, i)
 #define spin_acquire_nest(l, s, t, n, i)       lock_acquire_exclusive(l, s, t, n, i)
@@ -518,13 +511,13 @@ static inline void print_irqtrace_events(struct task_struct *curr)
 # define might_lock(lock)                                              \
 do {                                                                   \
        typecheck(struct lockdep_map *, &(lock)->dep_map);              \
-       lock_acquire(&(lock)->dep_map, 0, 0, 0, 2, NULL, _THIS_IP_);    \
+       lock_acquire(&(lock)->dep_map, 0, 0, 0, 1, NULL, _THIS_IP_);    \
        lock_release(&(lock)->dep_map, 0, _THIS_IP_);                   \
 } while (0)
 # define might_lock_read(lock)                                                 \
 do {                                                                   \
        typecheck(struct lockdep_map *, &(lock)->dep_map);              \
-       lock_acquire(&(lock)->dep_map, 0, 0, 1, 2, NULL, _THIS_IP_);    \
+       lock_acquire(&(lock)->dep_map, 0, 0, 1, 1, NULL, _THIS_IP_);    \
        lock_release(&(lock)->dep_map, 0, _THIS_IP_);                   \
 } while (0)
 #else
index ad1ae7f345ad9482df4a47c0ddc4ab11bd34e2ec..78c76cd4d37bdff2d1c56e2a9c1c199af6b7a77d 100644 (file)
@@ -387,7 +387,7 @@ struct max8997_dev {
        struct i2c_client *muic; /* slave addr 0x4a */
        struct mutex iolock;
 
-       int type;
+       unsigned long type;
        struct platform_device *battery; /* battery control (not fuel gauge) */
 
        int irq;
index 4ecb24b4b863be4158263466ce919e78b42714d5..d68ada502ff37c1e08164f723db8ef3e33d96a50 100644 (file)
@@ -163,7 +163,7 @@ struct max8998_dev {
        int ono;
        u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS];
        u8 irq_masks_cache[MAX8998_NUM_IRQ_REGS];
-       int type;
+       unsigned long type;
        bool wakeup;
 };
 
index a5a7f0130e9604837982d4b2f3bb9920fd5d090c..54b5458ec084a50ec06cc9f418d4e623e0aaf7bc 100644 (file)
@@ -252,7 +252,7 @@ struct tps65217_board {
 struct tps65217 {
        struct device *dev;
        struct tps65217_board *pdata;
-       unsigned int id;
+       unsigned long id;
        struct regulator_desc desc[TPS65217_NUM_REGULATOR];
        struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
        struct regmap *regmap;
@@ -263,7 +263,7 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev)
        return dev_get_drvdata(dev);
 }
 
-static inline int tps65217_chip_id(struct tps65217 *tps65217)
+static inline unsigned long tps65217_chip_id(struct tps65217 *tps65217)
 {
        return tps65217->id;
 }
index 554548cd3dd4683145ce5ef0a4b1e66fb829365d..130bc8d77fa5e38173b90c157092189cb3ff7479 100644 (file)
 #include <linux/pci.h>
 #include <linux/spinlock_types.h>
 #include <linux/semaphore.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/radix-tree.h>
+
 #include <linux/mlx5/device.h>
 #include <linux/mlx5/doorbell.h>
 
@@ -227,6 +229,7 @@ struct mlx5_uuar_info {
         * protect uuar allocation data structs
         */
        struct mutex            lock;
+       u32                     ver;
 };
 
 struct mlx5_bf {
index f28f46eade6a642873246fea247f3f5455a18acb..a0df4295e1717a23463d96d4f973a4330f2349ad 100644 (file)
@@ -175,7 +175,7 @@ extern unsigned int kobjsize(const void *objp);
  * Special vmas that are non-mergable, non-mlock()able.
  * Note: mm/huge_memory.c VM_NO_THP depends on this definition.
  */
-#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP)
+#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP)
 
 /*
  * mapping from the currently active vm_flags protection bits (the
@@ -399,8 +399,18 @@ static inline void compound_unlock_irqrestore(struct page *page,
 
 static inline struct page *compound_head(struct page *page)
 {
-       if (unlikely(PageTail(page)))
-               return page->first_page;
+       if (unlikely(PageTail(page))) {
+               struct page *head = page->first_page;
+
+               /*
+                * page->first_page may be a dangling pointer to an old
+                * compound page, so recheck that it is still a tail
+                * page before returning.
+                */
+               smp_rmb();
+               if (likely(PageTail(page)))
+                       return head;
+       }
        return page;
 }
 
@@ -757,7 +767,7 @@ static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid)
 #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
 static inline int page_cpupid_xchg_last(struct page *page, int cpupid)
 {
-       return xchg(&page->_last_cpupid, cpupid);
+       return xchg(&page->_last_cpupid, cpupid & LAST_CPUPID_MASK);
 }
 
 static inline int page_cpupid_last(struct page *page)
@@ -766,7 +776,7 @@ static inline int page_cpupid_last(struct page *page)
 }
 static inline void page_cpupid_reset_last(struct page *page)
 {
-       page->_last_cpupid = -1;
+       page->_last_cpupid = -1 & LAST_CPUPID_MASK;
 }
 #else
 static inline int page_cpupid_last(struct page *page)
@@ -1477,9 +1487,15 @@ static inline void pgtable_page_dtor(struct page *page)
 
 #if USE_SPLIT_PMD_PTLOCKS
 
+static struct page *pmd_to_page(pmd_t *pmd)
+{
+       unsigned long mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
+       return virt_to_page((void *)((unsigned long) pmd & mask));
+}
+
 static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd)
 {
-       return ptlock_ptr(virt_to_page(pmd));
+       return ptlock_ptr(pmd_to_page(pmd));
 }
 
 static inline bool pgtable_pmd_page_ctor(struct page *page)
@@ -1498,7 +1514,7 @@ static inline void pgtable_pmd_page_dtor(struct page *page)
        ptlock_free(page);
 }
 
-#define pmd_huge_pte(mm, pmd) (virt_to_page(pmd)->pmd_huge_pte)
+#define pmd_huge_pte(mm, pmd) (pmd_to_page(pmd)->pmd_huge_pte)
 
 #else
 
index 5f2052c831547a33b66606d78ac5713086d285e3..9b61b9bf81ac86a90c1ce70d12400b745b7582eb 100644 (file)
@@ -590,10 +590,10 @@ static inline bool zone_is_empty(struct zone *zone)
 
 /*
  * The NUMA zonelists are doubled because we need zonelists that restrict the
- * allocations to a single node for GFP_THISNODE.
+ * allocations to a single node for __GFP_THISNODE.
  *
  * [0] : Zonelist with fallback
- * [1] : No fallback (GFP_THISNODE)
+ * [1] : No fallback (__GFP_THISNODE)
  */
 #define MAX_ZONELISTS 2
 
index d3181936c138ba2583960815a722aa8f90938a9d..11692dea18aa25a9410ce842cdd851a4d15560c7 100644 (file)
@@ -46,6 +46,7 @@
  * - detects multi-task circular deadlocks and prints out all affected
  *   locks and tasks (and only those tasks)
  */
+struct optimistic_spin_queue;
 struct mutex {
        /* 1: unlocked, 0: locked, negative: locked, possible waiters */
        atomic_t                count;
@@ -55,7 +56,7 @@ struct mutex {
        struct task_struct      *owner;
 #endif
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-       void                    *spin_mlock;    /* Spinner MCS lock */
+       struct optimistic_spin_queue    *osq;   /* Spinner MCS lock */
 #endif
 #ifdef CONFIG_DEBUG_MUTEXES
        const char              *name;
@@ -179,4 +180,4 @@ extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
 # define arch_mutex_cpu_relax() cpu_relax()
 #endif
 
-#endif
+#endif /* __LINUX_MUTEX_H */
index 1005ebf175752774ada359369a313379a82dc85a..5a09a48f2658a64f7149ecddd30abd56c65cf69f 100644 (file)
@@ -163,4 +163,11 @@ enum {
 /* changeable features with no special hardware requirements */
 #define NETIF_F_SOFT_FEATURES  (NETIF_F_GSO | NETIF_F_GRO)
 
+#define NETIF_F_VLAN_FEATURES  (NETIF_F_HW_VLAN_CTAG_FILTER | \
+                                NETIF_F_HW_VLAN_CTAG_RX | \
+                                NETIF_F_HW_VLAN_CTAG_TX | \
+                                NETIF_F_HW_VLAN_STAG_FILTER | \
+                                NETIF_F_HW_VLAN_STAG_RX | \
+                                NETIF_F_HW_VLAN_STAG_TX)
+
 #endif /* _LINUX_NETDEV_FEATURES_H */
index 440a02ee6f92cda68d3438ab88af3896d7c41af2..daafd9561cbca2335c1f0a3f20cd593e30fa5206 100644 (file)
@@ -752,6 +752,9 @@ struct netdev_phys_port_id {
        unsigned char id_len;
 };
 
+typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
+                                      struct sk_buff *skb);
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -783,7 +786,7 @@ struct netdev_phys_port_id {
  *     Required can not be NULL.
  *
  * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
- *                         void *accel_priv);
+ *                         void *accel_priv, select_queue_fallback_t fallback);
  *     Called to decide which queue to when device supports multiple
  *     transmit queues.
  *
@@ -1005,7 +1008,8 @@ struct net_device_ops {
                                                   struct net_device *dev);
        u16                     (*ndo_select_queue)(struct net_device *dev,
                                                    struct sk_buff *skb,
-                                                   void *accel_priv);
+                                                   void *accel_priv,
+                                                   select_queue_fallback_t fallback);
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
@@ -1551,7 +1555,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
                                    struct sk_buff *skb,
                                    void *accel_priv);
-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
  * Net namespace inlines
@@ -2275,6 +2278,26 @@ static inline void netdev_reset_queue(struct net_device *dev_queue)
        netdev_tx_reset_queue(netdev_get_tx_queue(dev_queue, 0));
 }
 
+/**
+ *     netdev_cap_txqueue - check if selected tx queue exceeds device queues
+ *     @dev: network device
+ *     @queue_index: given tx queue index
+ *
+ *     Returns 0 if given tx queue index >= number of device tx queues,
+ *     otherwise returns the originally passed tx queue index.
+ */
+static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)
+{
+       if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+               net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
+                                    dev->name, queue_index,
+                                    dev->real_num_tx_queues);
+               return 0;
+       }
+
+       return queue_index;
+}
+
 /**
  *     netif_running - test if up
  *     @dev: network device
@@ -2991,7 +3014,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
 {
        return __skb_gso_segment(skb, features, true);
 }
-__be16 skb_network_protocol(struct sk_buff *skb);
+__be16 skb_network_protocol(struct sk_buff *skb, int *depth);
 
 static inline bool can_checksum_protocol(netdev_features_t features,
                                         __be16 protocol)
@@ -3068,7 +3091,12 @@ void netdev_change_features(struct net_device *dev);
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
                                        struct net_device *dev);
 
-netdev_features_t netif_skb_features(struct sk_buff *skb);
+netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+                                        const struct net_device *dev);
+static inline netdev_features_t netif_skb_features(struct sk_buff *skb)
+{
+       return netif_skb_dev_features(skb, skb->dev);
+}
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
index 3ccfcecf8999550b25c84d77edef546d4eb9cf54..5624e4e2763c2eb3d73f4e02d2752661ccd9c6b9 100644 (file)
@@ -379,12 +379,14 @@ struct nfs_openres {
  * Arguments to the open_confirm call.
  */
 struct nfs_open_confirmargs {
+       struct nfs4_sequence_args       seq_args;
        const struct nfs_fh *   fh;
        nfs4_stateid *          stateid;
        struct nfs_seqid *      seqid;
 };
 
 struct nfs_open_confirmres {
+       struct nfs4_sequence_res        seq_res;
        nfs4_stateid            stateid;
        struct nfs_seqid *      seqid;
 };
@@ -465,9 +467,14 @@ struct nfs_lockt_res {
 };
 
 struct nfs_release_lockowner_args {
+       struct nfs4_sequence_args       seq_args;
        struct nfs_lowner       lock_owner;
 };
 
+struct nfs_release_lockowner_res {
+       struct nfs4_sequence_res        seq_res;
+};
+
 struct nfs4_delegreturnargs {
        struct nfs4_sequence_args       seq_args;
        const struct nfs_fh *fhandle;
index 26ebcf41c2131d681aab56112b3390c773e70ab8..6b9aafed225fcd9a48228ac9f6044c7a956cc325 100644 (file)
@@ -80,13 +80,15 @@ struct nvme_dev {
        struct dma_pool *prp_small_pool;
        int instance;
        int queue_count;
-       int db_stride;
+       u32 db_stride;
        u32 ctrl_config;
        struct msix_entry *entry;
        struct nvme_bar __iomem *bar;
        struct list_head namespaces;
        struct kref kref;
        struct miscdevice miscdev;
+       work_func_t reset_workfn;
+       struct work_struct reset_work;
        char name[12];
        char serial[20];
        char model[40];
@@ -94,6 +96,8 @@ struct nvme_dev {
        u32 max_hw_sectors;
        u32 stripe_size;
        u16 oncs;
+       u16 abort_limit;
+       u8 initialized;
 };
 
 /*
@@ -165,6 +169,7 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
 struct sg_io_hdr;
 
 int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr);
+int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg);
 int nvme_sg_get_version_num(int __user *ip);
 
 #endif /* _LINUX_NVME_H */
index 70c64ba17fa51f7cca0e232b8f95b7669f5a3075..435cb995904dedc6329916f29cd2378b5e0e7b2e 100644 (file)
@@ -169,35 +169,15 @@ static inline const char *of_node_full_name(const struct device_node *np)
 
 extern struct device_node *of_find_node_by_name(struct device_node *from,
        const char *name);
-#define for_each_node_by_name(dn, name) \
-       for (dn = of_find_node_by_name(NULL, name); dn; \
-            dn = of_find_node_by_name(dn, name))
 extern struct device_node *of_find_node_by_type(struct device_node *from,
        const char *type);
-#define for_each_node_by_type(dn, type) \
-       for (dn = of_find_node_by_type(NULL, type); dn; \
-            dn = of_find_node_by_type(dn, type))
 extern struct device_node *of_find_compatible_node(struct device_node *from,
        const char *type, const char *compat);
-#define for_each_compatible_node(dn, type, compatible) \
-       for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
-            dn = of_find_compatible_node(dn, type, compatible))
 extern struct device_node *of_find_matching_node_and_match(
        struct device_node *from,
        const struct of_device_id *matches,
        const struct of_device_id **match);
-static inline struct device_node *of_find_matching_node(
-       struct device_node *from,
-       const struct of_device_id *matches)
-{
-       return of_find_matching_node_and_match(from, matches, NULL);
-}
-#define for_each_matching_node(dn, matches) \
-       for (dn = of_find_matching_node(NULL, matches); dn; \
-            dn = of_find_matching_node(dn, matches))
-#define for_each_matching_node_and_match(dn, matches, match) \
-       for (dn = of_find_matching_node_and_match(NULL, matches, match); \
-            dn; dn = of_find_matching_node_and_match(dn, matches, match))
+
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_get_parent(const struct device_node *node);
@@ -209,43 +189,11 @@ extern struct device_node *of_get_next_available_child(
 
 extern struct device_node *of_get_child_by_name(const struct device_node *node,
                                        const char *name);
-#define for_each_child_of_node(parent, child) \
-       for (child = of_get_next_child(parent, NULL); child != NULL; \
-            child = of_get_next_child(parent, child))
-
-#define for_each_available_child_of_node(parent, child) \
-       for (child = of_get_next_available_child(parent, NULL); child != NULL; \
-            child = of_get_next_available_child(parent, child))
-
-static inline int of_get_child_count(const struct device_node *np)
-{
-       struct device_node *child;
-       int num = 0;
-
-       for_each_child_of_node(np, child)
-               num++;
-
-       return num;
-}
-
-static inline int of_get_available_child_count(const struct device_node *np)
-{
-       struct device_node *child;
-       int num = 0;
-
-       for_each_available_child_of_node(np, child)
-               num++;
-
-       return num;
-}
 
 /* cache lookup */
 extern struct device_node *of_find_next_cache_node(const struct device_node *);
 extern struct device_node *of_find_node_with_property(
        struct device_node *from, const char *prop_name);
-#define for_each_node_with_property(dn, prop_name) \
-       for (dn = of_find_node_with_property(NULL, prop_name); dn; \
-            dn = of_find_node_with_property(dn, prop_name))
 
 extern struct property *of_find_property(const struct device_node *np,
                                         const char *name,
@@ -367,42 +315,53 @@ static inline struct device_node *of_find_node_by_name(struct device_node *from,
        return NULL;
 }
 
-static inline struct device_node *of_get_parent(const struct device_node *node)
+static inline struct device_node *of_find_node_by_type(struct device_node *from,
+       const char *type)
 {
        return NULL;
 }
 
-static inline bool of_have_populated_dt(void)
+static inline struct device_node *of_find_matching_node_and_match(
+       struct device_node *from,
+       const struct of_device_id *matches,
+       const struct of_device_id **match)
 {
-       return false;
+       return NULL;
 }
 
-/* Kill an unused variable warning on a device_node pointer */
-static inline void __of_use_dn(const struct device_node *np)
+static inline struct device_node *of_get_parent(const struct device_node *node)
 {
+       return NULL;
 }
 
-#define for_each_child_of_node(parent, child) \
-       while (__of_use_dn(parent), __of_use_dn(child), 0)
+static inline struct device_node *of_get_next_child(
+       const struct device_node *node, struct device_node *prev)
+{
+       return NULL;
+}
 
-#define for_each_available_child_of_node(parent, child) \
-       while (0)
+static inline struct device_node *of_get_next_available_child(
+       const struct device_node *node, struct device_node *prev)
+{
+       return NULL;
+}
 
-static inline struct device_node *of_get_child_by_name(
-                                       const struct device_node *node,
-                                       const char *name)
+static inline struct device_node *of_find_node_with_property(
+       struct device_node *from, const char *prop_name)
 {
        return NULL;
 }
 
-static inline int of_get_child_count(const struct device_node *np)
+static inline bool of_have_populated_dt(void)
 {
-       return 0;
+       return false;
 }
 
-static inline int of_get_available_child_count(const struct device_node *np)
+static inline struct device_node *of_get_child_by_name(
+                                       const struct device_node *node,
+                                       const char *name)
 {
-       return 0;
+       return NULL;
 }
 
 static inline int of_device_is_compatible(const struct device_node *device,
@@ -569,6 +528,13 @@ extern int of_node_to_nid(struct device_node *np);
 static inline int of_node_to_nid(struct device_node *device) { return 0; }
 #endif
 
+static inline struct device_node *of_find_matching_node(
+       struct device_node *from,
+       const struct of_device_id *matches)
+{
+       return of_find_matching_node_and_match(from, matches, NULL);
+}
+
 /**
  * of_property_read_bool - Findfrom a property
  * @np:                device node from which the property value is to be read.
@@ -618,6 +584,55 @@ static inline int of_property_read_u32(const struct device_node *np,
                s;                                              \
                s = of_prop_next_string(prop, s))
 
+#define for_each_node_by_name(dn, name) \
+       for (dn = of_find_node_by_name(NULL, name); dn; \
+            dn = of_find_node_by_name(dn, name))
+#define for_each_node_by_type(dn, type) \
+       for (dn = of_find_node_by_type(NULL, type); dn; \
+            dn = of_find_node_by_type(dn, type))
+#define for_each_compatible_node(dn, type, compatible) \
+       for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
+            dn = of_find_compatible_node(dn, type, compatible))
+#define for_each_matching_node(dn, matches) \
+       for (dn = of_find_matching_node(NULL, matches); dn; \
+            dn = of_find_matching_node(dn, matches))
+#define for_each_matching_node_and_match(dn, matches, match) \
+       for (dn = of_find_matching_node_and_match(NULL, matches, match); \
+            dn; dn = of_find_matching_node_and_match(dn, matches, match))
+
+#define for_each_child_of_node(parent, child) \
+       for (child = of_get_next_child(parent, NULL); child != NULL; \
+            child = of_get_next_child(parent, child))
+#define for_each_available_child_of_node(parent, child) \
+       for (child = of_get_next_available_child(parent, NULL); child != NULL; \
+            child = of_get_next_available_child(parent, child))
+
+#define for_each_node_with_property(dn, prop_name) \
+       for (dn = of_find_node_with_property(NULL, prop_name); dn; \
+            dn = of_find_node_with_property(dn, prop_name))
+
+static inline int of_get_child_count(const struct device_node *np)
+{
+       struct device_node *child;
+       int num = 0;
+
+       for_each_child_of_node(np, child)
+               num++;
+
+       return num;
+}
+
+static inline int of_get_available_child_count(const struct device_node *np)
+{
+       struct device_node *child;
+       int num = 0;
+
+       for_each_available_child_of_node(np, child)
+               num++;
+
+       return num;
+}
+
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE)
 extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
 extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
index 8d7dd6768cb760e5ec987ddbbc1e393319d53de0..ef370210ffb25ead579f83591b3ce152d3fc80d8 100644 (file)
@@ -78,11 +78,13 @@ static inline int of_device_uevent_modalias(struct device *dev,
 
 static inline void of_device_node_put(struct device *dev) { }
 
-static inline const struct of_device_id *of_match_device(
+static inline const struct of_device_id *__of_match_device(
                const struct of_device_id *matches, const struct device *dev)
 {
        return NULL;
 }
+#define of_match_device(matches, dev)  \
+       __of_match_device(of_match_ptr(matches), (dev))
 
 static inline struct device_node *of_cpu_device_node_get(int cpu)
 {
index e464b4e987e876fc4b5e2d35c478da36f4048f52..d1fe1a761047683e555a9544dd5c668d5ae6752b 100644 (file)
@@ -228,9 +228,9 @@ PAGEFLAG(OwnerPriv1, owner_priv_1) TESTCLEARFLAG(OwnerPriv1, owner_priv_1)
 TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback)
 PAGEFLAG(MappedToDisk, mappedtodisk)
 
-/* PG_readahead is only used for file reads; PG_reclaim is only for writes */
+/* PG_readahead is only used for reads; PG_reclaim is only for writes */
 PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
-PAGEFLAG(Readahead, reclaim)           /* Reminder to do async read-ahead */
+PAGEFLAG(Readahead, reclaim) TESTCLEARFLAG(Readahead, reclaim)
 
 #ifdef CONFIG_HIGHMEM
 /*
index fb57c892b214d6b3482c63a28061130f3a700a9c..33aa2caf0f0c9e5bd9e7cf07c8d92b08207be959 100644 (file)
@@ -1169,8 +1169,23 @@ void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 void pci_restore_msi_state(struct pci_dev *dev);
 int pci_msi_enabled(void);
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec);
+static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+{
+       int rc = pci_enable_msi_range(dev, nvec, nvec);
+       if (rc < 0)
+               return rc;
+       return 0;
+}
 int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
                          int minvec, int maxvec);
+static inline int pci_enable_msix_exact(struct pci_dev *dev,
+                                       struct msix_entry *entries, int nvec)
+{
+       int rc = pci_enable_msix_range(dev, entries, nvec, nvec);
+       if (rc < 0)
+               return rc;
+       return 0;
+}
 #else
 static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
 static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
@@ -1189,9 +1204,14 @@ static inline int pci_msi_enabled(void) { return 0; }
 static inline int pci_enable_msi_range(struct pci_dev *dev, int minvec,
                                       int maxvec)
 { return -ENOSYS; }
+static inline int pci_enable_msi_exact(struct pci_dev *dev, int nvec)
+{ return -ENOSYS; }
 static inline int pci_enable_msix_range(struct pci_dev *dev,
                      struct msix_entry *entries, int minvec, int maxvec)
 { return -ENOSYS; }
+static inline int pci_enable_msix_exact(struct pci_dev *dev,
+                     struct msix_entry *entries, int nvec)
+{ return -ENOSYS; }
 #endif
 
 #ifdef CONFIG_PCIEPORTBUS
index 97fbecdd7a401157cd290d6f4e981a8557ee4745..7399e6a3e9a00602722284d1d806a930898a450d 100644 (file)
 
 #define PCI_VENDOR_ID_INTEL            0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC      0x0008
+#define PCI_DEVICE_ID_INTEL_SNB_IMC    0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC    0x0154
+#define PCI_DEVICE_ID_INTEL_HSW_IMC    0x0c00
 #define PCI_DEVICE_ID_INTEL_PXHD_0     0x0320
 #define PCI_DEVICE_ID_INTEL_PXHD_1     0x0321
 #define PCI_DEVICE_ID_INTEL_PXH_0      0x0329
index e273e5ac19c9ca068825aa27fc01eca365a3f248..3f83459dbb20b557ec067b9d14d8dbf1f1e56ba3 100644 (file)
@@ -146,7 +146,9 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width)
        phy->attrs.bus_width = bus_width;
 }
 struct phy *phy_get(struct device *dev, const char *string);
+struct phy *phy_optional_get(struct device *dev, const char *string);
 struct phy *devm_phy_get(struct device *dev, const char *string);
+struct phy *devm_phy_optional_get(struct device *dev, const char *string);
 void phy_put(struct phy *phy);
 void devm_phy_put(struct device *dev, struct phy *phy);
 struct phy *of_phy_simple_xlate(struct device *dev,
@@ -232,11 +234,23 @@ static inline struct phy *phy_get(struct device *dev, const char *string)
        return ERR_PTR(-ENOSYS);
 }
 
+static inline struct phy *phy_optional_get(struct device *dev,
+                                          const char *string)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
 static inline struct phy *devm_phy_get(struct device *dev, const char *string)
 {
        return ERR_PTR(-ENOSYS);
 }
 
+static inline struct phy *devm_phy_optional_get(struct device *dev,
+                                               const char *string)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
 static inline void phy_put(struct phy *phy)
 {
 }
index dbaf9908411217c57a257309c5949e8d4b76ff5b..8183b46fbaa2d6da9817ead257735396a6ec7b0c 100644 (file)
@@ -247,9 +247,10 @@ static inline void list_splice_init_rcu(struct list_head *list,
  * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
  */
 #define list_entry_rcu(ptr, type, member) \
-       ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \
-        container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
-       })
+({ \
+       typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \
+       container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
+})
 
 /**
  * Where are list_empty_rcu() and list_first_entry_rcu()?
@@ -285,11 +286,11 @@ static inline void list_splice_init_rcu(struct list_head *list,
  * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
  */
 #define list_first_or_null_rcu(ptr, type, member) \
-       ({struct list_head *__ptr = (ptr); \
-         struct list_head *__next = ACCESS_ONCE(__ptr->next); \
-         likely(__ptr != __next) ? \
-               list_entry_rcu(__next, type, member) : NULL; \
-       })
+({ \
+       struct list_head *__ptr = (ptr); \
+       struct list_head *__next = ACCESS_ONCE(__ptr->next); \
+       likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \
+})
 
 /**
  * list_for_each_entry_rcu     -       iterate over rcu list of given type
index 72bf3a01a4ee67ac8908212c3de3897d383a2161..00a7fd61b3c6540521109c4c79e412a0833bef02 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2001
  *
@@ -44,7 +44,9 @@
 #include <linux/debugobjects.h>
 #include <linux/bug.h>
 #include <linux/compiler.h>
+#include <asm/barrier.h>
 
+extern int rcu_expedited; /* for sysctl */
 #ifdef CONFIG_RCU_TORTURE_TEST
 extern int rcutorture_runnable; /* for sysctl */
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
@@ -314,7 +316,7 @@ static inline bool rcu_lockdep_current_cpu_online(void)
 
 static inline void rcu_lock_acquire(struct lockdep_map *map)
 {
-       lock_acquire(map, 0, 0, 2, 1, NULL, _THIS_IP_);
+       lock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_);
 }
 
 static inline void rcu_lock_release(struct lockdep_map *map)
@@ -479,11 +481,9 @@ static inline void rcu_preempt_sleep_check(void)
        do {                                                            \
                rcu_preempt_sleep_check();                              \
                rcu_lockdep_assert(!lock_is_held(&rcu_bh_lock_map),     \
-                                  "Illegal context switch in RCU-bh"   \
-                                  " read-side critical section");      \
+                                  "Illegal context switch in RCU-bh read-side critical section"); \
                rcu_lockdep_assert(!lock_is_held(&rcu_sched_lock_map),  \
-                                  "Illegal context switch in RCU-sched"\
-                                  " read-side critical section");      \
+                                  "Illegal context switch in RCU-sched read-side critical section"); \
        } while (0)
 
 #else /* #ifdef CONFIG_PROVE_RCU */
@@ -510,43 +510,40 @@ static inline void rcu_preempt_sleep_check(void)
 #endif /* #else #ifdef __CHECKER__ */
 
 #define __rcu_access_pointer(p, space) \
-       ({ \
-               typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
-               rcu_dereference_sparse(p, space); \
-               ((typeof(*p) __force __kernel *)(_________p1)); \
-       })
+({ \
+       typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
+       rcu_dereference_sparse(p, space); \
+       ((typeof(*p) __force __kernel *)(_________p1)); \
+})
 #define __rcu_dereference_check(p, c, space) \
-       ({ \
-               typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
-               rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \
-                                     " usage"); \
-               rcu_dereference_sparse(p, space); \
-               smp_read_barrier_depends(); \
-               ((typeof(*p) __force __kernel *)(_________p1)); \
-       })
+({ \
+       typeof(*p) *_________p1 = (typeof(*p) *__force)ACCESS_ONCE(p); \
+       rcu_lockdep_assert(c, "suspicious rcu_dereference_check() usage"); \
+       rcu_dereference_sparse(p, space); \
+       smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
+       ((typeof(*p) __force __kernel *)(_________p1)); \
+})
 #define __rcu_dereference_protected(p, c, space) \
-       ({ \
-               rcu_lockdep_assert(c, "suspicious rcu_dereference_protected()" \
-                                     " usage"); \
-               rcu_dereference_sparse(p, space); \
-               ((typeof(*p) __force __kernel *)(p)); \
-       })
+({ \
+       rcu_lockdep_assert(c, "suspicious rcu_dereference_protected() usage"); \
+       rcu_dereference_sparse(p, space); \
+       ((typeof(*p) __force __kernel *)(p)); \
+})
 
 #define __rcu_access_index(p, space) \
-       ({ \
-               typeof(p) _________p1 = ACCESS_ONCE(p); \
-               rcu_dereference_sparse(p, space); \
-               (_________p1); \
-       })
+({ \
+       typeof(p) _________p1 = ACCESS_ONCE(p); \
+       rcu_dereference_sparse(p, space); \
+       (_________p1); \
+})
 #define __rcu_dereference_index_check(p, c) \
-       ({ \
-               typeof(p) _________p1 = ACCESS_ONCE(p); \
-               rcu_lockdep_assert(c, \
-                                  "suspicious rcu_dereference_index_check()" \
-                                  " usage"); \
-               smp_read_barrier_depends(); \
-               (_________p1); \
-       })
+({ \
+       typeof(p) _________p1 = ACCESS_ONCE(p); \
+       rcu_lockdep_assert(c, \
+                          "suspicious rcu_dereference_index_check() usage"); \
+       smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
+       (_________p1); \
+})
 
 /**
  * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
@@ -585,12 +582,7 @@ static inline void rcu_preempt_sleep_check(void)
  * please be careful when making changes to rcu_assign_pointer() and the
  * other macros that it invokes.
  */
-#define rcu_assign_pointer(p, v) \
-       do { \
-               smp_wmb(); \
-               ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
-       } while (0)
-
+#define rcu_assign_pointer(p, v) smp_store_release(&p, RCU_INITIALIZER(v))
 
 /**
  * rcu_access_pointer() - fetch RCU pointer with no dereferencing
@@ -1015,11 +1007,21 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
 #define kfree_rcu(ptr, rcu_head)                                       \
        __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
 
-#ifdef CONFIG_RCU_NOCB_CPU
+#if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL)
+static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
+{
+       *delta_jiffies = ULONG_MAX;
+       return 0;
+}
+#endif /* #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL) */
+
+#if defined(CONFIG_RCU_NOCB_CPU_ALL)
+static inline bool rcu_is_nocb_cpu(int cpu) { return true; }
+#elif defined(CONFIG_RCU_NOCB_CPU)
 bool rcu_is_nocb_cpu(int cpu);
 #else
 static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
-#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
+#endif
 
 
 /* Only for use by adaptive-ticks code. */
index 6f01771b571c00eede5aaae145fdcf7382e61cd9..425c659d54e576a1991aa9aa2d777ee001d66546 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
 
 #include <linux/cache.h>
 
+static inline unsigned long get_state_synchronize_rcu(void)
+{
+       return 0;
+}
+
+static inline void cond_synchronize_rcu(unsigned long oldstate)
+{
+       might_sleep();
+}
+
 static inline void rcu_barrier_bh(void)
 {
        wait_rcu_gp(call_rcu_bh);
@@ -68,12 +78,6 @@ static inline void kfree_call_rcu(struct rcu_head *head,
        call_rcu(head, func);
 }
 
-static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
-{
-       *delta_jiffies = ULONG_MAX;
-       return 0;
-}
-
 static inline void rcu_note_context_switch(int cpu)
 {
        rcu_sched_qs(cpu);
index 72137ee8c603b2c0c45ea7f729211e12cfad3941..a59ca05fd4e36eca1de98e849f6e8b9855b37c82 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
@@ -31,7 +31,9 @@
 #define __LINUX_RCUTREE_H
 
 void rcu_note_context_switch(int cpu);
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
 int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 void rcu_cpu_stall_reset(void);
 
 /*
@@ -74,6 +76,8 @@ static inline void synchronize_rcu_bh_expedited(void)
 void rcu_barrier(void);
 void rcu_barrier_bh(void);
 void rcu_barrier_sched(void);
+unsigned long get_state_synchronize_rcu(void);
+void cond_synchronize_rcu(unsigned long oldstate);
 
 extern unsigned long rcutorture_testseq;
 extern unsigned long rcutorture_vernum;
index 1da693d51255d974c60ba4b50527fe3e1808c03d..b66c2110cb1ff045dec9e7b23ba15a142e0f84fb 100644 (file)
@@ -250,8 +250,7 @@ struct rmap_walk_control {
        int (*rmap_one)(struct page *page, struct vm_area_struct *vma,
                                        unsigned long addr, void *arg);
        int (*done)(struct page *page);
-       int (*file_nonlinear)(struct page *, struct address_space *,
-                                       struct vm_area_struct *vma);
+       int (*file_nonlinear)(struct page *, struct address_space *, void *arg);
        struct anon_vma *(*anon_lock)(struct page *page);
        bool (*invalid_vma)(struct vm_area_struct *vma, void *arg);
 };
index 6f6c56f63c6860a36e6c06a32e55a11c8440ad0f..7cb07fd266808835ca8d4309891f19567cbe7503 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <uapi/linux/sched.h>
 
+#include <linux/sched/prio.h>
+
 
 struct sched_param {
        int sched_priority;
@@ -27,7 +29,7 @@ struct sched_param {
 
 #include <asm/page.h>
 #include <asm/ptrace.h>
-#include <asm/cputime.h>
+#include <linux/cputime.h>
 
 #include <linux/smp.h>
 #include <linux/sem.h>
@@ -128,6 +130,7 @@ struct bio_list;
 struct fs_struct;
 struct perf_event_context;
 struct blk_plug;
+struct filename;
 
 /*
  * List of flags we want to share for kernel threads,
@@ -1080,6 +1083,7 @@ struct sched_entity {
 #endif
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
+       int                     depth;
        struct sched_entity     *parent;
        /* rq on which this entity is (to be) queued: */
        struct cfs_rq           *cfs_rq;
@@ -1463,6 +1467,9 @@ struct task_struct {
        struct mutex perf_event_mutex;
        struct list_head perf_event_list;
 #endif
+#ifdef CONFIG_DEBUG_PREEMPT
+       unsigned long preempt_disable_ip;
+#endif
 #ifdef CONFIG_NUMA
        struct mempolicy *mempolicy;    /* Protected by alloc_lock */
        short il_next;
@@ -1473,9 +1480,10 @@ struct task_struct {
        unsigned int numa_scan_period;
        unsigned int numa_scan_period_max;
        int numa_preferred_nid;
-       int numa_migrate_deferred;
        unsigned long numa_migrate_retry;
        u64 node_stamp;                 /* migration stamp  */
+       u64 last_task_numa_placement;
+       u64 last_sum_exec_runtime;
        struct callback_head numa_work;
 
        struct list_head numa_entry;
@@ -1486,15 +1494,22 @@ struct task_struct {
         * Scheduling placement decisions are made based on the these counts.
         * The values remain static for the duration of a PTE scan
         */
-       unsigned long *numa_faults;
+       unsigned long *numa_faults_memory;
        unsigned long total_numa_faults;
 
        /*
         * numa_faults_buffer records faults per node during the current
-        * scan window. When the scan completes, the counts in numa_faults
-        * decay and these values are copied.
+        * scan window. When the scan completes, the counts in
+        * numa_faults_memory decay and these values are copied.
+        */
+       unsigned long *numa_faults_buffer_memory;
+
+       /*
+        * Track the nodes the process was running on when a NUMA hinting
+        * fault was incurred.
         */
-       unsigned long *numa_faults_buffer;
+       unsigned long *numa_faults_cpu;
+       unsigned long *numa_faults_buffer_cpu;
 
        /*
         * numa_faults_locality tracks if faults recorded during the last
@@ -1599,8 +1614,8 @@ extern void task_numa_fault(int last_node, int node, int pages, int flags);
 extern pid_t task_numa_group_id(struct task_struct *p);
 extern void set_numabalancing_state(bool enabled);
 extern void task_numa_free(struct task_struct *p);
-
-extern unsigned int sysctl_numa_balancing_migrate_deferred;
+extern bool should_numa_migrate_memory(struct task_struct *p, struct page *page,
+                                       int src_nid, int dst_cpu);
 #else
 static inline void task_numa_fault(int last_node, int node, int pages,
                                   int flags)
@@ -1616,6 +1631,11 @@ static inline void set_numabalancing_state(bool enabled)
 static inline void task_numa_free(struct task_struct *p)
 {
 }
+static inline bool should_numa_migrate_memory(struct task_struct *p,
+                               struct page *page, int src_nid, int dst_cpu)
+{
+       return true;
+}
 #endif
 
 static inline struct pid *task_pid(struct task_struct *task)
@@ -2083,7 +2103,16 @@ static inline void sched_autogroup_exit(struct signal_struct *sig) { }
 extern bool yield_to(struct task_struct *p, bool preempt);
 extern void set_user_nice(struct task_struct *p, long nice);
 extern int task_prio(const struct task_struct *p);
-extern int task_nice(const struct task_struct *p);
+/**
+ * task_nice - return the nice value of a given task.
+ * @p: the task in question.
+ *
+ * Return: The nice value [ -20 ... 0 ... 19 ].
+ */
+static inline int task_nice(const struct task_struct *p)
+{
+       return PRIO_TO_NICE((p)->static_prio);
+}
 extern int can_nice(const struct task_struct *p, const int nice);
 extern int task_curr(const struct task_struct *p);
 extern int idle_cpu(int cpu);
@@ -2315,7 +2344,7 @@ extern void do_group_exit(int);
 extern int allow_signal(int);
 extern int disallow_signal(int);
 
-extern int do_execve(const char *,
+extern int do_execve(struct filename *,
                     const char __user * const __user *,
                     const char __user * const __user *);
 extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h
new file mode 100644 (file)
index 0000000..ac32258
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _SCHED_PRIO_H
+#define _SCHED_PRIO_H
+
+#define MAX_NICE       19
+#define MIN_NICE       -20
+#define NICE_WIDTH     (MAX_NICE - MIN_NICE + 1)
+
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space.  This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO       100
+#define MAX_RT_PRIO            MAX_USER_RT_PRIO
+
+#define MAX_PRIO               (MAX_RT_PRIO + NICE_WIDTH)
+#define DEFAULT_PRIO           (MAX_RT_PRIO + NICE_WIDTH / 2)
+
+/*
+ * Convert user-nice values [ -20 ... 0 ... 19 ]
+ * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
+ * and back.
+ */
+#define NICE_TO_PRIO(nice)     ((nice) + DEFAULT_PRIO)
+#define PRIO_TO_NICE(prio)     ((prio) - DEFAULT_PRIO)
+
+/*
+ * 'User priority' is the nice value converted to something we
+ * can work with better when scaling various scheduler parameters,
+ * it's a [ 0 ... 39 ] range.
+ */
+#define USER_PRIO(p)           ((p)-MAX_RT_PRIO)
+#define TASK_USER_PRIO(p)      USER_PRIO((p)->static_prio)
+#define MAX_USER_PRIO          (USER_PRIO(MAX_PRIO))
+
+#endif /* _SCHED_PRIO_H */
index 34e4ebea8fce79efa8f1528747db18b7a11f75b4..6341f5be6e2474c0a7e30fdd75e3eae5b4286bf3 100644 (file)
@@ -1,24 +1,7 @@
 #ifndef _SCHED_RT_H
 #define _SCHED_RT_H
 
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space.  This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO       100
-#define MAX_RT_PRIO            MAX_USER_RT_PRIO
-
-#define MAX_PRIO               (MAX_RT_PRIO + 40)
-#define DEFAULT_PRIO           (MAX_RT_PRIO + 20)
+#include <linux/sched/prio.h>
 
 static inline int rt_prio(int prio)
 {
@@ -35,6 +18,7 @@ static inline int rt_task(struct task_struct *p)
 #ifdef CONFIG_RT_MUTEXES
 extern int rt_mutex_getprio(struct task_struct *p);
 extern void rt_mutex_setprio(struct task_struct *p, int prio);
+extern int rt_mutex_check_prio(struct task_struct *task, int newprio);
 extern struct task_struct *rt_mutex_get_top_task(struct task_struct *task);
 extern void rt_mutex_adjust_pi(struct task_struct *p);
 static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
@@ -46,6 +30,12 @@ static inline int rt_mutex_getprio(struct task_struct *p)
 {
        return p->normal_prio;
 }
+
+static inline int rt_mutex_check_prio(struct task_struct *task, int newprio)
+{
+       return 0;
+}
+
 static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
 {
        return NULL;
index 5623a7f965b7bbb07ab94a72351aec027ef4adb7..2fc42d191f79f77236b843a70775129c01207333 100644 (file)
@@ -1040,6 +1040,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     Allocate a security structure to the xp->security field; the security
  *     field is initialized to NULL when the xfrm_policy is allocated.
  *     Return 0 if operation was successful (memory to allocate, legal context)
+ *     @gfp is to specify the context for the allocation
  * @xfrm_policy_clone_security:
  *     @old_ctx contains an existing xfrm_sec_ctx.
  *     @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
@@ -1683,7 +1684,7 @@ struct security_operations {
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
        int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
-                       struct xfrm_user_sec_ctx *sec_ctx);
+                       struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp);
        int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
        void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
        int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
@@ -2859,7 +2860,8 @@ static inline void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 
-int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx);
+int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
+                              struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp);
 int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp);
 void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
 int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
@@ -2877,7 +2879,9 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
 
 #else  /* CONFIG_SECURITY_NETWORK_XFRM */
 
-static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
+static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
+                                            struct xfrm_user_sec_ctx *sec_ctx,
+                                            gfp_t gfp)
 {
        return 0;
 }
index f589c9af8cbf1250da1945bac436f27d92987e80..15ede6a823a6e2daa366551cd7bad13ac3dd5c03 100644 (file)
@@ -2451,8 +2451,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
                    unsigned int flags);
 void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
-void skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
-                 int len, int hlen);
+int skb_zerocopy(struct sk_buff *to, struct sk_buff *from,
+                int len, int hlen);
 void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
 int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
@@ -2725,7 +2725,7 @@ static inline void nf_reset(struct sk_buff *skb)
 
 static inline void nf_reset_trace(struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
        skb->nf_trace = 0;
 #endif
 }
@@ -2742,6 +2742,9 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
        dst->nf_bridge  = src->nf_bridge;
        nf_bridge_get(src->nf_bridge);
 #endif
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
+       dst->nf_trace = src->nf_trace;
+#endif
 }
 
 static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
@@ -2916,5 +2919,22 @@ static inline bool skb_head_is_locked(const struct sk_buff *skb)
 {
        return !skb->head_frag || skb_cloned(skb);
 }
+
+/**
+ * skb_gso_network_seglen - Return length of individual segments of a gso packet
+ *
+ * @skb: GSO skb
+ *
+ * skb_gso_network_seglen is used to determine the real size of the
+ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP).
+ *
+ * The MAC/L2 header is not accounted for.
+ */
+static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb)
+{
+       unsigned int hdr_len = skb_transport_header(skb) -
+                              skb_network_header(skb);
+       return hdr_len + skb_gso_transport_seglen(skb);
+}
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */
index 9260abdd67df801e002f18faf3f17bd00d494867..b5b2df60299e25c5c33b3be39ff90090c974689f 100644 (file)
@@ -410,7 +410,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
  *
  * %GFP_NOWAIT - Allocation will not sleep.
  *
- * %GFP_THISNODE - Allocate node-local memory only.
+ * %__GFP_THISNODE - Allocate node-local memory only.
  *
  * %GFP_DMA - Allocation suitable for DMA.
  *   Should only be used for kmalloc() caches. Otherwise, use a
index 3834f43f9993183cf180d1639d1d9d02c3b2721c..6ae004e437eadade24c8fac3bd6b5efc27c57744 100644 (file)
@@ -188,6 +188,9 @@ static inline void kick_all_cpus_sync(void) {  }
  */
 extern void arch_disable_smp_support(void);
 
+extern void arch_enable_nonboot_cpus_begin(void);
+extern void arch_enable_nonboot_cpus_end(void);
+
 void smp_setup_processor_id(void);
 
 #endif /* __LINUX_SMP_H */
index a1d4ca290862d766d5460f198503ae4530df3f45..4203c66d88033269692fa38ce50aebe17fee9419 100644 (file)
@@ -273,7 +273,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *     message while queuing transfers that arrive in the meantime. When the
  *     driver is finished with this message, it must call
  *     spi_finalize_current_message() so the subsystem can issue the next
- *     transfer
+ *     message
  * @unprepare_transfer_hardware: there are currently no more messages on the
  *     queue so the subsystem notifies the driver that it may relax the
  *     hardware by issuing this call
@@ -287,7 +287,10 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *                  - return 1 if the transfer is still in progress. When
  *                    the driver is finished with this transfer it must
  *                    call spi_finalize_current_transfer() so the subsystem
- *                    can issue the next transfer
+ *                    can issue the next transfer. Note: transfer_one and
+ *                    transfer_one_message are mutually exclusive; when both
+ *                    are set, the generic subsystem does not call your
+ *                    transfer_one callback.
  * @unprepare_message: undo any work done by prepare_message().
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *     number. Any individual value may be -ENOENT for CS lines that
index 9b058eecd40390b914d705809a1aabac3eff132b..a2783cb5d2753f6c6eb04e48086f461abedb8b6f 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright (C) IBM Corporation, 2006
  * Copyright (C) Fujitsu, 2012
index 40ed9e9a77e53c77448104a921c0595f2a7927eb..1e67b7a5968c77c2f9290e48801971adc9c0f3fc 100644 (file)
@@ -98,6 +98,8 @@ struct sigaltstack;
 #define __MAP(n,...) __MAP##n(__VA_ARGS__)
 
 #define __SC_DECL(t, a)        t a
+#define __TYPE_IS_L(t) (__same_type((t)0, 0L))
+#define __TYPE_IS_UL(t)        (__same_type((t)0, 0UL))
 #define __TYPE_IS_LL(t) (__same_type((t)0, 0LL) || __same_type((t)0, 0ULL))
 #define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a
 #define __SC_CAST(t, a)        (t) a
@@ -281,13 +283,15 @@ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
 asmlinkage long sys_sched_setparam(pid_t pid,
                                        struct sched_param __user *param);
 asmlinkage long sys_sched_setattr(pid_t pid,
-                                       struct sched_attr __user *attr);
+                                       struct sched_attr __user *attr,
+                                       unsigned int flags);
 asmlinkage long sys_sched_getscheduler(pid_t pid);
 asmlinkage long sys_sched_getparam(pid_t pid,
                                        struct sched_param __user *param);
 asmlinkage long sys_sched_getattr(pid_t pid,
                                        struct sched_attr __user *attr,
-                                       unsigned int size);
+                                       unsigned int size,
+                                       unsigned int flags);
 asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
                                        unsigned long __user *user_mask_ptr);
 asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
diff --git a/include/linux/torture.h b/include/linux/torture.h
new file mode 100644 (file)
index 0000000..b2e2b46
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Common functions for in-kernel torture tests.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright IBM Corporation, 2014
+ *
+ * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#ifndef __LINUX_TORTURE_H
+#define __LINUX_TORTURE_H
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/seqlock.h>
+#include <linux/lockdep.h>
+#include <linux/completion.h>
+#include <linux/debugobjects.h>
+#include <linux/bug.h>
+#include <linux/compiler.h>
+
+/* Definitions for a non-string torture-test module parameter. */
+#define torture_param(type, name, init, msg) \
+       static type name = init; \
+       module_param(name, type, 0444); \
+       MODULE_PARM_DESC(name, msg);
+
+#define TORTURE_FLAG "-torture:"
+#define TOROUT_STRING(s) \
+       pr_alert("%s" TORTURE_FLAG s "\n", torture_type)
+#define VERBOSE_TOROUT_STRING(s) \
+       do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0)
+#define VERBOSE_TOROUT_ERRSTRING(s) \
+       do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
+
+/* Definitions for a non-string torture-test module parameter. */
+#define torture_parm(type, name, init, msg) \
+       static type name = init; \
+       module_param(name, type, 0444); \
+       MODULE_PARM_DESC(name, msg);
+
+/* Definitions for online/offline exerciser. */
+int torture_onoff_init(long ooholdoff, long oointerval);
+char *torture_onoff_stats(char *page);
+bool torture_onoff_failures(void);
+
+/* Low-rider random number generator. */
+struct torture_random_state {
+       unsigned long trs_state;
+       long trs_count;
+};
+#define DEFINE_TORTURE_RANDOM(name) struct torture_random_state name = { 0, 0 }
+unsigned long torture_random(struct torture_random_state *trsp);
+
+/* Task shuffler, which causes CPUs to occasionally go idle. */
+void torture_shuffle_task_register(struct task_struct *tp);
+int torture_shuffle_init(long shuffint);
+
+/* Test auto-shutdown handling. */
+void torture_shutdown_absorb(const char *title);
+int torture_shutdown_init(int ssecs, void (*cleanup)(void));
+
+/* Task stuttering, which forces load/no-load transitions. */
+void stutter_wait(const char *title);
+int torture_stutter_init(int s);
+
+/* Initialization and cleanup. */
+void torture_init_begin(char *ttype, bool v, int *runnable);
+void torture_init_end(void);
+bool torture_cleanup(void);
+bool torture_must_stop(void);
+bool torture_must_stop_irq(void);
+void torture_kthread_stopping(char *title);
+int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
+                            char *f, struct task_struct **tp);
+void _torture_stop_kthread(char *m, struct task_struct **tp);
+
+#define torture_create_kthread(n, arg, tp) \
+       _torture_create_kthread(n, (arg), #n, "Creating " #n " task", \
+                               "Failed to create " #n, &(tp))
+#define torture_stop_kthread(n, tp) \
+       _torture_stop_kthread("Stopping " #n " task", &(tp))
+
+#endif /* __LINUX_TORTURE_H */
index accc497f8d729160b0234756e96d99607cf67f33..7159a0a933df2b016db23cdcd87487c19d5829d0 100644 (file)
@@ -60,6 +60,12 @@ struct tp_module {
        unsigned int num_tracepoints;
        struct tracepoint * const *tracepoints_ptrs;
 };
+bool trace_module_has_bad_taint(struct module *mod);
+#else
+static inline bool trace_module_has_bad_taint(struct module *mod)
+{
+       return false;
+}
 #endif /* CONFIG_MODULES */
 
 struct tracepoint_iter {
index c716da18c668fe37c4fe91dde3c6385cc81e2d21..7f6eb859873e4a24bcb5ebf30bf8b4485e61a622 100644 (file)
@@ -1265,8 +1265,6 @@ typedef void (*usb_complete_t)(struct urb *);
  * @sg: scatter gather buffer list, the buffer size of each element in
  *     the list (except the last) must be divisible by the endpoint's
  *     max packet size if no_sg_constraint isn't set in 'struct usb_bus'
- *     (FIXME: scatter-gather under xHCI is broken for periodic transfers.
- *     Do not use urb->sg for interrupt endpoints for now, only bulk.)
  * @num_mapped_sgs: (internal) number of mapped sg entries
  * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
index c3fa807459967286c0407c18da294ca6d95ced42..2c14d9cdd57aac88eb3121a4271b7c5fe3909a56 100644 (file)
@@ -88,6 +88,7 @@
 #define cdc_ncm_data_intf_is_mbim(x)  ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
 
 struct cdc_ncm_ctx {
+       struct usb_cdc_ncm_ntb_parameters ncm_parm;
        struct hrtimer tx_timer;
        struct tasklet_struct bh;
 
index e303eef94dd5cea92d16d7ae63aa35f5c3f1d4bb..0662e98fef72b21fdabb7d14ac1fd71f2066a140 100644 (file)
@@ -30,7 +30,7 @@ struct usbnet {
        struct driver_info      *driver_info;
        const char              *driver_name;
        void                    *driver_priv;
-       wait_queue_head_t       *wait;
+       wait_queue_head_t       wait;
        struct mutex            phy_mutex;
        unsigned char           suspend_count;
        unsigned char           pkt_cnt, pkt_err;
index c557c6d096def9a93bb5b00af4df87166539e048..3a712e2e7d762f479fc91377f1e37a9186172dc9 100644 (file)
@@ -71,12 +71,14 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                THP_ZERO_PAGE_ALLOC,
                THP_ZERO_PAGE_ALLOC_FAILED,
 #endif
+#ifdef CONFIG_DEBUG_TLBFLUSH
 #ifdef CONFIG_SMP
                NR_TLB_REMOTE_FLUSH,    /* cpu tried to flush others' tlbs */
                NR_TLB_REMOTE_FLUSH_RECEIVED,/* cpu received ipi for flush */
-#endif
+#endif /* CONFIG_SMP */
                NR_TLB_LOCAL_FLUSH_ALL,
                NR_TLB_LOCAL_FLUSH_ONE,
+#endif /* CONFIG_DEBUG_TLBFLUSH */
                NR_VM_EVENT_ITEMS
 };
 
index a67b384157689ec9fda2abfec0173122fc98a4a8..67ce70c8279be201e8ecb33fed569845a5386257 100644 (file)
@@ -83,6 +83,14 @@ static inline void vm_events_fold_cpu(int cpu)
 #define count_vm_numa_events(x, y) do { (void)(y); } while (0)
 #endif /* CONFIG_NUMA_BALANCING */
 
+#ifdef CONFIG_DEBUG_TLBFLUSH
+#define count_vm_tlb_event(x)     count_vm_event(x)
+#define count_vm_tlb_events(x, y)  count_vm_events(x, y)
+#else
+#define count_vm_tlb_event(x)     do {} while (0)
+#define count_vm_tlb_events(x, y) do { (void)(y); } while (0)
+#endif
+
 #define __count_zone_vm_events(item, zone, delta) \
                __count_vm_events(item##_NORMAL - ZONE_NORMAL + \
                zone_idx(zone), delta)
index abdbe5af119d93aa7c9ccab49dc848a29eb84eea..1b22c42e9c2d4f03bb2e16b32fbeb0c397b3e034 100644 (file)
@@ -177,17 +177,6 @@ struct execute_work {
 #define DECLARE_DEFERRABLE_WORK(n, f)                                  \
        struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f, TIMER_DEFERRABLE)
 
-/*
- * initialize a work item's function pointer
- */
-#define PREPARE_WORK(_work, _func)                                     \
-       do {                                                            \
-               (_work)->func = (_func);                                \
-       } while (0)
-
-#define PREPARE_DELAYED_WORK(_work, _func)                             \
-       PREPARE_WORK(&(_work)->work, (_func))
-
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
 extern void __init_work(struct work_struct *work, int onstack);
 extern void destroy_work_on_stack(struct work_struct *work);
@@ -219,7 +208,7 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
                (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0); \
                INIT_LIST_HEAD(&(_work)->entry);                        \
-               PREPARE_WORK((_work), (_func));                         \
+               (_work)->func = (_func);                                \
        } while (0)
 #else
 #define __INIT_WORK(_work, _func, _onstack)                            \
@@ -227,7 +216,7 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
                __init_work((_work), _onstack);                         \
                (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                INIT_LIST_HEAD(&(_work)->entry);                        \
-               PREPARE_WORK((_work), (_func));                         \
+               (_work)->func = (_func);                                \
        } while (0)
 #endif
 
@@ -297,17 +286,11 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
  * Documentation/workqueue.txt.
  */
 enum {
-       /*
-        * All wqs are now non-reentrant making the following flag
-        * meaningless.  Will be removed.
-        */
-       WQ_NON_REENTRANT        = 1 << 0, /* DEPRECATED */
-
        WQ_UNBOUND              = 1 << 1, /* not bound to any cpu */
        WQ_FREEZABLE            = 1 << 2, /* freeze during suspend */
        WQ_MEM_RECLAIM          = 1 << 3, /* may be used for memory reclaim */
        WQ_HIGHPRI              = 1 << 4, /* high priority */
-       WQ_CPU_INTENSIVE        = 1 << 5, /* cpu instensive workqueue */
+       WQ_CPU_INTENSIVE        = 1 << 5, /* cpu intensive workqueue */
        WQ_SYSFS                = 1 << 6, /* visible in sysfs, see wq_sysfs_register() */
 
        /*
@@ -421,10 +404,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
        static struct lock_class_key __key;                             \
        const char *__lock_name;                                        \
                                                                        \
-       if (__builtin_constant_p(fmt))                                  \
-               __lock_name = (fmt);                                    \
-       else                                                            \
-               __lock_name = #fmt;                                     \
+       __lock_name = #fmt#args;                                        \
                                                                        \
        __alloc_workqueue_key((fmt), (flags), (max_active),             \
                              &__key, __lock_name, ##args);             \
@@ -607,21 +587,6 @@ static inline bool keventd_up(void)
        return system_wq != NULL;
 }
 
-/*
- * Like above, but uses del_timer() instead of del_timer_sync(). This means,
- * if it returns 0 the timer function may be running and the queueing is in
- * progress.
- */
-static inline bool __deprecated __cancel_delayed_work(struct delayed_work *work)
-{
-       bool ret;
-
-       ret = del_timer(&work->timer);
-       if (ret)
-               work_clear_pending(&work->work);
-       return ret;
-}
-
 /* used to be different but now identical to flush_work(), deprecated */
 static inline bool __deprecated flush_work_sync(struct work_struct *work)
 {
index fc0e4320aa6d50d0e5f966e3f8b649506d461ac7..021b8a319b9e2cf7f0f60a5f6fedcfe3367f8016 100644 (file)
@@ -97,7 +97,7 @@ void writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
 int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason);
 int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
                                  enum wb_reason reason);
-void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this);
+void sync_inodes_sb(struct super_block *);
 void wakeup_flusher_threads(long nr_pages, enum wb_reason reason);
 void inode_wait_for_writeback(struct inode *inode);
 
index deb7ca75db488f94b0c697cbdfa1946c3263b63b..93cb18f729b5bac2185990b3eb36cbe5a1d74144 100644 (file)
@@ -15,4 +15,6 @@ struct datalink_proto {
        struct list_head node;
 };
 
+struct datalink_proto *make_EII_client(void);
+void destroy_EII_client(struct datalink_proto *dl);
 #endif
index ccc15588d108ecc2a33d5b2544b8e0e1feb33069..913b73d239f54a11b87e7b304e0cea825fc7e416 100644 (file)
@@ -200,6 +200,8 @@ static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
 }
 
 unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
+void dn_register_sysctl(void);
+void dn_unregister_sysctl(void);
 
 #define DN_MENUVER_ACC 0x01
 #define DN_MENUVER_USR 0x02
index b409ad6b8d7adbb5bd25ad3b71cbea5c8723b70e..55df9939bca268106384d10d330615ae091d3aea 100644 (file)
@@ -20,6 +20,8 @@ int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *,
                         struct sock *sk, int flags);
 int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
 void dn_rt_cache_flush(int delay);
+int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
+                struct packet_type *pt, struct net_device *orig_dev);
 
 /* Masks for flags field */
 #define DN_RT_F_PID 0x07 /* Mask for packet type                      */
index 96f3789b27bcc88ac38c0b433d1d81c1e8a3a82b..2a2d6bb34eb8b5923ca8b951f2a5e10acd99be40 100644 (file)
@@ -16,6 +16,7 @@
 struct ethoc_platform_data {
        u8 hwaddr[IFHWADDRLEN];
        s8 phy_id;
+       u32 eth_clkfreq;
 };
 
 #endif /* !LINUX_NET_ETHOC_H */
index 9650a3ffd2d2328f11859adc4a3169ae41b25442..b4956a5fcc3f117e9e4199a5ad7af94894fea859 100644 (file)
 #define IF_PREFIX_AUTOCONF     0x02
 
 enum {
+       INET6_IFADDR_STATE_PREDAD,
        INET6_IFADDR_STATE_DAD,
        INET6_IFADDR_STATE_POSTDAD,
+       INET6_IFADDR_STATE_ERRDAD,
        INET6_IFADDR_STATE_UP,
        INET6_IFADDR_STATE_DEAD,
 };
@@ -58,7 +60,7 @@ struct inet6_ifaddr {
        unsigned long           cstamp; /* created timestamp */
        unsigned long           tstamp; /* updated timestamp */
 
-       struct timer_list       dad_timer;
+       struct delayed_work     dad_work;
 
        struct inet6_dev        *idev;
        struct rt6_info         *rt;
index 48ed75c21260b8dd17e681021311bb8dae4f2617..e77c10405d515da16071461fe9f7385d8ac08556 100644 (file)
@@ -129,6 +129,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
 int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
                      struct ip_tunnel_parm *p);
 void ip_tunnel_setup(struct net_device *dev, int net_id);
+void ip_tunnel_dst_reset_all(struct ip_tunnel *t);
 
 /* Extract dsfield from inner protocol */
 static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
index 9e9e35465bafbaff131c893814abd44d99be712f..0143180fecc983a01fd5c1c3027f984d0f0be177 100644 (file)
@@ -140,6 +140,17 @@ static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
 }
 
 void ipxitf_down(struct ipx_interface *intrfc);
+struct ipx_interface *ipxitf_find_using_net(__be32 net);
+int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node);
+__be16 ipx_cksum(struct ipxhdr *packet, int length);
+int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
+                    unsigned char *node);
+void ipxrtr_del_routes(struct ipx_interface *intrfc);
+int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
+                       struct iovec *iov, size_t len, int noblock);
+int ipxrtr_route_skb(struct sk_buff *skb);
+struct ipx_route *ipxrtr_lookup(__be32 net);
+int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
 
 static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
 {
index da68c9a90ac56932638feca9cdbba6a61b75ba64..991dcd94cbbf33bc5617fcb3a0c280113c4a042a 100644 (file)
@@ -162,6 +162,14 @@ extern struct list_head net_namespace_list;
 struct net *get_net_ns_by_pid(pid_t pid);
 struct net *get_net_ns_by_fd(int pid);
 
+#ifdef CONFIG_SYSCTL
+void ipx_register_sysctl(void);
+void ipx_unregister_sysctl(void);
+#else
+#define ipx_register_sysctl()
+#define ipx_unregister_sysctl()
+#endif
+
 #ifdef CONFIG_NET_NS
 void __put_net(struct net *net);
 
index 01ea6eed1bb1ddcc9b8c9001286ae85730bea416..b2ac6246b7e0abe156b26a06bf9a4463331baa6e 100644 (file)
@@ -284,6 +284,8 @@ extern unsigned int nf_conntrack_max;
 extern unsigned int nf_conntrack_hash_rnd;
 void init_nf_conntrack_hash_rnd(void);
 
+void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl);
+
 #define NF_CT_STAT_INC(net, count)       __this_cpu_inc((net)->ct.stat->count)
 #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
 
index 57c8ff7955dfbd109e8ac2c731d595539220b3d4..e7e14ffe0f6a0e0f545af45864aa248980250da2 100644 (file)
@@ -252,6 +252,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
  *     @owner: module reference
  *     @policy: netlink attribute policy
  *     @maxattr: highest netlink attribute number
+ *     @family: address family for AF-specific types
  */
 struct nft_expr_type {
        const struct nft_expr_ops       *(*select_ops)(const struct nft_ctx *,
@@ -262,6 +263,7 @@ struct nft_expr_type {
        struct module                   *owner;
        const struct nla_policy         *policy;
        unsigned int                    maxattr;
+       u8                              family;
 };
 
 /**
@@ -320,7 +322,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
  *     struct nft_rule - nf_tables rule
  *
  *     @list: used internally
- *     @rcu_head: used internally for rcu
  *     @handle: rule handle
  *     @genmask: generation mask
  *     @dlen: length of expression data
@@ -328,7 +329,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
  */
 struct nft_rule {
        struct list_head                list;
-       struct rcu_head                 rcu_head;
        u64                             handle:46,
                                        genmask:2,
                                        dlen:16;
@@ -389,7 +389,6 @@ enum nft_chain_flags {
  *
  *     @rules: list of rules in the chain
  *     @list: used internally
- *     @rcu_head: used internally
  *     @net: net namespace that this chain belongs to
  *     @table: table that this chain belongs to
  *     @handle: chain handle
@@ -401,7 +400,6 @@ enum nft_chain_flags {
 struct nft_chain {
        struct list_head                rules;
        struct list_head                list;
-       struct rcu_head                 rcu_head;
        struct net                      *net;
        struct nft_table                *table;
        u64                             handle;
@@ -529,6 +527,9 @@ void nft_unregister_expr(struct nft_expr_type *);
 #define MODULE_ALIAS_NFT_CHAIN(family, name) \
        MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
 
+#define MODULE_ALIAS_NFT_AF_EXPR(family, name) \
+       MODULE_ALIAS("nft-expr-" __stringify(family) "-" name)
+
 #define MODULE_ALIAS_NFT_EXPR(name) \
        MODULE_ALIAS("nft-expr-" name)
 
diff --git a/include/net/netfilter/nft_reject.h b/include/net/netfilter/nft_reject.h
new file mode 100644 (file)
index 0000000..36b0da2
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _NFT_REJECT_H_
+#define _NFT_REJECT_H_
+
+struct nft_reject {
+       enum nft_reject_types   type:8;
+       u8                      icmp_code;
+};
+
+extern const struct nla_policy nft_reject_policy[];
+
+int nft_reject_init(const struct nft_ctx *ctx,
+                   const struct nft_expr *expr,
+                   const struct nlattr * const tb[]);
+
+int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr);
+
+void nft_reject_ipv4_eval(const struct nft_expr *expr,
+                         struct nft_data data[NFT_REG_MAX + 1],
+                         const struct nft_pktinfo *pkt);
+
+void nft_reject_ipv6_eval(const struct nft_expr *expr,
+                         struct nft_data data[NFT_REG_MAX + 1],
+                         const struct nft_pktinfo *pkt);
+
+#endif
index d992ca3145fec9826c1df1cf0affc95272a6af25..6ee76c804893fc9f291a469550b2356fe1b93c39 100644 (file)
@@ -1653,17 +1653,6 @@ struct sctp_association {
        /* This is the last advertised value of rwnd over a SACK chunk. */
        __u32 a_rwnd;
 
-       /* Number of bytes by which the rwnd has slopped.  The rwnd is allowed
-        * to slop over a maximum of the association's frag_point.
-        */
-       __u32 rwnd_over;
-
-       /* Keeps treack of rwnd pressure.  This happens when we have
-        * a window, but not recevie buffer (i.e small packets).  This one
-        * is releases slowly (1 PMTU at a time ).
-        */
-       __u32 rwnd_press;
-
        /* This is the sndbuf size in use for the association.
         * This corresponds to the sndbuf size for the association,
         * as specified in the sk->sndbuf.
@@ -1892,8 +1881,7 @@ void sctp_assoc_update(struct sctp_association *old,
 __u32 sctp_association_get_next_tsn(struct sctp_association *);
 
 void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *);
-void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
-void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
+void sctp_assoc_rwnd_update(struct sctp_association *, bool);
 void sctp_assoc_set_primary(struct sctp_association *,
                            struct sctp_transport *);
 void sctp_assoc_del_nonprimary_peers(struct sctp_association *,
index 5c3f7c3624aa00214572c47cd3b6dbb3777d93ee..b9586a137cadd38e8a36abcd34018cfe9b680047 100644 (file)
@@ -1488,6 +1488,11 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
  */
 #define sock_owned_by_user(sk) ((sk)->sk_lock.owned)
 
+static inline void sock_release_ownership(struct sock *sk)
+{
+       sk->sk_lock.owned = 0;
+}
+
 /*
  * Macro so as to not evaluate some arguments when
  * lockdep is not enabled.
@@ -2186,7 +2191,6 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
 {
 #define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL)                      | \
                           (1UL << SOCK_RCVTSTAMP)                      | \
-                          (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)       | \
                           (1UL << SOCK_TIMESTAMPING_SOFTWARE)          | \
                           (1UL << SOCK_TIMESTAMPING_RAW_HARDWARE)      | \
                           (1UL << SOCK_TIMESTAMPING_SYS_HARDWARE))
index 56fc366da6d5183b536648e949769a118ba33677..743accec6c76e056547102a0b429418b8450af65 100644 (file)
@@ -480,20 +480,21 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 #ifdef CONFIG_SYN_COOKIES
 #include <linux/ktime.h>
 
-/* Syncookies use a monotonic timer which increments every 64 seconds.
+/* Syncookies use a monotonic timer which increments every 60 seconds.
  * This counter is used both as a hash input and partially encoded into
  * the cookie value.  A cookie is only validated further if the delta
  * between the current counter value and the encoded one is less than this,
- * i.e. a sent cookie is valid only at most for 128 seconds (or less if
+ * i.e. a sent cookie is valid only at most for 2*60 seconds (or less if
  * the counter advances immediately after a cookie is generated).
  */
 #define MAX_SYNCOOKIE_AGE 2
 
 static inline u32 tcp_cookie_time(void)
 {
-       struct timespec now;
-       getnstimeofday(&now);
-       return now.tv_sec >> 6; /* 64 seconds granularity */
+       u64 val = get_jiffies_64();
+
+       do_div(val, 60 * HZ);
+       return val;
 }
 
 u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th,
@@ -1303,7 +1304,8 @@ struct tcp_fastopen_request {
        /* Fast Open cookie. Size 0 means a cookie request */
        struct tcp_fastopen_cookie      cookie;
        struct msghdr                   *data;  /* data in MSG_FASTOPEN */
-       u16                             copied; /* queued in tcp_connect() */
+       size_t                          size;
+       int                             copied; /* queued in tcp_connect() */
 };
 void tcp_free_fastopen_req(struct tcp_sock *tp);
 
index afa5730fb3bd2ff810f63f861f1b52b29e34c965..fb5654a8ca3cee1c65923c105f3760d607eaa1de 100644 (file)
@@ -1648,6 +1648,11 @@ static inline int xfrm_aevent_is_on(struct net *net)
 }
 #endif
 
+static inline int aead_len(struct xfrm_algo_aead *alg)
+{
+       return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
+}
+
 static inline int xfrm_alg_len(const struct xfrm_algo *alg)
 {
        return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -1686,6 +1691,12 @@ static inline int xfrm_replay_clone(struct xfrm_state *x,
        return 0;
 }
 
+static inline struct xfrm_algo_aead *xfrm_algo_aead_clone(struct xfrm_algo_aead *orig)
+{
+       return kmemdup(orig, aead_len(orig), GFP_KERNEL);
+}
+
+
 static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
 {
        return kmemdup(orig, xfrm_alg_len(orig), GFP_KERNEL);
index 8d4a1c06f7e4e9bb14c28992afbb37128fe31b56..6793f32ccb581f4313d052d7a228a0e7852e0973 100644 (file)
@@ -226,7 +226,8 @@ enum ib_port_cap_flags {
        IB_PORT_CAP_MASK_NOTICE_SUP             = 1 << 22,
        IB_PORT_BOOT_MGMT_SUP                   = 1 << 23,
        IB_PORT_LINK_LATENCY_SUP                = 1 << 24,
-       IB_PORT_CLIENT_REG_SUP                  = 1 << 25
+       IB_PORT_CLIENT_REG_SUP                  = 1 << 25,
+       IB_PORT_IP_BASED_GIDS                   = 1 << 26
 };
 
 enum ib_port_width {
index f843dd8722a97eb9ca7106c6e09f8dd43a6e903c..ef7872c20da9e5f2d16c5a950b0abd0d9e9e53b2 100644 (file)
@@ -172,7 +172,6 @@ struct sata_device {
         enum   ata_command_set command_set;
         struct smp_resp        rps_resp; /* report_phy_sata_resp */
         u8     port_no;        /* port number, if this is a PM (Port) */
-       int    pm_result;
 
        struct ata_port *ap;
        struct ata_host ata_host;
index 68d92e36facda52f6e4b249e108bd43c8847e92e..6e89ef6c11c1a42c853a8f87021bbf1244a14ffc 100644 (file)
@@ -449,14 +449,22 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
 /* dapm audio pin control and status */
 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm,
                            const char *pin);
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                    const char *pin);
 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
                             const char *pin);
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                     const char *pin);
 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin);
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                const char *pin);
 int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
                                const char *pin);
 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm);
 int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
                                  const char *pin);
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                          const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
                                const char *pin);
 void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
index ae5a17111968c7ca8bc8667a65d16393532ffbde..4483fadfa68d8fdc744743d6bc5bcd52de301608 100644 (file)
@@ -12,6 +12,7 @@ struct iscsit_transport {
        int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *);
        int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *);
        void (*iscsit_free_np)(struct iscsi_np *);
+       void (*iscsit_wait_conn)(struct iscsi_conn *);
        void (*iscsit_free_conn)(struct iscsi_conn *);
        int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *);
        int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32);
index c9c791209cd18e579c5477b6b1cbe195cba744a0..1772fadcff62aaa8ab1e3ab2b4a7aef15de87fa7 100644 (file)
@@ -525,7 +525,6 @@ struct se_cmd {
 #define CMD_T_COMPLETE         (1 << 2)
 #define CMD_T_SENT             (1 << 4)
 #define CMD_T_STOP             (1 << 5)
-#define CMD_T_FAILED           (1 << 6)
 #define CMD_T_DEV_ACTIVE       (1 << 7)
 #define CMD_T_REQUEST_STOP     (1 << 8)
 #define CMD_T_BUSY             (1 << 9)
index 9e9475c85de50ba2eb487e0903820b5845caf564..e5bf9a76f169681c356a1d14236d5e71d14bdb96 100644 (file)
@@ -42,7 +42,6 @@ TRACE_EVENT(pstate_sample,
                u32 state,
                u64 mperf,
                u64 aperf,
-               u32 energy,
                u32 freq
                ),
 
@@ -51,7 +50,6 @@ TRACE_EVENT(pstate_sample,
                state,
                mperf,
                aperf,
-               energy,
                freq
                ),
 
@@ -61,7 +59,6 @@ TRACE_EVENT(pstate_sample,
                __field(u32, state)
                __field(u64, mperf)
                __field(u64, aperf)
-               __field(u32, energy)
                __field(u32, freq)
 
        ),
@@ -72,17 +69,15 @@ TRACE_EVENT(pstate_sample,
                __entry->state = state;
                __entry->mperf = mperf;
                __entry->aperf = aperf;
-               __entry->energy = energy;
                __entry->freq = freq;
                ),
 
-       TP_printk("core_busy=%lu scaled=%lu state=%lu mperf=%llu aperf=%llu energy=%lu freq=%lu ",
+       TP_printk("core_busy=%lu scaled=%lu state=%lu mperf=%llu aperf=%llu freq=%lu ",
                (unsigned long)__entry->core_busy,
                (unsigned long)__entry->scaled_busy,
                (unsigned long)__entry->state,
                (unsigned long long)__entry->mperf,
                (unsigned long long)__entry->aperf,
-               (unsigned long)__entry->energy,
                (unsigned long)__entry->freq
                )
 
index ddc179b7a1052aa6c3fb9df408e3b5ad9e50d792..1fef3e6e943632e6b2e1619c6536bc328a81eb8f 100644 (file)
@@ -83,7 +83,7 @@ DECLARE_EVENT_CLASS(rpc_task_running,
                ),
 
        TP_fast_assign(
-               __entry->client_id = clnt->cl_clid;
+               __entry->client_id = clnt ? clnt->cl_clid : -1;
                __entry->task_id = task->tk_pid;
                __entry->action = action;
                __entry->runstate = task->tk_runstate;
@@ -91,7 +91,7 @@ DECLARE_EVENT_CLASS(rpc_task_running,
                __entry->flags = task->tk_flags;
                ),
 
-       TP_printk("task:%u@%u flags=%4.4x state=%4.4lx status=%d action=%pf",
+       TP_printk("task:%u@%d flags=%4.4x state=%4.4lx status=%d action=%pf",
                __entry->task_id, __entry->client_id,
                __entry->flags,
                __entry->runstate,
index c7bbbe794e65cdd0a41c7235bcee6e9718970876..464ea82e10dbf1f1a519b75c52f9e129a5a715e0 100644 (file)
@@ -287,11 +287,11 @@ TRACE_EVENT(writeback_queue_io,
                __field(int,            reason)
        ),
        TP_fast_assign(
-               unsigned long older_than_this = work->older_than_this;
+               unsigned long *older_than_this = work->older_than_this;
                strncpy(__entry->name, dev_name(wb->bdi->dev), 32);
-               __entry->older  = older_than_this;
+               __entry->older  = older_than_this ?  *older_than_this : 0;
                __entry->age    = older_than_this ?
-                                 (jiffies - older_than_this) * 1000 / HZ : -1;
+                                 (jiffies - *older_than_this) * 1000 / HZ : -1;
                __entry->moved  = moved;
                __entry->reason = work->reason;
        ),
index 1a8b28db37752707cb130566b6295eb3f8bc4b90..1ee19a24cc5f7170a3dab525767c669f3773dc7e 100644 (file)
@@ -310,15 +310,12 @@ static struct trace_event_functions ftrace_event_type_funcs_##call = {    \
 #undef __array
 #define __array(type, item, len)                                       \
        do {                                                            \
-               mutex_lock(&event_storage_mutex);                       \
+               char *type_str = #type"["__stringify(len)"]";           \
                BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);                 \
-               snprintf(event_storage, sizeof(event_storage),          \
-                        "%s[%d]", #type, len);                         \
-               ret = trace_define_field(event_call, event_storage, #item, \
+               ret = trace_define_field(event_call, type_str, #item,   \
                                 offsetof(typeof(field), item),         \
                                 sizeof(field.item),                    \
                                 is_signed_type(type), FILTER_OTHER);   \
-               mutex_unlock(&event_storage_mutex);                     \
                if (ret)                                                \
                        return ret;                                     \
        } while (0);
index a20a9b4d38713f5a92982457f0e8f330b0bfd58c..6db66783d268d9a286a86b836c9277bd89f5ac13 100644 (file)
@@ -191,6 +191,7 @@ __SYSCALL(__NR_quotactl, sys_quotactl)
 
 /* fs/readdir.c */
 #define __NR_getdents64 61
+#define __ARCH_WANT_COMPAT_SYS_GETDENTS64
 __SC_COMP(__NR_getdents64, sys_getdents64, compat_sys_getdents64)
 
 /* fs/read_write.c */
@@ -692,9 +693,13 @@ __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
 __SYSCALL(__NR_kcmp, sys_kcmp)
 #define __NR_finit_module 273
 __SYSCALL(__NR_finit_module, sys_finit_module)
+#define __NR_sched_setattr 274
+__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+#define __NR_sched_getattr 275
+__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
 
 #undef __NR_syscalls
-#define __NR_syscalls 274
+#define __NR_syscalls 276
 
 /*
  * All syscalls below here should go away really,
index 3c9a833992e872f095a4373d6cb5e33602129acc..b06c8ed687079759ea7e585589aac199ac288e22 100644 (file)
@@ -619,6 +619,8 @@ struct drm_gem_open {
 #define  DRM_PRIME_CAP_EXPORT          0x2
 #define DRM_CAP_TIMESTAMP_MONOTONIC    0x6
 #define DRM_CAP_ASYNC_PAGE_FLIP                0x7
+#define DRM_CAP_CURSOR_WIDTH           0x8
+#define DRM_CAP_CURSOR_HEIGHT          0x9
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
index 9971c560ed9aa42dc841e76b9586f05e25225d96..87792a5fee3bad7d143de81555a56ede7e532f1a 100644 (file)
@@ -87,6 +87,7 @@
 #define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
 #define DRM_VMW_PARAM_3D_CAPS_SIZE     8
 #define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
+#define DRM_VMW_PARAM_MAX_MOB_SIZE     10
 
 /**
  * struct drm_vmw_getparam_arg
index 1b8a0f4c95900b14e7d6f71fa54523409d3b2be6..b4d69092fbdbea488f4998c8e9fd4e158cf2465f 100644 (file)
@@ -558,7 +558,6 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code)
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64)
 #define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
                                    struct btrfs_ioctl_space_args)
-#define BTRFS_IOC_GLOBAL_RSV _IOR(BTRFS_IOCTL_MAGIC, 20, __u64)
 #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
 #define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
 #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
index 633b93cac1ed8680407119036d880e8e0a799452..e9a1d2d973b6aef256808d248d007804a689a1df 100644 (file)
@@ -128,22 +128,13 @@ struct in6_flowlabel_req {
  *     IPV6 extension headers
  */
 #if __UAPI_DEF_IPPROTO_V6
-enum {
-  IPPROTO_HOPOPTS = 0,         /* IPv6 hop-by-hop options      */
-#define IPPROTO_HOPOPTS                IPPROTO_HOPOPTS
-  IPPROTO_ROUTING = 43,                /* IPv6 routing header          */
-#define IPPROTO_ROUTING                IPPROTO_ROUTING
-  IPPROTO_FRAGMENT = 44,       /* IPv6 fragmentation header    */
-#define IPPROTO_FRAGMENT       IPPROTO_FRAGMENT
-  IPPROTO_ICMPV6 = 58,         /* ICMPv6                       */
-#define IPPROTO_ICMPV6         IPPROTO_ICMPV6
-  IPPROTO_NONE = 59,           /* IPv6 no next header          */
-#define IPPROTO_NONE           IPPROTO_NONE
-  IPPROTO_DSTOPTS = 60,                /* IPv6 destination options     */
-#define IPPROTO_DSTOPTS                IPPROTO_DSTOPTS
-  IPPROTO_MH = 135,            /* IPv6 mobility header         */
-#define IPPROTO_MH             IPPROTO_MH
-};
+#define IPPROTO_HOPOPTS                0       /* IPv6 hop-by-hop options      */
+#define IPPROTO_ROUTING                43      /* IPv6 routing header          */
+#define IPPROTO_FRAGMENT       44      /* IPv6 fragmentation header    */
+#define IPPROTO_ICMPV6         58      /* ICMPv6                       */
+#define IPPROTO_NONE           59      /* IPv6 no next header          */
+#define IPPROTO_DSTOPTS                60      /* IPv6 destination options     */
+#define IPPROTO_MH             135     /* IPv6 mobility header         */
 #endif /* __UAPI_DEF_IPPROTO_V6 */
 
 /*
index 7fabba5059cf6c362e67093b9ee37ffc4d188276..feb0b4c0814c0ff3ec93318612300d260fdf8442 100644 (file)
@@ -39,7 +39,7 @@ struct mic_copy_desc {
 #else
        struct iovec *iov;
 #endif
-       int iovcnt;
+       __u32 iovcnt;
        __u8 vr_idx;
        __u8 update_used;
        __u32 out_len;
index 989c04e0c56311c53fe75d1788699acd61621fc2..e5ab62201119938753af001c34a74c1fee9dbe22 100644 (file)
@@ -350,6 +350,16 @@ struct nvme_delete_queue {
        __u32                   rsvd11[5];
 };
 
+struct nvme_abort_cmd {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[9];
+       __le16                  sqid;
+       __u16                   cid;
+       __u32                   rsvd11[5];
+};
+
 struct nvme_download_firmware {
        __u8                    opcode;
        __u8                    flags;
@@ -384,6 +394,7 @@ struct nvme_command {
                struct nvme_download_firmware dlfw;
                struct nvme_format_cmd format;
                struct nvme_dsm_cmd dsm;
+               struct nvme_abort_cmd abort;
        };
 };
 
index 61257cb146539364bdce89c3b15eff115b81902b..5c459628e8c7492c7eaea4bf6cc75e6976438e82 100644 (file)
@@ -1,3 +1,5 @@
 # UAPI Header export list
 header-y += evtchn.h
+header-y += gntalloc.h
+header-y += gntdev.h
 header-y += privcmd.h
diff --git a/include/uapi/xen/gntalloc.h b/include/uapi/xen/gntalloc.h
new file mode 100644 (file)
index 0000000..76bd580
--- /dev/null
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * gntalloc.h
+ *
+ * Interface to /dev/xen/gntalloc.
+ *
+ * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov>
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef __LINUX_PUBLIC_GNTALLOC_H__
+#define __LINUX_PUBLIC_GNTALLOC_H__
+
+/*
+ * Allocates a new page and creates a new grant reference.
+ */
+#define IOCTL_GNTALLOC_ALLOC_GREF \
+_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_gntalloc_alloc_gref))
+struct ioctl_gntalloc_alloc_gref {
+       /* IN parameters */
+       /* The ID of the domain to be given access to the grants. */
+       uint16_t domid;
+       /* Flags for this mapping */
+       uint16_t flags;
+       /* Number of pages to map */
+       uint32_t count;
+       /* OUT parameters */
+       /* The offset to be used on a subsequent call to mmap(). */
+       uint64_t index;
+       /* The grant references of the newly created grant, one per page */
+       /* Variable size, depending on count */
+       uint32_t gref_ids[1];
+};
+
+#define GNTALLOC_FLAG_WRITABLE 1
+
+/*
+ * Deallocates the grant reference, allowing the associated page to be freed if
+ * no other domains are using it.
+ */
+#define IOCTL_GNTALLOC_DEALLOC_GREF \
+_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_gntalloc_dealloc_gref))
+struct ioctl_gntalloc_dealloc_gref {
+       /* IN parameters */
+       /* The offset returned in the map operation */
+       uint64_t index;
+       /* Number of references to unmap */
+       uint32_t count;
+};
+
+/*
+ * Sets up an unmap notification within the page, so that the other side can do
+ * cleanup if this side crashes. Required to implement cross-domain robust
+ * mutexes or close notification on communication channels.
+ *
+ * Each mapped page only supports one notification; multiple calls referring to
+ * the same page overwrite the previous notification. You must clear the
+ * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
+ * to occur.
+ */
+#define IOCTL_GNTALLOC_SET_UNMAP_NOTIFY \
+_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntalloc_unmap_notify))
+struct ioctl_gntalloc_unmap_notify {
+       /* IN parameters */
+       /* Offset in the file descriptor for a byte within the page (same as
+        * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to
+        * be cleared. Otherwise, it can be any byte in the page whose
+        * notification we are adjusting.
+        */
+       uint64_t index;
+       /* Action(s) to take on unmap */
+       uint32_t action;
+       /* Event channel to notify */
+       uint32_t event_channel_port;
+};
+
+/* Clear (set to zero) the byte specified by index */
+#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
+/* Send an interrupt on the indicated event channel */
+#define UNMAP_NOTIFY_SEND_EVENT 0x2
+
+#endif /* __LINUX_PUBLIC_GNTALLOC_H__ */
diff --git a/include/uapi/xen/gntdev.h b/include/uapi/xen/gntdev.h
new file mode 100644 (file)
index 0000000..5304bd3
--- /dev/null
@@ -0,0 +1,150 @@
+/******************************************************************************
+ * gntdev.h
+ * 
+ * Interface to /dev/xen/gntdev.
+ * 
+ * Copyright (c) 2007, D G Murray
+ * 
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __LINUX_PUBLIC_GNTDEV_H__
+#define __LINUX_PUBLIC_GNTDEV_H__
+
+struct ioctl_gntdev_grant_ref {
+       /* The domain ID of the grant to be mapped. */
+       uint32_t domid;
+       /* The grant reference of the grant to be mapped. */
+       uint32_t ref;
+};
+
+/*
+ * Inserts the grant references into the mapping table of an instance
+ * of gntdev. N.B. This does not perform the mapping, which is deferred
+ * until mmap() is called with @index as the offset.
+ */
+#define IOCTL_GNTDEV_MAP_GRANT_REF \
+_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref))
+struct ioctl_gntdev_map_grant_ref {
+       /* IN parameters */
+       /* The number of grants to be mapped. */
+       uint32_t count;
+       uint32_t pad;
+       /* OUT parameters */
+       /* The offset to be used on a subsequent call to mmap(). */
+       uint64_t index;
+       /* Variable IN parameter. */
+       /* Array of grant references, of size @count. */
+       struct ioctl_gntdev_grant_ref refs[1];
+};
+
+/*
+ * Removes the grant references from the mapping table of an instance of
+ * of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
+ * before this ioctl is called, or an error will result.
+ */
+#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
+_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref))
+struct ioctl_gntdev_unmap_grant_ref {
+       /* IN parameters */
+       /* The offset was returned by the corresponding map operation. */
+       uint64_t index;
+       /* The number of pages to be unmapped. */
+       uint32_t count;
+       uint32_t pad;
+};
+
+/*
+ * Returns the offset in the driver's address space that corresponds
+ * to @vaddr. This can be used to perform a munmap(), followed by an
+ * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by
+ * the caller. The number of pages that were allocated at the same time as
+ * @vaddr is returned in @count.
+ *
+ * N.B. Where more than one page has been mapped into a contiguous range, the
+ *      supplied @vaddr must correspond to the start of the range; otherwise
+ *      an error will result. It is only possible to munmap() the entire
+ *      contiguously-allocated range at once, and not any subrange thereof.
+ */
+#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \
+_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr))
+struct ioctl_gntdev_get_offset_for_vaddr {
+       /* IN parameters */
+       /* The virtual address of the first mapped page in a range. */
+       uint64_t vaddr;
+       /* OUT parameters */
+       /* The offset that was used in the initial mmap() operation. */
+       uint64_t offset;
+       /* The number of pages mapped in the VM area that begins at @vaddr. */
+       uint32_t count;
+       uint32_t pad;
+};
+
+/*
+ * Sets the maximum number of grants that may mapped at once by this gntdev
+ * instance.
+ *
+ * N.B. This must be called before any other ioctl is performed on the device.
+ */
+#define IOCTL_GNTDEV_SET_MAX_GRANTS \
+_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants))
+struct ioctl_gntdev_set_max_grants {
+       /* IN parameter */
+       /* The maximum number of grants that may be mapped at once. */
+       uint32_t count;
+};
+
+/*
+ * Sets up an unmap notification within the page, so that the other side can do
+ * cleanup if this side crashes. Required to implement cross-domain robust
+ * mutexes or close notification on communication channels.
+ *
+ * Each mapped page only supports one notification; multiple calls referring to
+ * the same page overwrite the previous notification. You must clear the
+ * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
+ * to occur.
+ */
+#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY \
+_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntdev_unmap_notify))
+struct ioctl_gntdev_unmap_notify {
+       /* IN parameters */
+       /* Offset in the file descriptor for a byte within the page (same as
+        * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to
+        * be cleared. Otherwise, it can be any byte in the page whose
+        * notification we are adjusting.
+        */
+       uint64_t index;
+       /* Action(s) to take on unmap */
+       uint32_t action;
+       /* Event channel to notify */
+       uint32_t event_channel_port;
+};
+
+/* Clear (set to zero) the byte specified by index */
+#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
+/* Send an interrupt on the indicated event channel */
+#define UNMAP_NOTIFY_SEND_EVENT 0x2
+
+#endif /* __LINUX_PUBLIC_GNTDEV_H__ */
diff --git a/include/xen/gntalloc.h b/include/xen/gntalloc.h
deleted file mode 100644 (file)
index 76bd580..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/******************************************************************************
- * gntalloc.h
- *
- * Interface to /dev/xen/gntalloc.
- *
- * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov>
- *
- * This file is in the public domain.
- */
-
-#ifndef __LINUX_PUBLIC_GNTALLOC_H__
-#define __LINUX_PUBLIC_GNTALLOC_H__
-
-/*
- * Allocates a new page and creates a new grant reference.
- */
-#define IOCTL_GNTALLOC_ALLOC_GREF \
-_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_gntalloc_alloc_gref))
-struct ioctl_gntalloc_alloc_gref {
-       /* IN parameters */
-       /* The ID of the domain to be given access to the grants. */
-       uint16_t domid;
-       /* Flags for this mapping */
-       uint16_t flags;
-       /* Number of pages to map */
-       uint32_t count;
-       /* OUT parameters */
-       /* The offset to be used on a subsequent call to mmap(). */
-       uint64_t index;
-       /* The grant references of the newly created grant, one per page */
-       /* Variable size, depending on count */
-       uint32_t gref_ids[1];
-};
-
-#define GNTALLOC_FLAG_WRITABLE 1
-
-/*
- * Deallocates the grant reference, allowing the associated page to be freed if
- * no other domains are using it.
- */
-#define IOCTL_GNTALLOC_DEALLOC_GREF \
-_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_gntalloc_dealloc_gref))
-struct ioctl_gntalloc_dealloc_gref {
-       /* IN parameters */
-       /* The offset returned in the map operation */
-       uint64_t index;
-       /* Number of references to unmap */
-       uint32_t count;
-};
-
-/*
- * Sets up an unmap notification within the page, so that the other side can do
- * cleanup if this side crashes. Required to implement cross-domain robust
- * mutexes or close notification on communication channels.
- *
- * Each mapped page only supports one notification; multiple calls referring to
- * the same page overwrite the previous notification. You must clear the
- * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
- * to occur.
- */
-#define IOCTL_GNTALLOC_SET_UNMAP_NOTIFY \
-_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntalloc_unmap_notify))
-struct ioctl_gntalloc_unmap_notify {
-       /* IN parameters */
-       /* Offset in the file descriptor for a byte within the page (same as
-        * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to
-        * be cleared. Otherwise, it can be any byte in the page whose
-        * notification we are adjusting.
-        */
-       uint64_t index;
-       /* Action(s) to take on unmap */
-       uint32_t action;
-       /* Event channel to notify */
-       uint32_t event_channel_port;
-};
-
-/* Clear (set to zero) the byte specified by index */
-#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
-/* Send an interrupt on the indicated event channel */
-#define UNMAP_NOTIFY_SEND_EVENT 0x2
-
-#endif /* __LINUX_PUBLIC_GNTALLOC_H__ */
diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h
deleted file mode 100644 (file)
index 5304bd3..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/******************************************************************************
- * gntdev.h
- * 
- * Interface to /dev/xen/gntdev.
- * 
- * Copyright (c) 2007, D G Murray
- * 
- * 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; or, when distributed
- * separately from the Linux kernel or incorporated into other
- * software packages, subject to the following license:
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __LINUX_PUBLIC_GNTDEV_H__
-#define __LINUX_PUBLIC_GNTDEV_H__
-
-struct ioctl_gntdev_grant_ref {
-       /* The domain ID of the grant to be mapped. */
-       uint32_t domid;
-       /* The grant reference of the grant to be mapped. */
-       uint32_t ref;
-};
-
-/*
- * Inserts the grant references into the mapping table of an instance
- * of gntdev. N.B. This does not perform the mapping, which is deferred
- * until mmap() is called with @index as the offset.
- */
-#define IOCTL_GNTDEV_MAP_GRANT_REF \
-_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref))
-struct ioctl_gntdev_map_grant_ref {
-       /* IN parameters */
-       /* The number of grants to be mapped. */
-       uint32_t count;
-       uint32_t pad;
-       /* OUT parameters */
-       /* The offset to be used on a subsequent call to mmap(). */
-       uint64_t index;
-       /* Variable IN parameter. */
-       /* Array of grant references, of size @count. */
-       struct ioctl_gntdev_grant_ref refs[1];
-};
-
-/*
- * Removes the grant references from the mapping table of an instance of
- * of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
- * before this ioctl is called, or an error will result.
- */
-#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
-_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref))
-struct ioctl_gntdev_unmap_grant_ref {
-       /* IN parameters */
-       /* The offset was returned by the corresponding map operation. */
-       uint64_t index;
-       /* The number of pages to be unmapped. */
-       uint32_t count;
-       uint32_t pad;
-};
-
-/*
- * Returns the offset in the driver's address space that corresponds
- * to @vaddr. This can be used to perform a munmap(), followed by an
- * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by
- * the caller. The number of pages that were allocated at the same time as
- * @vaddr is returned in @count.
- *
- * N.B. Where more than one page has been mapped into a contiguous range, the
- *      supplied @vaddr must correspond to the start of the range; otherwise
- *      an error will result. It is only possible to munmap() the entire
- *      contiguously-allocated range at once, and not any subrange thereof.
- */
-#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \
-_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr))
-struct ioctl_gntdev_get_offset_for_vaddr {
-       /* IN parameters */
-       /* The virtual address of the first mapped page in a range. */
-       uint64_t vaddr;
-       /* OUT parameters */
-       /* The offset that was used in the initial mmap() operation. */
-       uint64_t offset;
-       /* The number of pages mapped in the VM area that begins at @vaddr. */
-       uint32_t count;
-       uint32_t pad;
-};
-
-/*
- * Sets the maximum number of grants that may mapped at once by this gntdev
- * instance.
- *
- * N.B. This must be called before any other ioctl is performed on the device.
- */
-#define IOCTL_GNTDEV_SET_MAX_GRANTS \
-_IOC(_IOC_NONE, 'G', 3, sizeof(struct ioctl_gntdev_set_max_grants))
-struct ioctl_gntdev_set_max_grants {
-       /* IN parameter */
-       /* The maximum number of grants that may be mapped at once. */
-       uint32_t count;
-};
-
-/*
- * Sets up an unmap notification within the page, so that the other side can do
- * cleanup if this side crashes. Required to implement cross-domain robust
- * mutexes or close notification on communication channels.
- *
- * Each mapped page only supports one notification; multiple calls referring to
- * the same page overwrite the previous notification. You must clear the
- * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
- * to occur.
- */
-#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY \
-_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntdev_unmap_notify))
-struct ioctl_gntdev_unmap_notify {
-       /* IN parameters */
-       /* Offset in the file descriptor for a byte within the page (same as
-        * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to
-        * be cleared. Otherwise, it can be any byte in the page whose
-        * notification we are adjusting.
-        */
-       uint64_t index;
-       /* Action(s) to take on unmap */
-       uint32_t action;
-       /* Event channel to notify */
-       uint32_t event_channel_port;
-};
-
-/* Clear (set to zero) the byte specified by index */
-#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
-/* Send an interrupt on the indicated event channel */
-#define UNMAP_NOTIFY_SEND_EVENT 0x2
-
-#endif /* __LINUX_PUBLIC_GNTDEV_H__ */
index 7ad033dbc845eff5ce58a60dc69cf3f0bc77fe9f..a5af2a26d94f3f698072b3bf70a444bdb5da7978 100644 (file)
@@ -191,15 +191,11 @@ void gnttab_free_auto_xlat_frames(void);
 #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
 
 int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+                   struct gnttab_map_grant_ref *kmap_ops,
                    struct page **pages, unsigned int count);
-int gnttab_map_refs_userspace(struct gnttab_map_grant_ref *map_ops,
-                             struct gnttab_map_grant_ref *kmap_ops,
-                             struct page **pages, unsigned int count);
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+                     struct gnttab_map_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count);
-int gnttab_unmap_refs_userspace(struct gnttab_unmap_grant_ref *unmap_ops,
-                               struct gnttab_map_grant_ref *kunmap_ops,
-                               struct page **pages, unsigned int count);
 
 /* Perform a batch of grant map/copy operations. Retry every batch slot
  * for which the hypervisor returns GNTST_eagain. This is typically due
index ae665ac59c36b6812a0470d5a7e0124c3e13a69f..32ec05a6572f779cb735b7a9b3ca5567cd1aed8f 100644 (file)
@@ -113,13 +113,13 @@ typedef uint64_t blkif_sector_t;
  * it's less than the number provided by the backend. The indirect_grefs field
  * in blkif_request_indirect should be filled by the frontend with the
  * grant references of the pages that are holding the indirect segments.
- * This pages are filled with an array of blkif_request_segment_aligned
- * that hold the information about the segments. The number of indirect
- * pages to use is determined by the maximum number of segments
- * a indirect request contains. Every indirect page can contain a maximum
- * of 512 segments (PAGE_SIZE/sizeof(blkif_request_segment_aligned)),
- * so to calculate the number of indirect pages to use we have to do
- * ceil(indirect_segments/512).
+ * These pages are filled with an array of blkif_request_segment that hold the
+ * information about the segments. The number of indirect pages to use is
+ * determined by the number of segments an indirect request contains. Every
+ * indirect page can contain a maximum of
+ * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
+ * calculate the number of indirect pages to use we have to do
+ * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
  *
  * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
  * create the "feature-max-indirect-segments" node!
@@ -135,13 +135,12 @@ typedef uint64_t blkif_sector_t;
 
 #define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
 
-struct blkif_request_segment_aligned {
-       grant_ref_t gref;        /* reference to I/O buffer frame        */
-       /* @first_sect: first sector in frame to transfer (inclusive).   */
-       /* @last_sect: last sector in frame to transfer (inclusive).     */
-       uint8_t     first_sect, last_sect;
-       uint16_t    _pad; /* padding to make it 8 bytes, so it's cache-aligned */
-} __attribute__((__packed__));
+struct blkif_request_segment {
+               grant_ref_t gref;        /* reference to I/O buffer frame        */
+               /* @first_sect: first sector in frame to transfer (inclusive).   */
+               /* @last_sect: last sector in frame to transfer (inclusive).     */
+               uint8_t     first_sect, last_sect;
+};
 
 struct blkif_request_rw {
        uint8_t        nr_segments;  /* number of segments                   */
@@ -151,12 +150,7 @@ struct blkif_request_rw {
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
        blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-       struct blkif_request_segment {
-               grant_ref_t gref;        /* reference to I/O buffer frame        */
-               /* @first_sect: first sector in frame to transfer (inclusive).   */
-               /* @last_sect: last sector in frame to transfer (inclusive).     */
-               uint8_t     first_sect, last_sect;
-       } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+       struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 } __attribute__((__packed__));
 
 struct blkif_request_discard {
diff --git a/include/xen/interface/xencomm.h b/include/xen/interface/xencomm.h
deleted file mode 100644 (file)
index ac45e07..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Copyright (C) IBM Corp. 2006
- */
-
-#ifndef _XEN_XENCOMM_H_
-#define _XEN_XENCOMM_H_
-
-/* A xencomm descriptor is a scatter/gather list containing physical
- * addresses corresponding to a virtually contiguous memory area. The
- * hypervisor translates these physical addresses to machine addresses to copy
- * to and from the virtually contiguous area.
- */
-
-#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
-#define XENCOMM_INVALID (~0UL)
-
-struct xencomm_desc {
-    uint32_t magic;
-    uint32_t nr_addrs; /* the number of entries in address[] */
-    uint64_t address[0];
-};
-
-#endif /* _XEN_XENCOMM_H_ */
diff --git a/include/xen/xencomm.h b/include/xen/xencomm.h
deleted file mode 100644 (file)
index e43b039..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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
- *
- * Copyright (C) IBM Corp. 2006
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- *          Jerone Young <jyoung5@us.ibm.com>
- */
-
-#ifndef _LINUX_XENCOMM_H_
-#define _LINUX_XENCOMM_H_
-
-#include <xen/interface/xencomm.h>
-
-#define XENCOMM_MINI_ADDRS 3
-struct xencomm_mini {
-       struct xencomm_desc _desc;
-       uint64_t address[XENCOMM_MINI_ADDRS];
-};
-
-/* To avoid additionnal virt to phys conversion, an opaque structure is
-   presented.  */
-struct xencomm_handle;
-
-extern void xencomm_free(struct xencomm_handle *desc);
-extern struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes);
-extern struct xencomm_handle *__xencomm_map_no_alloc(void *ptr,
-                       unsigned long bytes,  struct xencomm_mini *xc_area);
-
-#if 0
-#define XENCOMM_MINI_ALIGNED(xc_desc, n)                               \
-       struct xencomm_mini xc_desc ## _base[(n)]                       \
-       __attribute__((__aligned__(sizeof(struct xencomm_mini))));      \
-       struct xencomm_mini *xc_desc = &xc_desc ## _base[0];
-#else
-/*
- * gcc bug workaround:
- * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
- * gcc doesn't handle properly stack variable with
- * __attribute__((__align__(sizeof(struct xencomm_mini))))
- */
-#define XENCOMM_MINI_ALIGNED(xc_desc, n)                               \
-       unsigned char xc_desc ## _base[((n) + 1 ) *                     \
-                                      sizeof(struct xencomm_mini)];    \
-       struct xencomm_mini *xc_desc = (struct xencomm_mini *)          \
-               ((unsigned long)xc_desc ## _base +                      \
-                (sizeof(struct xencomm_mini) -                         \
-                 ((unsigned long)xc_desc ## _base) %                   \
-                 sizeof(struct xencomm_mini)));
-#endif
-#define xencomm_map_no_alloc(ptr, bytes)                       \
-       ({ XENCOMM_MINI_ALIGNED(xc_desc, 1);                    \
-               __xencomm_map_no_alloc(ptr, bytes, xc_desc); })
-
-/* provided by architecture code: */
-extern unsigned long xencomm_vtop(unsigned long vaddr);
-
-static inline void *xencomm_pa(void *ptr)
-{
-       return (void *)xencomm_vtop((unsigned long)ptr);
-}
-
-#define xen_guest_handle(hnd)  ((hnd).p)
-
-#endif /* _LINUX_XENCOMM_H_ */
index 009a797dd24272afbe761c33f237287c9420be33..d56cb03c1b491036c981582568d780303d3ca250 100644 (file)
@@ -1387,6 +1387,13 @@ config FUTEX
          support for "fast userspace mutexes".  The resulting kernel may not
          run glibc-based applications correctly.
 
+config HAVE_FUTEX_CMPXCHG
+       bool
+       help
+         Architectures should select this if futex_atomic_cmpxchg_inatomic()
+         is implemented and always working. This removes a couple of runtime
+         checks.
+
 config EPOLL
        bool "Enable eventpoll support" if EXPERT
        default y
index 2fd9cef70ee8aa86261d8e2439b1c2a50f130925..9c7fd4c9249f2c72395fcaf2ac953f782a3e2b59 100644 (file)
@@ -561,7 +561,6 @@ asmlinkage void __init start_kernel(void)
        init_timers();
        hrtimers_init();
        softirq_init();
-       acpi_early_init();
        timekeeping_init();
        time_init();
        sched_clock_postinit();
@@ -613,6 +612,7 @@ asmlinkage void __init start_kernel(void)
        calibrate_delay();
        pidmap_init();
        anon_vma_init();
+       acpi_early_init();
 #ifdef CONFIG_X86
        if (efi_enabled(EFI_RUNTIME_SERVICES))
                efi_enter_virtual_mode();
@@ -812,7 +812,7 @@ void __init load_default_modules(void)
 static int run_init_process(const char *init_filename)
 {
        argv_init[0] = init_filename;
-       return do_execve(init_filename,
+       return do_execve(getname_kernel(init_filename),
                (const char __user *const __user *)argv_init,
                (const char __user *const __user *)envp_init);
 }
index f486b0096a67f32fe453cca13b40ad6268a76d45..98b9016cab6c84e4e86151458a5e9b8063ffc6f2 100644 (file)
@@ -430,9 +430,9 @@ COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
 }
 
 COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
-                      compat_ssize_t, msgsz, long, msgtyp, int, msgflg)
+                      compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
 {
-       return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, msgtyp,
+       return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
                         msgflg, compat_do_msg_fill);
 }
 
@@ -498,7 +498,7 @@ static inline int put_compat_msqid_ds(struct msqid64_ds *m,
        return err;
 }
 
-long compat_sys_msgctl(int first, int second, void __user *uptr)
+COMPAT_SYSCALL_DEFINE3(msgctl, int, first, int, second, void __user *, uptr)
 {
        int err, err2;
        struct msqid64_ds m64;
@@ -668,7 +668,7 @@ static inline int put_compat_shm_info(struct shm_info __user *ip,
        return err;
 }
 
-long compat_sys_shmctl(int first, int second, void __user *uptr)
+COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
 {
        void __user *p;
        struct shmid64_ds s64;
@@ -749,8 +749,9 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)
        return err;
 }
 
-long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
-               unsigned nsops, const struct compat_timespec __user *timeout)
+COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
+                      unsigned, nsops,
+                      const struct compat_timespec __user *, timeout)
 {
        struct timespec __user *ts64 = NULL;
        if (timeout) {
index 63d7c6de335bd3b4878f8f2cf65d1d9e3f7e9474..d5874729377296acc8a95cd0c27b7ab5eb903a76 100644 (file)
@@ -46,9 +46,9 @@ static inline int put_compat_mq_attr(const struct mq_attr *attr,
                | __put_user(attr->mq_curmsgs, &uattr->mq_curmsgs);
 }
 
-asmlinkage long compat_sys_mq_open(const char __user *u_name,
-                       int oflag, compat_mode_t mode,
-                       struct compat_mq_attr __user *u_attr)
+COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
+                      int, oflag, compat_mode_t, mode,
+                      struct compat_mq_attr __user *, u_attr)
 {
        void __user *p = NULL;
        if (u_attr && oflag & O_CREAT) {
@@ -78,10 +78,10 @@ static int compat_prepare_timeout(struct timespec __user **p,
        return 0;
 }
 
-asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
-                       const char __user *u_msg_ptr,
-                       size_t msg_len, unsigned int msg_prio,
-                       const struct compat_timespec __user *u_abs_timeout)
+COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
+                      const char __user *, u_msg_ptr,
+                      compat_size_t, msg_len, unsigned int, msg_prio,
+                      const struct compat_timespec __user *, u_abs_timeout)
 {
        struct timespec __user *u_ts;
 
@@ -92,10 +92,10 @@ asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
                        msg_prio, u_ts);
 }
 
-asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
-                       char __user *u_msg_ptr,
-                       size_t msg_len, unsigned int __user *u_msg_prio,
-                       const struct compat_timespec __user *u_abs_timeout)
+COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
+                      char __user *, u_msg_ptr,
+                      compat_size_t, msg_len, unsigned int __user *, u_msg_prio,
+                      const struct compat_timespec __user *, u_abs_timeout)
 {
        struct timespec __user *u_ts;
        if (compat_prepare_timeout(&u_ts, u_abs_timeout))
@@ -105,8 +105,8 @@ asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
                        u_msg_prio, u_ts);
 }
 
-asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
-                       const struct compat_sigevent __user *u_notification)
+COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
+                      const struct compat_sigevent __user *, u_notification)
 {
        struct sigevent __user *p = NULL;
        if (u_notification) {
@@ -122,9 +122,9 @@ asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
        return sys_mq_notify(mqdes, p);
 }
 
-asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes,
-                       const struct compat_mq_attr __user *u_mqstat,
-                       struct compat_mq_attr __user *u_omqstat)
+COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
+                      const struct compat_mq_attr __user *, u_mqstat,
+                      struct compat_mq_attr __user *, u_omqstat)
 {
        struct mq_attr mqstat;
        struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p));
index 383d638340b8417c8e31f53b935f8e8d833b2707..5bb8bfe671496e55b6c62df1d28922454a2a2dcf 100644 (file)
@@ -22,6 +22,16 @@ static void *get_mq(ctl_table *table)
        return which;
 }
 
+static int proc_mq_dointvec(ctl_table *table, int write,
+                           void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table mq_table;
+       memcpy(&mq_table, table, sizeof(mq_table));
+       mq_table.data = get_mq(table);
+
+       return proc_dointvec(&mq_table, write, buffer, lenp, ppos);
+}
+
 static int proc_mq_dointvec_minmax(ctl_table *table, int write,
        void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -33,12 +43,10 @@ static int proc_mq_dointvec_minmax(ctl_table *table, int write,
                                        lenp, ppos);
 }
 #else
+#define proc_mq_dointvec NULL
 #define proc_mq_dointvec_minmax NULL
 #endif
 
-static int msg_queues_limit_min = MIN_QUEUESMAX;
-static int msg_queues_limit_max = HARD_QUEUESMAX;
-
 static int msg_max_limit_min = MIN_MSGMAX;
 static int msg_max_limit_max = HARD_MSGMAX;
 
@@ -51,9 +59,7 @@ static ctl_table mq_sysctls[] = {
                .data           = &init_ipc_ns.mq_queues_max,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_mq_dointvec_minmax,
-               .extra1         = &msg_queues_limit_min,
-               .extra2         = &msg_queues_limit_max,
+               .proc_handler   = proc_mq_dointvec,
        },
        {
                .procname       = "msg_max",
index ccf1f9fd263acdfae7dc56a87bceddd3170f69d9..c3b31179122c326342597d40cd58db11d51da940 100644 (file)
@@ -433,9 +433,9 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
                error = -EACCES;
                goto out_unlock;
        }
-       if (ipc_ns->mq_queues_count >= HARD_QUEUESMAX ||
-           (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
-            !capable(CAP_SYS_RESOURCE))) {
+
+       if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
+           !capable(CAP_SYS_RESOURCE)) {
                error = -ENOSPC;
                goto out_unlock;
        }
index 245db1140ad66a2be47744f02ef0d80deea5006f..649853105a5d773d30fac9929327030cad118a67 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -901,6 +901,8 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
                return -EINVAL;
 
        if (msgflg & MSG_COPY) {
+               if ((msgflg & MSG_EXCEPT) || !(msgflg & IPC_NOWAIT))
+                       return -EINVAL;
                copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax));
                if (IS_ERR(copy))
                        return PTR_ERR(copy);
index bc010ee272b6cfec39892e6cb04b98cc06995e1a..f2a8b6246ce935e9d4ae5aeddc314e3d281c8539 100644 (file)
@@ -18,11 +18,13 @@ CFLAGS_REMOVE_cgroup-debug.o = -pg
 CFLAGS_REMOVE_irq_work.o = -pg
 endif
 
+# cond_syscall is currently not LTO compatible
+CFLAGS_sys_ni.o = $(DISABLE_LTO)
+
 obj-y += sched/
 obj-y += locking/
 obj-y += power/
 obj-y += printk/
-obj-y += cpu/
 obj-y += irq/
 obj-y += rcu/
 
@@ -93,6 +95,7 @@ obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_JUMP_LABEL) += jump_label.o
 obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
+obj-$(CONFIG_TORTURE_TEST) += torture.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
index 34c5a2310fbf9545eeff2e3fa803c8a361031bb3..95a20f3f52f1c9f35b7d6aa2cb0a8b7c05fdbc69 100644 (file)
@@ -182,7 +182,7 @@ struct audit_buffer {
 
 struct audit_reply {
        __u32 portid;
-       pid_t pid;
+       struct net *net;        
        struct sk_buff *skb;
 };
 
@@ -500,7 +500,7 @@ int audit_send_list(void *_dest)
 {
        struct audit_netlink_list *dest = _dest;
        struct sk_buff *skb;
-       struct net *net = get_net_ns_by_pid(dest->pid);
+       struct net *net = dest->net;
        struct audit_net *aunet = net_generic(net, audit_net_id);
 
        /* wait for parent to finish and send an ACK */
@@ -510,6 +510,7 @@ int audit_send_list(void *_dest)
        while ((skb = __skb_dequeue(&dest->q)) != NULL)
                netlink_unicast(aunet->nlsk, skb, dest->portid, 0);
 
+       put_net(net);
        kfree(dest);
 
        return 0;
@@ -543,7 +544,7 @@ out_kfree_skb:
 static int audit_send_reply_thread(void *arg)
 {
        struct audit_reply *reply = (struct audit_reply *)arg;
-       struct net *net = get_net_ns_by_pid(reply->pid);
+       struct net *net = reply->net;
        struct audit_net *aunet = net_generic(net, audit_net_id);
 
        mutex_lock(&audit_cmd_mutex);
@@ -552,12 +553,13 @@ static int audit_send_reply_thread(void *arg)
        /* Ignore failure. It'll only happen if the sender goes away,
           because our timeout is set to infinite. */
        netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0);
+       put_net(net);
        kfree(reply);
        return 0;
 }
 /**
  * audit_send_reply - send an audit reply message via netlink
- * @portid: netlink port to which to send reply
+ * @request_skb: skb of request we are replying to (used to target the reply)
  * @seq: sequence number
  * @type: audit message type
  * @done: done (last) flag
@@ -568,9 +570,11 @@ static int audit_send_reply_thread(void *arg)
  * Allocates an skb, builds the netlink message, and sends it to the port id.
  * No failure notifications.
  */
-static void audit_send_reply(__u32 portid, int seq, int type, int done,
+static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done,
                             int multi, const void *payload, int size)
 {
+       u32 portid = NETLINK_CB(request_skb).portid;
+       struct net *net = sock_net(NETLINK_CB(request_skb).sk);
        struct sk_buff *skb;
        struct task_struct *tsk;
        struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),
@@ -583,8 +587,8 @@ static void audit_send_reply(__u32 portid, int seq, int type, int done,
        if (!skb)
                goto out;
 
+       reply->net = get_net(net);
        reply->portid = portid;
-       reply->pid = task_pid_vnr(current);
        reply->skb = skb;
 
        tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
@@ -604,9 +608,19 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
        int err = 0;
 
        /* Only support the initial namespaces for now. */
+       /*
+        * We return ECONNREFUSED because it tricks userspace into thinking
+        * that audit was not configured into the kernel.  Lots of users
+        * configure their PAM stack (because that's what the distro does)
+        * to reject login if unable to send messages to audit.  If we return
+        * ECONNREFUSED the PAM stack thinks the kernel does not have audit
+        * configured in and will let login proceed.  If we return EPERM
+        * userspace will reject all logins.  This should be removed when we
+        * support non init namespaces!!
+        */
        if ((current_user_ns() != &init_user_ns) ||
            (task_active_pid_ns(current) != &init_pid_ns))
-               return -EPERM;
+               return -ECONNREFUSED;
 
        switch (msg_type) {
        case AUDIT_LIST:
@@ -673,8 +687,7 @@ static int audit_get_feature(struct sk_buff *skb)
 
        seq = nlmsg_hdr(skb)->nlmsg_seq;
 
-       audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0,
-                        &af, sizeof(af));
+       audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &af, sizeof(af));
 
        return 0;
 }
@@ -794,8 +807,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                s.backlog               = skb_queue_len(&audit_skb_queue);
                s.version               = AUDIT_VERSION_LATEST;
                s.backlog_wait_time     = audit_backlog_wait_time;
-               audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0,
-                                &s, sizeof(s));
+               audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
                break;
        }
        case AUDIT_SET: {
@@ -905,7 +917,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                           seq, data, nlmsg_len(nlh));
                break;
        case AUDIT_LIST_RULES:
-               err = audit_list_rules_send(NETLINK_CB(skb).portid, seq);
+               err = audit_list_rules_send(skb, seq);
                break;
        case AUDIT_TRIM:
                audit_trim_trees();
@@ -970,8 +982,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        memcpy(sig_data->ctx, ctx, len);
                        security_release_secctx(ctx, len);
                }
-               audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_SIGNAL_INFO,
-                               0, 0, sig_data, sizeof(*sig_data) + len);
+               audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
+                                sig_data, sizeof(*sig_data) + len);
                kfree(sig_data);
                break;
        case AUDIT_TTY_GET: {
@@ -983,8 +995,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                s.log_passwd = tsk->signal->audit_tty_log_passwd;
                spin_unlock(&tsk->sighand->siglock);
 
-               audit_send_reply(NETLINK_CB(skb).portid, seq,
-                                AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
+               audit_send_reply(skb, seq, AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
                break;
        }
        case AUDIT_TTY_SET: {
index 57cc64d67718903eebeab175030348df648b4f17..8df132214606f2b06e08e916196779b1aee64ad6 100644 (file)
@@ -247,7 +247,7 @@ extern void             audit_panic(const char *message);
 
 struct audit_netlink_list {
        __u32 portid;
-       pid_t pid;
+       struct net *net;
        struct sk_buff_head q;
 };
 
index 67ccf0e7cca92412f457175d5ff3e784b254966a..135944a7b28ab901a400d06fd583d831ac8167b9 100644 (file)
@@ -916,7 +916,7 @@ static int audit_tree_handle_event(struct fsnotify_group *group,
                                   struct fsnotify_mark *inode_mark,
                                   struct fsnotify_mark *vfsmount_mark,
                                   u32 mask, void *data, int data_type,
-                                  const unsigned char *file_name)
+                                  const unsigned char *file_name, u32 cookie)
 {
        return 0;
 }
index 2596fac5dcb4552a0d574decada597424df0587b..70b4554d2fbe093e4f83a045ed84705c7a9cffe0 100644 (file)
@@ -471,7 +471,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
                                    struct fsnotify_mark *inode_mark,
                                    struct fsnotify_mark *vfsmount_mark,
                                    u32 mask, void *data, int data_type,
-                                   const unsigned char *dname)
+                                   const unsigned char *dname, u32 cookie)
 {
        struct inode *inode;
        struct audit_parent *parent;
index 14a78cca384edb9cf8f36dc3f7fb5340c267c623..92062fd6cc8cec4deff933c04848782bfdcded11 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
 #include "audit.h"
 
 /*
@@ -1065,11 +1067,13 @@ int audit_rule_change(int type, __u32 portid, int seq, void *data,
 
 /**
  * audit_list_rules_send - list the audit rules
- * @portid: target portid for netlink audit messages
+ * @request_skb: skb of request we are replying to (used to target the reply)
  * @seq: netlink audit message sequence (serial) number
  */
-int audit_list_rules_send(__u32 portid, int seq)
+int audit_list_rules_send(struct sk_buff *request_skb, int seq)
 {
+       u32 portid = NETLINK_CB(request_skb).portid;
+       struct net *net = sock_net(NETLINK_CB(request_skb).sk);
        struct task_struct *tsk;
        struct audit_netlink_list *dest;
        int err = 0;
@@ -1083,8 +1087,8 @@ int audit_list_rules_send(__u32 portid, int seq)
        dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
        if (!dest)
                return -ENOMEM;
+       dest->net = get_net(net);
        dest->portid = portid;
-       dest->pid = task_pid_vnr(current);
        skb_queue_head_init(&dest->q);
 
        mutex_lock(&audit_filter_mutex);
index 10176cd5956a7ccd9c3f34093bca928a0f5b0323..7aef2f4b6c644963fb33c320c212eb856df8c69a 100644 (file)
@@ -1719,7 +1719,7 @@ void audit_putname(struct filename *name)
        struct audit_context *context = current->audit_context;
 
        BUG_ON(!context);
-       if (!context->in_syscall) {
+       if (!name->aname || !context->in_syscall) {
 #if AUDIT_DEBUG == 2
                printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n",
                       __FILE__, __LINE__, context->serial, name);
index e2f46ba37f7243c4278de77a8c8536ddc4c0aad5..0c753ddd223bf9d543dfbb2d89915a08ab537f46 100644 (file)
@@ -886,7 +886,9 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                 * per-subsystem and moved to css->id so that lookups are
                 * successful until the target css is released.
                 */
+               mutex_lock(&cgroup_mutex);
                idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+               mutex_unlock(&cgroup_mutex);
                cgrp->id = -1;
 
                call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
@@ -1566,10 +1568,10 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
                mutex_lock(&cgroup_mutex);
                mutex_lock(&cgroup_root_mutex);
 
-               root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp,
-                                          0, 1, GFP_KERNEL);
-               if (root_cgrp->id < 0)
+               ret = idr_alloc(&root->cgroup_idr, root_cgrp, 0, 1, GFP_KERNEL);
+               if (ret < 0)
                        goto unlock_drop;
+               root_cgrp->id = ret;
 
                /* Check for name clashes with existing mounts */
                ret = -EBUSY;
@@ -2763,10 +2765,7 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
         */
        update_before = cgroup_serial_nr_next;
 
-       mutex_unlock(&cgroup_mutex);
-
        /* add/rm files for all cgroups created before */
-       rcu_read_lock();
        css_for_each_descendant_pre(css, cgroup_css(root, ss)) {
                struct cgroup *cgrp = css->cgroup;
 
@@ -2775,23 +2774,19 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
 
                inode = cgrp->dentry->d_inode;
                dget(cgrp->dentry);
-               rcu_read_unlock();
-
                dput(prev);
                prev = cgrp->dentry;
 
+               mutex_unlock(&cgroup_mutex);
                mutex_lock(&inode->i_mutex);
                mutex_lock(&cgroup_mutex);
                if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
                        ret = cgroup_addrm_files(cgrp, cfts, is_add);
-               mutex_unlock(&cgroup_mutex);
                mutex_unlock(&inode->i_mutex);
-
-               rcu_read_lock();
                if (ret)
                        break;
        }
-       rcu_read_unlock();
+       mutex_unlock(&cgroup_mutex);
        dput(prev);
        deactivate_super(sb);
        return ret;
@@ -2910,9 +2905,14 @@ static void cgroup_enable_task_cg_lists(void)
                 * We should check if the process is exiting, otherwise
                 * it will race with cgroup_exit() in that the list
                 * entry won't be deleted though the process has exited.
+                * Do it while holding siglock so that we don't end up
+                * racing against cgroup_exit().
                 */
+               spin_lock_irq(&p->sighand->siglock);
                if (!(p->flags & PF_EXITING) && list_empty(&p->cg_list))
                        list_add(&p->cg_list, &task_css_set(p)->tasks);
+               spin_unlock_irq(&p->sighand->siglock);
+
                task_unlock(p);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
@@ -4112,17 +4112,17 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
 
        err = percpu_ref_init(&css->refcnt, css_release);
        if (err)
-               goto err_free;
+               goto err_free_css;
 
        init_css(css, ss, cgrp);
 
        err = cgroup_populate_dir(cgrp, 1 << ss->subsys_id);
        if (err)
-               goto err_free;
+               goto err_free_percpu_ref;
 
        err = online_css(css);
        if (err)
-               goto err_free;
+               goto err_clear_dir;
 
        dget(cgrp->dentry);
        css_get(css->parent);
@@ -4138,8 +4138,11 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
 
        return 0;
 
-err_free:
+err_clear_dir:
+       cgroup_clear_dir(css->cgroup, 1 << css->ss->subsys_id);
+err_free_percpu_ref:
        percpu_ref_cancel_init(&css->refcnt);
+err_free_css:
        ss->css_free(css);
        return err;
 }
@@ -4158,7 +4161,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        struct cgroup *cgrp;
        struct cgroup_name *name;
        struct cgroupfs_root *root = parent->root;
-       int ssid, err = 0;
+       int ssid, err;
        struct cgroup_subsys *ss;
        struct super_block *sb = root->sb;
 
@@ -4168,18 +4171,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                return -ENOMEM;
 
        name = cgroup_alloc_name(dentry);
-       if (!name)
+       if (!name) {
+               err = -ENOMEM;
                goto err_free_cgrp;
+       }
        rcu_assign_pointer(cgrp->name, name);
 
-       /*
-        * Temporarily set the pointer to NULL, so idr_find() won't return
-        * a half-baked cgroup.
-        */
-       cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
-       if (cgrp->id < 0)
-               goto err_free_name;
-
        /*
         * Only live parents can have children.  Note that the liveliness
         * check isn't strictly necessary because cgroup_mkdir() and
@@ -4189,7 +4186,17 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
         */
        if (!cgroup_lock_live_group(parent)) {
                err = -ENODEV;
-               goto err_free_id;
+               goto err_free_name;
+       }
+
+       /*
+        * Temporarily set the pointer to NULL, so idr_find() won't return
+        * a half-baked cgroup.
+        */
+       cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
+       if (cgrp->id < 0) {
+               err = -ENOMEM;
+               goto err_unlock;
        }
 
        /* Grab a reference on the superblock so the hierarchy doesn't
@@ -4221,7 +4228,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
         */
        err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
        if (err < 0)
-               goto err_unlock;
+               goto err_free_id;
        lockdep_assert_held(&dentry->d_inode->i_mutex);
 
        cgrp->serial_nr = cgroup_serial_nr_next++;
@@ -4257,12 +4264,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 
        return 0;
 
-err_unlock:
-       mutex_unlock(&cgroup_mutex);
-       /* Release the reference count that we took on the superblock */
-       deactivate_super(sb);
 err_free_id:
        idr_remove(&root->cgroup_idr, cgrp->id);
+       /* Release the reference count that we took on the superblock */
+       deactivate_super(sb);
+err_unlock:
+       mutex_unlock(&cgroup_mutex);
 err_free_name:
        kfree(rcu_dereference_raw(cgrp->name));
 err_free_cgrp:
index 0a09e481b70b6e97519841f2eebf57da2e02d851..488ff8c4cf48ec071ad6cdb824fe60af735b5c8f 100644 (file)
@@ -110,8 +110,8 @@ static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
        return 0;
 }
 
-asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
-               struct timezone __user *tz)
+COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
+                      struct timezone __user *, tz)
 {
        if (tv) {
                struct timeval ktv;
@@ -127,8 +127,8 @@ asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
        return 0;
 }
 
-asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
-               struct timezone __user *tz)
+COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
+                      struct timezone __user *, tz)
 {
        struct timespec kts;
        struct timezone ktz;
@@ -236,8 +236,8 @@ static long compat_nanosleep_restart(struct restart_block *restart)
        return ret;
 }
 
-asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
-                                    struct compat_timespec __user *rmtp)
+COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
+                      struct compat_timespec __user *, rmtp)
 {
        struct timespec tu, rmt;
        mm_segment_t oldfs;
@@ -328,7 +328,7 @@ static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
        return compat_jiffies_to_clock_t(clock_t_to_jiffies(x));
 }
 
-asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)
+COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf)
 {
        if (tbuf) {
                struct tms tms;
@@ -354,7 +354,7 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)
  * types that can be passed to put_user()/get_user().
  */
 
-asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set)
+COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set)
 {
        old_sigset_t s;
        long ret;
@@ -424,8 +424,8 @@ COMPAT_SYSCALL_DEFINE3(sigprocmask, int, how,
 
 #endif
 
-asmlinkage long compat_sys_setrlimit(unsigned int resource,
-               struct compat_rlimit __user *rlim)
+COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource,
+                      struct compat_rlimit __user *, rlim)
 {
        struct rlimit r;
 
@@ -443,8 +443,8 @@ asmlinkage long compat_sys_setrlimit(unsigned int resource,
 
 #ifdef COMPAT_RLIM_OLD_INFINITY
 
-asmlinkage long compat_sys_old_getrlimit(unsigned int resource,
-               struct compat_rlimit __user *rlim)
+COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
+                      struct compat_rlimit __user *, rlim)
 {
        struct rlimit r;
        int ret;
@@ -470,8 +470,8 @@ asmlinkage long compat_sys_old_getrlimit(unsigned int resource,
 
 #endif
 
-asmlinkage long compat_sys_getrlimit(unsigned int resource,
-               struct compat_rlimit __user *rlim)
+COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource,
+                      struct compat_rlimit __user *, rlim)
 {
        struct rlimit r;
        int ret;
@@ -596,9 +596,9 @@ static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
        return compat_get_bitmap(k, user_mask_ptr, len * 8);
 }
 
-asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
-                                            unsigned int len,
-                                            compat_ulong_t __user *user_mask_ptr)
+COMPAT_SYSCALL_DEFINE3(sched_setaffinity, compat_pid_t, pid,
+                      unsigned int, len,
+                      compat_ulong_t __user *, user_mask_ptr)
 {
        cpumask_var_t new_mask;
        int retval;
@@ -616,8 +616,8 @@ out:
        return retval;
 }
 
-asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
-                                            compat_ulong_t __user *user_mask_ptr)
+COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t,  pid, unsigned int, len,
+                      compat_ulong_t __user *, user_mask_ptr)
 {
        int ret;
        cpumask_var_t mask;
@@ -662,9 +662,9 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,
        return 0;
 }
 
-long compat_sys_timer_create(clockid_t which_clock,
-                       struct compat_sigevent __user *timer_event_spec,
-                       timer_t __user *created_timer_id)
+COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
+                      struct compat_sigevent __user *, timer_event_spec,
+                      timer_t __user *, created_timer_id)
 {
        struct sigevent __user *event = NULL;
 
@@ -680,9 +680,9 @@ long compat_sys_timer_create(clockid_t which_clock,
        return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-long compat_sys_timer_settime(timer_t timer_id, int flags,
-                         struct compat_itimerspec __user *new,
-                         struct compat_itimerspec __user *old)
+COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
+                      struct compat_itimerspec __user *, new,
+                      struct compat_itimerspec __user *, old)
 {
        long err;
        mm_segment_t oldfs;
@@ -703,8 +703,8 @@ long compat_sys_timer_settime(timer_t timer_id, int flags,
        return err;
 }
 
-long compat_sys_timer_gettime(timer_t timer_id,
-               struct compat_itimerspec __user *setting)
+COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
+                      struct compat_itimerspec __user *, setting)
 {
        long err;
        mm_segment_t oldfs;
@@ -720,8 +720,8 @@ long compat_sys_timer_gettime(timer_t timer_id,
        return err;
 }
 
-long compat_sys_clock_settime(clockid_t which_clock,
-               struct compat_timespec __user *tp)
+COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
+                      struct compat_timespec __user *, tp)
 {
        long err;
        mm_segment_t oldfs;
@@ -737,8 +737,8 @@ long compat_sys_clock_settime(clockid_t which_clock,
        return err;
 }
 
-long compat_sys_clock_gettime(clockid_t which_clock,
-               struct compat_timespec __user *tp)
+COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
+                      struct compat_timespec __user *, tp)
 {
        long err;
        mm_segment_t oldfs;
@@ -754,8 +754,8 @@ long compat_sys_clock_gettime(clockid_t which_clock,
        return err;
 }
 
-long compat_sys_clock_adjtime(clockid_t which_clock,
-               struct compat_timex __user *utp)
+COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
+                      struct compat_timex __user *, utp)
 {
        struct timex txc;
        mm_segment_t oldfs;
@@ -777,8 +777,8 @@ long compat_sys_clock_adjtime(clockid_t which_clock,
        return ret;
 }
 
-long compat_sys_clock_getres(clockid_t which_clock,
-               struct compat_timespec __user *tp)
+COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
+                      struct compat_timespec __user *, tp)
 {
        long err;
        mm_segment_t oldfs;
@@ -818,9 +818,9 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
        return err;
 }
 
-long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
-                           struct compat_timespec __user *rqtp,
-                           struct compat_timespec __user *rmtp)
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+                      struct compat_timespec __user *, rqtp,
+                      struct compat_timespec __user *, rmtp)
 {
        long err;
        mm_segment_t oldfs;
@@ -1010,7 +1010,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 
 /* compat_time_t is a 32 bit "long" and needs to get converted. */
 
-asmlinkage long compat_sys_time(compat_time_t __user * tloc)
+COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
 {
        compat_time_t i;
        struct timeval tv;
@@ -1026,7 +1026,7 @@ asmlinkage long compat_sys_time(compat_time_t __user * tloc)
        return i;
 }
 
-asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
+COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
 {
        struct timespec tv;
        int err;
@@ -1046,7 +1046,7 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
 
 #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
 
-asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp)
+COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
 {
        struct timex txc;
        int err, ret;
@@ -1065,11 +1065,11 @@ asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp)
 }
 
 #ifdef CONFIG_NUMA
-asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages,
-               compat_uptr_t __user *pages32,
-               const int __user *nodes,
-               int __user *status,
-               int flags)
+COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
+                      compat_uptr_t __user *, pages32,
+                      const int __user *, nodes,
+                      int __user *, status,
+                      int, flags)
 {
        const void __user * __user *pages;
        int i;
@@ -1085,10 +1085,10 @@ asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages,
        return sys_move_pages(pid, nr_pages, pages, nodes, status, flags);
 }
 
-asmlinkage long compat_sys_migrate_pages(compat_pid_t pid,
-                       compat_ulong_t maxnode,
-                       const compat_ulong_t __user *old_nodes,
-                       const compat_ulong_t __user *new_nodes)
+COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid,
+                      compat_ulong_t, maxnode,
+                      const compat_ulong_t __user *, old_nodes,
+                      const compat_ulong_t __user *, new_nodes)
 {
        unsigned long __user *old = NULL;
        unsigned long __user *new = NULL;
diff --git a/kernel/cpu/Makefile b/kernel/cpu/Makefile
deleted file mode 100644 (file)
index 59ab052..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-y  = idle.o
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c
deleted file mode 100644 (file)
index 277f494..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Generic entry point for the idle threads
- */
-#include <linux/sched.h>
-#include <linux/cpu.h>
-#include <linux/tick.h>
-#include <linux/mm.h>
-#include <linux/stackprotector.h>
-
-#include <asm/tlb.h>
-
-#include <trace/events/power.h>
-
-static int __read_mostly cpu_idle_force_poll;
-
-void cpu_idle_poll_ctrl(bool enable)
-{
-       if (enable) {
-               cpu_idle_force_poll++;
-       } else {
-               cpu_idle_force_poll--;
-               WARN_ON_ONCE(cpu_idle_force_poll < 0);
-       }
-}
-
-#ifdef CONFIG_GENERIC_IDLE_POLL_SETUP
-static int __init cpu_idle_poll_setup(char *__unused)
-{
-       cpu_idle_force_poll = 1;
-       return 1;
-}
-__setup("nohlt", cpu_idle_poll_setup);
-
-static int __init cpu_idle_nopoll_setup(char *__unused)
-{
-       cpu_idle_force_poll = 0;
-       return 1;
-}
-__setup("hlt", cpu_idle_nopoll_setup);
-#endif
-
-static inline int cpu_idle_poll(void)
-{
-       rcu_idle_enter();
-       trace_cpu_idle_rcuidle(0, smp_processor_id());
-       local_irq_enable();
-       while (!tif_need_resched())
-               cpu_relax();
-       trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
-       rcu_idle_exit();
-       return 1;
-}
-
-/* Weak implementations for optional arch specific functions */
-void __weak arch_cpu_idle_prepare(void) { }
-void __weak arch_cpu_idle_enter(void) { }
-void __weak arch_cpu_idle_exit(void) { }
-void __weak arch_cpu_idle_dead(void) { }
-void __weak arch_cpu_idle(void)
-{
-       cpu_idle_force_poll = 1;
-       local_irq_enable();
-}
-
-/*
- * Generic idle loop implementation
- */
-static void cpu_idle_loop(void)
-{
-       while (1) {
-               tick_nohz_idle_enter();
-
-               while (!need_resched()) {
-                       check_pgt_cache();
-                       rmb();
-
-                       if (cpu_is_offline(smp_processor_id()))
-                               arch_cpu_idle_dead();
-
-                       local_irq_disable();
-                       arch_cpu_idle_enter();
-
-                       /*
-                        * In poll mode we reenable interrupts and spin.
-                        *
-                        * Also if we detected in the wakeup from idle
-                        * path that the tick broadcast device expired
-                        * for us, we don't want to go deep idle as we
-                        * know that the IPI is going to arrive right
-                        * away
-                        */
-                       if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
-                               cpu_idle_poll();
-                       } else {
-                               if (!current_clr_polling_and_test()) {
-                                       stop_critical_timings();
-                                       rcu_idle_enter();
-                                       arch_cpu_idle();
-                                       WARN_ON_ONCE(irqs_disabled());
-                                       rcu_idle_exit();
-                                       start_critical_timings();
-                               } else {
-                                       local_irq_enable();
-                               }
-                               __current_set_polling();
-                       }
-                       arch_cpu_idle_exit();
-               }
-
-               /*
-                * Since we fell out of the loop above, we know
-                * TIF_NEED_RESCHED must be set, propagate it into
-                * PREEMPT_NEED_RESCHED.
-                *
-                * This is required because for polling idle loops we will
-                * not have had an IPI to fold the state for us.
-                */
-               preempt_set_need_resched();
-               tick_nohz_idle_exit();
-               schedule_preempt_disabled();
-       }
-}
-
-void cpu_startup_entry(enum cpuhp_state state)
-{
-       /*
-        * This #ifdef needs to die, but it's too late in the cycle to
-        * make this generic (arm and sh have never invoked the canary
-        * init for the non boot cpus!). Will be fixed in 3.11
-        */
-#ifdef CONFIG_X86
-       /*
-        * If we're the non-boot CPU, nothing set the stack canary up
-        * for us. The boot CPU already has it initialized but no harm
-        * in doing it again. This is a good place for updating it, as
-        * we wont ever return from this function (so the invalid
-        * canaries already on the stack wont ever trigger).
-        */
-       boot_init_stack_canary();
-#endif
-       __current_set_polling();
-       arch_cpu_idle_prepare();
-       cpu_idle_loop();
-}
index 4410ac6a55f1d9ae410976e3a8e7315acf88a61b..e6b1b66afe526acfa2a9ecbfc5bad9da76e8d9b4 100644 (file)
@@ -974,12 +974,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
  *    Temporarilly set tasks mems_allowed to target nodes of migration,
  *    so that the migration code can allocate pages on these nodes.
  *
- *    Call holding cpuset_mutex, so current's cpuset won't change
- *    during this call, as manage_mutex holds off any cpuset_attach()
- *    calls.  Therefore we don't need to take task_lock around the
- *    call to guarantee_online_mems(), as we know no one is changing
- *    our task's cpuset.
- *
  *    While the mm_struct we are migrating is typically from some
  *    other task, the task_struct mems_allowed that we are hacking
  *    is for our current task, which must allocate new pages for that
@@ -996,8 +990,10 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
 
        do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
 
+       rcu_read_lock();
        mems_cs = effective_nodemask_cpuset(task_cs(tsk));
        guarantee_online_mems(mems_cs, &tsk->mems_allowed);
+       rcu_read_unlock();
 }
 
 /*
@@ -2486,9 +2482,9 @@ int __cpuset_node_allowed_softwall(int node, gfp_t gfp_mask)
 
        task_lock(current);
        cs = nearest_hardwall_ancestor(task_cs(current));
+       allowed = node_isset(node, cs->mems_allowed);
        task_unlock(current);
 
-       allowed = node_isset(node, cs->mems_allowed);
        mutex_unlock(&callback_mutex);
        return allowed;
 }
index 334b3980ffc14d396e25ccb11644f7f038cbe6e4..99982a70ddade1f728e18bd1af020b3600c4b8a2 100644 (file)
@@ -1035,7 +1035,7 @@ int dbg_io_get_char(void)
  * otherwise as a quick means to stop program execution and "break" into
  * the debugger.
  */
-void kgdb_breakpoint(void)
+noinline void kgdb_breakpoint(void)
 {
        atomic_inc(&kgdb_setting_breakpoint);
        wmb(); /* Sync point before breakpoint */
index 56003c6edfd38c03e8dd523f1efb01d99bcf2e84..661951ab8ae731a5094e1a29101bb7e0797794ed 100644 (file)
@@ -231,11 +231,29 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
 #define NR_ACCUMULATED_SAMPLES 128
 static DEFINE_PER_CPU(u64, running_sample_length);
 
-void perf_sample_event_took(u64 sample_len_ns)
+static void perf_duration_warn(struct irq_work *w)
 {
+       u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
        u64 avg_local_sample_len;
        u64 local_samples_len;
+
+       local_samples_len = __get_cpu_var(running_sample_length);
+       avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
+
+       printk_ratelimited(KERN_WARNING
+                       "perf interrupt took too long (%lld > %lld), lowering "
+                       "kernel.perf_event_max_sample_rate to %d\n",
+                       avg_local_sample_len, allowed_ns >> 1,
+                       sysctl_perf_event_sample_rate);
+}
+
+static DEFINE_IRQ_WORK(perf_duration_work, perf_duration_warn);
+
+void perf_sample_event_took(u64 sample_len_ns)
+{
        u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
+       u64 avg_local_sample_len;
+       u64 local_samples_len;
 
        if (allowed_ns == 0)
                return;
@@ -263,13 +281,14 @@ void perf_sample_event_took(u64 sample_len_ns)
        sysctl_perf_event_sample_rate = max_samples_per_tick * HZ;
        perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
 
-       printk_ratelimited(KERN_WARNING
-                       "perf samples too long (%lld > %lld), lowering "
-                       "kernel.perf_event_max_sample_rate to %d\n",
-                       avg_local_sample_len, allowed_ns,
-                       sysctl_perf_event_sample_rate);
-
        update_perf_cpu_limits();
+
+       if (!irq_work_queue(&perf_duration_work)) {
+               early_printk("perf interrupt took too long (%lld > %lld), lowering "
+                            "kernel.perf_event_max_sample_rate to %d\n",
+                            avg_local_sample_len, allowed_ns >> 1,
+                            sysctl_perf_event_sample_rate);
+       }
 }
 
 static atomic64_t perf_event_id;
@@ -1714,7 +1733,7 @@ group_sched_in(struct perf_event *group_event,
               struct perf_event_context *ctx)
 {
        struct perf_event *event, *partial_group = NULL;
-       struct pmu *pmu = group_event->pmu;
+       struct pmu *pmu = ctx->pmu;
        u64 now = ctx->time;
        bool simulate = false;
 
@@ -2563,8 +2582,6 @@ static void perf_branch_stack_sched_in(struct task_struct *prev,
                if (cpuctx->ctx.nr_branch_stack > 0
                    && pmu->flush_branch_stack) {
 
-                       pmu = cpuctx->ctx.pmu;
-
                        perf_ctx_lock(cpuctx, cpuctx->task_ctx);
 
                        perf_pmu_disable(pmu);
@@ -6294,7 +6311,7 @@ static int perf_event_idx_default(struct perf_event *event)
  * Ensures all contexts with the same task_ctx_nr have the same
  * pmu_cpu_context too.
  */
-static void *find_pmu_context(int ctxn)
+static struct perf_cpu_context __percpu *find_pmu_context(int ctxn)
 {
        struct pmu *pmu;
 
@@ -7856,14 +7873,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu)
 static void __perf_event_exit_context(void *__info)
 {
        struct perf_event_context *ctx = __info;
-       struct perf_event *event, *tmp;
+       struct perf_event *event;
 
        perf_pmu_rotate_stop(ctx->pmu);
 
-       list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
-               __perf_remove_from_context(event);
-       list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
+       rcu_read_lock();
+       list_for_each_entry_rcu(event, &ctx->event_list, event_entry)
                __perf_remove_from_context(event);
+       rcu_read_unlock();
 }
 
 static void perf_event_exit_cpu_context(int cpu)
@@ -7887,11 +7904,11 @@ static void perf_event_exit_cpu(int cpu)
 {
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
+       perf_event_exit_cpu_context(cpu);
+
        mutex_lock(&swhash->hlist_mutex);
        swevent_hlist_release(swhash);
        mutex_unlock(&swhash->hlist_mutex);
-
-       perf_event_exit_cpu_context(cpu);
 }
 #else
 static inline void perf_event_exit_cpu(int cpu) { }
index 763faf037ec1cccb135b98d1deccf339f69cd2e5..d8a6446adbcbebe00410d0c8b3cef7b5bfb4b1c9 100644 (file)
@@ -36,7 +36,7 @@ extern struct exception_table_entry __start___ex_table[];
 extern struct exception_table_entry __stop___ex_table[];
 
 /* Cleared by build time tools if the table is already sorted. */
-u32 __initdata main_extable_sort_needed = 1;
+u32 __initdata __visible main_extable_sort_needed = 1;
 
 /* Sort the kernel's built-in exception table */
 void __init sort_main_extable(void)
index a17621c6cd4272182a78083e736c5972c741ed7a..332688e5e7b4c93e55f3785ceb6beb70f4b2182f 100644 (file)
@@ -237,6 +237,7 @@ void __put_task_struct(struct task_struct *tsk)
        WARN_ON(atomic_read(&tsk->usage));
        WARN_ON(tsk == current);
 
+       task_numa_free(tsk);
        security_task_free(tsk);
        exit_creds(tsk);
        delayacct_tsk_free(tsk);
index 44a1261cb9ff63a33eec42136be4794a0752a0ac..67dacaf93e56c0edb12b74a84b40da9fe596ea49 100644 (file)
  * enqueue.
  */
 
+#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
 int __read_mostly futex_cmpxchg_enabled;
+#endif
 
 /*
  * Futex flags used to encode options to functions and preserve them across
@@ -234,6 +236,7 @@ static const struct futex_q futex_q_init = {
  * waiting on a futex.
  */
 struct futex_hash_bucket {
+       atomic_t waiters;
        spinlock_t lock;
        struct plist_head chain;
 } ____cacheline_aligned_in_smp;
@@ -253,22 +256,37 @@ static inline void futex_get_mm(union futex_key *key)
        smp_mb__after_atomic_inc();
 }
 
-static inline bool hb_waiters_pending(struct futex_hash_bucket *hb)
+/*
+ * Reflects a new waiter being added to the waitqueue.
+ */
+static inline void hb_waiters_inc(struct futex_hash_bucket *hb)
 {
 #ifdef CONFIG_SMP
+       atomic_inc(&hb->waiters);
        /*
-        * Tasks trying to enter the critical region are most likely
-        * potential waiters that will be added to the plist. Ensure
-        * that wakers won't miss to-be-slept tasks in the window between
-        * the wait call and the actual plist_add.
+        * Full barrier (A), see the ordering comment above.
         */
-       if (spin_is_locked(&hb->lock))
-               return true;
-       smp_rmb(); /* Make sure we check the lock state first */
+       smp_mb__after_atomic_inc();
+#endif
+}
+
+/*
+ * Reflects a waiter being removed from the waitqueue by wakeup
+ * paths.
+ */
+static inline void hb_waiters_dec(struct futex_hash_bucket *hb)
+{
+#ifdef CONFIG_SMP
+       atomic_dec(&hb->waiters);
+#endif
+}
 
-       return !plist_head_empty(&hb->chain);
+static inline int hb_waiters_pending(struct futex_hash_bucket *hb)
+{
+#ifdef CONFIG_SMP
+       return atomic_read(&hb->waiters);
 #else
-       return true;
+       return 1;
 #endif
 }
 
@@ -954,6 +972,7 @@ static void __unqueue_futex(struct futex_q *q)
 
        hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock);
        plist_del(&q->list, &hb->chain);
+       hb_waiters_dec(hb);
 }
 
 /*
@@ -1257,7 +1276,9 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
         */
        if (likely(&hb1->chain != &hb2->chain)) {
                plist_del(&q->list, &hb1->chain);
+               hb_waiters_dec(hb1);
                plist_add(&q->list, &hb2->chain);
+               hb_waiters_inc(hb2);
                q->lock_ptr = &hb2->lock;
        }
        get_futex_key_refs(key2);
@@ -1600,6 +1621,17 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
        struct futex_hash_bucket *hb;
 
        hb = hash_futex(&q->key);
+
+       /*
+        * Increment the counter before taking the lock so that
+        * a potential waker won't miss a to-be-slept task that is
+        * waiting for the spinlock. This is safe as all queue_lock()
+        * users end up calling queue_me(). Similarly, for housekeeping,
+        * decrement the counter at queue_unlock() when some error has
+        * occurred and we don't end up adding the task to the list.
+        */
+       hb_waiters_inc(hb);
+
        q->lock_ptr = &hb->lock;
 
        spin_lock(&hb->lock); /* implies MB (A) */
@@ -1611,6 +1643,7 @@ queue_unlock(struct futex_hash_bucket *hb)
        __releases(&hb->lock)
 {
        spin_unlock(&hb->lock);
+       hb_waiters_dec(hb);
 }
 
 /**
@@ -2342,6 +2375,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
                 * Unqueue the futex_q and determine which it was.
                 */
                plist_del(&q->list, &hb->chain);
+               hb_waiters_dec(hb);
 
                /* Handle spurious wakeups gracefully */
                ret = -EWOULDBLOCK;
@@ -2843,9 +2877,28 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
        return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
 }
 
-static int __init futex_init(void)
+static void __init futex_detect_cmpxchg(void)
 {
+#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
        u32 curval;
+
+       /*
+        * This will fail and we want it. Some arch implementations do
+        * runtime detection of the futex_atomic_cmpxchg_inatomic()
+        * functionality. We want to know that before we call in any
+        * of the complex code paths. Also we want to prevent
+        * registration of robust lists in that case. NULL is
+        * guaranteed to fault and we get -EFAULT on functional
+        * implementation, the non-functional ones will return
+        * -ENOSYS.
+        */
+       if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
+               futex_cmpxchg_enabled = 1;
+#endif
+}
+
+static int __init futex_init(void)
+{
        unsigned int futex_shift;
        unsigned long i;
 
@@ -2861,20 +2914,11 @@ static int __init futex_init(void)
                                               &futex_shift, NULL,
                                               futex_hashsize, futex_hashsize);
        futex_hashsize = 1UL << futex_shift;
-       /*
-        * This will fail and we want it. Some arch implementations do
-        * runtime detection of the futex_atomic_cmpxchg_inatomic()
-        * functionality. We want to know that before we call in any
-        * of the complex code paths. Also we want to prevent
-        * registration of robust lists in that case. NULL is
-        * guaranteed to fault and we get -EFAULT on functional
-        * implementation, the non-functional ones will return
-        * -ENOSYS.
-        */
-       if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
-               futex_cmpxchg_enabled = 1;
+
+       futex_detect_cmpxchg();
 
        for (i = 0; i < futex_hashsize; i++) {
+               atomic_set(&futex_queues[i].waiters, 0);
                plist_head_init(&futex_queues[i].chain);
                spin_lock_init(&futex_queues[i].lock);
        }
index 4a1fef09f658b894ea5eef6a55cff8f55b97dd0e..07cbdfea9ae26a6584dee41cbef104c7b05ef111 100644 (file)
@@ -40,6 +40,7 @@ config IRQ_EDGE_EOI_HANDLER
 # Generic configurable interrupt chip implementation
 config GENERIC_IRQ_CHIP
        bool
+       select IRQ_DOMAIN
 
 # Generic irq_domain hw <--> linux irq number translation
 config IRQ_DOMAIN
index bd8e788d71e0dd582caa3f97602fd3b86acc21fb..1ef0606797c9c211b5b328aef7696a23b1eab652 100644 (file)
@@ -72,6 +72,51 @@ int devm_request_threaded_irq(struct device *dev, unsigned int irq,
 }
 EXPORT_SYMBOL(devm_request_threaded_irq);
 
+/**
+ *     devm_request_any_context_irq - allocate an interrupt line for a managed device
+ *     @dev: device to request interrupt for
+ *     @irq: Interrupt line to allocate
+ *     @handler: Function to be called when the IRQ occurs
+ *     @thread_fn: function to be called in a threaded interrupt context. NULL
+ *                 for devices which handle everything in @handler
+ *     @irqflags: Interrupt type flags
+ *     @devname: An ascii name for the claiming device
+ *     @dev_id: A cookie passed back to the handler function
+ *
+ *     Except for the extra @dev argument, this function takes the
+ *     same arguments and performs the same function as
+ *     request_any_context_irq().  IRQs requested with this function will be
+ *     automatically freed on driver detach.
+ *
+ *     If an IRQ allocated with this function needs to be freed
+ *     separately, devm_free_irq() must be used.
+ */
+int devm_request_any_context_irq(struct device *dev, unsigned int irq,
+                             irq_handler_t handler, unsigned long irqflags,
+                             const char *devname, void *dev_id)
+{
+       struct irq_devres *dr;
+       int rc;
+
+       dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
+                         GFP_KERNEL);
+       if (!dr)
+               return -ENOMEM;
+
+       rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
+       if (rc) {
+               devres_free(dr);
+               return rc;
+       }
+
+       dr->irq = irq;
+       dr->dev_id = dev_id;
+       devres_add(dev, dr);
+
+       return 0;
+}
+EXPORT_SYMBOL(devm_request_any_context_irq);
+
 /**
  *     devm_free_irq - free an interrupt
  *     @dev: device to free interrupt for
index 192a302d6cfd34d23d61294fed068fbc60adc858..8ab8e9390297a06ef7c4efc2a8ad502433b13879 100644 (file)
@@ -274,6 +274,7 @@ struct irq_desc *irq_to_desc(unsigned int irq)
 {
        return (irq < NR_IRQS) ? irq_desc + irq : NULL;
 }
+EXPORT_SYMBOL(irq_to_desc);
 
 static void free_desc(unsigned int irq)
 {
index cf68bb36fe5885dd2ba7b9c9ccef3c5165a320d3..f14033700c25cbc6872ccc2e60d33ee25a3493e9 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/topology.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
index 481a13c43b1708d3501a7f686760573c4eab6a34..d3bf660cb57fb8a26e55c3605dffc78ce82035f4 100644 (file)
@@ -802,8 +802,7 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc,
 
 static void wake_threads_waitq(struct irq_desc *desc)
 {
-       if (atomic_dec_and_test(&desc->threads_active) &&
-           waitqueue_active(&desc->wait_for_threads))
+       if (atomic_dec_and_test(&desc->threads_active))
                wake_up(&desc->wait_for_threads);
 }
 
index 55fcce6065cf6bc3213829fd8188cae90b61b778..a82170e2fa78e50fbefa29c6cf71b1eccadae175 100644 (file)
@@ -61,11 +61,11 @@ void __weak arch_irq_work_raise(void)
  *
  * Can be re-enqueued while the callback is still in progress.
  */
-void irq_work_queue(struct irq_work *work)
+bool irq_work_queue(struct irq_work *work)
 {
        /* Only queue if not already pending */
        if (!irq_work_claim(work))
-               return;
+               return false;
 
        /* Queue the entry and raise the IPI if needed. */
        preempt_disable();
@@ -83,6 +83,8 @@ void irq_work_queue(struct irq_work *work)
        }
 
        preempt_enable();
+
+       return true;
 }
 EXPORT_SYMBOL_GPL(irq_work_queue);
 
index 60bafbed06abd7a7b2defd0c031ca18b7287a37e..45601cf41bee0106ff37a7ef5112cfd065c4a7bc 100644 (file)
@@ -1039,10 +1039,10 @@ void __weak crash_unmap_reserved_pages(void)
 {}
 
 #ifdef CONFIG_COMPAT
-asmlinkage long compat_sys_kexec_load(unsigned long entry,
-                               unsigned long nr_segments,
-                               struct compat_kexec_segment __user *segments,
-                               unsigned long flags)
+COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
+                      compat_ulong_t, nr_segments,
+                      struct compat_kexec_segment __user *, segments,
+                      compat_ulong_t, flags)
 {
        struct compat_kexec_segment in;
        struct kexec_segment out, __user *ksegments;
index b086006c59e7c6957a51984a3ec101ea2db8525d..6b375af4958d1290c5c7a066903203802ee41d77 100644 (file)
@@ -239,7 +239,7 @@ static int ____call_usermodehelper(void *data)
 
        commit_creds(new);
 
-       retval = do_execve(sub_info->path,
+       retval = do_execve(getname_kernel(sub_info->path),
                           (const char __user *const __user *)sub_info->argv,
                           (const char __user *const __user *)sub_info->envp);
        if (!retval)
index d945a949760f0ec4a9fd09313e30fb5f651bc39a..e660964086e2e46d1066e143d29c21887f712d5d 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/sched.h>
 #include <linux/capability.h>
 
+#include <linux/rcupdate.h>    /* rcu_expedited */
+
 #define KERNEL_ATTR_RO(_name) \
 static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
 
index baab8e5e7f66acd327f71afd40fbd7530803a449..306a76b51e0f4308a1ef680e006e07333e98d3c0 100644 (file)
@@ -1,5 +1,5 @@
 
-obj-y += mutex.o semaphore.o rwsem.o lglock.o
+obj-y += mutex.o semaphore.o rwsem.o lglock.o mcs_spinlock.o
 
 ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_lockdep.o = -pg
@@ -23,3 +23,4 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
 obj-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o
+obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
index eb8a54783fa0f47bb9b51568ec9dfed3d51cc48d..b0e9467922e1a476bfe1d4d8503ac7623affcaea 100644 (file)
@@ -1936,12 +1936,12 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next)
 
        for (;;) {
                int distance = curr->lockdep_depth - depth + 1;
-               hlock = curr->held_locks + depth-1;
+               hlock = curr->held_locks + depth - 1;
                /*
                 * Only non-recursive-read entries get new dependencies
                 * added:
                 */
-               if (hlock->read != 2) {
+               if (hlock->read != 2 && hlock->check) {
                        if (!check_prev_add(curr, hlock, next,
                                                distance, trylock_loop))
                                return 0;
@@ -2098,7 +2098,7 @@ static int validate_chain(struct task_struct *curr, struct lockdep_map *lock,
         * (If lookup_chain_cache() returns with 1 it acquires
         * graph_lock for us)
         */
-       if (!hlock->trylock && (hlock->check == 2) &&
+       if (!hlock->trylock && hlock->check &&
            lookup_chain_cache(curr, hlock, chain_key)) {
                /*
                 * Check whether last held lock:
@@ -2517,7 +2517,7 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)
 
                BUG_ON(usage_bit >= LOCK_USAGE_STATES);
 
-               if (hlock_class(hlock)->key == __lockdep_no_validate__.subkeys)
+               if (!hlock->check)
                        continue;
 
                if (!mark_lock(curr, hlock, usage_bit))
@@ -2557,7 +2557,7 @@ static void __trace_hardirqs_on_caller(unsigned long ip)
        debug_atomic_inc(hardirqs_on_events);
 }
 
-void trace_hardirqs_on_caller(unsigned long ip)
+__visible void trace_hardirqs_on_caller(unsigned long ip)
 {
        time_hardirqs_on(CALLER_ADDR0, ip);
 
@@ -2610,7 +2610,7 @@ EXPORT_SYMBOL(trace_hardirqs_on);
 /*
  * Hardirqs were disabled:
  */
-void trace_hardirqs_off_caller(unsigned long ip)
+__visible void trace_hardirqs_off_caller(unsigned long ip)
 {
        struct task_struct *curr = current;
 
@@ -3055,9 +3055,6 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        int class_idx;
        u64 chain_key;
 
-       if (!prove_locking)
-               check = 1;
-
        if (unlikely(!debug_locks))
                return 0;
 
@@ -3069,8 +3066,8 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
                return 0;
 
-       if (lock->key == &__lockdep_no_validate__)
-               check = 1;
+       if (!prove_locking || lock->key == &__lockdep_no_validate__)
+               check = 0;
 
        if (subclass < NR_LOCKDEP_CACHING_CLASSES)
                class = lock->class_cache[subclass];
@@ -3138,7 +3135,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        hlock->holdtime_stamp = lockstat_clock();
 #endif
 
-       if (check == 2 && !mark_irqflags(curr, hlock))
+       if (check && !mark_irqflags(curr, hlock))
                return 0;
 
        /* mark it as used: */
@@ -4191,7 +4188,7 @@ void debug_show_held_locks(struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(debug_show_held_locks);
 
-void lockdep_sys_exit(void)
+asmlinkage void lockdep_sys_exit(void)
 {
        struct task_struct *curr = current;
 
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
new file mode 100644 (file)
index 0000000..f26b1a1
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Module-based torture test facility for locking
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2014
+ *
+ * Author: Paul E. McKenney <paulmck@us.ibm.com>
+ *     Based on kernel/rcu/torture.c.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/freezer.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/trace_clock.h>
+#include <asm/byteorder.h>
+#include <linux/torture.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>");
+
+torture_param(int, nwriters_stress, -1,
+            "Number of write-locking stress-test threads");
+torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
+torture_param(int, onoff_interval, 0,
+            "Time between CPU hotplugs (s), 0=disable");
+torture_param(int, shuffle_interval, 3,
+            "Number of jiffies between shuffles, 0=disable");
+torture_param(int, shutdown_secs, 0, "Shutdown time (j), <= zero to disable.");
+torture_param(int, stat_interval, 60,
+            "Number of seconds between stats printk()s");
+torture_param(int, stutter, 5, "Number of jiffies to run/halt test, 0=disable");
+torture_param(bool, verbose, true,
+            "Enable verbose debugging printk()s");
+
+static char *torture_type = "spin_lock";
+module_param(torture_type, charp, 0444);
+MODULE_PARM_DESC(torture_type,
+                "Type of lock to torture (spin_lock, spin_lock_irq, ...)");
+
+static atomic_t n_lock_torture_errors;
+
+static struct task_struct *stats_task;
+static struct task_struct **writer_tasks;
+
+static int nrealwriters_stress;
+static bool lock_is_write_held;
+
+struct lock_writer_stress_stats {
+       long n_write_lock_fail;
+       long n_write_lock_acquired;
+};
+static struct lock_writer_stress_stats *lwsa;
+
+#if defined(MODULE) || defined(CONFIG_LOCK_TORTURE_TEST_RUNNABLE)
+#define LOCKTORTURE_RUNNABLE_INIT 1
+#else
+#define LOCKTORTURE_RUNNABLE_INIT 0
+#endif
+int locktorture_runnable = LOCKTORTURE_RUNNABLE_INIT;
+module_param(locktorture_runnable, int, 0444);
+MODULE_PARM_DESC(locktorture_runnable, "Start locktorture at boot");
+
+/* Forward reference. */
+static void lock_torture_cleanup(void);
+
+/*
+ * Operations vector for selecting different types of tests.
+ */
+struct lock_torture_ops {
+       void (*init)(void);
+       int (*writelock)(void);
+       void (*write_delay)(struct torture_random_state *trsp);
+       void (*writeunlock)(void);
+       unsigned long flags;
+       const char *name;
+};
+
+static struct lock_torture_ops *cur_ops;
+
+/*
+ * Definitions for lock torture testing.
+ */
+
+static int torture_lock_busted_write_lock(void)
+{
+       return 0;  /* BUGGY, do not use in real life!!! */
+}
+
+static void torture_lock_busted_write_delay(struct torture_random_state *trsp)
+{
+       const unsigned long longdelay_us = 100;
+
+       /* We want a long delay occasionally to force massive contention.  */
+       if (!(torture_random(trsp) %
+             (nrealwriters_stress * 2000 * longdelay_us)))
+               mdelay(longdelay_us);
+#ifdef CONFIG_PREEMPT
+       if (!(torture_random(trsp) % (nrealwriters_stress * 20000)))
+               preempt_schedule();  /* Allow test to be preempted. */
+#endif
+}
+
+static void torture_lock_busted_write_unlock(void)
+{
+         /* BUGGY, do not use in real life!!! */
+}
+
+static struct lock_torture_ops lock_busted_ops = {
+       .writelock      = torture_lock_busted_write_lock,
+       .write_delay    = torture_lock_busted_write_delay,
+       .writeunlock    = torture_lock_busted_write_unlock,
+       .name           = "lock_busted"
+};
+
+static DEFINE_SPINLOCK(torture_spinlock);
+
+static int torture_spin_lock_write_lock(void) __acquires(torture_spinlock)
+{
+       spin_lock(&torture_spinlock);
+       return 0;
+}
+
+static void torture_spin_lock_write_delay(struct torture_random_state *trsp)
+{
+       const unsigned long shortdelay_us = 2;
+       const unsigned long longdelay_us = 100;
+
+       /* We want a short delay mostly to emulate likely code, and
+        * we want a long delay occasionally to force massive contention.
+        */
+       if (!(torture_random(trsp) %
+             (nrealwriters_stress * 2000 * longdelay_us)))
+               mdelay(longdelay_us);
+       if (!(torture_random(trsp) %
+             (nrealwriters_stress * 2 * shortdelay_us)))
+               udelay(shortdelay_us);
+#ifdef CONFIG_PREEMPT
+       if (!(torture_random(trsp) % (nrealwriters_stress * 20000)))
+               preempt_schedule();  /* Allow test to be preempted. */
+#endif
+}
+
+static void torture_spin_lock_write_unlock(void) __releases(torture_spinlock)
+{
+       spin_unlock(&torture_spinlock);
+}
+
+static struct lock_torture_ops spin_lock_ops = {
+       .writelock      = torture_spin_lock_write_lock,
+       .write_delay    = torture_spin_lock_write_delay,
+       .writeunlock    = torture_spin_lock_write_unlock,
+       .name           = "spin_lock"
+};
+
+static int torture_spin_lock_write_lock_irq(void)
+__acquires(torture_spinlock_irq)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&torture_spinlock, flags);
+       cur_ops->flags = flags;
+       return 0;
+}
+
+static void torture_lock_spin_write_unlock_irq(void)
+__releases(torture_spinlock)
+{
+       spin_unlock_irqrestore(&torture_spinlock, cur_ops->flags);
+}
+
+static struct lock_torture_ops spin_lock_irq_ops = {
+       .writelock      = torture_spin_lock_write_lock_irq,
+       .write_delay    = torture_spin_lock_write_delay,
+       .writeunlock    = torture_lock_spin_write_unlock_irq,
+       .name           = "spin_lock_irq"
+};
+
+/*
+ * Lock torture writer kthread.  Repeatedly acquires and releases
+ * the lock, checking for duplicate acquisitions.
+ */
+static int lock_torture_writer(void *arg)
+{
+       struct lock_writer_stress_stats *lwsp = arg;
+       static DEFINE_TORTURE_RANDOM(rand);
+
+       VERBOSE_TOROUT_STRING("lock_torture_writer task started");
+       set_user_nice(current, 19);
+
+       do {
+               schedule_timeout_uninterruptible(1);
+               cur_ops->writelock();
+               if (WARN_ON_ONCE(lock_is_write_held))
+                       lwsp->n_write_lock_fail++;
+               lock_is_write_held = 1;
+               lwsp->n_write_lock_acquired++;
+               cur_ops->write_delay(&rand);
+               lock_is_write_held = 0;
+               cur_ops->writeunlock();
+               stutter_wait("lock_torture_writer");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("lock_torture_writer");
+       return 0;
+}
+
+/*
+ * Create an lock-torture-statistics message in the specified buffer.
+ */
+static void lock_torture_printk(char *page)
+{
+       bool fail = 0;
+       int i;
+       long max = 0;
+       long min = lwsa[0].n_write_lock_acquired;
+       long long sum = 0;
+
+       for (i = 0; i < nrealwriters_stress; i++) {
+               if (lwsa[i].n_write_lock_fail)
+                       fail = true;
+               sum += lwsa[i].n_write_lock_acquired;
+               if (max < lwsa[i].n_write_lock_fail)
+                       max = lwsa[i].n_write_lock_fail;
+               if (min > lwsa[i].n_write_lock_fail)
+                       min = lwsa[i].n_write_lock_fail;
+       }
+       page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG);
+       page += sprintf(page,
+                       "Writes:  Total: %lld  Max/Min: %ld/%ld %s  Fail: %d %s\n",
+                       sum, max, min, max / 2 > min ? "???" : "",
+                       fail, fail ? "!!!" : "");
+       if (fail)
+               atomic_inc(&n_lock_torture_errors);
+}
+
+/*
+ * Print torture statistics.  Caller must ensure that there is only one
+ * call to this function at a given time!!!  This is normally accomplished
+ * by relying on the module system to only have one copy of the module
+ * loaded, and then by giving the lock_torture_stats kthread full control
+ * (or the init/cleanup functions when lock_torture_stats thread is not
+ * running).
+ */
+static void lock_torture_stats_print(void)
+{
+       int size = nrealwriters_stress * 200 + 8192;
+       char *buf;
+
+       buf = kmalloc(size, GFP_KERNEL);
+       if (!buf) {
+               pr_err("lock_torture_stats_print: Out of memory, need: %d",
+                      size);
+               return;
+       }
+       lock_torture_printk(buf);
+       pr_alert("%s", buf);
+       kfree(buf);
+}
+
+/*
+ * Periodically prints torture statistics, if periodic statistics printing
+ * was specified via the stat_interval module parameter.
+ *
+ * No need to worry about fullstop here, since this one doesn't reference
+ * volatile state or register callbacks.
+ */
+static int lock_torture_stats(void *arg)
+{
+       VERBOSE_TOROUT_STRING("lock_torture_stats task started");
+       do {
+               schedule_timeout_interruptible(stat_interval * HZ);
+               lock_torture_stats_print();
+               torture_shutdown_absorb("lock_torture_stats");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("lock_torture_stats");
+       return 0;
+}
+
+static inline void
+lock_torture_print_module_parms(struct lock_torture_ops *cur_ops,
+                               const char *tag)
+{
+       pr_alert("%s" TORTURE_FLAG
+                "--- %s: nwriters_stress=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n",
+                torture_type, tag, nrealwriters_stress, stat_interval, verbose,
+                shuffle_interval, stutter, shutdown_secs,
+                onoff_interval, onoff_holdoff);
+}
+
+static void lock_torture_cleanup(void)
+{
+       int i;
+
+       if (torture_cleanup())
+               return;
+
+       if (writer_tasks) {
+               for (i = 0; i < nrealwriters_stress; i++)
+                       torture_stop_kthread(lock_torture_writer,
+                                            writer_tasks[i]);
+               kfree(writer_tasks);
+               writer_tasks = NULL;
+       }
+
+       torture_stop_kthread(lock_torture_stats, stats_task);
+       lock_torture_stats_print();  /* -After- the stats thread is stopped! */
+
+       if (atomic_read(&n_lock_torture_errors))
+               lock_torture_print_module_parms(cur_ops,
+                                               "End of test: FAILURE");
+       else if (torture_onoff_failures())
+               lock_torture_print_module_parms(cur_ops,
+                                               "End of test: LOCK_HOTPLUG");
+       else
+               lock_torture_print_module_parms(cur_ops,
+                                               "End of test: SUCCESS");
+}
+
+static int __init lock_torture_init(void)
+{
+       int i;
+       int firsterr = 0;
+       static struct lock_torture_ops *torture_ops[] = {
+               &lock_busted_ops, &spin_lock_ops, &spin_lock_irq_ops,
+       };
+
+       torture_init_begin(torture_type, verbose, &locktorture_runnable);
+
+       /* Process args and tell the world that the torturer is on the job. */
+       for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
+               cur_ops = torture_ops[i];
+               if (strcmp(torture_type, cur_ops->name) == 0)
+                       break;
+       }
+       if (i == ARRAY_SIZE(torture_ops)) {
+               pr_alert("lock-torture: invalid torture type: \"%s\"\n",
+                        torture_type);
+               pr_alert("lock-torture types:");
+               for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
+                       pr_alert(" %s", torture_ops[i]->name);
+               pr_alert("\n");
+               torture_init_end();
+               return -EINVAL;
+       }
+       if (cur_ops->init)
+               cur_ops->init(); /* no "goto unwind" prior to this point!!! */
+
+       if (nwriters_stress >= 0)
+               nrealwriters_stress = nwriters_stress;
+       else
+               nrealwriters_stress = 2 * num_online_cpus();
+       lock_torture_print_module_parms(cur_ops, "Start of test");
+
+       /* Initialize the statistics so that each run gets its own numbers. */
+
+       lock_is_write_held = 0;
+       lwsa = kmalloc(sizeof(*lwsa) * nrealwriters_stress, GFP_KERNEL);
+       if (lwsa == NULL) {
+               VERBOSE_TOROUT_STRING("lwsa: Out of memory");
+               firsterr = -ENOMEM;
+               goto unwind;
+       }
+       for (i = 0; i < nrealwriters_stress; i++) {
+               lwsa[i].n_write_lock_fail = 0;
+               lwsa[i].n_write_lock_acquired = 0;
+       }
+
+       /* Start up the kthreads. */
+
+       if (onoff_interval > 0) {
+               firsterr = torture_onoff_init(onoff_holdoff * HZ,
+                                             onoff_interval * HZ);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (shuffle_interval > 0) {
+               firsterr = torture_shuffle_init(shuffle_interval);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (shutdown_secs > 0) {
+               firsterr = torture_shutdown_init(shutdown_secs,
+                                                lock_torture_cleanup);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (stutter > 0) {
+               firsterr = torture_stutter_init(stutter);
+               if (firsterr)
+                       goto unwind;
+       }
+
+       writer_tasks = kzalloc(nrealwriters_stress * sizeof(writer_tasks[0]),
+                              GFP_KERNEL);
+       if (writer_tasks == NULL) {
+               VERBOSE_TOROUT_ERRSTRING("writer_tasks: Out of memory");
+               firsterr = -ENOMEM;
+               goto unwind;
+       }
+       for (i = 0; i < nrealwriters_stress; i++) {
+               firsterr = torture_create_kthread(lock_torture_writer, &lwsa[i],
+                                                 writer_tasks[i]);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (stat_interval > 0) {
+               firsterr = torture_create_kthread(lock_torture_stats, NULL,
+                                                 stats_task);
+               if (firsterr)
+                       goto unwind;
+       }
+       torture_init_end();
+       return 0;
+
+unwind:
+       torture_init_end();
+       lock_torture_cleanup();
+       return firsterr;
+}
+
+module_init(lock_torture_init);
+module_exit(lock_torture_cleanup);
diff --git a/kernel/locking/mcs_spinlock.c b/kernel/locking/mcs_spinlock.c
new file mode 100644 (file)
index 0000000..838dc9e
--- /dev/null
@@ -0,0 +1,178 @@
+
+#include <linux/percpu.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include "mcs_spinlock.h"
+
+#ifdef CONFIG_SMP
+
+/*
+ * An MCS like lock especially tailored for optimistic spinning for sleeping
+ * lock implementations (mutex, rwsem, etc).
+ *
+ * Using a single mcs node per CPU is safe because sleeping locks should not be
+ * called from interrupt context and we have preemption disabled while
+ * spinning.
+ */
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct optimistic_spin_queue, osq_node);
+
+/*
+ * Get a stable @node->next pointer, either for unlock() or unqueue() purposes.
+ * Can return NULL in case we were the last queued and we updated @lock instead.
+ */
+static inline struct optimistic_spin_queue *
+osq_wait_next(struct optimistic_spin_queue **lock,
+             struct optimistic_spin_queue *node,
+             struct optimistic_spin_queue *prev)
+{
+       struct optimistic_spin_queue *next = NULL;
+
+       for (;;) {
+               if (*lock == node && cmpxchg(lock, node, prev) == node) {
+                       /*
+                        * We were the last queued, we moved @lock back. @prev
+                        * will now observe @lock and will complete its
+                        * unlock()/unqueue().
+                        */
+                       break;
+               }
+
+               /*
+                * We must xchg() the @node->next value, because if we were to
+                * leave it in, a concurrent unlock()/unqueue() from
+                * @node->next might complete Step-A and think its @prev is
+                * still valid.
+                *
+                * If the concurrent unlock()/unqueue() wins the race, we'll
+                * wait for either @lock to point to us, through its Step-B, or
+                * wait for a new @node->next from its Step-C.
+                */
+               if (node->next) {
+                       next = xchg(&node->next, NULL);
+                       if (next)
+                               break;
+               }
+
+               arch_mutex_cpu_relax();
+       }
+
+       return next;
+}
+
+bool osq_lock(struct optimistic_spin_queue **lock)
+{
+       struct optimistic_spin_queue *node = this_cpu_ptr(&osq_node);
+       struct optimistic_spin_queue *prev, *next;
+
+       node->locked = 0;
+       node->next = NULL;
+
+       node->prev = prev = xchg(lock, node);
+       if (likely(prev == NULL))
+               return true;
+
+       ACCESS_ONCE(prev->next) = node;
+
+       /*
+        * Normally @prev is untouchable after the above store; because at that
+        * moment unlock can proceed and wipe the node element from stack.
+        *
+        * However, since our nodes are static per-cpu storage, we're
+        * guaranteed their existence -- this allows us to apply
+        * cmpxchg in an attempt to undo our queueing.
+        */
+
+       while (!smp_load_acquire(&node->locked)) {
+               /*
+                * If we need to reschedule bail... so we can block.
+                */
+               if (need_resched())
+                       goto unqueue;
+
+               arch_mutex_cpu_relax();
+       }
+       return true;
+
+unqueue:
+       /*
+        * Step - A  -- stabilize @prev
+        *
+        * Undo our @prev->next assignment; this will make @prev's
+        * unlock()/unqueue() wait for a next pointer since @lock points to us
+        * (or later).
+        */
+
+       for (;;) {
+               if (prev->next == node &&
+                   cmpxchg(&prev->next, node, NULL) == node)
+                       break;
+
+               /*
+                * We can only fail the cmpxchg() racing against an unlock(),
+                * in which case we should observe @node->locked becomming
+                * true.
+                */
+               if (smp_load_acquire(&node->locked))
+                       return true;
+
+               arch_mutex_cpu_relax();
+
+               /*
+                * Or we race against a concurrent unqueue()'s step-B, in which
+                * case its step-C will write us a new @node->prev pointer.
+                */
+               prev = ACCESS_ONCE(node->prev);
+       }
+
+       /*
+        * Step - B -- stabilize @next
+        *
+        * Similar to unlock(), wait for @node->next or move @lock from @node
+        * back to @prev.
+        */
+
+       next = osq_wait_next(lock, node, prev);
+       if (!next)
+               return false;
+
+       /*
+        * Step - C -- unlink
+        *
+        * @prev is stable because its still waiting for a new @prev->next
+        * pointer, @next is stable because our @node->next pointer is NULL and
+        * it will wait in Step-A.
+        */
+
+       ACCESS_ONCE(next->prev) = prev;
+       ACCESS_ONCE(prev->next) = next;
+
+       return false;
+}
+
+void osq_unlock(struct optimistic_spin_queue **lock)
+{
+       struct optimistic_spin_queue *node = this_cpu_ptr(&osq_node);
+       struct optimistic_spin_queue *next;
+
+       /*
+        * Fast path for the uncontended case.
+        */
+       if (likely(cmpxchg(lock, node, NULL) == node))
+               return;
+
+       /*
+        * Second most likely case.
+        */
+       next = xchg(&node->next, NULL);
+       if (next) {
+               ACCESS_ONCE(next->locked) = 1;
+               return;
+       }
+
+       next = osq_wait_next(lock, node, NULL);
+       if (next)
+               ACCESS_ONCE(next->locked) = 1;
+}
+
+#endif
+
diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h
new file mode 100644 (file)
index 0000000..a2dbac4
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * MCS lock defines
+ *
+ * This file contains the main data structure and API definitions of MCS lock.
+ *
+ * The MCS lock (proposed by Mellor-Crummey and Scott) is a simple spin-lock
+ * with the desirable properties of being fair, and with each cpu trying
+ * to acquire the lock spinning on a local variable.
+ * It avoids expensive cache bouncings that common test-and-set spin-lock
+ * implementations incur.
+ */
+#ifndef __LINUX_MCS_SPINLOCK_H
+#define __LINUX_MCS_SPINLOCK_H
+
+#include <asm/mcs_spinlock.h>
+
+struct mcs_spinlock {
+       struct mcs_spinlock *next;
+       int locked; /* 1 if lock acquired */
+};
+
+#ifndef arch_mcs_spin_lock_contended
+/*
+ * Using smp_load_acquire() provides a memory barrier that ensures
+ * subsequent operations happen after the lock is acquired.
+ */
+#define arch_mcs_spin_lock_contended(l)                                        \
+do {                                                                   \
+       while (!(smp_load_acquire(l)))                                  \
+               arch_mutex_cpu_relax();                                 \
+} while (0)
+#endif
+
+#ifndef arch_mcs_spin_unlock_contended
+/*
+ * smp_store_release() provides a memory barrier to ensure all
+ * operations in the critical section has been completed before
+ * unlocking.
+ */
+#define arch_mcs_spin_unlock_contended(l)                              \
+       smp_store_release((l), 1)
+#endif
+
+/*
+ * Note: the smp_load_acquire/smp_store_release pair is not
+ * sufficient to form a full memory barrier across
+ * cpus for many architectures (except x86) for mcs_unlock and mcs_lock.
+ * For applications that need a full barrier across multiple cpus
+ * with mcs_unlock and mcs_lock pair, smp_mb__after_unlock_lock() should be
+ * used after mcs_lock.
+ */
+
+/*
+ * In order to acquire the lock, the caller should declare a local node and
+ * pass a reference of the node to this function in addition to the lock.
+ * If the lock has already been acquired, then this will proceed to spin
+ * on this node->locked until the previous lock holder sets the node->locked
+ * in mcs_spin_unlock().
+ *
+ * We don't inline mcs_spin_lock() so that perf can correctly account for the
+ * time spent in this lock function.
+ */
+static inline
+void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
+{
+       struct mcs_spinlock *prev;
+
+       /* Init node */
+       node->locked = 0;
+       node->next   = NULL;
+
+       prev = xchg(lock, node);
+       if (likely(prev == NULL)) {
+               /*
+                * Lock acquired, don't need to set node->locked to 1. Threads
+                * only spin on its own node->locked value for lock acquisition.
+                * However, since this thread can immediately acquire the lock
+                * and does not proceed to spin on its own node->locked, this
+                * value won't be used. If a debug mode is needed to
+                * audit lock status, then set node->locked value here.
+                */
+               return;
+       }
+       ACCESS_ONCE(prev->next) = node;
+
+       /* Wait until the lock holder passes the lock down. */
+       arch_mcs_spin_lock_contended(&node->locked);
+}
+
+/*
+ * Releases the lock. The caller should pass in the corresponding node that
+ * was used to acquire the lock.
+ */
+static inline
+void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
+{
+       struct mcs_spinlock *next = ACCESS_ONCE(node->next);
+
+       if (likely(!next)) {
+               /*
+                * Release the lock by setting it to NULL
+                */
+               if (likely(cmpxchg(lock, node, NULL) == node))
+                       return;
+               /* Wait until the next pointer is set */
+               while (!(next = ACCESS_ONCE(node->next)))
+                       arch_mutex_cpu_relax();
+       }
+
+       /* Pass lock to next waiter. */
+       arch_mcs_spin_unlock_contended(&next->locked);
+}
+
+/*
+ * Cancellable version of the MCS lock above.
+ *
+ * Intended for adaptive spinning of sleeping locks:
+ * mutex_lock()/rwsem_down_{read,write}() etc.
+ */
+
+struct optimistic_spin_queue {
+       struct optimistic_spin_queue *next, *prev;
+       int locked; /* 1 if lock acquired */
+};
+
+extern bool osq_lock(struct optimistic_spin_queue **lock);
+extern void osq_unlock(struct optimistic_spin_queue **lock);
+
+#endif /* __LINUX_MCS_SPINLOCK_H */
index faf6f5b53e775eefbc7ee4ea734ff0998be68d01..e1191c996c59cbe3b3d2aecb7b54fd570cef17b6 100644 (file)
@@ -83,6 +83,12 @@ void debug_mutex_unlock(struct mutex *lock)
 
        DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
        mutex_clear_owner(lock);
+
+       /*
+        * __mutex_slowpath_needs_to_unlock() is explicitly 0 for debug
+        * mutexes so that we can do it here after we've verified state.
+        */
+       atomic_set(&lock->count, 1);
 }
 
 void debug_mutex_init(struct mutex *lock, const char *name,
index 4dd6e4c219de9316593b61daae8e17cf8dc5d874..bc73d33c6760e174fd1bb2c8319c0faf5abc221f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/debug_locks.h>
+#include "mcs_spinlock.h"
 
 /*
  * In the DEBUG case we are using the "NULL fastpath" for mutexes,
 #ifdef CONFIG_DEBUG_MUTEXES
 # include "mutex-debug.h"
 # include <asm-generic/mutex-null.h>
+/*
+ * Must be 0 for the debug case so we do not do the unlock outside of the
+ * wait_lock region. debug_mutex_unlock() will do the actual unlock in this
+ * case.
+ */
+# undef __mutex_slowpath_needs_to_unlock
+# define  __mutex_slowpath_needs_to_unlock()   0
 #else
 # include "mutex.h"
 # include <asm/mutex.h>
@@ -52,7 +60,7 @@ __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
        INIT_LIST_HEAD(&lock->wait_list);
        mutex_clear_owner(lock);
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-       lock->spin_mlock = NULL;
+       lock->osq = NULL;
 #endif
 
        debug_mutex_init(lock, name, key);
@@ -67,8 +75,7 @@ EXPORT_SYMBOL(__mutex_init);
  * We also put the fastpath first in the kernel image, to make sure the
  * branch is predicted by the CPU as default-untaken.
  */
-static __used noinline void __sched
-__mutex_lock_slowpath(atomic_t *lock_count);
+__visible void __sched __mutex_lock_slowpath(atomic_t *lock_count);
 
 /**
  * mutex_lock - acquire the mutex
@@ -111,54 +118,7 @@ EXPORT_SYMBOL(mutex_lock);
  * more or less simultaneously, the spinners need to acquire a MCS lock
  * first before spinning on the owner field.
  *
- * We don't inline mspin_lock() so that perf can correctly account for the
- * time spent in this lock function.
  */
-struct mspin_node {
-       struct mspin_node *next ;
-       int               locked;       /* 1 if lock acquired */
-};
-#define        MLOCK(mutex)    ((struct mspin_node **)&((mutex)->spin_mlock))
-
-static noinline
-void mspin_lock(struct mspin_node **lock, struct mspin_node *node)
-{
-       struct mspin_node *prev;
-
-       /* Init node */
-       node->locked = 0;
-       node->next   = NULL;
-
-       prev = xchg(lock, node);
-       if (likely(prev == NULL)) {
-               /* Lock acquired */
-               node->locked = 1;
-               return;
-       }
-       ACCESS_ONCE(prev->next) = node;
-       smp_wmb();
-       /* Wait until the lock holder passes the lock down */
-       while (!ACCESS_ONCE(node->locked))
-               arch_mutex_cpu_relax();
-}
-
-static void mspin_unlock(struct mspin_node **lock, struct mspin_node *node)
-{
-       struct mspin_node *next = ACCESS_ONCE(node->next);
-
-       if (likely(!next)) {
-               /*
-                * Release the lock by setting it to NULL
-                */
-               if (cmpxchg(lock, node, NULL) == node)
-                       return;
-               /* Wait until the next pointer is set */
-               while (!(next = ACCESS_ONCE(node->next)))
-                       arch_mutex_cpu_relax();
-       }
-       ACCESS_ONCE(next->locked) = 1;
-       smp_wmb();
-}
 
 /*
  * Mutex spinning code migrated from kernel/sched/core.c
@@ -212,6 +172,9 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock)
        struct task_struct *owner;
        int retval = 1;
 
+       if (need_resched())
+               return 0;
+
        rcu_read_lock();
        owner = ACCESS_ONCE(lock->owner);
        if (owner)
@@ -225,7 +188,8 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock)
 }
 #endif
 
-static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
+__visible __used noinline
+void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
 
 /**
  * mutex_unlock - release the mutex
@@ -446,9 +410,11 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
        if (!mutex_can_spin_on_owner(lock))
                goto slowpath;
 
+       if (!osq_lock(&lock->osq))
+               goto slowpath;
+
        for (;;) {
                struct task_struct *owner;
-               struct mspin_node  node;
 
                if (use_ww_ctx && ww_ctx->acquired > 0) {
                        struct ww_mutex *ww;
@@ -463,19 +429,16 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                         * performed the optimistic spinning cannot be done.
                         */
                        if (ACCESS_ONCE(ww->ctx))
-                               goto slowpath;
+                               break;
                }
 
                /*
                 * If there's an owner, wait for it to either
                 * release the lock or go to sleep.
                 */
-               mspin_lock(MLOCK(lock), &node);
                owner = ACCESS_ONCE(lock->owner);
-               if (owner && !mutex_spin_on_owner(lock, owner)) {
-                       mspin_unlock(MLOCK(lock), &node);
-                       goto slowpath;
-               }
+               if (owner && !mutex_spin_on_owner(lock, owner))
+                       break;
 
                if ((atomic_read(&lock->count) == 1) &&
                    (atomic_cmpxchg(&lock->count, 1, 0) == 1)) {
@@ -488,11 +451,10 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                        }
 
                        mutex_set_owner(lock);
-                       mspin_unlock(MLOCK(lock), &node);
+                       osq_unlock(&lock->osq);
                        preempt_enable();
                        return 0;
                }
-               mspin_unlock(MLOCK(lock), &node);
 
                /*
                 * When there's no owner, we might have preempted between the
@@ -501,7 +463,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                 * the owner complete.
                 */
                if (!owner && (need_resched() || rt_task(task)))
-                       goto slowpath;
+                       break;
 
                /*
                 * The cpu_relax() call is a compiler barrier which forces
@@ -511,7 +473,15 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                 */
                arch_mutex_cpu_relax();
        }
+       osq_unlock(&lock->osq);
 slowpath:
+       /*
+        * If we fell out of the spin path because of need_resched(),
+        * reschedule now, before we try-lock the mutex. This avoids getting
+        * scheduled out right after we obtained the mutex.
+        */
+       if (need_resched())
+               schedule_preempt_disabled();
 #endif
        spin_lock_mutex(&lock->wait_lock, flags);
 
@@ -717,10 +687,6 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
        struct mutex *lock = container_of(lock_count, struct mutex, count);
        unsigned long flags;
 
-       spin_lock_mutex(&lock->wait_lock, flags);
-       mutex_release(&lock->dep_map, nested, _RET_IP_);
-       debug_mutex_unlock(lock);
-
        /*
         * some architectures leave the lock unlocked in the fastpath failure
         * case, others need to leave it locked. In the later case we have to
@@ -729,6 +695,10 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
        if (__mutex_slowpath_needs_to_unlock())
                atomic_set(&lock->count, 1);
 
+       spin_lock_mutex(&lock->wait_lock, flags);
+       mutex_release(&lock->dep_map, nested, _RET_IP_);
+       debug_mutex_unlock(lock);
+
        if (!list_empty(&lock->wait_list)) {
                /* get the first entry from the wait-list: */
                struct mutex_waiter *waiter =
@@ -746,7 +716,7 @@ __mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
 /*
  * Release the lock, slowpath:
  */
-static __used noinline void
+__visible void
 __mutex_unlock_slowpath(atomic_t *lock_count)
 {
        __mutex_unlock_common_slowpath(lock_count, 1);
@@ -803,7 +773,7 @@ int __sched mutex_lock_killable(struct mutex *lock)
 }
 EXPORT_SYMBOL(mutex_lock_killable);
 
-static __used noinline void __sched
+__visible void __sched
 __mutex_lock_slowpath(atomic_t *lock_count)
 {
        struct mutex *lock = container_of(lock_count, struct mutex, count);
index 2e960a2bab81a06ae90d7c48edba6a670d16ebaf..aa4dff04b594c2b058ba2193ef44644ff8dd54dc 100644 (file)
@@ -212,6 +212,18 @@ struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
        return task_top_pi_waiter(task)->task;
 }
 
+/*
+ * Called by sched_setscheduler() to check whether the priority change
+ * is overruled by a possible priority boosting.
+ */
+int rt_mutex_check_prio(struct task_struct *task, int newprio)
+{
+       if (!task_has_pi_waiters(task))
+               return 0;
+
+       return task_top_pi_waiter(task)->task->prio <= newprio;
+}
+
 /*
  * Adjust the priority of a task, after its pi_waiters got modified.
  *
index 19c5fa95e0b4d7d06587d5fc5feb2ff0295f1efe..1d66e08e897d166cf70bc2f41cdc3c3bbb57cf45 100644 (file)
@@ -143,6 +143,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, enum rwsem_wake_type wake_type)
 /*
  * wait for the read lock to be granted
  */
+__visible
 struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
 {
        long count, adjustment = -RWSEM_ACTIVE_READ_BIAS;
@@ -190,6 +191,7 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
 /*
  * wait until we successfully acquire the write lock
  */
+__visible
 struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
 {
        long count, adjustment = -RWSEM_ACTIVE_WRITE_BIAS;
@@ -252,6 +254,7 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
  * handle waking up a waiter on the semaphore
  * - up_read/up_write has decremented the active part of count if we come here
  */
+__visible
 struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
 {
        unsigned long flags;
@@ -272,6 +275,7 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
  * - caller incremented waiting part of count and discovered it still negative
  * - just wake up any readers at the front of the queue
  */
+__visible
 struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
 {
        unsigned long flags;
index d24fcf29cb64c16029857a89dbcdeaa1ef9d724a..8dc7f5e80dd8f75273ef15df03a14615de1579d4 100644 (file)
@@ -1015,7 +1015,7 @@ static size_t module_flags_taint(struct module *mod, char *buf)
                buf[l++] = 'C';
        /*
         * TAINT_FORCED_RMMOD: could be added.
-        * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
+        * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
         * apply to modules.
         */
        return l;
@@ -1948,6 +1948,10 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
 
                switch (sym[i].st_shndx) {
                case SHN_COMMON:
+                       /* Ignore common symbols */
+                       if (!strncmp(name, "__gnu_lto", 9))
+                               break;
+
                        /* We compiled with -fno-common.  These are not
                           supposed to happen.  */
                        pr_debug("Common symbol: %s\n", name);
index 2d5cc4ccff7f4b79f734bf12ea769fb14a2346b2..db4c8b08a50cef986f48f0e537f1b622d4e8b19a 100644 (file)
@@ -309,7 +309,7 @@ int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
         * racy then it does not matter what the result of the test
         * is, we re-check the list after having taken the lock anyway:
         */
-       if (rcu_dereference_raw(nh->head)) {
+       if (rcu_access_pointer(nh->head)) {
                down_read(&nh->rwsem);
                ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
                                        nr_calls);
index 6d6300375090e7b2345353174d85ed09f6f35ce4..cca8a913ae7c8d6314fda34a1f3853a364e32cfd 100644 (file)
@@ -199,7 +199,7 @@ struct tnt {
 static const struct tnt tnts[] = {
        { TAINT_PROPRIETARY_MODULE,     'P', 'G' },
        { TAINT_FORCED_MODULE,          'F', ' ' },
-       { TAINT_UNSAFE_SMP,             'S', ' ' },
+       { TAINT_CPU_OUT_OF_SPEC,        'S', ' ' },
        { TAINT_FORCED_RMMOD,           'R', ' ' },
        { TAINT_MACHINE_CHECK,          'M', ' ' },
        { TAINT_BAD_PAGE,               'B', ' ' },
@@ -459,7 +459,7 @@ EXPORT_SYMBOL(warn_slowpath_null);
  * Called when gcc's -fstack-protector feature is used, and
  * gcc detects corruption of the on-stack canary value
  */
-void __stack_chk_fail(void)
+__visible void __stack_chk_fail(void)
 {
        panic("stack-protector: Kernel stack is corrupted in: %p\n",
                __builtin_return_address(0));
index eacb8bd8cab4e1205230ecfdde12483be9846cf7..aba9c545a0e3940481f3b5ce54221906edb760e2 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kbd_kern.h>
 #include <linux/vt.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "power.h"
 
 #define SUSPEND_CONSOLE        (MAX_NR_CONSOLES-1)
index b1d255f041351779dacb5341dbcb0c0c4a09fb87..4dae9cbe9259f6a80712589370a39c705132f631 100644 (file)
@@ -1076,7 +1076,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                next_seq = log_next_seq;
 
                len = 0;
-               prev = 0;
                while (len >= 0 && seq < next_seq) {
                        struct printk_log *msg = log_from_idx(idx);
                        int textlen;
@@ -2788,7 +2787,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        next_idx = idx;
 
        l = 0;
-       prev = 0;
        while (seq < dumper->next_seq) {
                struct printk_log *msg = log_from_idx(idx);
 
index 6631e1ef55ab0970f095b42ec350982abd8d9678..ebdd9c1a86b4dfd7840df57c64f13f72a1401156 100644 (file)
@@ -549,14 +549,14 @@ static int create_hash_tables(void)
                struct page *page;
 
                page = alloc_pages_exact_node(node,
-                               GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+                               GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
                                0);
                if (!page)
                        goto out_cleanup;
                per_cpu(cpu_profile_hits, cpu)[1]
                                = (struct profile_hit *)page_address(page);
                page = alloc_pages_exact_node(node,
-                               GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+                               GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE,
                                0);
                if (!page)
                        goto out_cleanup;
index 1f4bcb3cc21cee5bcfd1b4e13a77eeff2af23a2b..adf98622cb32bdf0b995d25ca0c4477c098e9bcc 100644 (file)
@@ -1180,8 +1180,8 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
        return ret;
 }
 
-asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
-                                 compat_long_t addr, compat_long_t data)
+COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid,
+                      compat_long_t, addr, compat_long_t, data)
 {
        struct task_struct *child;
        long ret;
index 01e9ec37a3e39af2d7e5d889a770b099dc1eb473..807ccfbf69b3359fe85b736efd14d7050e5e4990 100644 (file)
@@ -1,5 +1,5 @@
 obj-y += update.o srcu.o
-obj-$(CONFIG_RCU_TORTURE_TEST) += torture.o
+obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_TREE_RCU) += tree.o
 obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
index 79c3877e9c5b83e089ef319a2e72a9aaddde6fa3..bfda2726ca454112569433a85a9467a20f5d7a45 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2011
  *
@@ -23,6 +23,7 @@
 #ifndef __LINUX_RCU_H
 #define __LINUX_RCU_H
 
+#include <trace/events/rcu.h>
 #ifdef CONFIG_RCU_TRACE
 #define RCU_TRACE(stmt) stmt
 #else /* #ifdef CONFIG_RCU_TRACE */
@@ -116,8 +117,6 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
        }
 }
 
-extern int rcu_expedited;
-
 #ifdef CONFIG_RCU_STALL_COMMON
 
 extern int rcu_cpu_stall_suppress;
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
new file mode 100644 (file)
index 0000000..bd30bc6
--- /dev/null
@@ -0,0 +1,1582 @@
+/*
+ * Read-Copy Update module-based torture test facility
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2005, 2006
+ *
+ * Authors: Paul E. McKenney <paulmck@us.ibm.com>
+ *       Josh Triplett <josh@freedesktop.org>
+ *
+ * See also:  Documentation/RCU/torture.txt
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/rcupdate.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/freezer.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/stat.h>
+#include <linux/srcu.h>
+#include <linux/slab.h>
+#include <linux/trace_clock.h>
+#include <asm/byteorder.h>
+#include <linux/torture.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
+
+
+torture_param(int, fqs_duration, 0,
+             "Duration of fqs bursts (us), 0 to disable");
+torture_param(int, fqs_holdoff, 0, "Holdoff time within fqs bursts (us)");
+torture_param(int, fqs_stutter, 3, "Wait time between fqs bursts (s)");
+torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
+torture_param(bool, gp_normal, false,
+            "Use normal (non-expedited) GP wait primitives");
+torture_param(int, irqreader, 1, "Allow RCU readers from irq handlers");
+torture_param(int, n_barrier_cbs, 0,
+            "# of callbacks/kthreads for barrier testing");
+torture_param(int, nfakewriters, 4, "Number of RCU fake writer threads");
+torture_param(int, nreaders, -1, "Number of RCU reader threads");
+torture_param(int, object_debug, 0,
+            "Enable debug-object double call_rcu() testing");
+torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
+torture_param(int, onoff_interval, 0,
+            "Time between CPU hotplugs (s), 0=disable");
+torture_param(int, shuffle_interval, 3, "Number of seconds between shuffles");
+torture_param(int, shutdown_secs, 0, "Shutdown time (s), <= zero to disable.");
+torture_param(int, stall_cpu, 0, "Stall duration (s), zero to disable.");
+torture_param(int, stall_cpu_holdoff, 10,
+            "Time to wait before starting stall (s).");
+torture_param(int, stat_interval, 60,
+            "Number of seconds between stats printk()s");
+torture_param(int, stutter, 5, "Number of seconds to run/halt test");
+torture_param(int, test_boost, 1, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
+torture_param(int, test_boost_duration, 4,
+            "Duration of each boost test, seconds.");
+torture_param(int, test_boost_interval, 7,
+            "Interval between boost tests, seconds.");
+torture_param(bool, test_no_idle_hz, true,
+            "Test support for tickless idle CPUs");
+torture_param(bool, verbose, true,
+            "Enable verbose debugging printk()s");
+
+static char *torture_type = "rcu";
+module_param(torture_type, charp, 0444);
+MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, ...)");
+
+static int nrealreaders;
+static struct task_struct *writer_task;
+static struct task_struct **fakewriter_tasks;
+static struct task_struct **reader_tasks;
+static struct task_struct *stats_task;
+static struct task_struct *fqs_task;
+static struct task_struct *boost_tasks[NR_CPUS];
+static struct task_struct *stall_task;
+static struct task_struct **barrier_cbs_tasks;
+static struct task_struct *barrier_task;
+
+#define RCU_TORTURE_PIPE_LEN 10
+
+struct rcu_torture {
+       struct rcu_head rtort_rcu;
+       int rtort_pipe_count;
+       struct list_head rtort_free;
+       int rtort_mbtest;
+};
+
+static LIST_HEAD(rcu_torture_freelist);
+static struct rcu_torture __rcu *rcu_torture_current;
+static unsigned long rcu_torture_current_version;
+static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
+static DEFINE_SPINLOCK(rcu_torture_lock);
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1],
+                     rcu_torture_count) = { 0 };
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1],
+                     rcu_torture_batch) = { 0 };
+static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
+static atomic_t n_rcu_torture_alloc;
+static atomic_t n_rcu_torture_alloc_fail;
+static atomic_t n_rcu_torture_free;
+static atomic_t n_rcu_torture_mberror;
+static atomic_t n_rcu_torture_error;
+static long n_rcu_torture_barrier_error;
+static long n_rcu_torture_boost_ktrerror;
+static long n_rcu_torture_boost_rterror;
+static long n_rcu_torture_boost_failure;
+static long n_rcu_torture_boosts;
+static long n_rcu_torture_timers;
+static long n_barrier_attempts;
+static long n_barrier_successes;
+static struct list_head rcu_torture_removed;
+
+#if defined(MODULE) || defined(CONFIG_RCU_TORTURE_TEST_RUNNABLE)
+#define RCUTORTURE_RUNNABLE_INIT 1
+#else
+#define RCUTORTURE_RUNNABLE_INIT 0
+#endif
+int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
+module_param(rcutorture_runnable, int, 0444);
+MODULE_PARM_DESC(rcutorture_runnable, "Start rcutorture at boot");
+
+#if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU)
+#define rcu_can_boost() 1
+#else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
+#define rcu_can_boost() 0
+#endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
+
+#ifdef CONFIG_RCU_TRACE
+static u64 notrace rcu_trace_clock_local(void)
+{
+       u64 ts = trace_clock_local();
+       unsigned long __maybe_unused ts_rem = do_div(ts, NSEC_PER_USEC);
+       return ts;
+}
+#else /* #ifdef CONFIG_RCU_TRACE */
+static u64 notrace rcu_trace_clock_local(void)
+{
+       return 0ULL;
+}
+#endif /* #else #ifdef CONFIG_RCU_TRACE */
+
+static unsigned long boost_starttime;  /* jiffies of next boost test start. */
+DEFINE_MUTEX(boost_mutex);             /* protect setting boost_starttime */
+                                       /*  and boost task create/destroy. */
+static atomic_t barrier_cbs_count;     /* Barrier callbacks registered. */
+static bool barrier_phase;             /* Test phase. */
+static atomic_t barrier_cbs_invoked;   /* Barrier callbacks invoked. */
+static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
+static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
+
+/*
+ * Allocate an element from the rcu_tortures pool.
+ */
+static struct rcu_torture *
+rcu_torture_alloc(void)
+{
+       struct list_head *p;
+
+       spin_lock_bh(&rcu_torture_lock);
+       if (list_empty(&rcu_torture_freelist)) {
+               atomic_inc(&n_rcu_torture_alloc_fail);
+               spin_unlock_bh(&rcu_torture_lock);
+               return NULL;
+       }
+       atomic_inc(&n_rcu_torture_alloc);
+       p = rcu_torture_freelist.next;
+       list_del_init(p);
+       spin_unlock_bh(&rcu_torture_lock);
+       return container_of(p, struct rcu_torture, rtort_free);
+}
+
+/*
+ * Free an element to the rcu_tortures pool.
+ */
+static void
+rcu_torture_free(struct rcu_torture *p)
+{
+       atomic_inc(&n_rcu_torture_free);
+       spin_lock_bh(&rcu_torture_lock);
+       list_add_tail(&p->rtort_free, &rcu_torture_freelist);
+       spin_unlock_bh(&rcu_torture_lock);
+}
+
+/*
+ * Operations vector for selecting different types of tests.
+ */
+
+struct rcu_torture_ops {
+       void (*init)(void);
+       int (*readlock)(void);
+       void (*read_delay)(struct torture_random_state *rrsp);
+       void (*readunlock)(int idx);
+       int (*completed)(void);
+       void (*deferred_free)(struct rcu_torture *p);
+       void (*sync)(void);
+       void (*exp_sync)(void);
+       void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
+       void (*cb_barrier)(void);
+       void (*fqs)(void);
+       void (*stats)(char *page);
+       int irq_capable;
+       int can_boost;
+       const char *name;
+};
+
+static struct rcu_torture_ops *cur_ops;
+
+/*
+ * Definitions for rcu torture testing.
+ */
+
+static int rcu_torture_read_lock(void) __acquires(RCU)
+{
+       rcu_read_lock();
+       return 0;
+}
+
+static void rcu_read_delay(struct torture_random_state *rrsp)
+{
+       const unsigned long shortdelay_us = 200;
+       const unsigned long longdelay_ms = 50;
+
+       /* We want a short delay sometimes to make a reader delay the grace
+        * period, and we want a long delay occasionally to trigger
+        * force_quiescent_state. */
+
+       if (!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms)))
+               mdelay(longdelay_ms);
+       if (!(torture_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
+               udelay(shortdelay_us);
+#ifdef CONFIG_PREEMPT
+       if (!preempt_count() &&
+           !(torture_random(rrsp) % (nrealreaders * 20000)))
+               preempt_schedule();  /* No QS if preempt_disable() in effect */
+#endif
+}
+
+static void rcu_torture_read_unlock(int idx) __releases(RCU)
+{
+       rcu_read_unlock();
+}
+
+static int rcu_torture_completed(void)
+{
+       return rcu_batches_completed();
+}
+
+static void
+rcu_torture_cb(struct rcu_head *p)
+{
+       int i;
+       struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
+
+       if (torture_must_stop_irq()) {
+               /* Test is ending, just drop callbacks on the floor. */
+               /* The next initialization will pick up the pieces. */
+               return;
+       }
+       i = rp->rtort_pipe_count;
+       if (i > RCU_TORTURE_PIPE_LEN)
+               i = RCU_TORTURE_PIPE_LEN;
+       atomic_inc(&rcu_torture_wcount[i]);
+       if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
+               rp->rtort_mbtest = 0;
+               rcu_torture_free(rp);
+       } else {
+               cur_ops->deferred_free(rp);
+       }
+}
+
+static int rcu_no_completed(void)
+{
+       return 0;
+}
+
+static void rcu_torture_deferred_free(struct rcu_torture *p)
+{
+       call_rcu(&p->rtort_rcu, rcu_torture_cb);
+}
+
+static void rcu_sync_torture_init(void)
+{
+       INIT_LIST_HEAD(&rcu_torture_removed);
+}
+
+static struct rcu_torture_ops rcu_ops = {
+       .init           = rcu_sync_torture_init,
+       .readlock       = rcu_torture_read_lock,
+       .read_delay     = rcu_read_delay,
+       .readunlock     = rcu_torture_read_unlock,
+       .completed      = rcu_torture_completed,
+       .deferred_free  = rcu_torture_deferred_free,
+       .sync           = synchronize_rcu,
+       .exp_sync       = synchronize_rcu_expedited,
+       .call           = call_rcu,
+       .cb_barrier     = rcu_barrier,
+       .fqs            = rcu_force_quiescent_state,
+       .stats          = NULL,
+       .irq_capable    = 1,
+       .can_boost      = rcu_can_boost(),
+       .name           = "rcu"
+};
+
+/*
+ * Definitions for rcu_bh torture testing.
+ */
+
+static int rcu_bh_torture_read_lock(void) __acquires(RCU_BH)
+{
+       rcu_read_lock_bh();
+       return 0;
+}
+
+static void rcu_bh_torture_read_unlock(int idx) __releases(RCU_BH)
+{
+       rcu_read_unlock_bh();
+}
+
+static int rcu_bh_torture_completed(void)
+{
+       return rcu_batches_completed_bh();
+}
+
+static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
+{
+       call_rcu_bh(&p->rtort_rcu, rcu_torture_cb);
+}
+
+static struct rcu_torture_ops rcu_bh_ops = {
+       .init           = rcu_sync_torture_init,
+       .readlock       = rcu_bh_torture_read_lock,
+       .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
+       .readunlock     = rcu_bh_torture_read_unlock,
+       .completed      = rcu_bh_torture_completed,
+       .deferred_free  = rcu_bh_torture_deferred_free,
+       .sync           = synchronize_rcu_bh,
+       .exp_sync       = synchronize_rcu_bh_expedited,
+       .call           = call_rcu_bh,
+       .cb_barrier     = rcu_barrier_bh,
+       .fqs            = rcu_bh_force_quiescent_state,
+       .stats          = NULL,
+       .irq_capable    = 1,
+       .name           = "rcu_bh"
+};
+
+/*
+ * Don't even think about trying any of these in real life!!!
+ * The names includes "busted", and they really means it!
+ * The only purpose of these functions is to provide a buggy RCU
+ * implementation to make sure that rcutorture correctly emits
+ * buggy-RCU error messages.
+ */
+static void rcu_busted_torture_deferred_free(struct rcu_torture *p)
+{
+       /* This is a deliberate bug for testing purposes only! */
+       rcu_torture_cb(&p->rtort_rcu);
+}
+
+static void synchronize_rcu_busted(void)
+{
+       /* This is a deliberate bug for testing purposes only! */
+}
+
+static void
+call_rcu_busted(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
+{
+       /* This is a deliberate bug for testing purposes only! */
+       func(head);
+}
+
+static struct rcu_torture_ops rcu_busted_ops = {
+       .init           = rcu_sync_torture_init,
+       .readlock       = rcu_torture_read_lock,
+       .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
+       .readunlock     = rcu_torture_read_unlock,
+       .completed      = rcu_no_completed,
+       .deferred_free  = rcu_busted_torture_deferred_free,
+       .sync           = synchronize_rcu_busted,
+       .exp_sync       = synchronize_rcu_busted,
+       .call           = call_rcu_busted,
+       .cb_barrier     = NULL,
+       .fqs            = NULL,
+       .stats          = NULL,
+       .irq_capable    = 1,
+       .name           = "rcu_busted"
+};
+
+/*
+ * Definitions for srcu torture testing.
+ */
+
+DEFINE_STATIC_SRCU(srcu_ctl);
+
+static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
+{
+       return srcu_read_lock(&srcu_ctl);
+}
+
+static void srcu_read_delay(struct torture_random_state *rrsp)
+{
+       long delay;
+       const long uspertick = 1000000 / HZ;
+       const long longdelay = 10;
+
+       /* We want there to be long-running readers, but not all the time. */
+
+       delay = torture_random(rrsp) %
+               (nrealreaders * 2 * longdelay * uspertick);
+       if (!delay)
+               schedule_timeout_interruptible(longdelay);
+       else
+               rcu_read_delay(rrsp);
+}
+
+static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
+{
+       srcu_read_unlock(&srcu_ctl, idx);
+}
+
+static int srcu_torture_completed(void)
+{
+       return srcu_batches_completed(&srcu_ctl);
+}
+
+static void srcu_torture_deferred_free(struct rcu_torture *rp)
+{
+       call_srcu(&srcu_ctl, &rp->rtort_rcu, rcu_torture_cb);
+}
+
+static void srcu_torture_synchronize(void)
+{
+       synchronize_srcu(&srcu_ctl);
+}
+
+static void srcu_torture_call(struct rcu_head *head,
+                             void (*func)(struct rcu_head *head))
+{
+       call_srcu(&srcu_ctl, head, func);
+}
+
+static void srcu_torture_barrier(void)
+{
+       srcu_barrier(&srcu_ctl);
+}
+
+static void srcu_torture_stats(char *page)
+{
+       int cpu;
+       int idx = srcu_ctl.completed & 0x1;
+
+       page += sprintf(page, "%s%s per-CPU(idx=%d):",
+                      torture_type, TORTURE_FLAG, idx);
+       for_each_possible_cpu(cpu) {
+               page += sprintf(page, " %d(%lu,%lu)", cpu,
+                              per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx],
+                              per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]);
+       }
+       sprintf(page, "\n");
+}
+
+static void srcu_torture_synchronize_expedited(void)
+{
+       synchronize_srcu_expedited(&srcu_ctl);
+}
+
+static struct rcu_torture_ops srcu_ops = {
+       .init           = rcu_sync_torture_init,
+       .readlock       = srcu_torture_read_lock,
+       .read_delay     = srcu_read_delay,
+       .readunlock     = srcu_torture_read_unlock,
+       .completed      = srcu_torture_completed,
+       .deferred_free  = srcu_torture_deferred_free,
+       .sync           = srcu_torture_synchronize,
+       .exp_sync       = srcu_torture_synchronize_expedited,
+       .call           = srcu_torture_call,
+       .cb_barrier     = srcu_torture_barrier,
+       .stats          = srcu_torture_stats,
+       .name           = "srcu"
+};
+
+/*
+ * Definitions for sched torture testing.
+ */
+
+static int sched_torture_read_lock(void)
+{
+       preempt_disable();
+       return 0;
+}
+
+static void sched_torture_read_unlock(int idx)
+{
+       preempt_enable();
+}
+
+static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
+{
+       call_rcu_sched(&p->rtort_rcu, rcu_torture_cb);
+}
+
+static struct rcu_torture_ops sched_ops = {
+       .init           = rcu_sync_torture_init,
+       .readlock       = sched_torture_read_lock,
+       .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
+       .readunlock     = sched_torture_read_unlock,
+       .completed      = rcu_no_completed,
+       .deferred_free  = rcu_sched_torture_deferred_free,
+       .sync           = synchronize_sched,
+       .exp_sync       = synchronize_sched_expedited,
+       .call           = call_rcu_sched,
+       .cb_barrier     = rcu_barrier_sched,
+       .fqs            = rcu_sched_force_quiescent_state,
+       .stats          = NULL,
+       .irq_capable    = 1,
+       .name           = "sched"
+};
+
+/*
+ * RCU torture priority-boost testing.  Runs one real-time thread per
+ * CPU for moderate bursts, repeatedly registering RCU callbacks and
+ * spinning waiting for them to be invoked.  If a given callback takes
+ * too long to be invoked, we assume that priority inversion has occurred.
+ */
+
+struct rcu_boost_inflight {
+       struct rcu_head rcu;
+       int inflight;
+};
+
+static void rcu_torture_boost_cb(struct rcu_head *head)
+{
+       struct rcu_boost_inflight *rbip =
+               container_of(head, struct rcu_boost_inflight, rcu);
+
+       smp_mb(); /* Ensure RCU-core accesses precede clearing ->inflight */
+       rbip->inflight = 0;
+}
+
+static int rcu_torture_boost(void *arg)
+{
+       unsigned long call_rcu_time;
+       unsigned long endtime;
+       unsigned long oldstarttime;
+       struct rcu_boost_inflight rbi = { .inflight = 0 };
+       struct sched_param sp;
+
+       VERBOSE_TOROUT_STRING("rcu_torture_boost started");
+
+       /* Set real-time priority. */
+       sp.sched_priority = 1;
+       if (sched_setscheduler(current, SCHED_FIFO, &sp) < 0) {
+               VERBOSE_TOROUT_STRING("rcu_torture_boost RT prio failed!");
+               n_rcu_torture_boost_rterror++;
+       }
+
+       init_rcu_head_on_stack(&rbi.rcu);
+       /* Each pass through the following loop does one boost-test cycle. */
+       do {
+               /* Wait for the next test interval. */
+               oldstarttime = boost_starttime;
+               while (ULONG_CMP_LT(jiffies, oldstarttime)) {
+                       schedule_timeout_interruptible(oldstarttime - jiffies);
+                       stutter_wait("rcu_torture_boost");
+                       if (torture_must_stop())
+                               goto checkwait;
+               }
+
+               /* Do one boost-test interval. */
+               endtime = oldstarttime + test_boost_duration * HZ;
+               call_rcu_time = jiffies;
+               while (ULONG_CMP_LT(jiffies, endtime)) {
+                       /* If we don't have a callback in flight, post one. */
+                       if (!rbi.inflight) {
+                               smp_mb(); /* RCU core before ->inflight = 1. */
+                               rbi.inflight = 1;
+                               call_rcu(&rbi.rcu, rcu_torture_boost_cb);
+                               if (jiffies - call_rcu_time >
+                                        test_boost_duration * HZ - HZ / 2) {
+                                       VERBOSE_TOROUT_STRING("rcu_torture_boost boosting failed");
+                                       n_rcu_torture_boost_failure++;
+                               }
+                               call_rcu_time = jiffies;
+                       }
+                       cond_resched();
+                       stutter_wait("rcu_torture_boost");
+                       if (torture_must_stop())
+                               goto checkwait;
+               }
+
+               /*
+                * Set the start time of the next test interval.
+                * Yes, this is vulnerable to long delays, but such
+                * delays simply cause a false negative for the next
+                * interval.  Besides, we are running at RT priority,
+                * so delays should be relatively rare.
+                */
+               while (oldstarttime == boost_starttime &&
+                      !kthread_should_stop()) {
+                       if (mutex_trylock(&boost_mutex)) {
+                               boost_starttime = jiffies +
+                                                 test_boost_interval * HZ;
+                               n_rcu_torture_boosts++;
+                               mutex_unlock(&boost_mutex);
+                               break;
+                       }
+                       schedule_timeout_uninterruptible(1);
+               }
+
+               /* Go do the stutter. */
+checkwait:     stutter_wait("rcu_torture_boost");
+       } while (!torture_must_stop());
+
+       /* Clean up and exit. */
+       while (!kthread_should_stop() || rbi.inflight) {
+               torture_shutdown_absorb("rcu_torture_boost");
+               schedule_timeout_uninterruptible(1);
+       }
+       smp_mb(); /* order accesses to ->inflight before stack-frame death. */
+       destroy_rcu_head_on_stack(&rbi.rcu);
+       torture_kthread_stopping("rcu_torture_boost");
+       return 0;
+}
+
+/*
+ * RCU torture force-quiescent-state kthread.  Repeatedly induces
+ * bursts of calls to force_quiescent_state(), increasing the probability
+ * of occurrence of some important types of race conditions.
+ */
+static int
+rcu_torture_fqs(void *arg)
+{
+       unsigned long fqs_resume_time;
+       int fqs_burst_remaining;
+
+       VERBOSE_TOROUT_STRING("rcu_torture_fqs task started");
+       do {
+               fqs_resume_time = jiffies + fqs_stutter * HZ;
+               while (ULONG_CMP_LT(jiffies, fqs_resume_time) &&
+                      !kthread_should_stop()) {
+                       schedule_timeout_interruptible(1);
+               }
+               fqs_burst_remaining = fqs_duration;
+               while (fqs_burst_remaining > 0 &&
+                      !kthread_should_stop()) {
+                       cur_ops->fqs();
+                       udelay(fqs_holdoff);
+                       fqs_burst_remaining -= fqs_holdoff;
+               }
+               stutter_wait("rcu_torture_fqs");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("rcu_torture_fqs");
+       return 0;
+}
+
+/*
+ * RCU torture writer kthread.  Repeatedly substitutes a new structure
+ * for that pointed to by rcu_torture_current, freeing the old structure
+ * after a series of grace periods (the "pipeline").
+ */
+static int
+rcu_torture_writer(void *arg)
+{
+       bool exp;
+       int i;
+       struct rcu_torture *rp;
+       struct rcu_torture *rp1;
+       struct rcu_torture *old_rp;
+       static DEFINE_TORTURE_RANDOM(rand);
+
+       VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
+       set_user_nice(current, MAX_NICE);
+
+       do {
+               schedule_timeout_uninterruptible(1);
+               rp = rcu_torture_alloc();
+               if (rp == NULL)
+                       continue;
+               rp->rtort_pipe_count = 0;
+               udelay(torture_random(&rand) & 0x3ff);
+               old_rp = rcu_dereference_check(rcu_torture_current,
+                                              current == writer_task);
+               rp->rtort_mbtest = 1;
+               rcu_assign_pointer(rcu_torture_current, rp);
+               smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
+               if (old_rp) {
+                       i = old_rp->rtort_pipe_count;
+                       if (i > RCU_TORTURE_PIPE_LEN)
+                               i = RCU_TORTURE_PIPE_LEN;
+                       atomic_inc(&rcu_torture_wcount[i]);
+                       old_rp->rtort_pipe_count++;
+                       if (gp_normal == gp_exp)
+                               exp = !!(torture_random(&rand) & 0x80);
+                       else
+                               exp = gp_exp;
+                       if (!exp) {
+                               cur_ops->deferred_free(old_rp);
+                       } else {
+                               cur_ops->exp_sync();
+                               list_add(&old_rp->rtort_free,
+                                        &rcu_torture_removed);
+                               list_for_each_entry_safe(rp, rp1,
+                                                        &rcu_torture_removed,
+                                                        rtort_free) {
+                                       i = rp->rtort_pipe_count;
+                                       if (i > RCU_TORTURE_PIPE_LEN)
+                                               i = RCU_TORTURE_PIPE_LEN;
+                                       atomic_inc(&rcu_torture_wcount[i]);
+                                       if (++rp->rtort_pipe_count >=
+                                           RCU_TORTURE_PIPE_LEN) {
+                                               rp->rtort_mbtest = 0;
+                                               list_del(&rp->rtort_free);
+                                               rcu_torture_free(rp);
+                                       }
+                                }
+                       }
+               }
+               rcutorture_record_progress(++rcu_torture_current_version);
+               stutter_wait("rcu_torture_writer");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("rcu_torture_writer");
+       return 0;
+}
+
+/*
+ * RCU torture fake writer kthread.  Repeatedly calls sync, with a random
+ * delay between calls.
+ */
+static int
+rcu_torture_fakewriter(void *arg)
+{
+       DEFINE_TORTURE_RANDOM(rand);
+
+       VERBOSE_TOROUT_STRING("rcu_torture_fakewriter task started");
+       set_user_nice(current, MAX_NICE);
+
+       do {
+               schedule_timeout_uninterruptible(1 + torture_random(&rand)%10);
+               udelay(torture_random(&rand) & 0x3ff);
+               if (cur_ops->cb_barrier != NULL &&
+                   torture_random(&rand) % (nfakewriters * 8) == 0) {
+                       cur_ops->cb_barrier();
+               } else if (gp_normal == gp_exp) {
+                       if (torture_random(&rand) & 0x80)
+                               cur_ops->sync();
+                       else
+                               cur_ops->exp_sync();
+               } else if (gp_normal) {
+                       cur_ops->sync();
+               } else {
+                       cur_ops->exp_sync();
+               }
+               stutter_wait("rcu_torture_fakewriter");
+       } while (!torture_must_stop());
+
+       torture_kthread_stopping("rcu_torture_fakewriter");
+       return 0;
+}
+
+void rcutorture_trace_dump(void)
+{
+       static atomic_t beenhere = ATOMIC_INIT(0);
+
+       if (atomic_read(&beenhere))
+               return;
+       if (atomic_xchg(&beenhere, 1) != 0)
+               return;
+       ftrace_dump(DUMP_ALL);
+}
+
+/*
+ * RCU torture reader from timer handler.  Dereferences rcu_torture_current,
+ * incrementing the corresponding element of the pipeline array.  The
+ * counter in the element should never be greater than 1, otherwise, the
+ * RCU implementation is broken.
+ */
+static void rcu_torture_timer(unsigned long unused)
+{
+       int idx;
+       int completed;
+       int completed_end;
+       static DEFINE_TORTURE_RANDOM(rand);
+       static DEFINE_SPINLOCK(rand_lock);
+       struct rcu_torture *p;
+       int pipe_count;
+       unsigned long long ts;
+
+       idx = cur_ops->readlock();
+       completed = cur_ops->completed();
+       ts = rcu_trace_clock_local();
+       p = rcu_dereference_check(rcu_torture_current,
+                                 rcu_read_lock_bh_held() ||
+                                 rcu_read_lock_sched_held() ||
+                                 srcu_read_lock_held(&srcu_ctl));
+       if (p == NULL) {
+               /* Leave because rcu_torture_writer is not yet underway */
+               cur_ops->readunlock(idx);
+               return;
+       }
+       if (p->rtort_mbtest == 0)
+               atomic_inc(&n_rcu_torture_mberror);
+       spin_lock(&rand_lock);
+       cur_ops->read_delay(&rand);
+       n_rcu_torture_timers++;
+       spin_unlock(&rand_lock);
+       preempt_disable();
+       pipe_count = p->rtort_pipe_count;
+       if (pipe_count > RCU_TORTURE_PIPE_LEN) {
+               /* Should not happen, but... */
+               pipe_count = RCU_TORTURE_PIPE_LEN;
+       }
+       completed_end = cur_ops->completed();
+       if (pipe_count > 1) {
+               do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts,
+                                         completed, completed_end);
+               rcutorture_trace_dump();
+       }
+       __this_cpu_inc(rcu_torture_count[pipe_count]);
+       completed = completed_end - completed;
+       if (completed > RCU_TORTURE_PIPE_LEN) {
+               /* Should not happen, but... */
+               completed = RCU_TORTURE_PIPE_LEN;
+       }
+       __this_cpu_inc(rcu_torture_batch[completed]);
+       preempt_enable();
+       cur_ops->readunlock(idx);
+}
+
+/*
+ * RCU torture reader kthread.  Repeatedly dereferences rcu_torture_current,
+ * incrementing the corresponding element of the pipeline array.  The
+ * counter in the element should never be greater than 1, otherwise, the
+ * RCU implementation is broken.
+ */
+static int
+rcu_torture_reader(void *arg)
+{
+       int completed;
+       int completed_end;
+       int idx;
+       DEFINE_TORTURE_RANDOM(rand);
+       struct rcu_torture *p;
+       int pipe_count;
+       struct timer_list t;
+       unsigned long long ts;
+
+       VERBOSE_TOROUT_STRING("rcu_torture_reader task started");
+       set_user_nice(current, MAX_NICE);
+       if (irqreader && cur_ops->irq_capable)
+               setup_timer_on_stack(&t, rcu_torture_timer, 0);
+
+       do {
+               if (irqreader && cur_ops->irq_capable) {
+                       if (!timer_pending(&t))
+                               mod_timer(&t, jiffies + 1);
+               }
+               idx = cur_ops->readlock();
+               completed = cur_ops->completed();
+               ts = rcu_trace_clock_local();
+               p = rcu_dereference_check(rcu_torture_current,
+                                         rcu_read_lock_bh_held() ||
+                                         rcu_read_lock_sched_held() ||
+                                         srcu_read_lock_held(&srcu_ctl));
+               if (p == NULL) {
+                       /* Wait for rcu_torture_writer to get underway */
+                       cur_ops->readunlock(idx);
+                       schedule_timeout_interruptible(HZ);
+                       continue;
+               }
+               if (p->rtort_mbtest == 0)
+                       atomic_inc(&n_rcu_torture_mberror);
+               cur_ops->read_delay(&rand);
+               preempt_disable();
+               pipe_count = p->rtort_pipe_count;
+               if (pipe_count > RCU_TORTURE_PIPE_LEN) {
+                       /* Should not happen, but... */
+                       pipe_count = RCU_TORTURE_PIPE_LEN;
+               }
+               completed_end = cur_ops->completed();
+               if (pipe_count > 1) {
+                       do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu,
+                                                 ts, completed, completed_end);
+                       rcutorture_trace_dump();
+               }
+               __this_cpu_inc(rcu_torture_count[pipe_count]);
+               completed = completed_end - completed;
+               if (completed > RCU_TORTURE_PIPE_LEN) {
+                       /* Should not happen, but... */
+                       completed = RCU_TORTURE_PIPE_LEN;
+               }
+               __this_cpu_inc(rcu_torture_batch[completed]);
+               preempt_enable();
+               cur_ops->readunlock(idx);
+               schedule();
+               stutter_wait("rcu_torture_reader");
+       } while (!torture_must_stop());
+       if (irqreader && cur_ops->irq_capable)
+               del_timer_sync(&t);
+       torture_kthread_stopping("rcu_torture_reader");
+       return 0;
+}
+
+/*
+ * Create an RCU-torture statistics message in the specified buffer.
+ */
+static void
+rcu_torture_printk(char *page)
+{
+       int cpu;
+       int i;
+       long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
+       long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
+
+       for_each_possible_cpu(cpu) {
+               for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+                       pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i];
+                       batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i];
+               }
+       }
+       for (i = RCU_TORTURE_PIPE_LEN - 1; i >= 0; i--) {
+               if (pipesummary[i] != 0)
+                       break;
+       }
+       page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG);
+       page += sprintf(page,
+                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
+                      rcu_torture_current,
+                      rcu_torture_current_version,
+                      list_empty(&rcu_torture_freelist),
+                      atomic_read(&n_rcu_torture_alloc),
+                      atomic_read(&n_rcu_torture_alloc_fail),
+                      atomic_read(&n_rcu_torture_free));
+       page += sprintf(page, "rtmbe: %d rtbke: %ld rtbre: %ld ",
+                      atomic_read(&n_rcu_torture_mberror),
+                      n_rcu_torture_boost_ktrerror,
+                      n_rcu_torture_boost_rterror);
+       page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ",
+                      n_rcu_torture_boost_failure,
+                      n_rcu_torture_boosts,
+                      n_rcu_torture_timers);
+       page = torture_onoff_stats(page);
+       page += sprintf(page, "barrier: %ld/%ld:%ld",
+                      n_barrier_successes,
+                      n_barrier_attempts,
+                      n_rcu_torture_barrier_error);
+       page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
+       if (atomic_read(&n_rcu_torture_mberror) != 0 ||
+           n_rcu_torture_barrier_error != 0 ||
+           n_rcu_torture_boost_ktrerror != 0 ||
+           n_rcu_torture_boost_rterror != 0 ||
+           n_rcu_torture_boost_failure != 0 ||
+           i > 1) {
+               page += sprintf(page, "!!! ");
+               atomic_inc(&n_rcu_torture_error);
+               WARN_ON_ONCE(1);
+       }
+       page += sprintf(page, "Reader Pipe: ");
+       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
+               page += sprintf(page, " %ld", pipesummary[i]);
+       page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
+       page += sprintf(page, "Reader Batch: ");
+       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
+               page += sprintf(page, " %ld", batchsummary[i]);
+       page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
+       page += sprintf(page, "Free-Block Circulation: ");
+       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+               page += sprintf(page, " %d",
+                              atomic_read(&rcu_torture_wcount[i]));
+       }
+       page += sprintf(page, "\n");
+       if (cur_ops->stats)
+               cur_ops->stats(page);
+}
+
+/*
+ * Print torture statistics.  Caller must ensure that there is only
+ * one call to this function at a given time!!!  This is normally
+ * accomplished by relying on the module system to only have one copy
+ * of the module loaded, and then by giving the rcu_torture_stats
+ * kthread full control (or the init/cleanup functions when rcu_torture_stats
+ * thread is not running).
+ */
+static void
+rcu_torture_stats_print(void)
+{
+       int size = nr_cpu_ids * 200 + 8192;
+       char *buf;
+
+       buf = kmalloc(size, GFP_KERNEL);
+       if (!buf) {
+               pr_err("rcu-torture: Out of memory, need: %d", size);
+               return;
+       }
+       rcu_torture_printk(buf);
+       pr_alert("%s", buf);
+       kfree(buf);
+}
+
+/*
+ * Periodically prints torture statistics, if periodic statistics printing
+ * was specified via the stat_interval module parameter.
+ */
+static int
+rcu_torture_stats(void *arg)
+{
+       VERBOSE_TOROUT_STRING("rcu_torture_stats task started");
+       do {
+               schedule_timeout_interruptible(stat_interval * HZ);
+               rcu_torture_stats_print();
+               torture_shutdown_absorb("rcu_torture_stats");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("rcu_torture_stats");
+       return 0;
+}
+
+static inline void
+rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
+{
+       pr_alert("%s" TORTURE_FLAG
+                "--- %s: nreaders=%d nfakewriters=%d "
+                "stat_interval=%d verbose=%d test_no_idle_hz=%d "
+                "shuffle_interval=%d stutter=%d irqreader=%d "
+                "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
+                "test_boost=%d/%d test_boost_interval=%d "
+                "test_boost_duration=%d shutdown_secs=%d "
+                "stall_cpu=%d stall_cpu_holdoff=%d "
+                "n_barrier_cbs=%d "
+                "onoff_interval=%d onoff_holdoff=%d\n",
+                torture_type, tag, nrealreaders, nfakewriters,
+                stat_interval, verbose, test_no_idle_hz, shuffle_interval,
+                stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
+                test_boost, cur_ops->can_boost,
+                test_boost_interval, test_boost_duration, shutdown_secs,
+                stall_cpu, stall_cpu_holdoff,
+                n_barrier_cbs,
+                onoff_interval, onoff_holdoff);
+}
+
+static void rcutorture_booster_cleanup(int cpu)
+{
+       struct task_struct *t;
+
+       if (boost_tasks[cpu] == NULL)
+               return;
+       mutex_lock(&boost_mutex);
+       t = boost_tasks[cpu];
+       boost_tasks[cpu] = NULL;
+       mutex_unlock(&boost_mutex);
+
+       /* This must be outside of the mutex, otherwise deadlock! */
+       torture_stop_kthread(rcu_torture_boost, t);
+}
+
+static int rcutorture_booster_init(int cpu)
+{
+       int retval;
+
+       if (boost_tasks[cpu] != NULL)
+               return 0;  /* Already created, nothing more to do. */
+
+       /* Don't allow time recalculation while creating a new task. */
+       mutex_lock(&boost_mutex);
+       VERBOSE_TOROUT_STRING("Creating rcu_torture_boost task");
+       boost_tasks[cpu] = kthread_create_on_node(rcu_torture_boost, NULL,
+                                                 cpu_to_node(cpu),
+                                                 "rcu_torture_boost");
+       if (IS_ERR(boost_tasks[cpu])) {
+               retval = PTR_ERR(boost_tasks[cpu]);
+               VERBOSE_TOROUT_STRING("rcu_torture_boost task create failed");
+               n_rcu_torture_boost_ktrerror++;
+               boost_tasks[cpu] = NULL;
+               mutex_unlock(&boost_mutex);
+               return retval;
+       }
+       kthread_bind(boost_tasks[cpu], cpu);
+       wake_up_process(boost_tasks[cpu]);
+       mutex_unlock(&boost_mutex);
+       return 0;
+}
+
+/*
+ * CPU-stall kthread.  It waits as specified by stall_cpu_holdoff, then
+ * induces a CPU stall for the time specified by stall_cpu.
+ */
+static int rcu_torture_stall(void *args)
+{
+       unsigned long stop_at;
+
+       VERBOSE_TOROUT_STRING("rcu_torture_stall task started");
+       if (stall_cpu_holdoff > 0) {
+               VERBOSE_TOROUT_STRING("rcu_torture_stall begin holdoff");
+               schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
+               VERBOSE_TOROUT_STRING("rcu_torture_stall end holdoff");
+       }
+       if (!kthread_should_stop()) {
+               stop_at = get_seconds() + stall_cpu;
+               /* RCU CPU stall is expected behavior in following code. */
+               pr_alert("rcu_torture_stall start.\n");
+               rcu_read_lock();
+               preempt_disable();
+               while (ULONG_CMP_LT(get_seconds(), stop_at))
+                       continue;  /* Induce RCU CPU stall warning. */
+               preempt_enable();
+               rcu_read_unlock();
+               pr_alert("rcu_torture_stall end.\n");
+       }
+       torture_shutdown_absorb("rcu_torture_stall");
+       while (!kthread_should_stop())
+               schedule_timeout_interruptible(10 * HZ);
+       return 0;
+}
+
+/* Spawn CPU-stall kthread, if stall_cpu specified. */
+static int __init rcu_torture_stall_init(void)
+{
+       if (stall_cpu <= 0)
+               return 0;
+       return torture_create_kthread(rcu_torture_stall, NULL, stall_task);
+}
+
+/* Callback function for RCU barrier testing. */
+void rcu_torture_barrier_cbf(struct rcu_head *rcu)
+{
+       atomic_inc(&barrier_cbs_invoked);
+}
+
+/* kthread function to register callbacks used to test RCU barriers. */
+static int rcu_torture_barrier_cbs(void *arg)
+{
+       long myid = (long)arg;
+       bool lastphase = 0;
+       bool newphase;
+       struct rcu_head rcu;
+
+       init_rcu_head_on_stack(&rcu);
+       VERBOSE_TOROUT_STRING("rcu_torture_barrier_cbs task started");
+       set_user_nice(current, MAX_NICE);
+       do {
+               wait_event(barrier_cbs_wq[myid],
+                          (newphase =
+                           ACCESS_ONCE(barrier_phase)) != lastphase ||
+                          torture_must_stop());
+               lastphase = newphase;
+               smp_mb(); /* ensure barrier_phase load before ->call(). */
+               if (torture_must_stop())
+                       break;
+               cur_ops->call(&rcu, rcu_torture_barrier_cbf);
+               if (atomic_dec_and_test(&barrier_cbs_count))
+                       wake_up(&barrier_wq);
+       } while (!torture_must_stop());
+       cur_ops->cb_barrier();
+       destroy_rcu_head_on_stack(&rcu);
+       torture_kthread_stopping("rcu_torture_barrier_cbs");
+       return 0;
+}
+
+/* kthread function to drive and coordinate RCU barrier testing. */
+static int rcu_torture_barrier(void *arg)
+{
+       int i;
+
+       VERBOSE_TOROUT_STRING("rcu_torture_barrier task starting");
+       do {
+               atomic_set(&barrier_cbs_invoked, 0);
+               atomic_set(&barrier_cbs_count, n_barrier_cbs);
+               smp_mb(); /* Ensure barrier_phase after prior assignments. */
+               barrier_phase = !barrier_phase;
+               for (i = 0; i < n_barrier_cbs; i++)
+                       wake_up(&barrier_cbs_wq[i]);
+               wait_event(barrier_wq,
+                          atomic_read(&barrier_cbs_count) == 0 ||
+                          torture_must_stop());
+               if (torture_must_stop())
+                       break;
+               n_barrier_attempts++;
+               cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */
+               if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) {
+                       n_rcu_torture_barrier_error++;
+                       WARN_ON_ONCE(1);
+               }
+               n_barrier_successes++;
+               schedule_timeout_interruptible(HZ / 10);
+       } while (!torture_must_stop());
+       torture_kthread_stopping("rcu_torture_barrier");
+       return 0;
+}
+
+/* Initialize RCU barrier testing. */
+static int rcu_torture_barrier_init(void)
+{
+       int i;
+       int ret;
+
+       if (n_barrier_cbs == 0)
+               return 0;
+       if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
+               pr_alert("%s" TORTURE_FLAG
+                        " Call or barrier ops missing for %s,\n",
+                        torture_type, cur_ops->name);
+               pr_alert("%s" TORTURE_FLAG
+                        " RCU barrier testing omitted from run.\n",
+                        torture_type);
+               return 0;
+       }
+       atomic_set(&barrier_cbs_count, 0);
+       atomic_set(&barrier_cbs_invoked, 0);
+       barrier_cbs_tasks =
+               kzalloc(n_barrier_cbs * sizeof(barrier_cbs_tasks[0]),
+                       GFP_KERNEL);
+       barrier_cbs_wq =
+               kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
+                       GFP_KERNEL);
+       if (barrier_cbs_tasks == NULL || !barrier_cbs_wq)
+               return -ENOMEM;
+       for (i = 0; i < n_barrier_cbs; i++) {
+               init_waitqueue_head(&barrier_cbs_wq[i]);
+               ret = torture_create_kthread(rcu_torture_barrier_cbs,
+                                            (void *)(long)i,
+                                            barrier_cbs_tasks[i]);
+               if (ret)
+                       return ret;
+       }
+       return torture_create_kthread(rcu_torture_barrier, NULL, barrier_task);
+}
+
+/* Clean up after RCU barrier testing. */
+static void rcu_torture_barrier_cleanup(void)
+{
+       int i;
+
+       torture_stop_kthread(rcu_torture_barrier, barrier_task);
+       if (barrier_cbs_tasks != NULL) {
+               for (i = 0; i < n_barrier_cbs; i++)
+                       torture_stop_kthread(rcu_torture_barrier_cbs,
+                                            barrier_cbs_tasks[i]);
+               kfree(barrier_cbs_tasks);
+               barrier_cbs_tasks = NULL;
+       }
+       if (barrier_cbs_wq != NULL) {
+               kfree(barrier_cbs_wq);
+               barrier_cbs_wq = NULL;
+       }
+}
+
+static int rcutorture_cpu_notify(struct notifier_block *self,
+                                unsigned long action, void *hcpu)
+{
+       long cpu = (long)hcpu;
+
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_DOWN_FAILED:
+               (void)rcutorture_booster_init(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               rcutorture_booster_cleanup(cpu);
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block rcutorture_cpu_nb = {
+       .notifier_call = rcutorture_cpu_notify,
+};
+
+static void
+rcu_torture_cleanup(void)
+{
+       int i;
+
+       rcutorture_record_test_transition();
+       if (torture_cleanup()) {
+               if (cur_ops->cb_barrier != NULL)
+                       cur_ops->cb_barrier();
+               return;
+       }
+
+       rcu_torture_barrier_cleanup();
+       torture_stop_kthread(rcu_torture_stall, stall_task);
+       torture_stop_kthread(rcu_torture_writer, writer_task);
+
+       if (reader_tasks) {
+               for (i = 0; i < nrealreaders; i++)
+                       torture_stop_kthread(rcu_torture_reader,
+                                            reader_tasks[i]);
+               kfree(reader_tasks);
+       }
+       rcu_torture_current = NULL;
+
+       if (fakewriter_tasks) {
+               for (i = 0; i < nfakewriters; i++) {
+                       torture_stop_kthread(rcu_torture_fakewriter,
+                                            fakewriter_tasks[i]);
+               }
+               kfree(fakewriter_tasks);
+               fakewriter_tasks = NULL;
+       }
+
+       torture_stop_kthread(rcu_torture_stats, stats_task);
+       torture_stop_kthread(rcu_torture_fqs, fqs_task);
+       if ((test_boost == 1 && cur_ops->can_boost) ||
+           test_boost == 2) {
+               unregister_cpu_notifier(&rcutorture_cpu_nb);
+               for_each_possible_cpu(i)
+                       rcutorture_booster_cleanup(i);
+       }
+
+       /* Wait for all RCU callbacks to fire.  */
+
+       if (cur_ops->cb_barrier != NULL)
+               cur_ops->cb_barrier();
+
+       rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
+
+       if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
+               rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
+       else if (torture_onoff_failures())
+               rcu_torture_print_module_parms(cur_ops,
+                                              "End of test: RCU_HOTPLUG");
+       else
+               rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
+}
+
+#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
+static void rcu_torture_leak_cb(struct rcu_head *rhp)
+{
+}
+
+static void rcu_torture_err_cb(struct rcu_head *rhp)
+{
+       /*
+        * This -might- happen due to race conditions, but is unlikely.
+        * The scenario that leads to this happening is that the
+        * first of the pair of duplicate callbacks is queued,
+        * someone else starts a grace period that includes that
+        * callback, then the second of the pair must wait for the
+        * next grace period.  Unlikely, but can happen.  If it
+        * does happen, the debug-objects subsystem won't have splatted.
+        */
+       pr_alert("rcutorture: duplicated callback was invoked.\n");
+}
+#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+
+/*
+ * Verify that double-free causes debug-objects to complain, but only
+ * if CONFIG_DEBUG_OBJECTS_RCU_HEAD=y.  Otherwise, say that the test
+ * cannot be carried out.
+ */
+static void rcu_test_debug_objects(void)
+{
+#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
+       struct rcu_head rh1;
+       struct rcu_head rh2;
+
+       init_rcu_head_on_stack(&rh1);
+       init_rcu_head_on_stack(&rh2);
+       pr_alert("rcutorture: WARN: Duplicate call_rcu() test starting.\n");
+
+       /* Try to queue the rh2 pair of callbacks for the same grace period. */
+       preempt_disable(); /* Prevent preemption from interrupting test. */
+       rcu_read_lock(); /* Make it impossible to finish a grace period. */
+       call_rcu(&rh1, rcu_torture_leak_cb); /* Start grace period. */
+       local_irq_disable(); /* Make it harder to start a new grace period. */
+       call_rcu(&rh2, rcu_torture_leak_cb);
+       call_rcu(&rh2, rcu_torture_err_cb); /* Duplicate callback. */
+       local_irq_enable();
+       rcu_read_unlock();
+       preempt_enable();
+
+       /* Wait for them all to get done so we can safely return. */
+       rcu_barrier();
+       pr_alert("rcutorture: WARN: Duplicate call_rcu() test complete.\n");
+       destroy_rcu_head_on_stack(&rh1);
+       destroy_rcu_head_on_stack(&rh2);
+#else /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+       pr_alert("rcutorture: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_rcu()\n");
+#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
+}
+
+static int __init
+rcu_torture_init(void)
+{
+       int i;
+       int cpu;
+       int firsterr = 0;
+       static struct rcu_torture_ops *torture_ops[] = {
+               &rcu_ops, &rcu_bh_ops, &rcu_busted_ops, &srcu_ops, &sched_ops,
+       };
+
+       torture_init_begin(torture_type, verbose, &rcutorture_runnable);
+
+       /* Process args and tell the world that the torturer is on the job. */
+       for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
+               cur_ops = torture_ops[i];
+               if (strcmp(torture_type, cur_ops->name) == 0)
+                       break;
+       }
+       if (i == ARRAY_SIZE(torture_ops)) {
+               pr_alert("rcu-torture: invalid torture type: \"%s\"\n",
+                        torture_type);
+               pr_alert("rcu-torture types:");
+               for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
+                       pr_alert(" %s", torture_ops[i]->name);
+               pr_alert("\n");
+               torture_init_end();
+               return -EINVAL;
+       }
+       if (cur_ops->fqs == NULL && fqs_duration != 0) {
+               pr_alert("rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n");
+               fqs_duration = 0;
+       }
+       if (cur_ops->init)
+               cur_ops->init(); /* no "goto unwind" prior to this point!!! */
+
+       if (nreaders >= 0)
+               nrealreaders = nreaders;
+       else
+               nrealreaders = 2 * num_online_cpus();
+       rcu_torture_print_module_parms(cur_ops, "Start of test");
+
+       /* Set up the freelist. */
+
+       INIT_LIST_HEAD(&rcu_torture_freelist);
+       for (i = 0; i < ARRAY_SIZE(rcu_tortures); i++) {
+               rcu_tortures[i].rtort_mbtest = 0;
+               list_add_tail(&rcu_tortures[i].rtort_free,
+                             &rcu_torture_freelist);
+       }
+
+       /* Initialize the statistics so that each run gets its own numbers. */
+
+       rcu_torture_current = NULL;
+       rcu_torture_current_version = 0;
+       atomic_set(&n_rcu_torture_alloc, 0);
+       atomic_set(&n_rcu_torture_alloc_fail, 0);
+       atomic_set(&n_rcu_torture_free, 0);
+       atomic_set(&n_rcu_torture_mberror, 0);
+       atomic_set(&n_rcu_torture_error, 0);
+       n_rcu_torture_barrier_error = 0;
+       n_rcu_torture_boost_ktrerror = 0;
+       n_rcu_torture_boost_rterror = 0;
+       n_rcu_torture_boost_failure = 0;
+       n_rcu_torture_boosts = 0;
+       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
+               atomic_set(&rcu_torture_wcount[i], 0);
+       for_each_possible_cpu(cpu) {
+               for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
+                       per_cpu(rcu_torture_count, cpu)[i] = 0;
+                       per_cpu(rcu_torture_batch, cpu)[i] = 0;
+               }
+       }
+
+       /* Start up the kthreads. */
+
+       firsterr = torture_create_kthread(rcu_torture_writer, NULL,
+                                         writer_task);
+       if (firsterr)
+               goto unwind;
+       fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
+                                  GFP_KERNEL);
+       if (fakewriter_tasks == NULL) {
+               VERBOSE_TOROUT_ERRSTRING("out of memory");
+               firsterr = -ENOMEM;
+               goto unwind;
+       }
+       for (i = 0; i < nfakewriters; i++) {
+               firsterr = torture_create_kthread(rcu_torture_fakewriter,
+                                                 NULL, fakewriter_tasks[i]);
+               if (firsterr)
+                       goto unwind;
+       }
+       reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]),
+                              GFP_KERNEL);
+       if (reader_tasks == NULL) {
+               VERBOSE_TOROUT_ERRSTRING("out of memory");
+               firsterr = -ENOMEM;
+               goto unwind;
+       }
+       for (i = 0; i < nrealreaders; i++) {
+               firsterr = torture_create_kthread(rcu_torture_reader, NULL,
+                                                 reader_tasks[i]);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (stat_interval > 0) {
+               firsterr = torture_create_kthread(rcu_torture_stats, NULL,
+                                                 stats_task);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (test_no_idle_hz) {
+               firsterr = torture_shuffle_init(shuffle_interval * HZ);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (stutter < 0)
+               stutter = 0;
+       if (stutter) {
+               firsterr = torture_stutter_init(stutter * HZ);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (fqs_duration < 0)
+               fqs_duration = 0;
+       if (fqs_duration) {
+               /* Create the fqs thread */
+               torture_create_kthread(rcu_torture_fqs, NULL, fqs_task);
+               if (firsterr)
+                       goto unwind;
+       }
+       if (test_boost_interval < 1)
+               test_boost_interval = 1;
+       if (test_boost_duration < 2)
+               test_boost_duration = 2;
+       if ((test_boost == 1 && cur_ops->can_boost) ||
+           test_boost == 2) {
+
+               boost_starttime = jiffies + test_boost_interval * HZ;
+               register_cpu_notifier(&rcutorture_cpu_nb);
+               for_each_possible_cpu(i) {
+                       if (cpu_is_offline(i))
+                               continue;  /* Heuristic: CPU can go offline. */
+                       firsterr = rcutorture_booster_init(i);
+                       if (firsterr)
+                               goto unwind;
+               }
+       }
+       firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
+       if (firsterr)
+               goto unwind;
+       firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval * HZ);
+       if (firsterr)
+               goto unwind;
+       firsterr = rcu_torture_stall_init();
+       if (firsterr)
+               goto unwind;
+       firsterr = rcu_torture_barrier_init();
+       if (firsterr)
+               goto unwind;
+       if (object_debug)
+               rcu_test_debug_objects();
+       rcutorture_record_test_transition();
+       torture_init_end();
+       return 0;
+
+unwind:
+       torture_init_end();
+       rcu_torture_cleanup();
+       return firsterr;
+}
+
+module_init(rcu_torture_init);
+module_exit(rcu_torture_cleanup);
index 3318d82843841971f4926d8a8f9eb9a375e2eab3..c639556f3fa06234dcc34517826fbf0420641e56 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright (C) IBM Corporation, 2006
  * Copyright (C) Fujitsu, 2012
@@ -36,8 +36,6 @@
 #include <linux/delay.h>
 #include <linux/srcu.h>
 
-#include <trace/events/rcu.h>
-
 #include "rcu.h"
 
 /*
@@ -398,7 +396,7 @@ void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
        rcu_batch_queue(&sp->batch_queue, head);
        if (!sp->running) {
                sp->running = true;
-               schedule_delayed_work(&sp->work, 0);
+               queue_delayed_work(system_power_efficient_wq, &sp->work, 0);
        }
        spin_unlock_irqrestore(&sp->queue_lock, flags);
 }
@@ -674,7 +672,8 @@ static void srcu_reschedule(struct srcu_struct *sp)
        }
 
        if (pending)
-               schedule_delayed_work(&sp->work, SRCU_INTERVAL);
+               queue_delayed_work(system_power_efficient_wq,
+                                  &sp->work, SRCU_INTERVAL);
 }
 
 /*
index 1254f312d02483f524319ee5ab9d2e1a13f48678..d9efcc13008c00201c130f87135348c7238118ff 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
 #include <linux/prefetch.h>
 #include <linux/ftrace_event.h>
 
-#ifdef CONFIG_RCU_TRACE
-#include <trace/events/rcu.h>
-#endif /* #else #ifdef CONFIG_RCU_TRACE */
-
 #include "rcu.h"
 
 /* Forward declarations for tiny_plugin.h. */
index 280d06cae3524160833d3441b5de5af3462798c7..4315285205626f7c27c38c774a4522a12b04adcf 100644 (file)
@@ -14,8 +14,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright (c) 2010 Linaro
  *
diff --git a/kernel/rcu/torture.c b/kernel/rcu/torture.c
deleted file mode 100644 (file)
index 732f8ae..0000000
+++ /dev/null
@@ -1,2148 +0,0 @@
-/*
- * Read-Copy Update module-based torture test facility
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * Copyright (C) IBM Corporation, 2005, 2006
- *
- * Authors: Paul E. McKenney <paulmck@us.ibm.com>
- *       Josh Triplett <josh@freedesktop.org>
- *
- * See also:  Documentation/RCU/torture.txt
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/smp.h>
-#include <linux/rcupdate.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/atomic.h>
-#include <linux/bitops.h>
-#include <linux/completion.h>
-#include <linux/moduleparam.h>
-#include <linux/percpu.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/freezer.h>
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <linux/stat.h>
-#include <linux/srcu.h>
-#include <linux/slab.h>
-#include <linux/trace_clock.h>
-#include <asm/byteorder.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
-
-MODULE_ALIAS("rcutorture");
-#ifdef MODULE_PARAM_PREFIX
-#undef MODULE_PARAM_PREFIX
-#endif
-#define MODULE_PARAM_PREFIX "rcutorture."
-
-static int fqs_duration;
-module_param(fqs_duration, int, 0444);
-MODULE_PARM_DESC(fqs_duration, "Duration of fqs bursts (us), 0 to disable");
-static int fqs_holdoff;
-module_param(fqs_holdoff, int, 0444);
-MODULE_PARM_DESC(fqs_holdoff, "Holdoff time within fqs bursts (us)");
-static int fqs_stutter = 3;
-module_param(fqs_stutter, int, 0444);
-MODULE_PARM_DESC(fqs_stutter, "Wait time between fqs bursts (s)");
-static bool gp_exp;
-module_param(gp_exp, bool, 0444);
-MODULE_PARM_DESC(gp_exp, "Use expedited GP wait primitives");
-static bool gp_normal;
-module_param(gp_normal, bool, 0444);
-MODULE_PARM_DESC(gp_normal, "Use normal (non-expedited) GP wait primitives");
-static int irqreader = 1;
-module_param(irqreader, int, 0444);
-MODULE_PARM_DESC(irqreader, "Allow RCU readers from irq handlers");
-static int n_barrier_cbs;
-module_param(n_barrier_cbs, int, 0444);
-MODULE_PARM_DESC(n_barrier_cbs, "# of callbacks/kthreads for barrier testing");
-static int nfakewriters = 4;
-module_param(nfakewriters, int, 0444);
-MODULE_PARM_DESC(nfakewriters, "Number of RCU fake writer threads");
-static int nreaders = -1;
-module_param(nreaders, int, 0444);
-MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
-static int object_debug;
-module_param(object_debug, int, 0444);
-MODULE_PARM_DESC(object_debug, "Enable debug-object double call_rcu() testing");
-static int onoff_holdoff;
-module_param(onoff_holdoff, int, 0444);
-MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
-static int onoff_interval;
-module_param(onoff_interval, int, 0444);
-MODULE_PARM_DESC(onoff_interval, "Time between CPU hotplugs (s), 0=disable");
-static int shuffle_interval = 3;
-module_param(shuffle_interval, int, 0444);
-MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
-static int shutdown_secs;
-module_param(shutdown_secs, int, 0444);
-MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), <= zero to disable.");
-static int stall_cpu;
-module_param(stall_cpu, int, 0444);
-MODULE_PARM_DESC(stall_cpu, "Stall duration (s), zero to disable.");
-static int stall_cpu_holdoff = 10;
-module_param(stall_cpu_holdoff, int, 0444);
-MODULE_PARM_DESC(stall_cpu_holdoff, "Time to wait before starting stall (s).");
-static int stat_interval = 60;
-module_param(stat_interval, int, 0644);
-MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
-static int stutter = 5;
-module_param(stutter, int, 0444);
-MODULE_PARM_DESC(stutter, "Number of seconds to run/halt test");
-static int test_boost = 1;
-module_param(test_boost, int, 0444);
-MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
-static int test_boost_duration = 4;
-module_param(test_boost_duration, int, 0444);
-MODULE_PARM_DESC(test_boost_duration, "Duration of each boost test, seconds.");
-static int test_boost_interval = 7;
-module_param(test_boost_interval, int, 0444);
-MODULE_PARM_DESC(test_boost_interval, "Interval between boost tests, seconds.");
-static bool test_no_idle_hz = true;
-module_param(test_no_idle_hz, bool, 0444);
-MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
-static char *torture_type = "rcu";
-module_param(torture_type, charp, 0444);
-MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh, ...)");
-static bool verbose;
-module_param(verbose, bool, 0444);
-MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
-
-#define TORTURE_FLAG "-torture:"
-#define PRINTK_STRING(s) \
-       do { pr_alert("%s" TORTURE_FLAG s "\n", torture_type); } while (0)
-#define VERBOSE_PRINTK_STRING(s) \
-       do { if (verbose) pr_alert("%s" TORTURE_FLAG s "\n", torture_type); } while (0)
-#define VERBOSE_PRINTK_ERRSTRING(s) \
-       do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
-
-static int nrealreaders;
-static struct task_struct *writer_task;
-static struct task_struct **fakewriter_tasks;
-static struct task_struct **reader_tasks;
-static struct task_struct *stats_task;
-static struct task_struct *shuffler_task;
-static struct task_struct *stutter_task;
-static struct task_struct *fqs_task;
-static struct task_struct *boost_tasks[NR_CPUS];
-static struct task_struct *shutdown_task;
-#ifdef CONFIG_HOTPLUG_CPU
-static struct task_struct *onoff_task;
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-static struct task_struct *stall_task;
-static struct task_struct **barrier_cbs_tasks;
-static struct task_struct *barrier_task;
-
-#define RCU_TORTURE_PIPE_LEN 10
-
-struct rcu_torture {
-       struct rcu_head rtort_rcu;
-       int rtort_pipe_count;
-       struct list_head rtort_free;
-       int rtort_mbtest;
-};
-
-static LIST_HEAD(rcu_torture_freelist);
-static struct rcu_torture __rcu *rcu_torture_current;
-static unsigned long rcu_torture_current_version;
-static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
-static DEFINE_SPINLOCK(rcu_torture_lock);
-static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
-       { 0 };
-static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) =
-       { 0 };
-static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
-static atomic_t n_rcu_torture_alloc;
-static atomic_t n_rcu_torture_alloc_fail;
-static atomic_t n_rcu_torture_free;
-static atomic_t n_rcu_torture_mberror;
-static atomic_t n_rcu_torture_error;
-static long n_rcu_torture_barrier_error;
-static long n_rcu_torture_boost_ktrerror;
-static long n_rcu_torture_boost_rterror;
-static long n_rcu_torture_boost_failure;
-static long n_rcu_torture_boosts;
-static long n_rcu_torture_timers;
-static long n_offline_attempts;
-static long n_offline_successes;
-static unsigned long sum_offline;
-static int min_offline = -1;
-static int max_offline;
-static long n_online_attempts;
-static long n_online_successes;
-static unsigned long sum_online;
-static int min_online = -1;
-static int max_online;
-static long n_barrier_attempts;
-static long n_barrier_successes;
-static struct list_head rcu_torture_removed;
-static cpumask_var_t shuffle_tmp_mask;
-
-static int stutter_pause_test;
-
-#if defined(MODULE) || defined(CONFIG_RCU_TORTURE_TEST_RUNNABLE)
-#define RCUTORTURE_RUNNABLE_INIT 1
-#else
-#define RCUTORTURE_RUNNABLE_INIT 0
-#endif
-int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT;
-module_param(rcutorture_runnable, int, 0444);
-MODULE_PARM_DESC(rcutorture_runnable, "Start rcutorture at boot");
-
-#if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU)
-#define rcu_can_boost() 1
-#else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
-#define rcu_can_boost() 0
-#endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
-
-#ifdef CONFIG_RCU_TRACE
-static u64 notrace rcu_trace_clock_local(void)
-{
-       u64 ts = trace_clock_local();
-       unsigned long __maybe_unused ts_rem = do_div(ts, NSEC_PER_USEC);
-       return ts;
-}
-#else /* #ifdef CONFIG_RCU_TRACE */
-static u64 notrace rcu_trace_clock_local(void)
-{
-       return 0ULL;
-}
-#endif /* #else #ifdef CONFIG_RCU_TRACE */
-
-static unsigned long shutdown_time;    /* jiffies to system shutdown. */
-static unsigned long boost_starttime;  /* jiffies of next boost test start. */
-DEFINE_MUTEX(boost_mutex);             /* protect setting boost_starttime */
-                                       /*  and boost task create/destroy. */
-static atomic_t barrier_cbs_count;     /* Barrier callbacks registered. */
-static bool barrier_phase;             /* Test phase. */
-static atomic_t barrier_cbs_invoked;   /* Barrier callbacks invoked. */
-static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
-static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
-
-/* Mediate rmmod and system shutdown.  Concurrent rmmod & shutdown illegal! */
-
-#define FULLSTOP_DONTSTOP 0    /* Normal operation. */
-#define FULLSTOP_SHUTDOWN 1    /* System shutdown with rcutorture running. */
-#define FULLSTOP_RMMOD    2    /* Normal rmmod of rcutorture. */
-static int fullstop = FULLSTOP_RMMOD;
-/*
- * Protect fullstop transitions and spawning of kthreads.
- */
-static DEFINE_MUTEX(fullstop_mutex);
-
-/* Forward reference. */
-static void rcu_torture_cleanup(void);
-
-/*
- * Detect and respond to a system shutdown.
- */
-static int
-rcutorture_shutdown_notify(struct notifier_block *unused1,
-                          unsigned long unused2, void *unused3)
-{
-       mutex_lock(&fullstop_mutex);
-       if (fullstop == FULLSTOP_DONTSTOP)
-               fullstop = FULLSTOP_SHUTDOWN;
-       else
-               pr_warn(/* but going down anyway, so... */
-                      "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
-       mutex_unlock(&fullstop_mutex);
-       return NOTIFY_DONE;
-}
-
-/*
- * Absorb kthreads into a kernel function that won't return, so that
- * they won't ever access module text or data again.
- */
-static void rcutorture_shutdown_absorb(const char *title)
-{
-       if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
-               pr_notice(
-                      "rcutorture thread %s parking due to system shutdown\n",
-                      title);
-               schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
-       }
-}
-
-/*
- * Allocate an element from the rcu_tortures pool.
- */
-static struct rcu_torture *
-rcu_torture_alloc(void)
-{
-       struct list_head *p;
-
-       spin_lock_bh(&rcu_torture_lock);
-       if (list_empty(&rcu_torture_freelist)) {
-               atomic_inc(&n_rcu_torture_alloc_fail);
-               spin_unlock_bh(&rcu_torture_lock);
-               return NULL;
-       }
-       atomic_inc(&n_rcu_torture_alloc);
-       p = rcu_torture_freelist.next;
-       list_del_init(p);
-       spin_unlock_bh(&rcu_torture_lock);
-       return container_of(p, struct rcu_torture, rtort_free);
-}
-
-/*
- * Free an element to the rcu_tortures pool.
- */
-static void
-rcu_torture_free(struct rcu_torture *p)
-{
-       atomic_inc(&n_rcu_torture_free);
-       spin_lock_bh(&rcu_torture_lock);
-       list_add_tail(&p->rtort_free, &rcu_torture_freelist);
-       spin_unlock_bh(&rcu_torture_lock);
-}
-
-struct rcu_random_state {
-       unsigned long rrs_state;
-       long rrs_count;
-};
-
-#define RCU_RANDOM_MULT 39916801  /* prime */
-#define RCU_RANDOM_ADD 479001701 /* prime */
-#define RCU_RANDOM_REFRESH 10000
-
-#define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 }
-
-/*
- * Crude but fast random-number generator.  Uses a linear congruential
- * generator, with occasional help from cpu_clock().
- */
-static unsigned long
-rcu_random(struct rcu_random_state *rrsp)
-{
-       if (--rrsp->rrs_count < 0) {
-               rrsp->rrs_state += (unsigned long)local_clock();
-               rrsp->rrs_count = RCU_RANDOM_REFRESH;
-       }
-       rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD;
-       return swahw32(rrsp->rrs_state);
-}
-
-static void
-rcu_stutter_wait(const char *title)
-{
-       while (stutter_pause_test || !rcutorture_runnable) {
-               if (rcutorture_runnable)
-                       schedule_timeout_interruptible(1);
-               else
-                       schedule_timeout_interruptible(round_jiffies_relative(HZ));
-               rcutorture_shutdown_absorb(title);
-       }
-}
-
-/*
- * Operations vector for selecting different types of tests.
- */
-
-struct rcu_torture_ops {
-       void (*init)(void);
-       int (*readlock)(void);
-       void (*read_delay)(struct rcu_random_state *rrsp);
-       void (*readunlock)(int idx);
-       int (*completed)(void);
-       void (*deferred_free)(struct rcu_torture *p);
-       void (*sync)(void);
-       void (*exp_sync)(void);
-       void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
-       void (*cb_barrier)(void);
-       void (*fqs)(void);
-       void (*stats)(char *page);
-       int irq_capable;
-       int can_boost;
-       const char *name;
-};
-
-static struct rcu_torture_ops *cur_ops;
-
-/*
- * Definitions for rcu torture testing.
- */
-
-static int rcu_torture_read_lock(void) __acquires(RCU)
-{
-       rcu_read_lock();
-       return 0;
-}
-
-static void rcu_read_delay(struct rcu_random_state *rrsp)
-{
-       const unsigned long shortdelay_us = 200;
-       const unsigned long longdelay_ms = 50;
-
-       /* We want a short delay sometimes to make a reader delay the grace
-        * period, and we want a long delay occasionally to trigger
-        * force_quiescent_state. */
-
-       if (!(rcu_random(rrsp) % (nrealreaders * 2000 * longdelay_ms)))
-               mdelay(longdelay_ms);
-       if (!(rcu_random(rrsp) % (nrealreaders * 2 * shortdelay_us)))
-               udelay(shortdelay_us);
-#ifdef CONFIG_PREEMPT
-       if (!preempt_count() && !(rcu_random(rrsp) % (nrealreaders * 20000)))
-               preempt_schedule();  /* No QS if preempt_disable() in effect */
-#endif
-}
-
-static void rcu_torture_read_unlock(int idx) __releases(RCU)
-{
-       rcu_read_unlock();
-}
-
-static int rcu_torture_completed(void)
-{
-       return rcu_batches_completed();
-}
-
-static void
-rcu_torture_cb(struct rcu_head *p)
-{
-       int i;
-       struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
-
-       if (fullstop != FULLSTOP_DONTSTOP) {
-               /* Test is ending, just drop callbacks on the floor. */
-               /* The next initialization will pick up the pieces. */
-               return;
-       }
-       i = rp->rtort_pipe_count;
-       if (i > RCU_TORTURE_PIPE_LEN)
-               i = RCU_TORTURE_PIPE_LEN;
-       atomic_inc(&rcu_torture_wcount[i]);
-       if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
-               rp->rtort_mbtest = 0;
-               rcu_torture_free(rp);
-       } else {
-               cur_ops->deferred_free(rp);
-       }
-}
-
-static int rcu_no_completed(void)
-{
-       return 0;
-}
-
-static void rcu_torture_deferred_free(struct rcu_torture *p)
-{
-       call_rcu(&p->rtort_rcu, rcu_torture_cb);
-}
-
-static void rcu_sync_torture_init(void)
-{
-       INIT_LIST_HEAD(&rcu_torture_removed);
-}
-
-static struct rcu_torture_ops rcu_ops = {
-       .init           = rcu_sync_torture_init,
-       .readlock       = rcu_torture_read_lock,
-       .read_delay     = rcu_read_delay,
-       .readunlock     = rcu_torture_read_unlock,
-       .completed      = rcu_torture_completed,
-       .deferred_free  = rcu_torture_deferred_free,
-       .sync           = synchronize_rcu,
-       .exp_sync       = synchronize_rcu_expedited,
-       .call           = call_rcu,
-       .cb_barrier     = rcu_barrier,
-       .fqs            = rcu_force_quiescent_state,
-       .stats          = NULL,
-       .irq_capable    = 1,
-       .can_boost      = rcu_can_boost(),
-       .name           = "rcu"
-};
-
-/*
- * Definitions for rcu_bh torture testing.
- */
-
-static int rcu_bh_torture_read_lock(void) __acquires(RCU_BH)
-{
-       rcu_read_lock_bh();
-       return 0;
-}
-
-static void rcu_bh_torture_read_unlock(int idx) __releases(RCU_BH)
-{
-       rcu_read_unlock_bh();
-}
-
-static int rcu_bh_torture_completed(void)
-{
-       return rcu_batches_completed_bh();
-}
-
-static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
-{
-       call_rcu_bh(&p->rtort_rcu, rcu_torture_cb);
-}
-
-static struct rcu_torture_ops rcu_bh_ops = {
-       .init           = rcu_sync_torture_init,
-       .readlock       = rcu_bh_torture_read_lock,
-       .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
-       .readunlock     = rcu_bh_torture_read_unlock,
-       .completed      = rcu_bh_torture_completed,
-       .deferred_free  = rcu_bh_torture_deferred_free,
-       .sync           = synchronize_rcu_bh,
-       .exp_sync       = synchronize_rcu_bh_expedited,
-       .call           = call_rcu_bh,
-       .cb_barrier     = rcu_barrier_bh,
-       .fqs            = rcu_bh_force_quiescent_state,
-       .stats          = NULL,
-       .irq_capable    = 1,
-       .name           = "rcu_bh"
-};
-
-/*
- * Definitions for srcu torture testing.
- */
-
-DEFINE_STATIC_SRCU(srcu_ctl);
-
-static int srcu_torture_read_lock(void) __acquires(&srcu_ctl)
-{
-       return srcu_read_lock(&srcu_ctl);
-}
-
-static void srcu_read_delay(struct rcu_random_state *rrsp)
-{
-       long delay;
-       const long uspertick = 1000000 / HZ;
-       const long longdelay = 10;
-
-       /* We want there to be long-running readers, but not all the time. */
-
-       delay = rcu_random(rrsp) % (nrealreaders * 2 * longdelay * uspertick);
-       if (!delay)
-               schedule_timeout_interruptible(longdelay);
-       else
-               rcu_read_delay(rrsp);
-}
-
-static void srcu_torture_read_unlock(int idx) __releases(&srcu_ctl)
-{
-       srcu_read_unlock(&srcu_ctl, idx);
-}
-
-static int srcu_torture_completed(void)
-{
-       return srcu_batches_completed(&srcu_ctl);
-}
-
-static void srcu_torture_deferred_free(struct rcu_torture *rp)
-{
-       call_srcu(&srcu_ctl, &rp->rtort_rcu, rcu_torture_cb);
-}
-
-static void srcu_torture_synchronize(void)
-{
-       synchronize_srcu(&srcu_ctl);
-}
-
-static void srcu_torture_call(struct rcu_head *head,
-                             void (*func)(struct rcu_head *head))
-{
-       call_srcu(&srcu_ctl, head, func);
-}
-
-static void srcu_torture_barrier(void)
-{
-       srcu_barrier(&srcu_ctl);
-}
-
-static void srcu_torture_stats(char *page)
-{
-       int cpu;
-       int idx = srcu_ctl.completed & 0x1;
-
-       page += sprintf(page, "%s%s per-CPU(idx=%d):",
-                      torture_type, TORTURE_FLAG, idx);
-       for_each_possible_cpu(cpu) {
-               page += sprintf(page, " %d(%lu,%lu)", cpu,
-                              per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx],
-                              per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]);
-       }
-       sprintf(page, "\n");
-}
-
-static void srcu_torture_synchronize_expedited(void)
-{
-       synchronize_srcu_expedited(&srcu_ctl);
-}
-
-static struct rcu_torture_ops srcu_ops = {
-       .init           = rcu_sync_torture_init,
-       .readlock       = srcu_torture_read_lock,
-       .read_delay     = srcu_read_delay,
-       .readunlock     = srcu_torture_read_unlock,
-       .completed      = srcu_torture_completed,
-       .deferred_free  = srcu_torture_deferred_free,
-       .sync           = srcu_torture_synchronize,
-       .exp_sync       = srcu_torture_synchronize_expedited,
-       .call           = srcu_torture_call,
-       .cb_barrier     = srcu_torture_barrier,
-       .stats          = srcu_torture_stats,
-       .name           = "srcu"
-};
-
-/*
- * Definitions for sched torture testing.
- */
-
-static int sched_torture_read_lock(void)
-{
-       preempt_disable();
-       return 0;
-}
-
-static void sched_torture_read_unlock(int idx)
-{
-       preempt_enable();
-}
-
-static void rcu_sched_torture_deferred_free(struct rcu_torture *p)
-{
-       call_rcu_sched(&p->rtort_rcu, rcu_torture_cb);
-}
-
-static struct rcu_torture_ops sched_ops = {
-       .init           = rcu_sync_torture_init,
-       .readlock       = sched_torture_read_lock,
-       .read_delay     = rcu_read_delay,  /* just reuse rcu's version. */
-       .readunlock     = sched_torture_read_unlock,
-       .completed      = rcu_no_completed,
-       .deferred_free  = rcu_sched_torture_deferred_free,
-       .sync           = synchronize_sched,
-       .exp_sync       = synchronize_sched_expedited,
-       .call           = call_rcu_sched,
-       .cb_barrier     = rcu_barrier_sched,
-       .fqs            = rcu_sched_force_quiescent_state,
-       .stats          = NULL,
-       .irq_capable    = 1,
-       .name           = "sched"
-};
-
-/*
- * RCU torture priority-boost testing.  Runs one real-time thread per
- * CPU for moderate bursts, repeatedly registering RCU callbacks and
- * spinning waiting for them to be invoked.  If a given callback takes
- * too long to be invoked, we assume that priority inversion has occurred.
- */
-
-struct rcu_boost_inflight {
-       struct rcu_head rcu;
-       int inflight;
-};
-
-static void rcu_torture_boost_cb(struct rcu_head *head)
-{
-       struct rcu_boost_inflight *rbip =
-               container_of(head, struct rcu_boost_inflight, rcu);
-
-       smp_mb(); /* Ensure RCU-core accesses precede clearing ->inflight */
-       rbip->inflight = 0;
-}
-
-static int rcu_torture_boost(void *arg)
-{
-       unsigned long call_rcu_time;
-       unsigned long endtime;
-       unsigned long oldstarttime;
-       struct rcu_boost_inflight rbi = { .inflight = 0 };
-       struct sched_param sp;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_boost started");
-
-       /* Set real-time priority. */
-       sp.sched_priority = 1;
-       if (sched_setscheduler(current, SCHED_FIFO, &sp) < 0) {
-               VERBOSE_PRINTK_STRING("rcu_torture_boost RT prio failed!");
-               n_rcu_torture_boost_rterror++;
-       }
-
-       init_rcu_head_on_stack(&rbi.rcu);
-       /* Each pass through the following loop does one boost-test cycle. */
-       do {
-               /* Wait for the next test interval. */
-               oldstarttime = boost_starttime;
-               while (ULONG_CMP_LT(jiffies, oldstarttime)) {
-                       schedule_timeout_interruptible(oldstarttime - jiffies);
-                       rcu_stutter_wait("rcu_torture_boost");
-                       if (kthread_should_stop() ||
-                           fullstop != FULLSTOP_DONTSTOP)
-                               goto checkwait;
-               }
-
-               /* Do one boost-test interval. */
-               endtime = oldstarttime + test_boost_duration * HZ;
-               call_rcu_time = jiffies;
-               while (ULONG_CMP_LT(jiffies, endtime)) {
-                       /* If we don't have a callback in flight, post one. */
-                       if (!rbi.inflight) {
-                               smp_mb(); /* RCU core before ->inflight = 1. */
-                               rbi.inflight = 1;
-                               call_rcu(&rbi.rcu, rcu_torture_boost_cb);
-                               if (jiffies - call_rcu_time >
-                                        test_boost_duration * HZ - HZ / 2) {
-                                       VERBOSE_PRINTK_STRING("rcu_torture_boost boosting failed");
-                                       n_rcu_torture_boost_failure++;
-                               }
-                               call_rcu_time = jiffies;
-                       }
-                       cond_resched();
-                       rcu_stutter_wait("rcu_torture_boost");
-                       if (kthread_should_stop() ||
-                           fullstop != FULLSTOP_DONTSTOP)
-                               goto checkwait;
-               }
-
-               /*
-                * Set the start time of the next test interval.
-                * Yes, this is vulnerable to long delays, but such
-                * delays simply cause a false negative for the next
-                * interval.  Besides, we are running at RT priority,
-                * so delays should be relatively rare.
-                */
-               while (oldstarttime == boost_starttime &&
-                      !kthread_should_stop()) {
-                       if (mutex_trylock(&boost_mutex)) {
-                               boost_starttime = jiffies +
-                                                 test_boost_interval * HZ;
-                               n_rcu_torture_boosts++;
-                               mutex_unlock(&boost_mutex);
-                               break;
-                       }
-                       schedule_timeout_uninterruptible(1);
-               }
-
-               /* Go do the stutter. */
-checkwait:     rcu_stutter_wait("rcu_torture_boost");
-       } while (!kthread_should_stop() && fullstop  == FULLSTOP_DONTSTOP);
-
-       /* Clean up and exit. */
-       VERBOSE_PRINTK_STRING("rcu_torture_boost task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_boost");
-       while (!kthread_should_stop() || rbi.inflight)
-               schedule_timeout_uninterruptible(1);
-       smp_mb(); /* order accesses to ->inflight before stack-frame death. */
-       destroy_rcu_head_on_stack(&rbi.rcu);
-       return 0;
-}
-
-/*
- * RCU torture force-quiescent-state kthread.  Repeatedly induces
- * bursts of calls to force_quiescent_state(), increasing the probability
- * of occurrence of some important types of race conditions.
- */
-static int
-rcu_torture_fqs(void *arg)
-{
-       unsigned long fqs_resume_time;
-       int fqs_burst_remaining;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_fqs task started");
-       do {
-               fqs_resume_time = jiffies + fqs_stutter * HZ;
-               while (ULONG_CMP_LT(jiffies, fqs_resume_time) &&
-                      !kthread_should_stop()) {
-                       schedule_timeout_interruptible(1);
-               }
-               fqs_burst_remaining = fqs_duration;
-               while (fqs_burst_remaining > 0 &&
-                      !kthread_should_stop()) {
-                       cur_ops->fqs();
-                       udelay(fqs_holdoff);
-                       fqs_burst_remaining -= fqs_holdoff;
-               }
-               rcu_stutter_wait("rcu_torture_fqs");
-       } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
-       VERBOSE_PRINTK_STRING("rcu_torture_fqs task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_fqs");
-       while (!kthread_should_stop())
-               schedule_timeout_uninterruptible(1);
-       return 0;
-}
-
-/*
- * RCU torture writer kthread.  Repeatedly substitutes a new structure
- * for that pointed to by rcu_torture_current, freeing the old structure
- * after a series of grace periods (the "pipeline").
- */
-static int
-rcu_torture_writer(void *arg)
-{
-       bool exp;
-       int i;
-       struct rcu_torture *rp;
-       struct rcu_torture *rp1;
-       struct rcu_torture *old_rp;
-       static DEFINE_RCU_RANDOM(rand);
-
-       VERBOSE_PRINTK_STRING("rcu_torture_writer task started");
-       set_user_nice(current, 19);
-
-       do {
-               schedule_timeout_uninterruptible(1);
-               rp = rcu_torture_alloc();
-               if (rp == NULL)
-                       continue;
-               rp->rtort_pipe_count = 0;
-               udelay(rcu_random(&rand) & 0x3ff);
-               old_rp = rcu_dereference_check(rcu_torture_current,
-                                              current == writer_task);
-               rp->rtort_mbtest = 1;
-               rcu_assign_pointer(rcu_torture_current, rp);
-               smp_wmb(); /* Mods to old_rp must follow rcu_assign_pointer() */
-               if (old_rp) {
-                       i = old_rp->rtort_pipe_count;
-                       if (i > RCU_TORTURE_PIPE_LEN)
-                               i = RCU_TORTURE_PIPE_LEN;
-                       atomic_inc(&rcu_torture_wcount[i]);
-                       old_rp->rtort_pipe_count++;
-                       if (gp_normal == gp_exp)
-                               exp = !!(rcu_random(&rand) & 0x80);
-                       else
-                               exp = gp_exp;
-                       if (!exp) {
-                               cur_ops->deferred_free(old_rp);
-                       } else {
-                               cur_ops->exp_sync();
-                               list_add(&old_rp->rtort_free,
-                                        &rcu_torture_removed);
-                               list_for_each_entry_safe(rp, rp1,
-                                                        &rcu_torture_removed,
-                                                        rtort_free) {
-                                       i = rp->rtort_pipe_count;
-                                       if (i > RCU_TORTURE_PIPE_LEN)
-                                               i = RCU_TORTURE_PIPE_LEN;
-                                       atomic_inc(&rcu_torture_wcount[i]);
-                                       if (++rp->rtort_pipe_count >=
-                                           RCU_TORTURE_PIPE_LEN) {
-                                               rp->rtort_mbtest = 0;
-                                               list_del(&rp->rtort_free);
-                                               rcu_torture_free(rp);
-                                       }
-                                }
-                       }
-               }
-               rcutorture_record_progress(++rcu_torture_current_version);
-               rcu_stutter_wait("rcu_torture_writer");
-       } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
-       VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_writer");
-       while (!kthread_should_stop())
-               schedule_timeout_uninterruptible(1);
-       return 0;
-}
-
-/*
- * RCU torture fake writer kthread.  Repeatedly calls sync, with a random
- * delay between calls.
- */
-static int
-rcu_torture_fakewriter(void *arg)
-{
-       DEFINE_RCU_RANDOM(rand);
-
-       VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task started");
-       set_user_nice(current, 19);
-
-       do {
-               schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
-               udelay(rcu_random(&rand) & 0x3ff);
-               if (cur_ops->cb_barrier != NULL &&
-                   rcu_random(&rand) % (nfakewriters * 8) == 0) {
-                       cur_ops->cb_barrier();
-               } else if (gp_normal == gp_exp) {
-                       if (rcu_random(&rand) & 0x80)
-                               cur_ops->sync();
-                       else
-                               cur_ops->exp_sync();
-               } else if (gp_normal) {
-                       cur_ops->sync();
-               } else {
-                       cur_ops->exp_sync();
-               }
-               rcu_stutter_wait("rcu_torture_fakewriter");
-       } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
-
-       VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_fakewriter");
-       while (!kthread_should_stop())
-               schedule_timeout_uninterruptible(1);
-       return 0;
-}
-
-void rcutorture_trace_dump(void)
-{
-       static atomic_t beenhere = ATOMIC_INIT(0);
-
-       if (atomic_read(&beenhere))
-               return;
-       if (atomic_xchg(&beenhere, 1) != 0)
-               return;
-       ftrace_dump(DUMP_ALL);
-}
-
-/*
- * RCU torture reader from timer handler.  Dereferences rcu_torture_current,
- * incrementing the corresponding element of the pipeline array.  The
- * counter in the element should never be greater than 1, otherwise, the
- * RCU implementation is broken.
- */
-static void rcu_torture_timer(unsigned long unused)
-{
-       int idx;
-       int completed;
-       int completed_end;
-       static DEFINE_RCU_RANDOM(rand);
-       static DEFINE_SPINLOCK(rand_lock);
-       struct rcu_torture *p;
-       int pipe_count;
-       unsigned long long ts;
-
-       idx = cur_ops->readlock();
-       completed = cur_ops->completed();
-       ts = rcu_trace_clock_local();
-       p = rcu_dereference_check(rcu_torture_current,
-                                 rcu_read_lock_bh_held() ||
-                                 rcu_read_lock_sched_held() ||
-                                 srcu_read_lock_held(&srcu_ctl));
-       if (p == NULL) {
-               /* Leave because rcu_torture_writer is not yet underway */
-               cur_ops->readunlock(idx);
-               return;
-       }
-       if (p->rtort_mbtest == 0)
-               atomic_inc(&n_rcu_torture_mberror);
-       spin_lock(&rand_lock);
-       cur_ops->read_delay(&rand);
-       n_rcu_torture_timers++;
-       spin_unlock(&rand_lock);
-       preempt_disable();
-       pipe_count = p->rtort_pipe_count;
-       if (pipe_count > RCU_TORTURE_PIPE_LEN) {
-               /* Should not happen, but... */
-               pipe_count = RCU_TORTURE_PIPE_LEN;
-       }
-       completed_end = cur_ops->completed();
-       if (pipe_count > 1) {
-               do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts,
-                                         completed, completed_end);
-               rcutorture_trace_dump();
-       }
-       __this_cpu_inc(rcu_torture_count[pipe_count]);
-       completed = completed_end - completed;
-       if (completed > RCU_TORTURE_PIPE_LEN) {
-               /* Should not happen, but... */
-               completed = RCU_TORTURE_PIPE_LEN;
-       }
-       __this_cpu_inc(rcu_torture_batch[completed]);
-       preempt_enable();
-       cur_ops->readunlock(idx);
-}
-
-/*
- * RCU torture reader kthread.  Repeatedly dereferences rcu_torture_current,
- * incrementing the corresponding element of the pipeline array.  The
- * counter in the element should never be greater than 1, otherwise, the
- * RCU implementation is broken.
- */
-static int
-rcu_torture_reader(void *arg)
-{
-       int completed;
-       int completed_end;
-       int idx;
-       DEFINE_RCU_RANDOM(rand);
-       struct rcu_torture *p;
-       int pipe_count;
-       struct timer_list t;
-       unsigned long long ts;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_reader task started");
-       set_user_nice(current, 19);
-       if (irqreader && cur_ops->irq_capable)
-               setup_timer_on_stack(&t, rcu_torture_timer, 0);
-
-       do {
-               if (irqreader && cur_ops->irq_capable) {
-                       if (!timer_pending(&t))
-                               mod_timer(&t, jiffies + 1);
-               }
-               idx = cur_ops->readlock();
-               completed = cur_ops->completed();
-               ts = rcu_trace_clock_local();
-               p = rcu_dereference_check(rcu_torture_current,
-                                         rcu_read_lock_bh_held() ||
-                                         rcu_read_lock_sched_held() ||
-                                         srcu_read_lock_held(&srcu_ctl));
-               if (p == NULL) {
-                       /* Wait for rcu_torture_writer to get underway */
-                       cur_ops->readunlock(idx);
-                       schedule_timeout_interruptible(HZ);
-                       continue;
-               }
-               if (p->rtort_mbtest == 0)
-                       atomic_inc(&n_rcu_torture_mberror);
-               cur_ops->read_delay(&rand);
-               preempt_disable();
-               pipe_count = p->rtort_pipe_count;
-               if (pipe_count > RCU_TORTURE_PIPE_LEN) {
-                       /* Should not happen, but... */
-                       pipe_count = RCU_TORTURE_PIPE_LEN;
-               }
-               completed_end = cur_ops->completed();
-               if (pipe_count > 1) {
-                       do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu,
-                                                 ts, completed, completed_end);
-                       rcutorture_trace_dump();
-               }
-               __this_cpu_inc(rcu_torture_count[pipe_count]);
-               completed = completed_end - completed;
-               if (completed > RCU_TORTURE_PIPE_LEN) {
-                       /* Should not happen, but... */
-                       completed = RCU_TORTURE_PIPE_LEN;
-               }
-               __this_cpu_inc(rcu_torture_batch[completed]);
-               preempt_enable();
-               cur_ops->readunlock(idx);
-               schedule();
-               rcu_stutter_wait("rcu_torture_reader");
-       } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
-       VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_reader");
-       if (irqreader && cur_ops->irq_capable)
-               del_timer_sync(&t);
-       while (!kthread_should_stop())
-               schedule_timeout_uninterruptible(1);
-       return 0;
-}
-
-/*
- * Create an RCU-torture statistics message in the specified buffer.
- */
-static void
-rcu_torture_printk(char *page)
-{
-       int cpu;
-       int i;
-       long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
-       long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
-
-       for_each_possible_cpu(cpu) {
-               for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
-                       pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i];
-                       batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i];
-               }
-       }
-       for (i = RCU_TORTURE_PIPE_LEN - 1; i >= 0; i--) {
-               if (pipesummary[i] != 0)
-                       break;
-       }
-       page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG);
-       page += sprintf(page,
-                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
-                      rcu_torture_current,
-                      rcu_torture_current_version,
-                      list_empty(&rcu_torture_freelist),
-                      atomic_read(&n_rcu_torture_alloc),
-                      atomic_read(&n_rcu_torture_alloc_fail),
-                      atomic_read(&n_rcu_torture_free));
-       page += sprintf(page, "rtmbe: %d rtbke: %ld rtbre: %ld ",
-                      atomic_read(&n_rcu_torture_mberror),
-                      n_rcu_torture_boost_ktrerror,
-                      n_rcu_torture_boost_rterror);
-       page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ",
-                      n_rcu_torture_boost_failure,
-                      n_rcu_torture_boosts,
-                      n_rcu_torture_timers);
-       page += sprintf(page,
-                      "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
-                      n_online_successes, n_online_attempts,
-                      n_offline_successes, n_offline_attempts,
-                      min_online, max_online,
-                      min_offline, max_offline,
-                      sum_online, sum_offline, HZ);
-       page += sprintf(page, "barrier: %ld/%ld:%ld",
-                      n_barrier_successes,
-                      n_barrier_attempts,
-                      n_rcu_torture_barrier_error);
-       page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
-       if (atomic_read(&n_rcu_torture_mberror) != 0 ||
-           n_rcu_torture_barrier_error != 0 ||
-           n_rcu_torture_boost_ktrerror != 0 ||
-           n_rcu_torture_boost_rterror != 0 ||
-           n_rcu_torture_boost_failure != 0 ||
-           i > 1) {
-               page += sprintf(page, "!!! ");
-               atomic_inc(&n_rcu_torture_error);
-               WARN_ON_ONCE(1);
-       }
-       page += sprintf(page, "Reader Pipe: ");
-       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
-               page += sprintf(page, " %ld", pipesummary[i]);
-       page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
-       page += sprintf(page, "Reader Batch: ");
-       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
-               page += sprintf(page, " %ld", batchsummary[i]);
-       page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
-       page += sprintf(page, "Free-Block Circulation: ");
-       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
-               page += sprintf(page, " %d",
-                              atomic_read(&rcu_torture_wcount[i]));
-       }
-       page += sprintf(page, "\n");
-       if (cur_ops->stats)
-               cur_ops->stats(page);
-}
-
-/*
- * Print torture statistics.  Caller must ensure that there is only
- * one call to this function at a given time!!!  This is normally
- * accomplished by relying on the module system to only have one copy
- * of the module loaded, and then by giving the rcu_torture_stats
- * kthread full control (or the init/cleanup functions when rcu_torture_stats
- * thread is not running).
- */
-static void
-rcu_torture_stats_print(void)
-{
-       int size = nr_cpu_ids * 200 + 8192;
-       char *buf;
-
-       buf = kmalloc(size, GFP_KERNEL);
-       if (!buf) {
-               pr_err("rcu-torture: Out of memory, need: %d", size);
-               return;
-       }
-       rcu_torture_printk(buf);
-       pr_alert("%s", buf);
-       kfree(buf);
-}
-
-/*
- * Periodically prints torture statistics, if periodic statistics printing
- * was specified via the stat_interval module parameter.
- *
- * No need to worry about fullstop here, since this one doesn't reference
- * volatile state or register callbacks.
- */
-static int
-rcu_torture_stats(void *arg)
-{
-       VERBOSE_PRINTK_STRING("rcu_torture_stats task started");
-       do {
-               schedule_timeout_interruptible(stat_interval * HZ);
-               rcu_torture_stats_print();
-               rcutorture_shutdown_absorb("rcu_torture_stats");
-       } while (!kthread_should_stop());
-       VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping");
-       return 0;
-}
-
-static int rcu_idle_cpu;       /* Force all torture tasks off this CPU */
-
-/* Shuffle tasks such that we allow @rcu_idle_cpu to become idle. A special case
- * is when @rcu_idle_cpu = -1, when we allow the tasks to run on all CPUs.
- */
-static void rcu_torture_shuffle_tasks(void)
-{
-       int i;
-
-       cpumask_setall(shuffle_tmp_mask);
-       get_online_cpus();
-
-       /* No point in shuffling if there is only one online CPU (ex: UP) */
-       if (num_online_cpus() == 1) {
-               put_online_cpus();
-               return;
-       }
-
-       if (rcu_idle_cpu != -1)
-               cpumask_clear_cpu(rcu_idle_cpu, shuffle_tmp_mask);
-
-       set_cpus_allowed_ptr(current, shuffle_tmp_mask);
-
-       if (reader_tasks) {
-               for (i = 0; i < nrealreaders; i++)
-                       if (reader_tasks[i])
-                               set_cpus_allowed_ptr(reader_tasks[i],
-                                                    shuffle_tmp_mask);
-       }
-       if (fakewriter_tasks) {
-               for (i = 0; i < nfakewriters; i++)
-                       if (fakewriter_tasks[i])
-                               set_cpus_allowed_ptr(fakewriter_tasks[i],
-                                                    shuffle_tmp_mask);
-       }
-       if (writer_task)
-               set_cpus_allowed_ptr(writer_task, shuffle_tmp_mask);
-       if (stats_task)
-               set_cpus_allowed_ptr(stats_task, shuffle_tmp_mask);
-       if (stutter_task)
-               set_cpus_allowed_ptr(stutter_task, shuffle_tmp_mask);
-       if (fqs_task)
-               set_cpus_allowed_ptr(fqs_task, shuffle_tmp_mask);
-       if (shutdown_task)
-               set_cpus_allowed_ptr(shutdown_task, shuffle_tmp_mask);
-#ifdef CONFIG_HOTPLUG_CPU
-       if (onoff_task)
-               set_cpus_allowed_ptr(onoff_task, shuffle_tmp_mask);
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-       if (stall_task)
-               set_cpus_allowed_ptr(stall_task, shuffle_tmp_mask);
-       if (barrier_cbs_tasks)
-               for (i = 0; i < n_barrier_cbs; i++)
-                       if (barrier_cbs_tasks[i])
-                               set_cpus_allowed_ptr(barrier_cbs_tasks[i],
-                                                    shuffle_tmp_mask);
-       if (barrier_task)
-               set_cpus_allowed_ptr(barrier_task, shuffle_tmp_mask);
-
-       if (rcu_idle_cpu == -1)
-               rcu_idle_cpu = num_online_cpus() - 1;
-       else
-               rcu_idle_cpu--;
-
-       put_online_cpus();
-}
-
-/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
- * system to become idle at a time and cut off its timer ticks. This is meant
- * to test the support for such tickless idle CPU in RCU.
- */
-static int
-rcu_torture_shuffle(void *arg)
-{
-       VERBOSE_PRINTK_STRING("rcu_torture_shuffle task started");
-       do {
-               schedule_timeout_interruptible(shuffle_interval * HZ);
-               rcu_torture_shuffle_tasks();
-               rcutorture_shutdown_absorb("rcu_torture_shuffle");
-       } while (!kthread_should_stop());
-       VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
-       return 0;
-}
-
-/* Cause the rcutorture test to "stutter", starting and stopping all
- * threads periodically.
- */
-static int
-rcu_torture_stutter(void *arg)
-{
-       VERBOSE_PRINTK_STRING("rcu_torture_stutter task started");
-       do {
-               schedule_timeout_interruptible(stutter * HZ);
-               stutter_pause_test = 1;
-               if (!kthread_should_stop())
-                       schedule_timeout_interruptible(stutter * HZ);
-               stutter_pause_test = 0;
-               rcutorture_shutdown_absorb("rcu_torture_stutter");
-       } while (!kthread_should_stop());
-       VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");
-       return 0;
-}
-
-static inline void
-rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
-{
-       pr_alert("%s" TORTURE_FLAG
-                "--- %s: nreaders=%d nfakewriters=%d "
-                "stat_interval=%d verbose=%d test_no_idle_hz=%d "
-                "shuffle_interval=%d stutter=%d irqreader=%d "
-                "fqs_duration=%d fqs_holdoff=%d fqs_stutter=%d "
-                "test_boost=%d/%d test_boost_interval=%d "
-                "test_boost_duration=%d shutdown_secs=%d "
-                "stall_cpu=%d stall_cpu_holdoff=%d "
-                "n_barrier_cbs=%d "
-                "onoff_interval=%d onoff_holdoff=%d\n",
-                torture_type, tag, nrealreaders, nfakewriters,
-                stat_interval, verbose, test_no_idle_hz, shuffle_interval,
-                stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
-                test_boost, cur_ops->can_boost,
-                test_boost_interval, test_boost_duration, shutdown_secs,
-                stall_cpu, stall_cpu_holdoff,
-                n_barrier_cbs,
-                onoff_interval, onoff_holdoff);
-}
-
-static struct notifier_block rcutorture_shutdown_nb = {
-       .notifier_call = rcutorture_shutdown_notify,
-};
-
-static void rcutorture_booster_cleanup(int cpu)
-{
-       struct task_struct *t;
-
-       if (boost_tasks[cpu] == NULL)
-               return;
-       mutex_lock(&boost_mutex);
-       VERBOSE_PRINTK_STRING("Stopping rcu_torture_boost task");
-       t = boost_tasks[cpu];
-       boost_tasks[cpu] = NULL;
-       mutex_unlock(&boost_mutex);
-
-       /* This must be outside of the mutex, otherwise deadlock! */
-       kthread_stop(t);
-       boost_tasks[cpu] = NULL;
-}
-
-static int rcutorture_booster_init(int cpu)
-{
-       int retval;
-
-       if (boost_tasks[cpu] != NULL)
-               return 0;  /* Already created, nothing more to do. */
-
-       /* Don't allow time recalculation while creating a new task. */
-       mutex_lock(&boost_mutex);
-       VERBOSE_PRINTK_STRING("Creating rcu_torture_boost task");
-       boost_tasks[cpu] = kthread_create_on_node(rcu_torture_boost, NULL,
-                                                 cpu_to_node(cpu),
-                                                 "rcu_torture_boost");
-       if (IS_ERR(boost_tasks[cpu])) {
-               retval = PTR_ERR(boost_tasks[cpu]);
-               VERBOSE_PRINTK_STRING("rcu_torture_boost task create failed");
-               n_rcu_torture_boost_ktrerror++;
-               boost_tasks[cpu] = NULL;
-               mutex_unlock(&boost_mutex);
-               return retval;
-       }
-       kthread_bind(boost_tasks[cpu], cpu);
-       wake_up_process(boost_tasks[cpu]);
-       mutex_unlock(&boost_mutex);
-       return 0;
-}
-
-/*
- * Cause the rcutorture test to shutdown the system after the test has
- * run for the time specified by the shutdown_secs module parameter.
- */
-static int
-rcu_torture_shutdown(void *arg)
-{
-       long delta;
-       unsigned long jiffies_snap;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_shutdown task started");
-       jiffies_snap = ACCESS_ONCE(jiffies);
-       while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
-              !kthread_should_stop()) {
-               delta = shutdown_time - jiffies_snap;
-               if (verbose)
-                       pr_alert("%s" TORTURE_FLAG
-                                "rcu_torture_shutdown task: %lu jiffies remaining\n",
-                                torture_type, delta);
-               schedule_timeout_interruptible(delta);
-               jiffies_snap = ACCESS_ONCE(jiffies);
-       }
-       if (kthread_should_stop()) {
-               VERBOSE_PRINTK_STRING("rcu_torture_shutdown task stopping");
-               return 0;
-       }
-
-       /* OK, shut down the system. */
-
-       VERBOSE_PRINTK_STRING("rcu_torture_shutdown task shutting down system");
-       shutdown_task = NULL;   /* Avoid self-kill deadlock. */
-       rcu_torture_cleanup();  /* Get the success/failure message. */
-       kernel_power_off();     /* Shut down the system. */
-       return 0;
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
-/*
- * Execute random CPU-hotplug operations at the interval specified
- * by the onoff_interval.
- */
-static int
-rcu_torture_onoff(void *arg)
-{
-       int cpu;
-       unsigned long delta;
-       int maxcpu = -1;
-       DEFINE_RCU_RANDOM(rand);
-       int ret;
-       unsigned long starttime;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_onoff task started");
-       for_each_online_cpu(cpu)
-               maxcpu = cpu;
-       WARN_ON(maxcpu < 0);
-       if (onoff_holdoff > 0) {
-               VERBOSE_PRINTK_STRING("rcu_torture_onoff begin holdoff");
-               schedule_timeout_interruptible(onoff_holdoff * HZ);
-               VERBOSE_PRINTK_STRING("rcu_torture_onoff end holdoff");
-       }
-       while (!kthread_should_stop()) {
-               cpu = (rcu_random(&rand) >> 4) % (maxcpu + 1);
-               if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
-                       if (verbose)
-                               pr_alert("%s" TORTURE_FLAG
-                                        "rcu_torture_onoff task: offlining %d\n",
-                                        torture_type, cpu);
-                       starttime = jiffies;
-                       n_offline_attempts++;
-                       ret = cpu_down(cpu);
-                       if (ret) {
-                               if (verbose)
-                                       pr_alert("%s" TORTURE_FLAG
-                                                "rcu_torture_onoff task: offline %d failed: errno %d\n",
-                                                torture_type, cpu, ret);
-                       } else {
-                               if (verbose)
-                                       pr_alert("%s" TORTURE_FLAG
-                                                "rcu_torture_onoff task: offlined %d\n",
-                                                torture_type, cpu);
-                               n_offline_successes++;
-                               delta = jiffies - starttime;
-                               sum_offline += delta;
-                               if (min_offline < 0) {
-                                       min_offline = delta;
-                                       max_offline = delta;
-                               }
-                               if (min_offline > delta)
-                                       min_offline = delta;
-                               if (max_offline < delta)
-                                       max_offline = delta;
-                       }
-               } else if (cpu_is_hotpluggable(cpu)) {
-                       if (verbose)
-                               pr_alert("%s" TORTURE_FLAG
-                                        "rcu_torture_onoff task: onlining %d\n",
-                                        torture_type, cpu);
-                       starttime = jiffies;
-                       n_online_attempts++;
-                       ret = cpu_up(cpu);
-                       if (ret) {
-                               if (verbose)
-                                       pr_alert("%s" TORTURE_FLAG
-                                                "rcu_torture_onoff task: online %d failed: errno %d\n",
-                                                torture_type, cpu, ret);
-                       } else {
-                               if (verbose)
-                                       pr_alert("%s" TORTURE_FLAG
-                                                "rcu_torture_onoff task: onlined %d\n",
-                                                torture_type, cpu);
-                               n_online_successes++;
-                               delta = jiffies - starttime;
-                               sum_online += delta;
-                               if (min_online < 0) {
-                                       min_online = delta;
-                                       max_online = delta;
-                               }
-                               if (min_online > delta)
-                                       min_online = delta;
-                               if (max_online < delta)
-                                       max_online = delta;
-                       }
-               }
-               schedule_timeout_interruptible(onoff_interval * HZ);
-       }
-       VERBOSE_PRINTK_STRING("rcu_torture_onoff task stopping");
-       return 0;
-}
-
-static int
-rcu_torture_onoff_init(void)
-{
-       int ret;
-
-       if (onoff_interval <= 0)
-               return 0;
-       onoff_task = kthread_run(rcu_torture_onoff, NULL, "rcu_torture_onoff");
-       if (IS_ERR(onoff_task)) {
-               ret = PTR_ERR(onoff_task);
-               onoff_task = NULL;
-               return ret;
-       }
-       return 0;
-}
-
-static void rcu_torture_onoff_cleanup(void)
-{
-       if (onoff_task == NULL)
-               return;
-       VERBOSE_PRINTK_STRING("Stopping rcu_torture_onoff task");
-       kthread_stop(onoff_task);
-       onoff_task = NULL;
-}
-
-#else /* #ifdef CONFIG_HOTPLUG_CPU */
-
-static int
-rcu_torture_onoff_init(void)
-{
-       return 0;
-}
-
-static void rcu_torture_onoff_cleanup(void)
-{
-}
-
-#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
-
-/*
- * CPU-stall kthread.  It waits as specified by stall_cpu_holdoff, then
- * induces a CPU stall for the time specified by stall_cpu.
- */
-static int rcu_torture_stall(void *args)
-{
-       unsigned long stop_at;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_stall task started");
-       if (stall_cpu_holdoff > 0) {
-               VERBOSE_PRINTK_STRING("rcu_torture_stall begin holdoff");
-               schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
-               VERBOSE_PRINTK_STRING("rcu_torture_stall end holdoff");
-       }
-       if (!kthread_should_stop()) {
-               stop_at = get_seconds() + stall_cpu;
-               /* RCU CPU stall is expected behavior in following code. */
-               pr_alert("rcu_torture_stall start.\n");
-               rcu_read_lock();
-               preempt_disable();
-               while (ULONG_CMP_LT(get_seconds(), stop_at))
-                       continue;  /* Induce RCU CPU stall warning. */
-               preempt_enable();
-               rcu_read_unlock();
-               pr_alert("rcu_torture_stall end.\n");
-       }
-       rcutorture_shutdown_absorb("rcu_torture_stall");
-       while (!kthread_should_stop())
-               schedule_timeout_interruptible(10 * HZ);
-       return 0;
-}
-
-/* Spawn CPU-stall kthread, if stall_cpu specified. */
-static int __init rcu_torture_stall_init(void)
-{
-       int ret;
-
-       if (stall_cpu <= 0)
-               return 0;
-       stall_task = kthread_run(rcu_torture_stall, NULL, "rcu_torture_stall");
-       if (IS_ERR(stall_task)) {
-               ret = PTR_ERR(stall_task);
-               stall_task = NULL;
-               return ret;
-       }
-       return 0;
-}
-
-/* Clean up after the CPU-stall kthread, if one was spawned. */
-static void rcu_torture_stall_cleanup(void)
-{
-       if (stall_task == NULL)
-               return;
-       VERBOSE_PRINTK_STRING("Stopping rcu_torture_stall_task.");
-       kthread_stop(stall_task);
-       stall_task = NULL;
-}
-
-/* Callback function for RCU barrier testing. */
-void rcu_torture_barrier_cbf(struct rcu_head *rcu)
-{
-       atomic_inc(&barrier_cbs_invoked);
-}
-
-/* kthread function to register callbacks used to test RCU barriers. */
-static int rcu_torture_barrier_cbs(void *arg)
-{
-       long myid = (long)arg;
-       bool lastphase = 0;
-       bool newphase;
-       struct rcu_head rcu;
-
-       init_rcu_head_on_stack(&rcu);
-       VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task started");
-       set_user_nice(current, 19);
-       do {
-               wait_event(barrier_cbs_wq[myid],
-                          (newphase =
-                           ACCESS_ONCE(barrier_phase)) != lastphase ||
-                          kthread_should_stop() ||
-                          fullstop != FULLSTOP_DONTSTOP);
-               lastphase = newphase;
-               smp_mb(); /* ensure barrier_phase load before ->call(). */
-               if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
-                       break;
-               cur_ops->call(&rcu, rcu_torture_barrier_cbf);
-               if (atomic_dec_and_test(&barrier_cbs_count))
-                       wake_up(&barrier_wq);
-       } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
-       VERBOSE_PRINTK_STRING("rcu_torture_barrier_cbs task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
-       while (!kthread_should_stop())
-               schedule_timeout_interruptible(1);
-       cur_ops->cb_barrier();
-       destroy_rcu_head_on_stack(&rcu);
-       return 0;
-}
-
-/* kthread function to drive and coordinate RCU barrier testing. */
-static int rcu_torture_barrier(void *arg)
-{
-       int i;
-
-       VERBOSE_PRINTK_STRING("rcu_torture_barrier task starting");
-       do {
-               atomic_set(&barrier_cbs_invoked, 0);
-               atomic_set(&barrier_cbs_count, n_barrier_cbs);
-               smp_mb(); /* Ensure barrier_phase after prior assignments. */
-               barrier_phase = !barrier_phase;
-               for (i = 0; i < n_barrier_cbs; i++)
-                       wake_up(&barrier_cbs_wq[i]);
-               wait_event(barrier_wq,
-                          atomic_read(&barrier_cbs_count) == 0 ||
-                          kthread_should_stop() ||
-                          fullstop != FULLSTOP_DONTSTOP);
-               if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
-                       break;
-               n_barrier_attempts++;
-               cur_ops->cb_barrier(); /* Implies smp_mb() for wait_event(). */
-               if (atomic_read(&barrier_cbs_invoked) != n_barrier_cbs) {
-                       n_rcu_torture_barrier_error++;
-                       WARN_ON_ONCE(1);
-               }
-               n_barrier_successes++;
-               schedule_timeout_interruptible(HZ / 10);
-       } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
-       VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_barrier");
-       while (!kthread_should_stop())
-               schedule_timeout_interruptible(1);
-       return 0;
-}
-
-/* Initialize RCU barrier testing. */
-static int rcu_torture_barrier_init(void)
-{
-       int i;
-       int ret;
-
-       if (n_barrier_cbs == 0)
-               return 0;
-       if (cur_ops->call == NULL || cur_ops->cb_barrier == NULL) {
-               pr_alert("%s" TORTURE_FLAG
-                        " Call or barrier ops missing for %s,\n",
-                        torture_type, cur_ops->name);
-               pr_alert("%s" TORTURE_FLAG
-                        " RCU barrier testing omitted from run.\n",
-                        torture_type);
-               return 0;
-       }
-       atomic_set(&barrier_cbs_count, 0);
-       atomic_set(&barrier_cbs_invoked, 0);
-       barrier_cbs_tasks =
-               kzalloc(n_barrier_cbs * sizeof(barrier_cbs_tasks[0]),
-                       GFP_KERNEL);
-       barrier_cbs_wq =
-               kzalloc(n_barrier_cbs * sizeof(barrier_cbs_wq[0]),
-                       GFP_KERNEL);
-       if (barrier_cbs_tasks == NULL || !barrier_cbs_wq)
-               return -ENOMEM;
-       for (i = 0; i < n_barrier_cbs; i++) {
-               init_waitqueue_head(&barrier_cbs_wq[i]);
-               barrier_cbs_tasks[i] = kthread_run(rcu_torture_barrier_cbs,
-                                                  (void *)(long)i,
-                                                  "rcu_torture_barrier_cbs");
-               if (IS_ERR(barrier_cbs_tasks[i])) {
-                       ret = PTR_ERR(barrier_cbs_tasks[i]);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier_cbs");
-                       barrier_cbs_tasks[i] = NULL;
-                       return ret;
-               }
-       }
-       barrier_task = kthread_run(rcu_torture_barrier, NULL,
-                                  "rcu_torture_barrier");
-       if (IS_ERR(barrier_task)) {
-               ret = PTR_ERR(barrier_task);
-               VERBOSE_PRINTK_ERRSTRING("Failed to create rcu_torture_barrier");
-               barrier_task = NULL;
-       }
-       return 0;
-}
-
-/* Clean up after RCU barrier testing. */
-static void rcu_torture_barrier_cleanup(void)
-{
-       int i;
-
-       if (barrier_task != NULL) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier task");
-               kthread_stop(barrier_task);
-               barrier_task = NULL;
-       }
-       if (barrier_cbs_tasks != NULL) {
-               for (i = 0; i < n_barrier_cbs; i++) {
-                       if (barrier_cbs_tasks[i] != NULL) {
-                               VERBOSE_PRINTK_STRING("Stopping rcu_torture_barrier_cbs task");
-                               kthread_stop(barrier_cbs_tasks[i]);
-                               barrier_cbs_tasks[i] = NULL;
-                       }
-               }
-               kfree(barrier_cbs_tasks);
-               barrier_cbs_tasks = NULL;
-       }
-       if (barrier_cbs_wq != NULL) {
-               kfree(barrier_cbs_wq);
-               barrier_cbs_wq = NULL;
-       }
-}
-
-static int rcutorture_cpu_notify(struct notifier_block *self,
-                                unsigned long action, void *hcpu)
-{
-       long cpu = (long)hcpu;
-
-       switch (action) {
-       case CPU_ONLINE:
-       case CPU_DOWN_FAILED:
-               (void)rcutorture_booster_init(cpu);
-               break;
-       case CPU_DOWN_PREPARE:
-               rcutorture_booster_cleanup(cpu);
-               break;
-       default:
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block rcutorture_cpu_nb = {
-       .notifier_call = rcutorture_cpu_notify,
-};
-
-static void
-rcu_torture_cleanup(void)
-{
-       int i;
-
-       mutex_lock(&fullstop_mutex);
-       rcutorture_record_test_transition();
-       if (fullstop == FULLSTOP_SHUTDOWN) {
-               pr_warn(/* but going down anyway, so... */
-                      "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
-               mutex_unlock(&fullstop_mutex);
-               schedule_timeout_uninterruptible(10);
-               if (cur_ops->cb_barrier != NULL)
-                       cur_ops->cb_barrier();
-               return;
-       }
-       fullstop = FULLSTOP_RMMOD;
-       mutex_unlock(&fullstop_mutex);
-       unregister_reboot_notifier(&rcutorture_shutdown_nb);
-       rcu_torture_barrier_cleanup();
-       rcu_torture_stall_cleanup();
-       if (stutter_task) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
-               kthread_stop(stutter_task);
-       }
-       stutter_task = NULL;
-       if (shuffler_task) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
-               kthread_stop(shuffler_task);
-               free_cpumask_var(shuffle_tmp_mask);
-       }
-       shuffler_task = NULL;
-
-       if (writer_task) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
-               kthread_stop(writer_task);
-       }
-       writer_task = NULL;
-
-       if (reader_tasks) {
-               for (i = 0; i < nrealreaders; i++) {
-                       if (reader_tasks[i]) {
-                               VERBOSE_PRINTK_STRING(
-                                       "Stopping rcu_torture_reader task");
-                               kthread_stop(reader_tasks[i]);
-                       }
-                       reader_tasks[i] = NULL;
-               }
-               kfree(reader_tasks);
-               reader_tasks = NULL;
-       }
-       rcu_torture_current = NULL;
-
-       if (fakewriter_tasks) {
-               for (i = 0; i < nfakewriters; i++) {
-                       if (fakewriter_tasks[i]) {
-                               VERBOSE_PRINTK_STRING(
-                                       "Stopping rcu_torture_fakewriter task");
-                               kthread_stop(fakewriter_tasks[i]);
-                       }
-                       fakewriter_tasks[i] = NULL;
-               }
-               kfree(fakewriter_tasks);
-               fakewriter_tasks = NULL;
-       }
-
-       if (stats_task) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
-               kthread_stop(stats_task);
-       }
-       stats_task = NULL;
-
-       if (fqs_task) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_fqs task");
-               kthread_stop(fqs_task);
-       }
-       fqs_task = NULL;
-       if ((test_boost == 1 && cur_ops->can_boost) ||
-           test_boost == 2) {
-               unregister_cpu_notifier(&rcutorture_cpu_nb);
-               for_each_possible_cpu(i)
-                       rcutorture_booster_cleanup(i);
-       }
-       if (shutdown_task != NULL) {
-               VERBOSE_PRINTK_STRING("Stopping rcu_torture_shutdown task");
-               kthread_stop(shutdown_task);
-       }
-       shutdown_task = NULL;
-       rcu_torture_onoff_cleanup();
-
-       /* Wait for all RCU callbacks to fire.  */
-
-       if (cur_ops->cb_barrier != NULL)
-               cur_ops->cb_barrier();
-
-       rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
-
-       if (atomic_read(&n_rcu_torture_error) || n_rcu_torture_barrier_error)
-               rcu_torture_print_module_parms(cur_ops, "End of test: FAILURE");
-       else if (n_online_successes != n_online_attempts ||
-                n_offline_successes != n_offline_attempts)
-               rcu_torture_print_module_parms(cur_ops,
-                                              "End of test: RCU_HOTPLUG");
-       else
-               rcu_torture_print_module_parms(cur_ops, "End of test: SUCCESS");
-}
-
-#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
-static void rcu_torture_leak_cb(struct rcu_head *rhp)
-{
-}
-
-static void rcu_torture_err_cb(struct rcu_head *rhp)
-{
-       /*
-        * This -might- happen due to race conditions, but is unlikely.
-        * The scenario that leads to this happening is that the
-        * first of the pair of duplicate callbacks is queued,
-        * someone else starts a grace period that includes that
-        * callback, then the second of the pair must wait for the
-        * next grace period.  Unlikely, but can happen.  If it
-        * does happen, the debug-objects subsystem won't have splatted.
-        */
-       pr_alert("rcutorture: duplicated callback was invoked.\n");
-}
-#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-
-/*
- * Verify that double-free causes debug-objects to complain, but only
- * if CONFIG_DEBUG_OBJECTS_RCU_HEAD=y.  Otherwise, say that the test
- * cannot be carried out.
- */
-static void rcu_test_debug_objects(void)
-{
-#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
-       struct rcu_head rh1;
-       struct rcu_head rh2;
-
-       init_rcu_head_on_stack(&rh1);
-       init_rcu_head_on_stack(&rh2);
-       pr_alert("rcutorture: WARN: Duplicate call_rcu() test starting.\n");
-
-       /* Try to queue the rh2 pair of callbacks for the same grace period. */
-       preempt_disable(); /* Prevent preemption from interrupting test. */
-       rcu_read_lock(); /* Make it impossible to finish a grace period. */
-       call_rcu(&rh1, rcu_torture_leak_cb); /* Start grace period. */
-       local_irq_disable(); /* Make it harder to start a new grace period. */
-       call_rcu(&rh2, rcu_torture_leak_cb);
-       call_rcu(&rh2, rcu_torture_err_cb); /* Duplicate callback. */
-       local_irq_enable();
-       rcu_read_unlock();
-       preempt_enable();
-
-       /* Wait for them all to get done so we can safely return. */
-       rcu_barrier();
-       pr_alert("rcutorture: WARN: Duplicate call_rcu() test complete.\n");
-       destroy_rcu_head_on_stack(&rh1);
-       destroy_rcu_head_on_stack(&rh2);
-#else /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-       pr_alert("rcutorture: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_rcu()\n");
-#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-}
-
-static int __init
-rcu_torture_init(void)
-{
-       int i;
-       int cpu;
-       int firsterr = 0;
-       int retval;
-       static struct rcu_torture_ops *torture_ops[] = {
-               &rcu_ops, &rcu_bh_ops, &srcu_ops, &sched_ops,
-       };
-
-       mutex_lock(&fullstop_mutex);
-
-       /* Process args and tell the world that the torturer is on the job. */
-       for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
-               cur_ops = torture_ops[i];
-               if (strcmp(torture_type, cur_ops->name) == 0)
-                       break;
-       }
-       if (i == ARRAY_SIZE(torture_ops)) {
-               pr_alert("rcu-torture: invalid torture type: \"%s\"\n",
-                        torture_type);
-               pr_alert("rcu-torture types:");
-               for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
-                       pr_alert(" %s", torture_ops[i]->name);
-               pr_alert("\n");
-               mutex_unlock(&fullstop_mutex);
-               return -EINVAL;
-       }
-       if (cur_ops->fqs == NULL && fqs_duration != 0) {
-               pr_alert("rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n");
-               fqs_duration = 0;
-       }
-       if (cur_ops->init)
-               cur_ops->init(); /* no "goto unwind" prior to this point!!! */
-
-       if (nreaders >= 0)
-               nrealreaders = nreaders;
-       else
-               nrealreaders = 2 * num_online_cpus();
-       rcu_torture_print_module_parms(cur_ops, "Start of test");
-       fullstop = FULLSTOP_DONTSTOP;
-
-       /* Set up the freelist. */
-
-       INIT_LIST_HEAD(&rcu_torture_freelist);
-       for (i = 0; i < ARRAY_SIZE(rcu_tortures); i++) {
-               rcu_tortures[i].rtort_mbtest = 0;
-               list_add_tail(&rcu_tortures[i].rtort_free,
-                             &rcu_torture_freelist);
-       }
-
-       /* Initialize the statistics so that each run gets its own numbers. */
-
-       rcu_torture_current = NULL;
-       rcu_torture_current_version = 0;
-       atomic_set(&n_rcu_torture_alloc, 0);
-       atomic_set(&n_rcu_torture_alloc_fail, 0);
-       atomic_set(&n_rcu_torture_free, 0);
-       atomic_set(&n_rcu_torture_mberror, 0);
-       atomic_set(&n_rcu_torture_error, 0);
-       n_rcu_torture_barrier_error = 0;
-       n_rcu_torture_boost_ktrerror = 0;
-       n_rcu_torture_boost_rterror = 0;
-       n_rcu_torture_boost_failure = 0;
-       n_rcu_torture_boosts = 0;
-       for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
-               atomic_set(&rcu_torture_wcount[i], 0);
-       for_each_possible_cpu(cpu) {
-               for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
-                       per_cpu(rcu_torture_count, cpu)[i] = 0;
-                       per_cpu(rcu_torture_batch, cpu)[i] = 0;
-               }
-       }
-
-       /* Start up the kthreads. */
-
-       VERBOSE_PRINTK_STRING("Creating rcu_torture_writer task");
-       writer_task = kthread_create(rcu_torture_writer, NULL,
-                                    "rcu_torture_writer");
-       if (IS_ERR(writer_task)) {
-               firsterr = PTR_ERR(writer_task);
-               VERBOSE_PRINTK_ERRSTRING("Failed to create writer");
-               writer_task = NULL;
-               goto unwind;
-       }
-       wake_up_process(writer_task);
-       fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]),
-                                  GFP_KERNEL);
-       if (fakewriter_tasks == NULL) {
-               VERBOSE_PRINTK_ERRSTRING("out of memory");
-               firsterr = -ENOMEM;
-               goto unwind;
-       }
-       for (i = 0; i < nfakewriters; i++) {
-               VERBOSE_PRINTK_STRING("Creating rcu_torture_fakewriter task");
-               fakewriter_tasks[i] = kthread_run(rcu_torture_fakewriter, NULL,
-                                                 "rcu_torture_fakewriter");
-               if (IS_ERR(fakewriter_tasks[i])) {
-                       firsterr = PTR_ERR(fakewriter_tasks[i]);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create fakewriter");
-                       fakewriter_tasks[i] = NULL;
-                       goto unwind;
-               }
-       }
-       reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]),
-                              GFP_KERNEL);
-       if (reader_tasks == NULL) {
-               VERBOSE_PRINTK_ERRSTRING("out of memory");
-               firsterr = -ENOMEM;
-               goto unwind;
-       }
-       for (i = 0; i < nrealreaders; i++) {
-               VERBOSE_PRINTK_STRING("Creating rcu_torture_reader task");
-               reader_tasks[i] = kthread_run(rcu_torture_reader, NULL,
-                                             "rcu_torture_reader");
-               if (IS_ERR(reader_tasks[i])) {
-                       firsterr = PTR_ERR(reader_tasks[i]);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create reader");
-                       reader_tasks[i] = NULL;
-                       goto unwind;
-               }
-       }
-       if (stat_interval > 0) {
-               VERBOSE_PRINTK_STRING("Creating rcu_torture_stats task");
-               stats_task = kthread_run(rcu_torture_stats, NULL,
-                                       "rcu_torture_stats");
-               if (IS_ERR(stats_task)) {
-                       firsterr = PTR_ERR(stats_task);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create stats");
-                       stats_task = NULL;
-                       goto unwind;
-               }
-       }
-       if (test_no_idle_hz) {
-               rcu_idle_cpu = num_online_cpus() - 1;
-
-               if (!alloc_cpumask_var(&shuffle_tmp_mask, GFP_KERNEL)) {
-                       firsterr = -ENOMEM;
-                       VERBOSE_PRINTK_ERRSTRING("Failed to alloc mask");
-                       goto unwind;
-               }
-
-               /* Create the shuffler thread */
-               shuffler_task = kthread_run(rcu_torture_shuffle, NULL,
-                                         "rcu_torture_shuffle");
-               if (IS_ERR(shuffler_task)) {
-                       free_cpumask_var(shuffle_tmp_mask);
-                       firsterr = PTR_ERR(shuffler_task);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create shuffler");
-                       shuffler_task = NULL;
-                       goto unwind;
-               }
-       }
-       if (stutter < 0)
-               stutter = 0;
-       if (stutter) {
-               /* Create the stutter thread */
-               stutter_task = kthread_run(rcu_torture_stutter, NULL,
-                                         "rcu_torture_stutter");
-               if (IS_ERR(stutter_task)) {
-                       firsterr = PTR_ERR(stutter_task);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create stutter");
-                       stutter_task = NULL;
-                       goto unwind;
-               }
-       }
-       if (fqs_duration < 0)
-               fqs_duration = 0;
-       if (fqs_duration) {
-               /* Create the stutter thread */
-               fqs_task = kthread_run(rcu_torture_fqs, NULL,
-                                      "rcu_torture_fqs");
-               if (IS_ERR(fqs_task)) {
-                       firsterr = PTR_ERR(fqs_task);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create fqs");
-                       fqs_task = NULL;
-                       goto unwind;
-               }
-       }
-       if (test_boost_interval < 1)
-               test_boost_interval = 1;
-       if (test_boost_duration < 2)
-               test_boost_duration = 2;
-       if ((test_boost == 1 && cur_ops->can_boost) ||
-           test_boost == 2) {
-
-               boost_starttime = jiffies + test_boost_interval * HZ;
-               register_cpu_notifier(&rcutorture_cpu_nb);
-               for_each_possible_cpu(i) {
-                       if (cpu_is_offline(i))
-                               continue;  /* Heuristic: CPU can go offline. */
-                       retval = rcutorture_booster_init(i);
-                       if (retval < 0) {
-                               firsterr = retval;
-                               goto unwind;
-                       }
-               }
-       }
-       if (shutdown_secs > 0) {
-               shutdown_time = jiffies + shutdown_secs * HZ;
-               shutdown_task = kthread_create(rcu_torture_shutdown, NULL,
-                                              "rcu_torture_shutdown");
-               if (IS_ERR(shutdown_task)) {
-                       firsterr = PTR_ERR(shutdown_task);
-                       VERBOSE_PRINTK_ERRSTRING("Failed to create shutdown");
-                       shutdown_task = NULL;
-                       goto unwind;
-               }
-               wake_up_process(shutdown_task);
-       }
-       i = rcu_torture_onoff_init();
-       if (i != 0) {
-               firsterr = i;
-               goto unwind;
-       }
-       register_reboot_notifier(&rcutorture_shutdown_nb);
-       i = rcu_torture_stall_init();
-       if (i != 0) {
-               firsterr = i;
-               goto unwind;
-       }
-       retval = rcu_torture_barrier_init();
-       if (retval != 0) {
-               firsterr = retval;
-               goto unwind;
-       }
-       if (object_debug)
-               rcu_test_debug_objects();
-       rcutorture_record_test_transition();
-       mutex_unlock(&fullstop_mutex);
-       return 0;
-
-unwind:
-       mutex_unlock(&fullstop_mutex);
-       rcu_torture_cleanup();
-       return firsterr;
-}
-
-module_init(rcu_torture_init);
-module_exit(rcu_torture_cleanup);
index b3d116cd072d7bd24803a52c8d6b478930bd6b8b..0c47e300210ad61c3d79854426150fd5246f5750 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
@@ -58,8 +58,6 @@
 #include <linux/suspend.h>
 
 #include "tree.h"
-#include <trace/events/rcu.h>
-
 #include "rcu.h"
 
 MODULE_ALIAS("rcutree");
@@ -837,7 +835,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
         * to the next.  Only do this for the primary flavor of RCU.
         */
        if (rdp->rsp == rcu_state &&
-           ULONG_CMP_GE(ACCESS_ONCE(jiffies), rdp->rsp->jiffies_resched)) {
+           ULONG_CMP_GE(jiffies, rdp->rsp->jiffies_resched)) {
                rdp->rsp->jiffies_resched += 5;
                resched_cpu(rdp->cpu);
        }
@@ -847,7 +845,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
-       unsigned long j = ACCESS_ONCE(jiffies);
+       unsigned long j = jiffies;
        unsigned long j1;
 
        rsp->gp_start = j;
@@ -1005,7 +1003,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 
        if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp))
                return;
-       j = ACCESS_ONCE(jiffies);
+       j = jiffies;
 
        /*
         * Lots of memory barriers to reject false positives.
@@ -1423,13 +1421,14 @@ static int rcu_gp_init(struct rcu_state *rsp)
 
        /* Advance to a new grace period and initialize state. */
        record_gp_stall_check_time(rsp);
-       smp_wmb(); /* Record GP times before starting GP. */
-       rsp->gpnum++;
+       /* Record GP times before starting GP, hence smp_store_release(). */
+       smp_store_release(&rsp->gpnum, rsp->gpnum + 1);
        trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
        raw_spin_unlock_irq(&rnp->lock);
 
        /* Exclude any concurrent CPU-hotplug operations. */
        mutex_lock(&rsp->onoff_mutex);
+       smp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */
 
        /*
         * Set the quiescent-state-needed bits in all the rcu_node
@@ -1557,10 +1556,11 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
        }
        rnp = rcu_get_root(rsp);
        raw_spin_lock_irq(&rnp->lock);
-       smp_mb__after_unlock_lock();
+       smp_mb__after_unlock_lock(); /* Order GP before ->completed update. */
        rcu_nocb_gp_set(rnp, nocb);
 
-       rsp->completed = rsp->gpnum; /* Declare grace period done. */
+       /* Declare grace period done. */
+       ACCESS_ONCE(rsp->completed) = rsp->gpnum;
        trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end"));
        rsp->fqs_state = RCU_GP_IDLE;
        rdp = this_cpu_ptr(rsp->rda);
@@ -2304,7 +2304,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
                if (rnp_old != NULL)
                        raw_spin_unlock(&rnp_old->fqslock);
                if (ret) {
-                       rsp->n_force_qs_lh++;
+                       ACCESS_ONCE(rsp->n_force_qs_lh)++;
                        return;
                }
                rnp_old = rnp;
@@ -2316,7 +2316,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
        smp_mb__after_unlock_lock();
        raw_spin_unlock(&rnp_old->fqslock);
        if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
-               rsp->n_force_qs_lh++;
+               ACCESS_ONCE(rsp->n_force_qs_lh)++;
                raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
                return;  /* Someone beat us to it. */
        }
@@ -2639,6 +2639,58 @@ void synchronize_rcu_bh(void)
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
 
+/**
+ * get_state_synchronize_rcu - Snapshot current RCU state
+ *
+ * Returns a cookie that is used by a later call to cond_synchronize_rcu()
+ * to determine whether or not a full grace period has elapsed in the
+ * meantime.
+ */
+unsigned long get_state_synchronize_rcu(void)
+{
+       /*
+        * Any prior manipulation of RCU-protected data must happen
+        * before the load from ->gpnum.
+        */
+       smp_mb();  /* ^^^ */
+
+       /*
+        * Make sure this load happens before the purportedly
+        * time-consuming work between get_state_synchronize_rcu()
+        * and cond_synchronize_rcu().
+        */
+       return smp_load_acquire(&rcu_state->gpnum);
+}
+EXPORT_SYMBOL_GPL(get_state_synchronize_rcu);
+
+/**
+ * cond_synchronize_rcu - Conditionally wait for an RCU grace period
+ *
+ * @oldstate: return value from earlier call to get_state_synchronize_rcu()
+ *
+ * If a full RCU grace period has elapsed since the earlier call to
+ * get_state_synchronize_rcu(), just return.  Otherwise, invoke
+ * synchronize_rcu() to wait for a full grace period.
+ *
+ * Yes, this function does not take counter wrap into account.  But
+ * counter wrap is harmless.  If the counter wraps, we have waited for
+ * more than 2 billion grace periods (and way more on a 64-bit system!),
+ * so waiting for one additional grace period should be just fine.
+ */
+void cond_synchronize_rcu(unsigned long oldstate)
+{
+       unsigned long newstate;
+
+       /*
+        * Ensure that this load happens before any RCU-destructive
+        * actions the caller might carry out after we return.
+        */
+       newstate = smp_load_acquire(&rcu_state->completed);
+       if (ULONG_CMP_GE(oldstate, newstate))
+               synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(cond_synchronize_rcu);
+
 static int synchronize_sched_expedited_cpu_stop(void *data)
 {
        /*
@@ -2880,7 +2932,7 @@ static int rcu_pending(int cpu)
  * non-NULL, store an indication of whether all callbacks are lazy.
  * (If there are no callbacks, all of them are deemed to be lazy.)
  */
-static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
+static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
 {
        bool al = true;
        bool hc = false;
index 8c19873f1ac9b7eda78d55595dae0913b4ad45e3..75dc3c39a02a110b3d0f7b6b3b0557806f883094 100644 (file)
@@ -13,8 +13,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
index 6e2ef4b2b920bc3db08ececbc37d74cf83b8dc14..962d1d589929e2b9c8350bd4432d96c4e31017f2 100644 (file)
@@ -14,8 +14,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright Red Hat, 2009
  * Copyright IBM Corporation, 2009
@@ -1586,11 +1586,13 @@ static void rcu_prepare_kthreads(int cpu)
  * Because we not have RCU_FAST_NO_HZ, just check whether this CPU needs
  * any flavor of RCU.
  */
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
 int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
 {
        *delta_jiffies = ULONG_MAX;
        return rcu_cpu_has_callbacks(cpu, NULL);
 }
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 
 /*
  * Because we do not have RCU_FAST_NO_HZ, don't bother cleaning up
@@ -1656,7 +1658,7 @@ extern int tick_nohz_active;
  * only if it has been awhile since the last time we did so.  Afterwards,
  * if there are any callbacks ready for immediate invocation, return true.
  */
-static bool rcu_try_advance_all_cbs(void)
+static bool __maybe_unused rcu_try_advance_all_cbs(void)
 {
        bool cbs_ready = false;
        struct rcu_data *rdp;
@@ -1696,6 +1698,7 @@ static bool rcu_try_advance_all_cbs(void)
  *
  * The caller must have disabled interrupts.
  */
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
 int rcu_needs_cpu(int cpu, unsigned long *dj)
 {
        struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
@@ -1726,6 +1729,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
        }
        return 0;
 }
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 
 /*
  * Prepare a CPU for idle from an RCU perspective.  The first major task
@@ -1739,6 +1743,7 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
  */
 static void rcu_prepare_for_idle(int cpu)
 {
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
        struct rcu_data *rdp;
        struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
        struct rcu_node *rnp;
@@ -1790,6 +1795,7 @@ static void rcu_prepare_for_idle(int cpu)
                rcu_accelerate_cbs(rsp, rnp, rdp);
                raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
        }
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 }
 
 /*
@@ -1799,11 +1805,12 @@ static void rcu_prepare_for_idle(int cpu)
  */
 static void rcu_cleanup_after_idle(int cpu)
 {
-
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
        if (rcu_is_nocb_cpu(cpu))
                return;
        if (rcu_try_advance_all_cbs())
                invoke_rcu_core();
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 }
 
 /*
@@ -2101,6 +2108,7 @@ static void rcu_init_one_nocb(struct rcu_node *rnp)
        init_waitqueue_head(&rnp->nocb_gp_wq[1]);
 }
 
+#ifndef CONFIG_RCU_NOCB_CPU_ALL
 /* Is the specified CPU a no-CPUs CPU? */
 bool rcu_is_nocb_cpu(int cpu)
 {
@@ -2108,6 +2116,7 @@ bool rcu_is_nocb_cpu(int cpu)
                return cpumask_test_cpu(cpu, rcu_nocb_mask);
        return false;
 }
+#endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 
 /*
  * Enqueue the specified string of rcu_head structures onto the specified
@@ -2893,7 +2902,7 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
  * CPU unless the grace period has extended for too long.
  *
  * This code relies on the fact that all NO_HZ_FULL CPUs are also
- * CONFIG_RCU_NOCB_CPUs.
+ * CONFIG_RCU_NOCB_CPU CPUs.
  */
 static bool rcu_nohz_full_cpu(struct rcu_state *rsp)
 {
index 4def475336d412bcbfd8aa4e34a600e0f8b62d41..5cdc62e1beeb635a36ee87098a7f38110a651382 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2008
  *
@@ -273,7 +273,7 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
                   rsp->n_force_qs, rsp->n_force_qs_ngp,
                   rsp->n_force_qs - rsp->n_force_qs_ngp,
-                  rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen);
+                  ACCESS_ONCE(rsp->n_force_qs_lh), rsp->qlen_lazy, rsp->qlen);
        for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) {
                if (rnp->level != level) {
                        seq_puts(m, "\n");
index c54609faf233ba21a49835d32a9132eb56853f14..4c0a9b0af469a1f5fa3242d594653fee0f004505 100644 (file)
@@ -12,8 +12,8 @@
  * 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.
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
  *
  * Copyright IBM Corporation, 2001
  *
@@ -49,7 +49,6 @@
 #include <linux/module.h>
 
 #define CREATE_TRACE_POINTS
-#include <trace/events/rcu.h>
 
 #include "rcu.h"
 
index 9a95c8c2af2af0e9fb62c794926df3f1775a9dbe..ab32b7b0db5c6b30b4cc64e61e6a857fb51c87e6 100644 (file)
@@ -13,7 +13,7 @@ endif
 
 obj-y += core.o proc.o clock.o cputime.o
 obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o
-obj-y += wait.o completion.o
+obj-y += wait.o completion.o idle.o
 obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
 obj-$(CONFIG_SCHEDSTATS) += stats.o
index 4a073539c58e69992ed2133a73444ceffc9cd3fa..e73efba98301f77715c5e5e17b8e65a98bbb3769 100644 (file)
@@ -203,7 +203,7 @@ int proc_sched_autogroup_set_nice(struct task_struct *p, int nice)
        struct autogroup *ag;
        int err;
 
-       if (nice < -20 || nice > 19)
+       if (nice < MIN_NICE || nice > MAX_NICE)
                return -EINVAL;
 
        err = security_task_setnice(current, nice);
index 43c2bcc35761e40c9342522b4fa87b92cdefd8f4..b30a2924ef1429a60152a40101ec4828c5e23268 100644 (file)
@@ -301,14 +301,14 @@ u64 sched_clock_cpu(int cpu)
        if (unlikely(!sched_clock_running))
                return 0ull;
 
-       preempt_disable();
+       preempt_disable_notrace();
        scd = cpu_sdc(cpu);
 
        if (cpu != smp_processor_id())
                clock = sched_clock_remote(scd);
        else
                clock = sched_clock_local(scd);
-       preempt_enable();
+       preempt_enable_notrace();
 
        return clock;
 }
index c0339e206cc2401807fbe434bb2c9158d64f9e1e..3c4d096544ce4179c24403d0c41b3758c1842eab 100644 (file)
@@ -826,19 +826,13 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
 #endif
 #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
        if (static_key_false((&paravirt_steal_rq_enabled))) {
-               u64 st;
-
                steal = paravirt_steal_clock(cpu_of(rq));
                steal -= rq->prev_steal_time_rq;
 
                if (unlikely(steal > delta))
                        steal = delta;
 
-               st = steal_ticks(steal);
-               steal = st * TICK_NSEC;
-
                rq->prev_steal_time_rq += steal;
-
                delta -= steal;
        }
 #endif
@@ -1748,8 +1742,10 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
        p->numa_scan_seq = p->mm ? p->mm->numa_scan_seq : 0;
        p->numa_scan_period = sysctl_numa_balancing_scan_delay;
        p->numa_work.next = &p->numa_work;
-       p->numa_faults = NULL;
-       p->numa_faults_buffer = NULL;
+       p->numa_faults_memory = NULL;
+       p->numa_faults_buffer_memory = NULL;
+       p->last_task_numa_placement = 0;
+       p->last_sum_exec_runtime = 0;
 
        INIT_LIST_HEAD(&p->numa_entry);
        p->numa_group = NULL;
@@ -1955,7 +1951,7 @@ static int dl_overflow(struct task_struct *p, int policy,
 {
 
        struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
-       u64 period = attr->sched_period;
+       u64 period = attr->sched_period ?: attr->sched_deadline;
        u64 runtime = attr->sched_runtime;
        u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
        int cpus, err = -1;
@@ -2152,8 +2148,6 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
        if (mm)
                mmdrop(mm);
        if (unlikely(prev_state == TASK_DEAD)) {
-               task_numa_free(prev);
-
                if (prev->sched_class->task_dead)
                        prev->sched_class->task_dead(prev);
 
@@ -2170,13 +2164,6 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
 
 #ifdef CONFIG_SMP
 
-/* assumes rq->lock is held */
-static inline void pre_schedule(struct rq *rq, struct task_struct *prev)
-{
-       if (prev->sched_class->pre_schedule)
-               prev->sched_class->pre_schedule(rq, prev);
-}
-
 /* rq->lock is NOT held, but preemption is disabled */
 static inline void post_schedule(struct rq *rq)
 {
@@ -2194,10 +2181,6 @@ static inline void post_schedule(struct rq *rq)
 
 #else
 
-static inline void pre_schedule(struct rq *rq, struct task_struct *p)
-{
-}
-
 static inline void post_schedule(struct rq *rq)
 {
 }
@@ -2513,8 +2496,13 @@ void __kprobes preempt_count_add(int val)
        DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
                                PREEMPT_MASK - 10);
 #endif
-       if (preempt_count() == val)
-               trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
+       if (preempt_count() == val) {
+               unsigned long ip = get_parent_ip(CALLER_ADDR1);
+#ifdef CONFIG_DEBUG_PREEMPT
+               current->preempt_disable_ip = ip;
+#endif
+               trace_preempt_off(CALLER_ADDR0, ip);
+       }
 }
 EXPORT_SYMBOL(preempt_count_add);
 
@@ -2557,6 +2545,13 @@ static noinline void __schedule_bug(struct task_struct *prev)
        print_modules();
        if (irqs_disabled())
                print_irqtrace_events(prev);
+#ifdef CONFIG_DEBUG_PREEMPT
+       if (in_atomic_preempt_off()) {
+               pr_err("Preemption disabled at:");
+               print_ip_sym(current->preempt_disable_ip);
+               pr_cont("\n");
+       }
+#endif
        dump_stack();
        add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
 }
@@ -2580,36 +2575,34 @@ static inline void schedule_debug(struct task_struct *prev)
        schedstat_inc(this_rq(), sched_count);
 }
 
-static void put_prev_task(struct rq *rq, struct task_struct *prev)
-{
-       if (prev->on_rq || rq->skip_clock_update < 0)
-               update_rq_clock(rq);
-       prev->sched_class->put_prev_task(rq, prev);
-}
-
 /*
  * Pick up the highest-prio task:
  */
 static inline struct task_struct *
-pick_next_task(struct rq *rq)
+pick_next_task(struct rq *rq, struct task_struct *prev)
 {
-       const struct sched_class *class;
+       const struct sched_class *class = &fair_sched_class;
        struct task_struct *p;
 
        /*
         * Optimization: we know that if all tasks are in
         * the fair class we can call that function directly:
         */
-       if (likely(rq->nr_running == rq->cfs.h_nr_running)) {
-               p = fair_sched_class.pick_next_task(rq);
-               if (likely(p))
+       if (likely(prev->sched_class == class &&
+                  rq->nr_running == rq->cfs.h_nr_running)) {
+               p = fair_sched_class.pick_next_task(rq, prev);
+               if (likely(p && p != RETRY_TASK))
                        return p;
        }
 
+again:
        for_each_class(class) {
-               p = class->pick_next_task(rq);
-               if (p)
+               p = class->pick_next_task(rq, prev);
+               if (p) {
+                       if (unlikely(p == RETRY_TASK))
+                               goto again;
                        return p;
+               }
        }
 
        BUG(); /* the idle class will always have a runnable task */
@@ -2703,13 +2696,10 @@ need_resched:
                switch_count = &prev->nvcsw;
        }
 
-       pre_schedule(rq, prev);
-
-       if (unlikely(!rq->nr_running))
-               idle_balance(cpu, rq);
+       if (prev->on_rq || rq->skip_clock_update < 0)
+               update_rq_clock(rq);
 
-       put_prev_task(rq, prev);
-       next = pick_next_task(rq);
+       next = pick_next_task(rq, prev);
        clear_tsk_need_resched(prev);
        clear_preempt_need_resched();
        rq->skip_clock_update = 0;
@@ -2911,7 +2901,8 @@ EXPORT_SYMBOL(sleep_on_timeout);
  * This function changes the 'effective' priority of a task. It does
  * not touch ->normal_prio like __setscheduler().
  *
- * Used by the rt_mutex code to implement priority inheritance logic.
+ * Used by the rt_mutex code to implement priority inheritance
+ * logic. Call site only calls if the priority of the task changed.
  */
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
@@ -3001,7 +2992,7 @@ void set_user_nice(struct task_struct *p, long nice)
        unsigned long flags;
        struct rq *rq;
 
-       if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
+       if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE)
                return;
        /*
         * We have to be careful, if called from sys_setpriority(),
@@ -3079,11 +3070,11 @@ SYSCALL_DEFINE1(nice, int, increment)
        if (increment > 40)
                increment = 40;
 
-       nice = TASK_NICE(current) + increment;
-       if (nice < -20)
-               nice = -20;
-       if (nice > 19)
-               nice = 19;
+       nice = task_nice(current) + increment;
+       if (nice < MIN_NICE)
+               nice = MIN_NICE;
+       if (nice > MAX_NICE)
+               nice = MAX_NICE;
 
        if (increment < 0 && !can_nice(current, nice))
                return -EPERM;
@@ -3111,18 +3102,6 @@ int task_prio(const struct task_struct *p)
        return p->prio - MAX_RT_PRIO;
 }
 
-/**
- * task_nice - return the nice value of a given task.
- * @p: the task in question.
- *
- * Return: The nice value [ -20 ... 0 ... 19 ].
- */
-int task_nice(const struct task_struct *p)
-{
-       return TASK_NICE(p);
-}
-EXPORT_SYMBOL(task_nice);
-
 /**
  * idle_cpu - is a given cpu idle currently?
  * @cpu: the processor in question.
@@ -3192,9 +3171,8 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
        dl_se->dl_new = 1;
 }
 
-/* Actually do priority change: must hold pi & rq lock. */
-static void __setscheduler(struct rq *rq, struct task_struct *p,
-                          const struct sched_attr *attr)
+static void __setscheduler_params(struct task_struct *p,
+               const struct sched_attr *attr)
 {
        int policy = attr->sched_policy;
 
@@ -3214,9 +3192,21 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
         * getparam()/getattr() don't report silly values for !rt tasks.
         */
        p->rt_priority = attr->sched_priority;
-
        p->normal_prio = normal_prio(p);
-       p->prio = rt_mutex_getprio(p);
+       set_load_weight(p);
+}
+
+/* Actually do priority change: must hold pi & rq lock. */
+static void __setscheduler(struct rq *rq, struct task_struct *p,
+                          const struct sched_attr *attr)
+{
+       __setscheduler_params(p, attr);
+
+       /*
+        * If we get here, there was no pi waiters boosting the
+        * task. It is safe to use the normal prio.
+        */
+       p->prio = normal_prio(p);
 
        if (dl_prio(p->prio))
                p->sched_class = &dl_sched_class;
@@ -3224,8 +3214,6 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
                p->sched_class = &rt_sched_class;
        else
                p->sched_class = &fair_sched_class;
-
-       set_load_weight(p);
 }
 
 static void
@@ -3278,6 +3266,8 @@ static int __sched_setscheduler(struct task_struct *p,
                                const struct sched_attr *attr,
                                bool user)
 {
+       int newprio = dl_policy(attr->sched_policy) ? MAX_DL_PRIO - 1 :
+                     MAX_RT_PRIO - 1 - attr->sched_priority;
        int retval, oldprio, oldpolicy = -1, on_rq, running;
        int policy = attr->sched_policy;
        unsigned long flags;
@@ -3322,7 +3312,7 @@ recheck:
         */
        if (user && !capable(CAP_SYS_NICE)) {
                if (fair_policy(policy)) {
-                       if (attr->sched_nice < TASK_NICE(p) &&
+                       if (attr->sched_nice < task_nice(p) &&
                            !can_nice(p, attr->sched_nice))
                                return -EPERM;
                }
@@ -3341,12 +3331,21 @@ recheck:
                                return -EPERM;
                }
 
+                /*
+                 * Can't set/change SCHED_DEADLINE policy at all for now
+                 * (safest behavior); in the future we would like to allow
+                 * unprivileged DL tasks to increase their relative deadline
+                 * or reduce their runtime (both ways reducing utilization)
+                 */
+               if (dl_policy(policy))
+                       return -EPERM;
+
                /*
                 * Treat SCHED_IDLE as nice 20. Only allow a switch to
                 * SCHED_NORMAL if the RLIMIT_NICE would normally permit it.
                 */
                if (p->policy == SCHED_IDLE && policy != SCHED_IDLE) {
-                       if (!can_nice(p, TASK_NICE(p)))
+                       if (!can_nice(p, task_nice(p)))
                                return -EPERM;
                }
 
@@ -3383,16 +3382,18 @@ recheck:
        }
 
        /*
-        * If not changing anything there's no need to proceed further:
+        * If not changing anything there's no need to proceed further,
+        * but store a possible modification of reset_on_fork.
         */
        if (unlikely(policy == p->policy)) {
-               if (fair_policy(policy) && attr->sched_nice != TASK_NICE(p))
+               if (fair_policy(policy) && attr->sched_nice != task_nice(p))
                        goto change;
                if (rt_policy(policy) && attr->sched_priority != p->rt_priority)
                        goto change;
                if (dl_policy(policy))
                        goto change;
 
+               p->sched_reset_on_fork = reset_on_fork;
                task_rq_unlock(rq, p, &flags);
                return 0;
        }
@@ -3446,6 +3447,24 @@ change:
                return -EBUSY;
        }
 
+       p->sched_reset_on_fork = reset_on_fork;
+       oldprio = p->prio;
+
+       /*
+        * Special case for priority boosted tasks.
+        *
+        * If the new priority is lower or equal (user space view)
+        * than the current (boosted) priority, we just store the new
+        * normal parameters and do not touch the scheduler class and
+        * the runqueue. This will be done when the task deboost
+        * itself.
+        */
+       if (rt_mutex_check_prio(p, newprio)) {
+               __setscheduler_params(p, attr);
+               task_rq_unlock(rq, p, &flags);
+               return 0;
+       }
+
        on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
@@ -3453,16 +3472,18 @@ change:
        if (running)
                p->sched_class->put_prev_task(rq, p);
 
-       p->sched_reset_on_fork = reset_on_fork;
-
-       oldprio = p->prio;
        prev_class = p->sched_class;
        __setscheduler(rq, p, attr);
 
        if (running)
                p->sched_class->set_curr_task(rq);
-       if (on_rq)
-               enqueue_task(rq, p, 0);
+       if (on_rq) {
+               /*
+                * We enqueue to tail when the priority of a task is
+                * increased (user space view).
+                */
+               enqueue_task(rq, p, oldprio <= p->prio ? ENQUEUE_HEAD : 0);
+       }
 
        check_class_changed(rq, p, prev_class, oldprio);
        task_rq_unlock(rq, p, &flags);
@@ -3618,7 +3639,7 @@ static int sched_copy_attr(struct sched_attr __user *uattr,
         * XXX: do we want to be lenient like existing syscalls; or do we want
         * to be strict and return an error on out-of-bounds values?
         */
-       attr->sched_nice = clamp(attr->sched_nice, -20, 19);
+       attr->sched_nice = clamp(attr->sched_nice, MIN_NICE, MAX_NICE);
 
 out:
        return ret;
@@ -3664,13 +3685,14 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
  * @pid: the pid in question.
  * @uattr: structure containing the extended parameters.
  */
-SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr)
+SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
+                              unsigned int, flags)
 {
        struct sched_attr attr;
        struct task_struct *p;
        int retval;
 
-       if (!uattr || pid < 0)
+       if (!uattr || pid < 0 || flags)
                return -EINVAL;
 
        if (sched_copy_attr(uattr, &attr))
@@ -3789,7 +3811,7 @@ static int sched_read_attr(struct sched_attr __user *uattr,
                attr->size = usize;
        }
 
-       ret = copy_to_user(uattr, attr, usize);
+       ret = copy_to_user(uattr, attr, attr->size);
        if (ret)
                return -EFAULT;
 
@@ -3807,8 +3829,8 @@ err_size:
  * @uattr: structure containing the extended parameters.
  * @size: sizeof(attr) for fwd/bwd comp.
  */
-SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
-               unsigned int, size)
+SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
+               unsigned int, size, unsigned int, flags)
 {
        struct sched_attr attr = {
                .size = sizeof(struct sched_attr),
@@ -3817,7 +3839,7 @@ SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
        int retval;
 
        if (!uattr || pid < 0 || size > PAGE_SIZE ||
-           size < SCHED_ATTR_SIZE_VER0)
+           size < SCHED_ATTR_SIZE_VER0 || flags)
                return -EINVAL;
 
        rcu_read_lock();
@@ -3838,7 +3860,7 @@ SYSCALL_DEFINE3(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
        else if (task_has_rt_policy(p))
                attr.sched_priority = p->rt_priority;
        else
-               attr.sched_nice = TASK_NICE(p);
+               attr.sched_nice = task_nice(p);
 
        rcu_read_unlock();
 
@@ -4476,6 +4498,7 @@ void init_idle(struct task_struct *idle, int cpu)
        rcu_read_unlock();
 
        rq->curr = rq->idle = idle;
+       idle->on_rq = 1;
 #if defined(CONFIG_SMP)
        idle->on_cpu = 1;
 #endif
@@ -4695,8 +4718,10 @@ void idle_task_exit(void)
 
        BUG_ON(cpu_online(smp_processor_id()));
 
-       if (mm != &init_mm)
+       if (mm != &init_mm) {
                switch_mm(mm, &init_mm, current);
+               finish_arch_post_lock_switch();
+       }
        mmdrop(mm);
 }
 
@@ -4714,6 +4739,22 @@ static void calc_load_migrate(struct rq *rq)
                atomic_long_add(delta, &calc_load_tasks);
 }
 
+static void put_prev_task_fake(struct rq *rq, struct task_struct *prev)
+{
+}
+
+static const struct sched_class fake_sched_class = {
+       .put_prev_task = put_prev_task_fake,
+};
+
+static struct task_struct fake_task = {
+       /*
+        * Avoid pull_{rt,dl}_task()
+        */
+       .prio = MAX_PRIO + 1,
+       .sched_class = &fake_sched_class,
+};
+
 /*
  * Migrate all tasks from the rq, sleeping tasks will be migrated by
  * try_to_wake_up()->select_task_rq().
@@ -4754,7 +4795,7 @@ static void migrate_tasks(unsigned int dead_cpu)
                if (rq->nr_running == 1)
                        break;
 
-               next = pick_next_task(rq);
+               next = pick_next_task(rq, &fake_task);
                BUG_ON(!next);
                next->sched_class->put_prev_task(rq, next);
 
@@ -4844,7 +4885,7 @@ set_table_entry(struct ctl_table *entry,
 static struct ctl_table *
 sd_alloc_ctl_domain_table(struct sched_domain *sd)
 {
-       struct ctl_table *table = sd_alloc_ctl_entry(13);
+       struct ctl_table *table = sd_alloc_ctl_entry(14);
 
        if (table == NULL)
                return NULL;
@@ -4872,9 +4913,12 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd)
                sizeof(int), 0644, proc_dointvec_minmax, false);
        set_table_entry(&table[10], "flags", &sd->flags,
                sizeof(int), 0644, proc_dointvec_minmax, false);
-       set_table_entry(&table[11], "name", sd->name,
+       set_table_entry(&table[11], "max_newidle_lb_cost",
+               &sd->max_newidle_lb_cost,
+               sizeof(long), 0644, proc_doulongvec_minmax, false);
+       set_table_entry(&table[12], "name", sd->name,
                CORENAME_MAX_SIZE, 0444, proc_dostring, false);
-       /* &table[12] is terminator */
+       /* &table[13] is terminator */
 
        return table;
 }
@@ -6851,7 +6895,6 @@ void __init sched_init(void)
 
                rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime;
 #ifdef CONFIG_RT_GROUP_SCHED
-               INIT_LIST_HEAD(&rq->leaf_rt_rq_list);
                init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i, NULL);
 #endif
 
@@ -6940,7 +6983,8 @@ void __might_sleep(const char *file, int line, int preempt_offset)
        static unsigned long prev_jiffy;        /* ratelimiting */
 
        rcu_sleep_check(); /* WARN_ON_ONCE() by default, no rate limit reqd. */
-       if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) ||
+       if ((preempt_count_equals(preempt_offset) && !irqs_disabled() &&
+            !is_idle_task(current)) ||
            system_state != SYSTEM_RUNNING || oops_in_progress)
                return;
        if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
@@ -6958,6 +7002,13 @@ void __might_sleep(const char *file, int line, int preempt_offset)
        debug_show_held_locks(current);
        if (irqs_disabled())
                print_irqtrace_events(current);
+#ifdef CONFIG_DEBUG_PREEMPT
+       if (!preempt_count_equals(preempt_offset)) {
+               pr_err("Preemption disabled at:");
+               print_ip_sym(current->preempt_disable_ip);
+               pr_cont("\n");
+       }
+#endif
        dump_stack();
 }
 EXPORT_SYMBOL(__might_sleep);
@@ -7011,7 +7062,7 @@ void normalize_rt_tasks(void)
                         * Renice negative nice level userspace
                         * tasks back to 0:
                         */
-                       if (TASK_NICE(p) < 0 && p->mm)
+                       if (task_nice(p) < 0 && p->mm)
                                set_user_nice(p, 0);
                        continue;
                }
@@ -7425,6 +7476,7 @@ static int sched_dl_global_constraints(void)
        u64 period = global_rt_period();
        u64 new_bw = to_ratio(period, runtime);
        int cpu, ret = 0;
+       unsigned long flags;
 
        /*
         * Here we want to check the bandwidth not being set to some
@@ -7438,10 +7490,10 @@ static int sched_dl_global_constraints(void)
        for_each_possible_cpu(cpu) {
                struct dl_bw *dl_b = dl_bw_of(cpu);
 
-               raw_spin_lock(&dl_b->lock);
+               raw_spin_lock_irqsave(&dl_b->lock, flags);
                if (new_bw < dl_b->total_bw)
                        ret = -EBUSY;
-               raw_spin_unlock(&dl_b->lock);
+               raw_spin_unlock_irqrestore(&dl_b->lock, flags);
 
                if (ret)
                        break;
@@ -7454,6 +7506,7 @@ static void sched_dl_do_global(void)
 {
        u64 new_bw = -1;
        int cpu;
+       unsigned long flags;
 
        def_dl_bandwidth.dl_period = global_rt_period();
        def_dl_bandwidth.dl_runtime = global_rt_runtime();
@@ -7467,9 +7520,9 @@ static void sched_dl_do_global(void)
        for_each_possible_cpu(cpu) {
                struct dl_bw *dl_b = dl_bw_of(cpu);
 
-               raw_spin_lock(&dl_b->lock);
+               raw_spin_lock_irqsave(&dl_b->lock, flags);
                dl_b->bw = new_bw;
-               raw_spin_unlock(&dl_b->lock);
+               raw_spin_unlock_irqrestore(&dl_b->lock, flags);
        }
 }
 
@@ -7478,7 +7531,8 @@ static int sched_rt_global_validate(void)
        if (sysctl_sched_rt_period <= 0)
                return -EINVAL;
 
-       if (sysctl_sched_rt_runtime > sysctl_sched_rt_period)
+       if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
+               (sysctl_sched_rt_runtime > sysctl_sched_rt_period))
                return -EINVAL;
 
        return 0;
index 045fc74e3f0928fd73e1924b5b678f7d56654613..5b9bb42b2d47e760f3a7cd17af24ba37d2cf07ea 100644 (file)
@@ -70,7 +70,7 @@ static void cpudl_heapify(struct cpudl *cp, int idx)
 
 static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl)
 {
-       WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID);
+       WARN_ON(idx == IDX_INVALID || !cpu_present(idx));
 
        if (dl_time_before(new_dl, cp->elements[idx].dl)) {
                cp->elements[idx].dl = new_dl;
@@ -117,7 +117,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
        }
 
 out:
-       WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1);
+       WARN_ON(best_cpu != -1 && !cpu_present(best_cpu));
 
        return best_cpu;
 }
@@ -137,7 +137,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid)
        int old_idx, new_cpu;
        unsigned long flags;
 
-       WARN_ON(cpu > num_present_cpus());
+       WARN_ON(!cpu_present(cpu));
 
        raw_spin_lock_irqsave(&cp->lock, flags);
        old_idx = cp->cpu_to_idx[cpu];
index 99947919e30bc68963d3bfa937ebad8a2c90ba87..a95097cb4591b5bfa2466adb5600895e782fc661 100644 (file)
@@ -142,7 +142,7 @@ void account_user_time(struct task_struct *p, cputime_t cputime,
        p->utimescaled += cputime_scaled;
        account_group_user_time(p, cputime);
 
-       index = (TASK_NICE(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
+       index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
 
        /* Add user time to cpustat. */
        task_group_account_field(p, index, (__force u64) cputime);
@@ -169,7 +169,7 @@ static void account_guest_time(struct task_struct *p, cputime_t cputime,
        p->gtime += cputime;
 
        /* Add guest time to cpustat. */
-       if (TASK_NICE(p) > 0) {
+       if (task_nice(p) > 0) {
                cpustat[CPUTIME_NICE] += (__force u64) cputime;
                cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime;
        } else {
@@ -258,16 +258,22 @@ static __always_inline bool steal_account_process_tick(void)
 {
 #ifdef CONFIG_PARAVIRT
        if (static_key_false(&paravirt_steal_enabled)) {
-               u64 steal, st = 0;
+               u64 steal;
+               cputime_t steal_ct;
 
                steal = paravirt_steal_clock(smp_processor_id());
                steal -= this_rq()->prev_steal_time;
 
-               st = steal_ticks(steal);
-               this_rq()->prev_steal_time += st * TICK_NSEC;
+               /*
+                * cputime_t may be less precise than nsecs (eg: if it's
+                * based on jiffies). Lets cast the result to cputime
+                * granularity and account the rest on the next rounds.
+                */
+               steal_ct = nsecs_to_cputime(steal);
+               this_rq()->prev_steal_time += cputime_to_nsecs(steal_ct);
 
-               account_steal_time(st);
-               return st;
+               account_steal_time(steal_ct);
+               return steal_ct;
        }
 #endif
        return false;
index 0dd5e0971a0778a3e09ee8a91f5851dfa1dc25a9..27ef409255253367d35fd598ddb01550612df040 100644 (file)
@@ -121,7 +121,7 @@ static inline void dl_clear_overload(struct rq *rq)
 
 static void update_dl_migration(struct dl_rq *dl_rq)
 {
-       if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_total > 1) {
+       if (dl_rq->dl_nr_migratory && dl_rq->dl_nr_running > 1) {
                if (!dl_rq->overloaded) {
                        dl_set_overload(rq_of_dl_rq(dl_rq));
                        dl_rq->overloaded = 1;
@@ -135,9 +135,7 @@ static void update_dl_migration(struct dl_rq *dl_rq)
 static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
 {
        struct task_struct *p = dl_task_of(dl_se);
-       dl_rq = &rq_of_dl_rq(dl_rq)->dl;
 
-       dl_rq->dl_nr_total++;
        if (p->nr_cpus_allowed > 1)
                dl_rq->dl_nr_migratory++;
 
@@ -147,9 +145,7 @@ static void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
 static void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
 {
        struct task_struct *p = dl_task_of(dl_se);
-       dl_rq = &rq_of_dl_rq(dl_rq)->dl;
 
-       dl_rq->dl_nr_total--;
        if (p->nr_cpus_allowed > 1)
                dl_rq->dl_nr_migratory--;
 
@@ -214,6 +210,16 @@ static inline int has_pushable_dl_tasks(struct rq *rq)
 
 static int push_dl_task(struct rq *rq);
 
+static inline bool need_pull_dl_task(struct rq *rq, struct task_struct *prev)
+{
+       return dl_task(prev);
+}
+
+static inline void set_post_schedule(struct rq *rq)
+{
+       rq->post_schedule = has_pushable_dl_tasks(rq);
+}
+
 #else
 
 static inline
@@ -236,6 +242,19 @@ void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
 {
 }
 
+static inline bool need_pull_dl_task(struct rq *rq, struct task_struct *prev)
+{
+       return false;
+}
+
+static inline int pull_dl_task(struct rq *rq)
+{
+       return 0;
+}
+
+static inline void set_post_schedule(struct rq *rq)
+{
+}
 #endif /* CONFIG_SMP */
 
 static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags);
@@ -566,6 +585,8 @@ int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se)
        return 1;
 }
 
+extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);
+
 /*
  * Update the current task's runtime statistics (provided it is still
  * a -deadline task and has not been removed from the dl_rq).
@@ -588,8 +609,8 @@ static void update_curr_dl(struct rq *rq)
         * approach need further study.
         */
        delta_exec = rq_clock_task(rq) - curr->se.exec_start;
-       if (unlikely((s64)delta_exec < 0))
-               delta_exec = 0;
+       if (unlikely((s64)delta_exec <= 0))
+               return;
 
        schedstat_set(curr->se.statistics.exec_max,
                      max(curr->se.statistics.exec_max, delta_exec));
@@ -629,11 +650,13 @@ static void update_curr_dl(struct rq *rq)
                struct rt_rq *rt_rq = &rq->rt;
 
                raw_spin_lock(&rt_rq->rt_runtime_lock);
-               rt_rq->rt_time += delta_exec;
                /*
                 * We'll let actual RT tasks worry about the overflow here, we
-                * have our own CBS to keep us inline -- see above.
+                * have our own CBS to keep us inline; only account when RT
+                * bandwidth is relevant.
                 */
+               if (sched_rt_bandwidth_account(rt_rq))
+                       rt_rq->rt_time += delta_exec;
                raw_spin_unlock(&rt_rq->rt_runtime_lock);
        }
 }
@@ -717,6 +740,7 @@ void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
 
        WARN_ON(!dl_prio(prio));
        dl_rq->dl_nr_running++;
+       inc_nr_running(rq_of_dl_rq(dl_rq));
 
        inc_dl_deadline(dl_rq, deadline);
        inc_dl_migration(dl_se, dl_rq);
@@ -730,6 +754,7 @@ void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
        WARN_ON(!dl_prio(prio));
        WARN_ON(!dl_rq->dl_nr_running);
        dl_rq->dl_nr_running--;
+       dec_nr_running(rq_of_dl_rq(dl_rq));
 
        dec_dl_deadline(dl_rq, dl_se->deadline);
        dec_dl_migration(dl_se, dl_rq);
@@ -836,8 +861,6 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
 
        if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
                enqueue_pushable_dl_task(rq, p);
-
-       inc_nr_running(rq);
 }
 
 static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
@@ -850,8 +873,6 @@ static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
 {
        update_curr_dl(rq);
        __dequeue_task_dl(rq, p, flags);
-
-       dec_nr_running(rq);
 }
 
 /*
@@ -944,6 +965,8 @@ static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p)
        resched_task(rq->curr);
 }
 
+static int pull_dl_task(struct rq *this_rq);
+
 #endif /* CONFIG_SMP */
 
 /*
@@ -990,7 +1013,7 @@ static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
        return rb_entry(left, struct sched_dl_entity, rb_node);
 }
 
-struct task_struct *pick_next_task_dl(struct rq *rq)
+struct task_struct *pick_next_task_dl(struct rq *rq, struct task_struct *prev)
 {
        struct sched_dl_entity *dl_se;
        struct task_struct *p;
@@ -998,9 +1021,20 @@ struct task_struct *pick_next_task_dl(struct rq *rq)
 
        dl_rq = &rq->dl;
 
+       if (need_pull_dl_task(rq, prev))
+               pull_dl_task(rq);
+       /*
+        * When prev is DL, we may throttle it in put_prev_task().
+        * So, we update time before we check for dl_nr_running.
+        */
+       if (prev->sched_class == &dl_sched_class)
+               update_curr_dl(rq);
+
        if (unlikely(!dl_rq->dl_nr_running))
                return NULL;
 
+       put_prev_task(rq, prev);
+
        dl_se = pick_next_dl_entity(rq, dl_rq);
        BUG_ON(!dl_se);
 
@@ -1015,9 +1049,7 @@ struct task_struct *pick_next_task_dl(struct rq *rq)
                start_hrtick_dl(rq, p);
 #endif
 
-#ifdef CONFIG_SMP
-       rq->post_schedule = has_pushable_dl_tasks(rq);
-#endif /* CONFIG_SMP */
+       set_post_schedule(rq);
 
        return p;
 }
@@ -1426,13 +1458,6 @@ skip:
        return ret;
 }
 
-static void pre_schedule_dl(struct rq *rq, struct task_struct *prev)
-{
-       /* Try to pull other tasks here */
-       if (dl_task(prev))
-               pull_dl_task(rq);
-}
-
 static void post_schedule_dl(struct rq *rq)
 {
        push_dl_tasks(rq);
@@ -1560,7 +1585,7 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
        if (unlikely(p->dl.dl_throttled))
                return;
 
-       if (p->on_rq || rq->curr != p) {
+       if (p->on_rq && rq->curr != p) {
 #ifdef CONFIG_SMP
                if (rq->dl.overloaded && push_dl_task(rq) && rq != task_rq(p))
                        /* Only reschedule if pushing failed */
@@ -1625,7 +1650,6 @@ const struct sched_class dl_sched_class = {
        .set_cpus_allowed       = set_cpus_allowed_dl,
        .rq_online              = rq_online_dl,
        .rq_offline             = rq_offline_dl,
-       .pre_schedule           = pre_schedule_dl,
        .post_schedule          = post_schedule_dl,
        .task_woken             = task_woken_dl,
 #endif
index dd52e7ffb10ed3e16dd36ca01a08e9438fcd7872..f3344c31632aee78050316de3138fbe69280d027 100644 (file)
@@ -321,6 +321,7 @@ do {                                                                        \
        P(sched_goidle);
 #ifdef CONFIG_SMP
        P64(avg_idle);
+       P64(max_idle_balance_cost);
 #endif
 
        P(ttwu_count);
@@ -533,15 +534,15 @@ static void sched_show_numa(struct task_struct *p, struct seq_file *m)
                        unsigned long nr_faults = -1;
                        int cpu_current, home_node;
 
-                       if (p->numa_faults)
-                               nr_faults = p->numa_faults[2*node + i];
+                       if (p->numa_faults_memory)
+                               nr_faults = p->numa_faults_memory[2*node + i];
 
                        cpu_current = !i ? (task_node(p) == node) :
                                (pol && node_isset(node, pol->v.nodes));
 
                        home_node = (p->numa_preferred_nid == node);
 
-                       SEQ_printf(m, "numa_faults, %d, %d, %d, %d, %ld\n",
+                       SEQ_printf(m, "numa_faults_memory, %d, %d, %d, %d, %ld\n",
                                i, node, cpu_current, home_node, nr_faults);
                }
        }
index 966cc2bfcb77586d2ce9c55986aae2a3f2dce521..7e9bd0b1fa9ef1aa16880a5a10601374c7bb618b 100644 (file)
@@ -322,13 +322,13 @@ static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
        list_for_each_entry_rcu(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
 
 /* Do the two (enqueued) entities belong to the same group ? */
-static inline int
+static inline struct cfs_rq *
 is_same_group(struct sched_entity *se, struct sched_entity *pse)
 {
        if (se->cfs_rq == pse->cfs_rq)
-               return 1;
+               return se->cfs_rq;
 
-       return 0;
+       return NULL;
 }
 
 static inline struct sched_entity *parent_entity(struct sched_entity *se)
@@ -336,17 +336,6 @@ static inline struct sched_entity *parent_entity(struct sched_entity *se)
        return se->parent;
 }
 
-/* return depth at which a sched entity is present in the hierarchy */
-static inline int depth_se(struct sched_entity *se)
-{
-       int depth = 0;
-
-       for_each_sched_entity(se)
-               depth++;
-
-       return depth;
-}
-
 static void
 find_matching_se(struct sched_entity **se, struct sched_entity **pse)
 {
@@ -360,8 +349,8 @@ find_matching_se(struct sched_entity **se, struct sched_entity **pse)
         */
 
        /* First walk up until both entities are at same depth */
-       se_depth = depth_se(*se);
-       pse_depth = depth_se(*pse);
+       se_depth = (*se)->depth;
+       pse_depth = (*pse)->depth;
 
        while (se_depth > pse_depth) {
                se_depth--;
@@ -426,12 +415,6 @@ static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq)
 #define for_each_leaf_cfs_rq(rq, cfs_rq) \
                for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
 
-static inline int
-is_same_group(struct sched_entity *se, struct sched_entity *pse)
-{
-       return 1;
-}
-
 static inline struct sched_entity *parent_entity(struct sched_entity *se)
 {
        return NULL;
@@ -819,14 +802,6 @@ unsigned int sysctl_numa_balancing_scan_size = 256;
 /* Scan @scan_size MB every @scan_period after an initial @scan_delay in ms */
 unsigned int sysctl_numa_balancing_scan_delay = 1000;
 
-/*
- * After skipping a page migration on a shared page, skip N more numa page
- * migrations unconditionally. This reduces the number of NUMA migrations
- * in shared memory workloads, and has the effect of pulling tasks towards
- * where their memory lives, over pulling the memory towards the task.
- */
-unsigned int sysctl_numa_balancing_migrate_deferred = 16;
-
 static unsigned int task_nr_scan_windows(struct task_struct *p)
 {
        unsigned long rss = 0;
@@ -893,10 +868,26 @@ struct numa_group {
        struct list_head task_list;
 
        struct rcu_head rcu;
+       nodemask_t active_nodes;
        unsigned long total_faults;
+       /*
+        * Faults_cpu is used to decide whether memory should move
+        * towards the CPU. As a consequence, these stats are weighted
+        * more by CPU use than by memory faults.
+        */
+       unsigned long *faults_cpu;
        unsigned long faults[0];
 };
 
+/* Shared or private faults. */
+#define NR_NUMA_HINT_FAULT_TYPES 2
+
+/* Memory and CPU locality */
+#define NR_NUMA_HINT_FAULT_STATS (NR_NUMA_HINT_FAULT_TYPES * 2)
+
+/* Averaged statistics, and temporary buffers. */
+#define NR_NUMA_HINT_FAULT_BUCKETS (NR_NUMA_HINT_FAULT_STATS * 2)
+
 pid_t task_numa_group_id(struct task_struct *p)
 {
        return p->numa_group ? p->numa_group->gid : 0;
@@ -904,16 +895,16 @@ pid_t task_numa_group_id(struct task_struct *p)
 
 static inline int task_faults_idx(int nid, int priv)
 {
-       return 2 * nid + priv;
+       return NR_NUMA_HINT_FAULT_TYPES * nid + priv;
 }
 
 static inline unsigned long task_faults(struct task_struct *p, int nid)
 {
-       if (!p->numa_faults)
+       if (!p->numa_faults_memory)
                return 0;
 
-       return p->numa_faults[task_faults_idx(nid, 0)] +
-               p->numa_faults[task_faults_idx(nid, 1)];
+       return p->numa_faults_memory[task_faults_idx(nid, 0)] +
+               p->numa_faults_memory[task_faults_idx(nid, 1)];
 }
 
 static inline unsigned long group_faults(struct task_struct *p, int nid)
@@ -925,6 +916,12 @@ static inline unsigned long group_faults(struct task_struct *p, int nid)
                p->numa_group->faults[task_faults_idx(nid, 1)];
 }
 
+static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
+{
+       return group->faults_cpu[task_faults_idx(nid, 0)] +
+               group->faults_cpu[task_faults_idx(nid, 1)];
+}
+
 /*
  * These return the fraction of accesses done by a particular task, or
  * task group, on a particular numa node.  The group weight is given a
@@ -935,7 +932,7 @@ static inline unsigned long task_weight(struct task_struct *p, int nid)
 {
        unsigned long total_faults;
 
-       if (!p->numa_faults)
+       if (!p->numa_faults_memory)
                return 0;
 
        total_faults = p->total_numa_faults;
@@ -954,6 +951,69 @@ static inline unsigned long group_weight(struct task_struct *p, int nid)
        return 1000 * group_faults(p, nid) / p->numa_group->total_faults;
 }
 
+bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
+                               int src_nid, int dst_cpu)
+{
+       struct numa_group *ng = p->numa_group;
+       int dst_nid = cpu_to_node(dst_cpu);
+       int last_cpupid, this_cpupid;
+
+       this_cpupid = cpu_pid_to_cpupid(dst_cpu, current->pid);
+
+       /*
+        * Multi-stage node selection is used in conjunction with a periodic
+        * migration fault to build a temporal task<->page relation. By using
+        * a two-stage filter we remove short/unlikely relations.
+        *
+        * Using P(p) ~ n_p / n_t as per frequentist probability, we can equate
+        * a task's usage of a particular page (n_p) per total usage of this
+        * page (n_t) (in a given time-span) to a probability.
+        *
+        * Our periodic faults will sample this probability and getting the
+        * same result twice in a row, given these samples are fully
+        * independent, is then given by P(n)^2, provided our sample period
+        * is sufficiently short compared to the usage pattern.
+        *
+        * This quadric squishes small probabilities, making it less likely we
+        * act on an unlikely task<->page relation.
+        */
+       last_cpupid = page_cpupid_xchg_last(page, this_cpupid);
+       if (!cpupid_pid_unset(last_cpupid) &&
+                               cpupid_to_nid(last_cpupid) != dst_nid)
+               return false;
+
+       /* Always allow migrate on private faults */
+       if (cpupid_match_pid(p, last_cpupid))
+               return true;
+
+       /* A shared fault, but p->numa_group has not been set up yet. */
+       if (!ng)
+               return true;
+
+       /*
+        * Do not migrate if the destination is not a node that
+        * is actively used by this numa group.
+        */
+       if (!node_isset(dst_nid, ng->active_nodes))
+               return false;
+
+       /*
+        * Source is a node that is not actively used by this
+        * numa group, while the destination is. Migrate.
+        */
+       if (!node_isset(src_nid, ng->active_nodes))
+               return true;
+
+       /*
+        * Both source and destination are nodes in active
+        * use by this numa group. Maximize memory bandwidth
+        * by migrating from more heavily used groups, to less
+        * heavily used ones, spreading the load around.
+        * Use a 1/4 hysteresis to avoid spurious page movement.
+        */
+       return group_faults(p, dst_nid) < (group_faults(p, src_nid) * 3 / 4);
+}
+
 static unsigned long weighted_cpuload(const int cpu);
 static unsigned long source_load(int cpu, int type);
 static unsigned long target_load(int cpu, int type);
@@ -1267,7 +1327,7 @@ static int task_numa_migrate(struct task_struct *p)
 static void numa_migrate_preferred(struct task_struct *p)
 {
        /* This task has no NUMA fault statistics yet */
-       if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults))
+       if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults_memory))
                return;
 
        /* Periodically retry migrating the task to the preferred node */
@@ -1281,6 +1341,38 @@ static void numa_migrate_preferred(struct task_struct *p)
        task_numa_migrate(p);
 }
 
+/*
+ * Find the nodes on which the workload is actively running. We do this by
+ * tracking the nodes from which NUMA hinting faults are triggered. This can
+ * be different from the set of nodes where the workload's memory is currently
+ * located.
+ *
+ * The bitmask is used to make smarter decisions on when to do NUMA page
+ * migrations, To prevent flip-flopping, and excessive page migrations, nodes
+ * are added when they cause over 6/16 of the maximum number of faults, but
+ * only removed when they drop below 3/16.
+ */
+static void update_numa_active_node_mask(struct numa_group *numa_group)
+{
+       unsigned long faults, max_faults = 0;
+       int nid;
+
+       for_each_online_node(nid) {
+               faults = group_faults_cpu(numa_group, nid);
+               if (faults > max_faults)
+                       max_faults = faults;
+       }
+
+       for_each_online_node(nid) {
+               faults = group_faults_cpu(numa_group, nid);
+               if (!node_isset(nid, numa_group->active_nodes)) {
+                       if (faults > max_faults * 6 / 16)
+                               node_set(nid, numa_group->active_nodes);
+               } else if (faults < max_faults * 3 / 16)
+                       node_clear(nid, numa_group->active_nodes);
+       }
+}
+
 /*
  * When adapting the scan rate, the period is divided into NUMA_PERIOD_SLOTS
  * increments. The more local the fault statistics are, the higher the scan
@@ -1355,11 +1447,41 @@ static void update_task_scan_period(struct task_struct *p,
        memset(p->numa_faults_locality, 0, sizeof(p->numa_faults_locality));
 }
 
+/*
+ * Get the fraction of time the task has been running since the last
+ * NUMA placement cycle. The scheduler keeps similar statistics, but
+ * decays those on a 32ms period, which is orders of magnitude off
+ * from the dozens-of-seconds NUMA balancing period. Use the scheduler
+ * stats only if the task is so new there are no NUMA statistics yet.
+ */
+static u64 numa_get_avg_runtime(struct task_struct *p, u64 *period)
+{
+       u64 runtime, delta, now;
+       /* Use the start of this time slice to avoid calculations. */
+       now = p->se.exec_start;
+       runtime = p->se.sum_exec_runtime;
+
+       if (p->last_task_numa_placement) {
+               delta = runtime - p->last_sum_exec_runtime;
+               *period = now - p->last_task_numa_placement;
+       } else {
+               delta = p->se.avg.runnable_avg_sum;
+               *period = p->se.avg.runnable_avg_period;
+       }
+
+       p->last_sum_exec_runtime = runtime;
+       p->last_task_numa_placement = now;
+
+       return delta;
+}
+
 static void task_numa_placement(struct task_struct *p)
 {
        int seq, nid, max_nid = -1, max_group_nid = -1;
        unsigned long max_faults = 0, max_group_faults = 0;
        unsigned long fault_types[2] = { 0, 0 };
+       unsigned long total_faults;
+       u64 runtime, period;
        spinlock_t *group_lock = NULL;
 
        seq = ACCESS_ONCE(p->mm->numa_scan_seq);
@@ -1368,6 +1490,10 @@ static void task_numa_placement(struct task_struct *p)
        p->numa_scan_seq = seq;
        p->numa_scan_period_max = task_scan_max(p);
 
+       total_faults = p->numa_faults_locality[0] +
+                      p->numa_faults_locality[1];
+       runtime = numa_get_avg_runtime(p, &period);
+
        /* If the task is part of a group prevent parallel updates to group stats */
        if (p->numa_group) {
                group_lock = &p->numa_group->lock;
@@ -1379,24 +1505,37 @@ static void task_numa_placement(struct task_struct *p)
                unsigned long faults = 0, group_faults = 0;
                int priv, i;
 
-               for (priv = 0; priv < 2; priv++) {
-                       long diff;
+               for (priv = 0; priv < NR_NUMA_HINT_FAULT_TYPES; priv++) {
+                       long diff, f_diff, f_weight;
 
                        i = task_faults_idx(nid, priv);
-                       diff = -p->numa_faults[i];
 
                        /* Decay existing window, copy faults since last scan */
-                       p->numa_faults[i] >>= 1;
-                       p->numa_faults[i] += p->numa_faults_buffer[i];
-                       fault_types[priv] += p->numa_faults_buffer[i];
-                       p->numa_faults_buffer[i] = 0;
+                       diff = p->numa_faults_buffer_memory[i] - p->numa_faults_memory[i] / 2;
+                       fault_types[priv] += p->numa_faults_buffer_memory[i];
+                       p->numa_faults_buffer_memory[i] = 0;
 
-                       faults += p->numa_faults[i];
-                       diff += p->numa_faults[i];
+                       /*
+                        * Normalize the faults_from, so all tasks in a group
+                        * count according to CPU use, instead of by the raw
+                        * number of faults. Tasks with little runtime have
+                        * little over-all impact on throughput, and thus their
+                        * faults are less important.
+                        */
+                       f_weight = div64_u64(runtime << 16, period + 1);
+                       f_weight = (f_weight * p->numa_faults_buffer_cpu[i]) /
+                                  (total_faults + 1);
+                       f_diff = f_weight - p->numa_faults_cpu[i] / 2;
+                       p->numa_faults_buffer_cpu[i] = 0;
+
+                       p->numa_faults_memory[i] += diff;
+                       p->numa_faults_cpu[i] += f_diff;
+                       faults += p->numa_faults_memory[i];
                        p->total_numa_faults += diff;
                        if (p->numa_group) {
                                /* safe because we can only change our own group */
                                p->numa_group->faults[i] += diff;
+                               p->numa_group->faults_cpu[i] += f_diff;
                                p->numa_group->total_faults += diff;
                                group_faults += p->numa_group->faults[i];
                        }
@@ -1416,6 +1555,7 @@ static void task_numa_placement(struct task_struct *p)
        update_task_scan_period(p, fault_types[0], fault_types[1]);
 
        if (p->numa_group) {
+               update_numa_active_node_mask(p->numa_group);
                /*
                 * If the preferred task and group nids are different,
                 * iterate over the nodes again to find the best place.
@@ -1465,7 +1605,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
 
        if (unlikely(!p->numa_group)) {
                unsigned int size = sizeof(struct numa_group) +
-                                   2*nr_node_ids*sizeof(unsigned long);
+                                   4*nr_node_ids*sizeof(unsigned long);
 
                grp = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
                if (!grp)
@@ -1475,9 +1615,14 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
                spin_lock_init(&grp->lock);
                INIT_LIST_HEAD(&grp->task_list);
                grp->gid = p->pid;
+               /* Second half of the array tracks nids where faults happen */
+               grp->faults_cpu = grp->faults + NR_NUMA_HINT_FAULT_TYPES *
+                                               nr_node_ids;
+
+               node_set(task_node(current), grp->active_nodes);
 
-               for (i = 0; i < 2*nr_node_ids; i++)
-                       grp->faults[i] = p->numa_faults[i];
+               for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
+                       grp->faults[i] = p->numa_faults_memory[i];
 
                grp->total_faults = p->total_numa_faults;
 
@@ -1534,9 +1679,9 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
 
        double_lock(&my_grp->lock, &grp->lock);
 
-       for (i = 0; i < 2*nr_node_ids; i++) {
-               my_grp->faults[i] -= p->numa_faults[i];
-               grp->faults[i] += p->numa_faults[i];
+       for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) {
+               my_grp->faults[i] -= p->numa_faults_memory[i];
+               grp->faults[i] += p->numa_faults_memory[i];
        }
        my_grp->total_faults -= p->total_numa_faults;
        grp->total_faults += p->total_numa_faults;
@@ -1562,12 +1707,12 @@ void task_numa_free(struct task_struct *p)
 {
        struct numa_group *grp = p->numa_group;
        int i;
-       void *numa_faults = p->numa_faults;
+       void *numa_faults = p->numa_faults_memory;
 
        if (grp) {
                spin_lock(&grp->lock);
-               for (i = 0; i < 2*nr_node_ids; i++)
-                       grp->faults[i] -= p->numa_faults[i];
+               for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
+                       grp->faults[i] -= p->numa_faults_memory[i];
                grp->total_faults -= p->total_numa_faults;
 
                list_del(&p->numa_entry);
@@ -1577,18 +1722,21 @@ void task_numa_free(struct task_struct *p)
                put_numa_group(grp);
        }
 
-       p->numa_faults = NULL;
-       p->numa_faults_buffer = NULL;
+       p->numa_faults_memory = NULL;
+       p->numa_faults_buffer_memory = NULL;
+       p->numa_faults_cpu= NULL;
+       p->numa_faults_buffer_cpu = NULL;
        kfree(numa_faults);
 }
 
 /*
  * Got a PROT_NONE fault for a page on @node.
  */
-void task_numa_fault(int last_cpupid, int node, int pages, int flags)
+void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
 {
        struct task_struct *p = current;
        bool migrated = flags & TNF_MIGRATED;
+       int cpu_node = task_node(current);
        int priv;
 
        if (!numabalancing_enabled)
@@ -1603,16 +1751,24 @@ void task_numa_fault(int last_cpupid, int node, int pages, int flags)
                return;
 
        /* Allocate buffer to track faults on a per-node basis */
-       if (unlikely(!p->numa_faults)) {
-               int size = sizeof(*p->numa_faults) * 2 * nr_node_ids;
+       if (unlikely(!p->numa_faults_memory)) {
+               int size = sizeof(*p->numa_faults_memory) *
+                          NR_NUMA_HINT_FAULT_BUCKETS * nr_node_ids;
 
-               /* numa_faults and numa_faults_buffer share the allocation */
-               p->numa_faults = kzalloc(size * 2, GFP_KERNEL|__GFP_NOWARN);
-               if (!p->numa_faults)
+               p->numa_faults_memory = kzalloc(size, GFP_KERNEL|__GFP_NOWARN);
+               if (!p->numa_faults_memory)
                        return;
 
-               BUG_ON(p->numa_faults_buffer);
-               p->numa_faults_buffer = p->numa_faults + (2 * nr_node_ids);
+               BUG_ON(p->numa_faults_buffer_memory);
+               /*
+                * The averaged statistics, shared & private, memory & cpu,
+                * occupy the first half of the array. The second half of the
+                * array is for current counters, which are averaged into the
+                * first set by task_numa_placement.
+                */
+               p->numa_faults_cpu = p->numa_faults_memory + (2 * nr_node_ids);
+               p->numa_faults_buffer_memory = p->numa_faults_memory + (4 * nr_node_ids);
+               p->numa_faults_buffer_cpu = p->numa_faults_memory + (6 * nr_node_ids);
                p->total_numa_faults = 0;
                memset(p->numa_faults_locality, 0, sizeof(p->numa_faults_locality));
        }
@@ -1641,7 +1797,8 @@ void task_numa_fault(int last_cpupid, int node, int pages, int flags)
        if (migrated)
                p->numa_pages_migrated += pages;
 
-       p->numa_faults_buffer[task_faults_idx(node, priv)] += pages;
+       p->numa_faults_buffer_memory[task_faults_idx(mem_node, priv)] += pages;
+       p->numa_faults_buffer_cpu[task_faults_idx(cpu_node, priv)] += pages;
        p->numa_faults_locality[!!(flags & TNF_FAULT_LOCAL)] += pages;
 }
 
@@ -1757,6 +1914,8 @@ void task_numa_work(struct callback_head *work)
                        start = end;
                        if (pages <= 0)
                                goto out;
+
+                       cond_resched();
                } while (end != vma->vm_end);
        }
 
@@ -2217,13 +2376,20 @@ static inline void __update_group_entity_contrib(struct sched_entity *se)
                se->avg.load_avg_contrib >>= NICE_0_SHIFT;
        }
 }
-#else
+
+static inline void update_rq_runnable_avg(struct rq *rq, int runnable)
+{
+       __update_entity_runnable_avg(rq_clock_task(rq), &rq->avg, runnable);
+       __update_tg_runnable_avg(&rq->avg, &rq->cfs);
+}
+#else /* CONFIG_FAIR_GROUP_SCHED */
 static inline void __update_cfs_rq_tg_load_contrib(struct cfs_rq *cfs_rq,
                                                 int force_update) {}
 static inline void __update_tg_runnable_avg(struct sched_avg *sa,
                                                  struct cfs_rq *cfs_rq) {}
 static inline void __update_group_entity_contrib(struct sched_entity *se) {}
-#endif
+static inline void update_rq_runnable_avg(struct rq *rq, int runnable) {}
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 
 static inline void __update_task_entity_contrib(struct sched_entity *se)
 {
@@ -2321,12 +2487,6 @@ static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq, int force_update)
        __update_cfs_rq_tg_load_contrib(cfs_rq, force_update);
 }
 
-static inline void update_rq_runnable_avg(struct rq *rq, int runnable)
-{
-       __update_entity_runnable_avg(rq_clock_task(rq), &rq->avg, runnable);
-       __update_tg_runnable_avg(&rq->avg, &rq->cfs);
-}
-
 /* Add the load generated by se into cfs_rq's child load-average */
 static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq,
                                                  struct sched_entity *se,
@@ -2414,7 +2574,10 @@ void idle_exit_fair(struct rq *this_rq)
        update_rq_runnable_avg(this_rq, 0);
 }
 
-#else
+static int idle_balance(struct rq *this_rq);
+
+#else /* CONFIG_SMP */
+
 static inline void update_entity_load_avg(struct sched_entity *se,
                                          int update_cfs_rq) {}
 static inline void update_rq_runnable_avg(struct rq *rq, int runnable) {}
@@ -2426,7 +2589,13 @@ static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq,
                                           int sleep) {}
 static inline void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq,
                                              int force_update) {}
-#endif
+
+static inline int idle_balance(struct rq *rq)
+{
+       return 0;
+}
+
+#endif /* CONFIG_SMP */
 
 static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
@@ -2576,10 +2745,10 @@ static void __clear_buddies_last(struct sched_entity *se)
 {
        for_each_sched_entity(se) {
                struct cfs_rq *cfs_rq = cfs_rq_of(se);
-               if (cfs_rq->last == se)
-                       cfs_rq->last = NULL;
-               else
+               if (cfs_rq->last != se)
                        break;
+
+               cfs_rq->last = NULL;
        }
 }
 
@@ -2587,10 +2756,10 @@ static void __clear_buddies_next(struct sched_entity *se)
 {
        for_each_sched_entity(se) {
                struct cfs_rq *cfs_rq = cfs_rq_of(se);
-               if (cfs_rq->next == se)
-                       cfs_rq->next = NULL;
-               else
+               if (cfs_rq->next != se)
                        break;
+
+               cfs_rq->next = NULL;
        }
 }
 
@@ -2598,10 +2767,10 @@ static void __clear_buddies_skip(struct sched_entity *se)
 {
        for_each_sched_entity(se) {
                struct cfs_rq *cfs_rq = cfs_rq_of(se);
-               if (cfs_rq->skip == se)
-                       cfs_rq->skip = NULL;
-               else
+               if (cfs_rq->skip != se)
                        break;
+
+               cfs_rq->skip = NULL;
        }
 }
 
@@ -2744,17 +2913,36 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
  * 3) pick the "last" process, for cache locality
  * 4) do not run the "skip" process, if something else is available
  */
-static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
+static struct sched_entity *
+pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr)
 {
-       struct sched_entity *se = __pick_first_entity(cfs_rq);
-       struct sched_entity *left = se;
+       struct sched_entity *left = __pick_first_entity(cfs_rq);
+       struct sched_entity *se;
+
+       /*
+        * If curr is set we have to see if its left of the leftmost entity
+        * still in the tree, provided there was anything in the tree at all.
+        */
+       if (!left || (curr && entity_before(curr, left)))
+               left = curr;
+
+       se = left; /* ideally we run the leftmost entity */
 
        /*
         * Avoid running the skip buddy, if running something else can
         * be done without getting too unfair.
         */
        if (cfs_rq->skip == se) {
-               struct sched_entity *second = __pick_next_entity(se);
+               struct sched_entity *second;
+
+               if (se == curr) {
+                       second = __pick_first_entity(cfs_rq);
+               } else {
+                       second = __pick_next_entity(se);
+                       if (!second || (curr && entity_before(curr, second)))
+                               second = curr;
+               }
+
                if (second && wakeup_preempt_entity(second, left) < 1)
                        se = second;
        }
@@ -2776,7 +2964,7 @@ static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
        return se;
 }
 
-static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq);
+static bool check_cfs_rq_runtime(struct cfs_rq *cfs_rq);
 
 static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
 {
@@ -3431,22 +3619,23 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq)
 }
 
 /* conditionally throttle active cfs_rq's from put_prev_entity() */
-static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq)
+static bool check_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 {
        if (!cfs_bandwidth_used())
-               return;
+               return false;
 
        if (likely(!cfs_rq->runtime_enabled || cfs_rq->runtime_remaining > 0))
-               return;
+               return false;
 
        /*
         * it's possible for a throttled entity to be forced into a running
         * state (e.g. set_curr_task), in this case we're finished.
         */
        if (cfs_rq_throttled(cfs_rq))
-               return;
+               return true;
 
        throttle_cfs_rq(cfs_rq);
+       return true;
 }
 
 static enum hrtimer_restart sched_cfs_slack_timer(struct hrtimer *timer)
@@ -3556,7 +3745,7 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
 }
 
 static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec) {}
-static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
+static bool check_cfs_rq_runtime(struct cfs_rq *cfs_rq) { return false; }
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
 static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
 
@@ -4211,13 +4400,14 @@ done:
 }
 
 /*
- * sched_balance_self: balance the current task (running on cpu) in domains
- * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and
- * SD_BALANCE_EXEC.
+ * select_task_rq_fair: Select target runqueue for the waking task in domains
+ * that have the 'sd_flag' flag set. In practice, this is SD_BALANCE_WAKE,
+ * SD_BALANCE_FORK, or SD_BALANCE_EXEC.
  *
- * Balance, ie. select the least loaded group.
+ * Balances load by selecting the idlest cpu in the idlest group, or under
+ * certain conditions an idle sibling cpu if the domain has SD_WAKE_AFFINE set.
  *
- * Returns the target CPU number, or the same CPU if no balancing is needed.
+ * Returns the target cpu number.
  *
  * preempt must be disabled.
  */
@@ -4492,26 +4682,124 @@ preempt:
                set_last_buddy(se);
 }
 
-static struct task_struct *pick_next_task_fair(struct rq *rq)
+static struct task_struct *
+pick_next_task_fair(struct rq *rq, struct task_struct *prev)
 {
-       struct task_struct *p;
        struct cfs_rq *cfs_rq = &rq->cfs;
        struct sched_entity *se;
+       struct task_struct *p;
+       int new_tasks;
 
+again:
+#ifdef CONFIG_FAIR_GROUP_SCHED
        if (!cfs_rq->nr_running)
-               return NULL;
+               goto idle;
+
+       if (prev->sched_class != &fair_sched_class)
+               goto simple;
+
+       /*
+        * Because of the set_next_buddy() in dequeue_task_fair() it is rather
+        * likely that a next task is from the same cgroup as the current.
+        *
+        * Therefore attempt to avoid putting and setting the entire cgroup
+        * hierarchy, only change the part that actually changes.
+        */
 
        do {
-               se = pick_next_entity(cfs_rq);
+               struct sched_entity *curr = cfs_rq->curr;
+
+               /*
+                * Since we got here without doing put_prev_entity() we also
+                * have to consider cfs_rq->curr. If it is still a runnable
+                * entity, update_curr() will update its vruntime, otherwise
+                * forget we've ever seen it.
+                */
+               if (curr && curr->on_rq)
+                       update_curr(cfs_rq);
+               else
+                       curr = NULL;
+
+               /*
+                * This call to check_cfs_rq_runtime() will do the throttle and
+                * dequeue its entity in the parent(s). Therefore the 'simple'
+                * nr_running test will indeed be correct.
+                */
+               if (unlikely(check_cfs_rq_runtime(cfs_rq)))
+                       goto simple;
+
+               se = pick_next_entity(cfs_rq, curr);
+               cfs_rq = group_cfs_rq(se);
+       } while (cfs_rq);
+
+       p = task_of(se);
+
+       /*
+        * Since we haven't yet done put_prev_entity and if the selected task
+        * is a different task than we started out with, try and touch the
+        * least amount of cfs_rqs.
+        */
+       if (prev != p) {
+               struct sched_entity *pse = &prev->se;
+
+               while (!(cfs_rq = is_same_group(se, pse))) {
+                       int se_depth = se->depth;
+                       int pse_depth = pse->depth;
+
+                       if (se_depth <= pse_depth) {
+                               put_prev_entity(cfs_rq_of(pse), pse);
+                               pse = parent_entity(pse);
+                       }
+                       if (se_depth >= pse_depth) {
+                               set_next_entity(cfs_rq_of(se), se);
+                               se = parent_entity(se);
+                       }
+               }
+
+               put_prev_entity(cfs_rq, pse);
+               set_next_entity(cfs_rq, se);
+       }
+
+       if (hrtick_enabled(rq))
+               hrtick_start_fair(rq, p);
+
+       return p;
+simple:
+       cfs_rq = &rq->cfs;
+#endif
+
+       if (!cfs_rq->nr_running)
+               goto idle;
+
+       put_prev_task(rq, prev);
+
+       do {
+               se = pick_next_entity(cfs_rq, NULL);
                set_next_entity(cfs_rq, se);
                cfs_rq = group_cfs_rq(se);
        } while (cfs_rq);
 
        p = task_of(se);
+
        if (hrtick_enabled(rq))
                hrtick_start_fair(rq, p);
 
        return p;
+
+idle:
+       new_tasks = idle_balance(rq);
+       /*
+        * Because idle_balance() releases (and re-acquires) rq->lock, it is
+        * possible for any higher priority task to appear. In that case we
+        * must re-start the pick_next_entity() loop.
+        */
+       if (new_tasks < 0)
+               return RETRY_TASK;
+
+       if (new_tasks > 0)
+               goto again;
+
+       return NULL;
 }
 
 /*
@@ -4749,7 +5037,7 @@ static void move_task(struct task_struct *p, struct lb_env *env)
  * Is this task likely cache-hot:
  */
 static int
-task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
+task_hot(struct task_struct *p, u64 now)
 {
        s64 delta;
 
@@ -4783,7 +5071,7 @@ static bool migrate_improves_locality(struct task_struct *p, struct lb_env *env)
 {
        int src_nid, dst_nid;
 
-       if (!sched_feat(NUMA_FAVOUR_HIGHER) || !p->numa_faults ||
+       if (!sched_feat(NUMA_FAVOUR_HIGHER) || !p->numa_faults_memory ||
            !(env->sd->flags & SD_NUMA)) {
                return false;
        }
@@ -4814,7 +5102,7 @@ static bool migrate_degrades_locality(struct task_struct *p, struct lb_env *env)
        if (!sched_feat(NUMA) || !sched_feat(NUMA_RESIST_LOWER))
                return false;
 
-       if (!p->numa_faults || !(env->sd->flags & SD_NUMA))
+       if (!p->numa_faults_memory || !(env->sd->flags & SD_NUMA))
                return false;
 
        src_nid = cpu_to_node(env->src_cpu);
@@ -4910,7 +5198,7 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
         * 2) task is cache cold, or
         * 3) too many balance attempts have failed.
         */
-       tsk_cache_hot = task_hot(p, rq_clock_task(env->src_rq), env->sd);
+       tsk_cache_hot = task_hot(p, rq_clock_task(env->src_rq));
        if (!tsk_cache_hot)
                tsk_cache_hot = migrate_degrades_locality(p, env);
 
@@ -5773,12 +6061,10 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds)
        pwr_now /= SCHED_POWER_SCALE;
 
        /* Amount of load we'd subtract */
-       tmp = (busiest->load_per_task * SCHED_POWER_SCALE) /
-               busiest->group_power;
-       if (busiest->avg_load > tmp) {
+       if (busiest->avg_load > scaled_busy_load_per_task) {
                pwr_move += busiest->group_power *
                            min(busiest->load_per_task,
-                               busiest->avg_load - tmp);
+                               busiest->avg_load - scaled_busy_load_per_task);
        }
 
        /* Amount of load we'd add */
@@ -6357,17 +6643,23 @@ out:
  * idle_balance is called by schedule() if this_cpu is about to become
  * idle. Attempts to pull tasks from other CPUs.
  */
-void idle_balance(int this_cpu, struct rq *this_rq)
+static int idle_balance(struct rq *this_rq)
 {
        struct sched_domain *sd;
        int pulled_task = 0;
        unsigned long next_balance = jiffies + HZ;
        u64 curr_cost = 0;
+       int this_cpu = this_rq->cpu;
 
+       idle_enter_fair(this_rq);
+       /*
+        * We must set idle_stamp _before_ calling idle_balance(), such that we
+        * measure the duration of idle_balance() as idle time.
+        */
        this_rq->idle_stamp = rq_clock(this_rq);
 
        if (this_rq->avg_idle < sysctl_sched_migration_cost)
-               return;
+               goto out;
 
        /*
         * Drop the rq->lock, but keep IRQ/preempt disabled.
@@ -6405,15 +6697,22 @@ void idle_balance(int this_cpu, struct rq *this_rq)
                interval = msecs_to_jiffies(sd->balance_interval);
                if (time_after(next_balance, sd->last_balance + interval))
                        next_balance = sd->last_balance + interval;
-               if (pulled_task) {
-                       this_rq->idle_stamp = 0;
+               if (pulled_task)
                        break;
-               }
        }
        rcu_read_unlock();
 
        raw_spin_lock(&this_rq->lock);
 
+       /*
+        * While browsing the domains, we released the rq lock.
+        * A task could have be enqueued in the meantime
+        */
+       if (this_rq->cfs.h_nr_running && !pulled_task) {
+               pulled_task = 1;
+               goto out;
+       }
+
        if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
                /*
                 * We are going idle. next_balance may be set based on
@@ -6424,6 +6723,20 @@ void idle_balance(int this_cpu, struct rq *this_rq)
 
        if (curr_cost > this_rq->max_idle_balance_cost)
                this_rq->max_idle_balance_cost = curr_cost;
+
+out:
+       /* Is there a task of a high priority class? */
+       if (this_rq->nr_running != this_rq->cfs.h_nr_running &&
+           (this_rq->dl.dl_nr_running ||
+            (this_rq->rt.rt_nr_running && !rt_rq_throttled(&this_rq->rt))))
+               pulled_task = -1;
+
+       if (pulled_task) {
+               idle_exit_fair(this_rq);
+               this_rq->idle_stamp = 0;
+       }
+
+       return pulled_task;
 }
 
 /*
@@ -6494,6 +6807,11 @@ out_unlock:
        return 0;
 }
 
+static inline int on_null_domain(struct rq *rq)
+{
+       return unlikely(!rcu_dereference_sched(rq->sd));
+}
+
 #ifdef CONFIG_NO_HZ_COMMON
 /*
  * idle load balancing details
@@ -6548,8 +6866,13 @@ static void nohz_balancer_kick(void)
 static inline void nohz_balance_exit_idle(int cpu)
 {
        if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
-               cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
-               atomic_dec(&nohz.nr_cpus);
+               /*
+                * Completely isolated CPUs don't ever set, so we must test.
+                */
+               if (likely(cpumask_test_cpu(cpu, nohz.idle_cpus_mask))) {
+                       cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+                       atomic_dec(&nohz.nr_cpus);
+               }
                clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
        }
 }
@@ -6603,6 +6926,12 @@ void nohz_balance_enter_idle(int cpu)
        if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
                return;
 
+       /*
+        * If we're a completely isolated CPU, we don't play.
+        */
+       if (on_null_domain(cpu_rq(cpu)))
+               return;
+
        cpumask_set_cpu(cpu, nohz.idle_cpus_mask);
        atomic_inc(&nohz.nr_cpus);
        set_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
@@ -6865,11 +7194,6 @@ static void run_rebalance_domains(struct softirq_action *h)
        nohz_idle_balance(this_rq, idle);
 }
 
-static inline int on_null_domain(struct rq *rq)
-{
-       return !rcu_dereference_sched(rq->sd);
-}
-
 /*
  * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing.
  */
@@ -6999,15 +7323,15 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p)
        struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
        /*
-        * Ensure the task's vruntime is normalized, so that when its
+        * Ensure the task's vruntime is normalized, so that when it's
         * switched back to the fair class the enqueue_entity(.flags=0) will
         * do the right thing.
         *
-        * If it was on_rq, then the dequeue_entity(.flags=0) will already
-        * have normalized the vruntime, if it was !on_rq, then only when
+        * If it's on_rq, then the dequeue_entity(.flags=0) will already
+        * have normalized the vruntime, if it's !on_rq, then only when
         * the task is sleeping will it still have non-normalized vruntime.
         */
-       if (!se->on_rq && p->state != TASK_RUNNING) {
+       if (!p->on_rq && p->state != TASK_RUNNING) {
                /*
                 * Fix up our vruntime so that the current sleep doesn't
                 * cause 'unlimited' sleep bonus.
@@ -7034,7 +7358,15 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p)
  */
 static void switched_to_fair(struct rq *rq, struct task_struct *p)
 {
-       if (!p->se.on_rq)
+       struct sched_entity *se = &p->se;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+       /*
+        * Since the real-depth could have been changed (only FAIR
+        * class maintain depth value), reset depth properly.
+        */
+       se->depth = se->parent ? se->parent->depth + 1 : 0;
+#endif
+       if (!se->on_rq)
                return;
 
        /*
@@ -7082,7 +7414,9 @@ void init_cfs_rq(struct cfs_rq *cfs_rq)
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static void task_move_group_fair(struct task_struct *p, int on_rq)
 {
+       struct sched_entity *se = &p->se;
        struct cfs_rq *cfs_rq;
+
        /*
         * If the task was not on the rq at the time of this cgroup movement
         * it must have been asleep, sleeping tasks keep their ->vruntime
@@ -7108,23 +7442,24 @@ static void task_move_group_fair(struct task_struct *p, int on_rq)
         * To prevent boost or penalty in the new cfs_rq caused by delta
         * min_vruntime between the two cfs_rqs, we skip vruntime adjustment.
         */
-       if (!on_rq && (!p->se.sum_exec_runtime || p->state == TASK_WAKING))
+       if (!on_rq && (!se->sum_exec_runtime || p->state == TASK_WAKING))
                on_rq = 1;
 
        if (!on_rq)
-               p->se.vruntime -= cfs_rq_of(&p->se)->min_vruntime;
+               se->vruntime -= cfs_rq_of(se)->min_vruntime;
        set_task_rq(p, task_cpu(p));
+       se->depth = se->parent ? se->parent->depth + 1 : 0;
        if (!on_rq) {
-               cfs_rq = cfs_rq_of(&p->se);
-               p->se.vruntime += cfs_rq->min_vruntime;
+               cfs_rq = cfs_rq_of(se);
+               se->vruntime += cfs_rq->min_vruntime;
 #ifdef CONFIG_SMP
                /*
                 * migrate_task_rq_fair() will have removed our previous
                 * contribution, but we must synchronize for ongoing future
                 * decay.
                 */
-               p->se.avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
-               cfs_rq->blocked_load_avg += p->se.avg.load_avg_contrib;
+               se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter);
+               cfs_rq->blocked_load_avg += se->avg.load_avg_contrib;
 #endif
        }
 }
@@ -7220,10 +7555,13 @@ void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
        if (!se)
                return;
 
-       if (!parent)
+       if (!parent) {
                se->cfs_rq = &rq->cfs;
-       else
+               se->depth = 0;
+       } else {
                se->cfs_rq = parent->my_q;
+               se->depth = parent->depth + 1;
+       }
 
        se->my_q = cfs_rq;
        /* guarantee group entities always have weight */
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
new file mode 100644 (file)
index 0000000..b7976a1
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Generic entry point for the idle threads
+ */
+#include <linux/sched.h>
+#include <linux/cpu.h>
+#include <linux/cpuidle.h>
+#include <linux/tick.h>
+#include <linux/mm.h>
+#include <linux/stackprotector.h>
+
+#include <asm/tlb.h>
+
+#include <trace/events/power.h>
+
+static int __read_mostly cpu_idle_force_poll;
+
+void cpu_idle_poll_ctrl(bool enable)
+{
+       if (enable) {
+               cpu_idle_force_poll++;
+       } else {
+               cpu_idle_force_poll--;
+               WARN_ON_ONCE(cpu_idle_force_poll < 0);
+       }
+}
+
+#ifdef CONFIG_GENERIC_IDLE_POLL_SETUP
+static int __init cpu_idle_poll_setup(char *__unused)
+{
+       cpu_idle_force_poll = 1;
+       return 1;
+}
+__setup("nohlt", cpu_idle_poll_setup);
+
+static int __init cpu_idle_nopoll_setup(char *__unused)
+{
+       cpu_idle_force_poll = 0;
+       return 1;
+}
+__setup("hlt", cpu_idle_nopoll_setup);
+#endif
+
+static inline int cpu_idle_poll(void)
+{
+       rcu_idle_enter();
+       trace_cpu_idle_rcuidle(0, smp_processor_id());
+       local_irq_enable();
+       while (!tif_need_resched())
+               cpu_relax();
+       trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
+       rcu_idle_exit();
+       return 1;
+}
+
+/* Weak implementations for optional arch specific functions */
+void __weak arch_cpu_idle_prepare(void) { }
+void __weak arch_cpu_idle_enter(void) { }
+void __weak arch_cpu_idle_exit(void) { }
+void __weak arch_cpu_idle_dead(void) { }
+void __weak arch_cpu_idle(void)
+{
+       cpu_idle_force_poll = 1;
+       local_irq_enable();
+}
+
+/*
+ * Generic idle loop implementation
+ */
+static void cpu_idle_loop(void)
+{
+       while (1) {
+               tick_nohz_idle_enter();
+
+               while (!need_resched()) {
+                       check_pgt_cache();
+                       rmb();
+
+                       if (cpu_is_offline(smp_processor_id()))
+                               arch_cpu_idle_dead();
+
+                       local_irq_disable();
+                       arch_cpu_idle_enter();
+
+                       /*
+                        * In poll mode we reenable interrupts and spin.
+                        *
+                        * Also if we detected in the wakeup from idle
+                        * path that the tick broadcast device expired
+                        * for us, we don't want to go deep idle as we
+                        * know that the IPI is going to arrive right
+                        * away
+                        */
+                       if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
+                               cpu_idle_poll();
+                       } else {
+                               if (!current_clr_polling_and_test()) {
+                                       stop_critical_timings();
+                                       rcu_idle_enter();
+                                       if (cpuidle_idle_call())
+                                               arch_cpu_idle();
+                                       if (WARN_ON_ONCE(irqs_disabled()))
+                                               local_irq_enable();
+                                       rcu_idle_exit();
+                                       start_critical_timings();
+                               } else {
+                                       local_irq_enable();
+                               }
+                               __current_set_polling();
+                       }
+                       arch_cpu_idle_exit();
+               }
+
+               /*
+                * Since we fell out of the loop above, we know
+                * TIF_NEED_RESCHED must be set, propagate it into
+                * PREEMPT_NEED_RESCHED.
+                *
+                * This is required because for polling idle loops we will
+                * not have had an IPI to fold the state for us.
+                */
+               preempt_set_need_resched();
+               tick_nohz_idle_exit();
+               schedule_preempt_disabled();
+       }
+}
+
+void cpu_startup_entry(enum cpuhp_state state)
+{
+       /*
+        * This #ifdef needs to die, but it's too late in the cycle to
+        * make this generic (arm and sh have never invoked the canary
+        * init for the non boot cpus!). Will be fixed in 3.11
+        */
+#ifdef CONFIG_X86
+       /*
+        * If we're the non-boot CPU, nothing set the stack canary up
+        * for us. The boot CPU already has it initialized but no harm
+        * in doing it again. This is a good place for updating it, as
+        * we wont ever return from this function (so the invalid
+        * canaries already on the stack wont ever trigger).
+        */
+       boot_init_stack_canary();
+#endif
+       __current_set_polling();
+       arch_cpu_idle_prepare();
+       cpu_idle_loop();
+}
index 516c3d9ceea1455cee6c5a7b96db7f92a141f9af..879f2b75266a9933823a2056541af469cdc9c3dd 100644 (file)
@@ -13,18 +13,8 @@ select_task_rq_idle(struct task_struct *p, int cpu, int sd_flag, int flags)
 {
        return task_cpu(p); /* IDLE tasks as never migrated */
 }
-
-static void pre_schedule_idle(struct rq *rq, struct task_struct *prev)
-{
-       idle_exit_fair(rq);
-       rq_last_tick_reset(rq);
-}
-
-static void post_schedule_idle(struct rq *rq)
-{
-       idle_enter_fair(rq);
-}
 #endif /* CONFIG_SMP */
+
 /*
  * Idle tasks are unconditionally rescheduled:
  */
@@ -33,13 +23,12 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
        resched_task(rq->idle);
 }
 
-static struct task_struct *pick_next_task_idle(struct rq *rq)
+static struct task_struct *
+pick_next_task_idle(struct rq *rq, struct task_struct *prev)
 {
+       put_prev_task(rq, prev);
+
        schedstat_inc(rq, sched_goidle);
-#ifdef CONFIG_SMP
-       /* Trigger the post schedule to do an idle_enter for CFS */
-       rq->post_schedule = 1;
-#endif
        return rq->idle;
 }
 
@@ -58,6 +47,8 @@ dequeue_task_idle(struct rq *rq, struct task_struct *p, int flags)
 
 static void put_prev_task_idle(struct rq *rq, struct task_struct *prev)
 {
+       idle_exit_fair(rq);
+       rq_last_tick_reset(rq);
 }
 
 static void task_tick_idle(struct rq *rq, struct task_struct *curr, int queued)
@@ -101,8 +92,6 @@ const struct sched_class idle_sched_class = {
 
 #ifdef CONFIG_SMP
        .select_task_rq         = select_task_rq_idle,
-       .pre_schedule           = pre_schedule_idle,
-       .post_schedule          = post_schedule_idle,
 #endif
 
        .set_curr_task          = set_curr_task_idle,
index a2740b775b456ed27c56ad088007c83e1873458b..d8cdf1618551c80143e0f5fd38de556d089eb1f6 100644 (file)
@@ -229,6 +229,14 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
 
 #ifdef CONFIG_SMP
 
+static int pull_rt_task(struct rq *this_rq);
+
+static inline bool need_pull_rt_task(struct rq *rq, struct task_struct *prev)
+{
+       /* Try to pull RT tasks here if we lower this rq's prio */
+       return rq->rt.highest_prio.curr > prev->prio;
+}
+
 static inline int rt_overloaded(struct rq *rq)
 {
        return atomic_read(&rq->rd->rto_count);
@@ -315,6 +323,15 @@ static inline int has_pushable_tasks(struct rq *rq)
        return !plist_head_empty(&rq->rt.pushable_tasks);
 }
 
+static inline void set_post_schedule(struct rq *rq)
+{
+       /*
+        * We detect this state here so that we can avoid taking the RQ
+        * lock again later if there is no need to push
+        */
+       rq->post_schedule = has_pushable_tasks(rq);
+}
+
 static void enqueue_pushable_task(struct rq *rq, struct task_struct *p)
 {
        plist_del(&p->pushable_tasks, &rq->rt.pushable_tasks);
@@ -359,6 +376,19 @@ void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 {
 }
 
+static inline bool need_pull_rt_task(struct rq *rq, struct task_struct *prev)
+{
+       return false;
+}
+
+static inline int pull_rt_task(struct rq *this_rq)
+{
+       return 0;
+}
+
+static inline void set_post_schedule(struct rq *rq)
+{
+}
 #endif /* CONFIG_SMP */
 
 static inline int on_rt_rq(struct sched_rt_entity *rt_se)
@@ -440,11 +470,6 @@ static void sched_rt_rq_dequeue(struct rt_rq *rt_rq)
                dequeue_rt_entity(rt_se);
 }
 
-static inline int rt_rq_throttled(struct rt_rq *rt_rq)
-{
-       return rt_rq->rt_throttled && !rt_rq->rt_nr_boosted;
-}
-
 static int rt_se_boosted(struct sched_rt_entity *rt_se)
 {
        struct rt_rq *rt_rq = group_rt_rq(rt_se);
@@ -515,11 +540,6 @@ static inline void sched_rt_rq_dequeue(struct rt_rq *rt_rq)
 {
 }
 
-static inline int rt_rq_throttled(struct rt_rq *rt_rq)
-{
-       return rt_rq->rt_throttled;
-}
-
 static inline const struct cpumask *sched_rt_period_mask(void)
 {
        return cpu_online_mask;
@@ -538,6 +558,14 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
 
 #endif /* CONFIG_RT_GROUP_SCHED */
 
+bool sched_rt_bandwidth_account(struct rt_rq *rt_rq)
+{
+       struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
+
+       return (hrtimer_active(&rt_b->rt_period_timer) ||
+               rt_rq->rt_time < rt_b->rt_runtime);
+}
+
 #ifdef CONFIG_SMP
 /*
  * We ran out of runtime, see if we can borrow some from our neighbours.
@@ -1310,15 +1338,7 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
 {
        struct sched_rt_entity *rt_se;
        struct task_struct *p;
-       struct rt_rq *rt_rq;
-
-       rt_rq = &rq->rt;
-
-       if (!rt_rq->rt_nr_running)
-               return NULL;
-
-       if (rt_rq_throttled(rt_rq))
-               return NULL;
+       struct rt_rq *rt_rq  = &rq->rt;
 
        do {
                rt_se = pick_next_rt_entity(rq, rt_rq);
@@ -1332,21 +1352,45 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq)
        return p;
 }
 
-static struct task_struct *pick_next_task_rt(struct rq *rq)
+static struct task_struct *
+pick_next_task_rt(struct rq *rq, struct task_struct *prev)
 {
-       struct task_struct *p = _pick_next_task_rt(rq);
+       struct task_struct *p;
+       struct rt_rq *rt_rq = &rq->rt;
+
+       if (need_pull_rt_task(rq, prev)) {
+               pull_rt_task(rq);
+               /*
+                * pull_rt_task() can drop (and re-acquire) rq->lock; this
+                * means a dl task can slip in, in which case we need to
+                * re-start task selection.
+                */
+               if (unlikely(rq->dl.dl_nr_running))
+                       return RETRY_TASK;
+       }
+
+       /*
+        * We may dequeue prev's rt_rq in put_prev_task().
+        * So, we update time before rt_nr_running check.
+        */
+       if (prev->sched_class == &rt_sched_class)
+               update_curr_rt(rq);
+
+       if (!rt_rq->rt_nr_running)
+               return NULL;
+
+       if (rt_rq_throttled(rt_rq))
+               return NULL;
+
+       put_prev_task(rq, prev);
+
+       p = _pick_next_task_rt(rq);
 
        /* The running task is never eligible for pushing */
        if (p)
                dequeue_pushable_task(rq, p);
 
-#ifdef CONFIG_SMP
-       /*
-        * We detect this state here so that we can avoid taking the RQ
-        * lock again later if there is no need to push
-        */
-       rq->post_schedule = has_pushable_tasks(rq);
-#endif
+       set_post_schedule(rq);
 
        return p;
 }
@@ -1716,13 +1760,6 @@ skip:
        return ret;
 }
 
-static void pre_schedule_rt(struct rq *rq, struct task_struct *prev)
-{
-       /* Try to pull RT tasks here if we lower this rq's prio */
-       if (rq->rt.highest_prio.curr > prev->prio)
-               pull_rt_task(rq);
-}
-
 static void post_schedule_rt(struct rq *rq)
 {
        push_rt_tasks(rq);
@@ -1825,7 +1862,7 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p)
                resched_task(rq->curr);
 }
 
-void init_sched_rt_class(void)
+void __init init_sched_rt_class(void)
 {
        unsigned int i;
 
@@ -1999,7 +2036,6 @@ const struct sched_class rt_sched_class = {
        .set_cpus_allowed       = set_cpus_allowed_rt,
        .rq_online              = rq_online_rt,
        .rq_offline             = rq_offline_rt,
-       .pre_schedule           = pre_schedule_rt,
        .post_schedule          = post_schedule_rt,
        .task_woken             = task_woken_rt,
        .switched_from          = switched_from_rt,
index c2119fd20f8b6dc2042a80603d44223ab9365dec..c9007f28d3a222ca97b5fb98210b2ecc1e756b7a 100644 (file)
@@ -23,24 +23,6 @@ extern atomic_long_t calc_load_tasks;
 extern long calc_load_fold_active(struct rq *this_rq);
 extern void update_cpu_load_active(struct rq *this_rq);
 
-/*
- * Convert user-nice values [ -20 ... 0 ... 19 ]
- * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
- * and back.
- */
-#define NICE_TO_PRIO(nice)     (MAX_RT_PRIO + (nice) + 20)
-#define PRIO_TO_NICE(prio)     ((prio) - MAX_RT_PRIO - 20)
-#define TASK_NICE(p)           PRIO_TO_NICE((p)->static_prio)
-
-/*
- * 'User priority' is the nice value converted to something we
- * can work with better when scaling various scheduler parameters,
- * it's a [ 0 ... 39 ] range.
- */
-#define USER_PRIO(p)           ((p)-MAX_RT_PRIO)
-#define TASK_USER_PRIO(p)      USER_PRIO((p)->static_prio)
-#define MAX_USER_PRIO          (USER_PRIO(MAX_PRIO))
-
 /*
  * Helpers for converting nanosecond timing to jiffy resolution
  */
@@ -441,6 +423,18 @@ struct rt_rq {
 #endif
 };
 
+#ifdef CONFIG_RT_GROUP_SCHED
+static inline int rt_rq_throttled(struct rt_rq *rt_rq)
+{
+       return rt_rq->rt_throttled && !rt_rq->rt_nr_boosted;
+}
+#else
+static inline int rt_rq_throttled(struct rt_rq *rt_rq)
+{
+       return rt_rq->rt_throttled;
+}
+#endif
+
 /* Deadline class' related fields in a runqueue */
 struct dl_rq {
        /* runqueue is an rbtree, ordered by deadline */
@@ -462,7 +456,6 @@ struct dl_rq {
        } earliest_dl;
 
        unsigned long dl_nr_migratory;
-       unsigned long dl_nr_total;
        int overloaded;
 
        /*
@@ -559,11 +552,9 @@ struct rq {
 #ifdef CONFIG_FAIR_GROUP_SCHED
        /* list of leaf cfs_rq on this cpu: */
        struct list_head leaf_cfs_rq_list;
-#endif /* CONFIG_FAIR_GROUP_SCHED */
 
-#ifdef CONFIG_RT_GROUP_SCHED
-       struct list_head leaf_rt_rq_list;
-#endif
+       struct sched_avg avg;
+#endif /* CONFIG_FAIR_GROUP_SCHED */
 
        /*
         * This is part of a global counter where only the total sum
@@ -652,8 +643,6 @@ struct rq {
 #ifdef CONFIG_SMP
        struct llist_head wake_list;
 #endif
-
-       struct sched_avg avg;
 };
 
 static inline int cpu_of(struct rq *rq)
@@ -1113,6 +1102,8 @@ static const u32 prio_to_wmult[40] = {
 
 #define DEQUEUE_SLEEP          1
 
+#define RETRY_TASK             ((void *)-1UL)
+
 struct sched_class {
        const struct sched_class *next;
 
@@ -1123,14 +1114,22 @@ struct sched_class {
 
        void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);
 
-       struct task_struct * (*pick_next_task) (struct rq *rq);
+       /*
+        * It is the responsibility of the pick_next_task() method that will
+        * return the next task to call put_prev_task() on the @prev task or
+        * something equivalent.
+        *
+        * May return RETRY_TASK when it finds a higher prio class has runnable
+        * tasks.
+        */
+       struct task_struct * (*pick_next_task) (struct rq *rq,
+                                               struct task_struct *prev);
        void (*put_prev_task) (struct rq *rq, struct task_struct *p);
 
 #ifdef CONFIG_SMP
        int  (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
        void (*migrate_task_rq)(struct task_struct *p, int next_cpu);
 
-       void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
        void (*post_schedule) (struct rq *this_rq);
        void (*task_waking) (struct task_struct *task);
        void (*task_woken) (struct rq *this_rq, struct task_struct *task);
@@ -1160,6 +1159,11 @@ struct sched_class {
 #endif
 };
 
+static inline void put_prev_task(struct rq *rq, struct task_struct *prev)
+{
+       prev->sched_class->put_prev_task(rq, prev);
+}
+
 #define sched_class_highest (&stop_sched_class)
 #define for_each_class(class) \
    for (class = sched_class_highest; class; class = class->next)
@@ -1176,16 +1180,14 @@ extern const struct sched_class idle_sched_class;
 extern void update_group_power(struct sched_domain *sd, int cpu);
 
 extern void trigger_load_balance(struct rq *rq);
-extern void idle_balance(int this_cpu, struct rq *this_rq);
 
 extern void idle_enter_fair(struct rq *this_rq);
 extern void idle_exit_fair(struct rq *this_rq);
 
-#else  /* CONFIG_SMP */
+#else
 
-static inline void idle_balance(int cpu, struct rq *rq)
-{
-}
+static inline void idle_enter_fair(struct rq *rq) { }
+static inline void idle_exit_fair(struct rq *rq) { }
 
 #endif
 
@@ -1214,16 +1216,6 @@ extern void update_idle_cpu_load(struct rq *this_rq);
 
 extern void init_task_runnable_average(struct task_struct *p);
 
-#ifdef CONFIG_PARAVIRT
-static inline u64 steal_ticks(u64 steal)
-{
-       if (unlikely(steal > NSEC_PER_SEC))
-               return div_u64(steal, TICK_NSEC);
-
-       return __iter_div_u64_rem(steal, TICK_NSEC, &steal);
-}
-#endif
-
 static inline void inc_nr_running(struct rq *rq)
 {
        rq->nr_running++;
index fdb6bb0b33561af759e24d8806776dfc0823867c..d6ce65dde5412d4b4b9d8473caf92318ba7fcb24 100644 (file)
@@ -23,16 +23,19 @@ check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags)
        /* we're never preempted */
 }
 
-static struct task_struct *pick_next_task_stop(struct rq *rq)
+static struct task_struct *
+pick_next_task_stop(struct rq *rq, struct task_struct *prev)
 {
        struct task_struct *stop = rq->stop;
 
-       if (stop && stop->on_rq) {
-               stop->se.exec_start = rq_clock_task(rq);
-               return stop;
-       }
+       if (!stop || !stop->on_rq)
+               return NULL;
 
-       return NULL;
+       put_prev_task(rq, prev);
+
+       stop->se.exec_start = rq_clock_task(rq);
+
+       return stop;
 }
 
 static void
index 84571e09c9079e8887f73a0f24beefe58e00ff77..01fbae5b97b765199feccfbb6f985c1309dc3475 100644 (file)
@@ -293,7 +293,7 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
         */
        smp_call_function_single(min(cpu1, cpu2),
                                 &irq_cpu_stop_queue_work,
-                                &call_args, 0);
+                                &call_args, 1);
        lg_local_unlock(&stop_cpus_lock);
        preempt_enable();
 
index c0a58be780a407a5bf350e852db1c9800c98dd34..adaeab6f7a870ae69537baebf4ca092a161d5013 100644 (file)
@@ -174,10 +174,10 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
 
        /* normalize: avoid signed division (rounding problems) */
        error = -ESRCH;
-       if (niceval < -20)
-               niceval = -20;
-       if (niceval > 19)
-               niceval = 19;
+       if (niceval < MIN_NICE)
+               niceval = MIN_NICE;
+       if (niceval > MAX_NICE)
+               niceval = MAX_NICE;
 
        rcu_read_lock();
        read_lock(&tasklist_lock);
index 49e13e1f8fe6a5e481edb3026ae20360918986c3..7754ff16f3342c42d21509437c4c8f3c110694f6 100644 (file)
@@ -385,13 +385,6 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
-       {
-               .procname       = "numa_balancing_migrate_deferred",
-               .data           = &sysctl_numa_balancing_migrate_deferred,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
        {
                .procname       = "numa_balancing",
                .data           = NULL, /* filled in by handler */
index 7a925ba456fb5d617d19b98daf2ca39356c4eca6..a6a5bf53e86d25575f90518399407a4fb65a85ed 100644 (file)
  * HZ shrinks, so values greater than 8 overflow 32bits when
  * HZ=100.
  */
+#if HZ < 34
+#define JIFFIES_SHIFT  6
+#elif HZ < 67
+#define JIFFIES_SHIFT  7
+#else
 #define JIFFIES_SHIFT  8
+#endif
 
 static cycle_t jiffies_read(struct clocksource *cs)
 {
index 0abb364642818e4ef842ab2f3631d15cb80400f2..4d23dc4d8139988e13946ee48d37a76333c916c0 100644 (file)
@@ -116,20 +116,42 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
 void __init sched_clock_register(u64 (*read)(void), int bits,
                                 unsigned long rate)
 {
+       u64 res, wrap, new_mask, new_epoch, cyc, ns;
+       u32 new_mult, new_shift;
+       ktime_t new_wrap_kt;
        unsigned long r;
-       u64 res, wrap;
        char r_unit;
 
        if (cd.rate > rate)
                return;
 
        WARN_ON(!irqs_disabled());
-       read_sched_clock = read;
-       sched_clock_mask = CLOCKSOURCE_MASK(bits);
-       cd.rate = rate;
 
        /* calculate the mult/shift to convert counter ticks to ns. */
-       clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
+       clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
+
+       new_mask = CLOCKSOURCE_MASK(bits);
+
+       /* calculate how many ns until we wrap */
+       wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask);
+       new_wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
+
+       /* update epoch for new counter and update epoch_ns from old counter*/
+       new_epoch = read();
+       cyc = read_sched_clock();
+       ns = cd.epoch_ns + cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
+                         cd.mult, cd.shift);
+
+       raw_write_seqcount_begin(&cd.seq);
+       read_sched_clock = read;
+       sched_clock_mask = new_mask;
+       cd.rate = rate;
+       cd.wrap_kt = new_wrap_kt;
+       cd.mult = new_mult;
+       cd.shift = new_shift;
+       cd.epoch_cyc = new_epoch;
+       cd.epoch_ns = ns;
+       raw_write_seqcount_end(&cd.seq);
 
        r = rate;
        if (r >= 4000000) {
@@ -141,22 +163,12 @@ void __init sched_clock_register(u64 (*read)(void), int bits,
        } else
                r_unit = ' ';
 
-       /* calculate how many ns until we wrap */
-       wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
-       cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
-
        /* calculate the ns resolution of this counter */
-       res = cyc_to_ns(1ULL, cd.mult, cd.shift);
+       res = cyc_to_ns(1ULL, new_mult, new_shift);
+
        pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
                bits, r, r_unit, res, wrap);
 
-       update_sched_clock();
-
-       /*
-        * Ensure that sched_clock() starts off at 0ns
-        */
-       cd.epoch_ns = 0;
-
        /* Enable IRQ time accounting if we have a fast enough sched_clock */
        if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
                enable_sched_clock_irqtime();
index 63c7b2d9ed8ee43d74d00deedbe2b287683f4a0a..64c5990fd500b86e86e9d0a92d86fa7b7b45a0b1 100644 (file)
@@ -817,6 +817,7 @@ out:
 static void tick_broadcast_clear_oneshot(int cpu)
 {
        cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
+       cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
 }
 
 static void tick_broadcast_init_next_event(struct cpumask *mask,
index 0aa4ce81bc168e2432f8f76e1e62c0b41512d47b..5b40279ecd711d93074a33b0198dff6201c202e8 100644 (file)
@@ -1435,7 +1435,8 @@ void update_wall_time(void)
 out:
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
        if (clock_set)
-               clock_was_set();
+               /* Have to call _delayed version, since in irq context*/
+               clock_was_set_delayed();
 }
 
 /**
index 1d35ddadc045753a2b13bc9017eaef38abc89383..87bd529879c23bb12705fa0144cff354064f91dc 100644 (file)
@@ -52,7 +52,7 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/timer.h>
 
-u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
+__visible u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
 
 EXPORT_SYMBOL(jiffies_64);
 
diff --git a/kernel/torture.c b/kernel/torture.c
new file mode 100644 (file)
index 0000000..acc9afc
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * Common functions for in-kernel torture tests.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2014
+ *
+ * Author: Paul E. McKenney <paulmck@us.ibm.com>
+ *     Based on kernel/rcu/torture.c.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/freezer.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/trace_clock.h>
+#include <asm/byteorder.h>
+#include <linux/torture.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>");
+
+static char *torture_type;
+static bool verbose;
+
+/* Mediate rmmod and system shutdown.  Concurrent rmmod & shutdown illegal! */
+#define FULLSTOP_DONTSTOP 0    /* Normal operation. */
+#define FULLSTOP_SHUTDOWN 1    /* System shutdown with torture running. */
+#define FULLSTOP_RMMOD    2    /* Normal rmmod of torture. */
+static int fullstop = FULLSTOP_RMMOD;
+static DEFINE_MUTEX(fullstop_mutex);
+static int *torture_runnable;
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/*
+ * Variables for online-offline handling.  Only present if CPU hotplug
+ * is enabled, otherwise does nothing.
+ */
+
+static struct task_struct *onoff_task;
+static long onoff_holdoff;
+static long onoff_interval;
+static long n_offline_attempts;
+static long n_offline_successes;
+static unsigned long sum_offline;
+static int min_offline = -1;
+static int max_offline;
+static long n_online_attempts;
+static long n_online_successes;
+static unsigned long sum_online;
+static int min_online = -1;
+static int max_online;
+
+/*
+ * Execute random CPU-hotplug operations at the interval specified
+ * by the onoff_interval.
+ */
+static int
+torture_onoff(void *arg)
+{
+       int cpu;
+       unsigned long delta;
+       int maxcpu = -1;
+       DEFINE_TORTURE_RANDOM(rand);
+       int ret;
+       unsigned long starttime;
+
+       VERBOSE_TOROUT_STRING("torture_onoff task started");
+       for_each_online_cpu(cpu)
+               maxcpu = cpu;
+       WARN_ON(maxcpu < 0);
+       if (onoff_holdoff > 0) {
+               VERBOSE_TOROUT_STRING("torture_onoff begin holdoff");
+               schedule_timeout_interruptible(onoff_holdoff);
+               VERBOSE_TOROUT_STRING("torture_onoff end holdoff");
+       }
+       while (!torture_must_stop()) {
+               cpu = (torture_random(&rand) >> 4) % (maxcpu + 1);
+               if (cpu_online(cpu) && cpu_is_hotpluggable(cpu)) {
+                       if (verbose)
+                               pr_alert("%s" TORTURE_FLAG
+                                        "torture_onoff task: offlining %d\n",
+                                        torture_type, cpu);
+                       starttime = jiffies;
+                       n_offline_attempts++;
+                       ret = cpu_down(cpu);
+                       if (ret) {
+                               if (verbose)
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "torture_onoff task: offline %d failed: errno %d\n",
+                                                torture_type, cpu, ret);
+                       } else {
+                               if (verbose)
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "torture_onoff task: offlined %d\n",
+                                                torture_type, cpu);
+                               n_offline_successes++;
+                               delta = jiffies - starttime;
+                               sum_offline += delta;
+                               if (min_offline < 0) {
+                                       min_offline = delta;
+                                       max_offline = delta;
+                               }
+                               if (min_offline > delta)
+                                       min_offline = delta;
+                               if (max_offline < delta)
+                                       max_offline = delta;
+                       }
+               } else if (cpu_is_hotpluggable(cpu)) {
+                       if (verbose)
+                               pr_alert("%s" TORTURE_FLAG
+                                        "torture_onoff task: onlining %d\n",
+                                        torture_type, cpu);
+                       starttime = jiffies;
+                       n_online_attempts++;
+                       ret = cpu_up(cpu);
+                       if (ret) {
+                               if (verbose)
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "torture_onoff task: online %d failed: errno %d\n",
+                                                torture_type, cpu, ret);
+                       } else {
+                               if (verbose)
+                                       pr_alert("%s" TORTURE_FLAG
+                                                "torture_onoff task: onlined %d\n",
+                                                torture_type, cpu);
+                               n_online_successes++;
+                               delta = jiffies - starttime;
+                               sum_online += delta;
+                               if (min_online < 0) {
+                                       min_online = delta;
+                                       max_online = delta;
+                               }
+                               if (min_online > delta)
+                                       min_online = delta;
+                               if (max_online < delta)
+                                       max_online = delta;
+                       }
+               }
+               schedule_timeout_interruptible(onoff_interval);
+       }
+       torture_kthread_stopping("torture_onoff");
+       return 0;
+}
+
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+
+/*
+ * Initiate online-offline handling.
+ */
+int torture_onoff_init(long ooholdoff, long oointerval)
+{
+       int ret = 0;
+
+#ifdef CONFIG_HOTPLUG_CPU
+       onoff_holdoff = ooholdoff;
+       onoff_interval = oointerval;
+       if (onoff_interval <= 0)
+               return 0;
+       ret = torture_create_kthread(torture_onoff, NULL, onoff_task);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+       return ret;
+}
+EXPORT_SYMBOL_GPL(torture_onoff_init);
+
+/*
+ * Clean up after online/offline testing.
+ */
+static void torture_onoff_cleanup(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       if (onoff_task == NULL)
+               return;
+       VERBOSE_TOROUT_STRING("Stopping torture_onoff task");
+       kthread_stop(onoff_task);
+       onoff_task = NULL;
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+}
+EXPORT_SYMBOL_GPL(torture_onoff_cleanup);
+
+/*
+ * Print online/offline testing statistics.
+ */
+char *torture_onoff_stats(char *page)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       page += sprintf(page,
+                      "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
+                      n_online_successes, n_online_attempts,
+                      n_offline_successes, n_offline_attempts,
+                      min_online, max_online,
+                      min_offline, max_offline,
+                      sum_online, sum_offline, HZ);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+       return page;
+}
+EXPORT_SYMBOL_GPL(torture_onoff_stats);
+
+/*
+ * Were all the online/offline operations successful?
+ */
+bool torture_onoff_failures(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       return n_online_successes != n_online_attempts ||
+              n_offline_successes != n_offline_attempts;
+#else /* #ifdef CONFIG_HOTPLUG_CPU */
+       return false;
+#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
+}
+EXPORT_SYMBOL_GPL(torture_onoff_failures);
+
+#define TORTURE_RANDOM_MULT    39916801  /* prime */
+#define TORTURE_RANDOM_ADD     479001701 /* prime */
+#define TORTURE_RANDOM_REFRESH 10000
+
+/*
+ * Crude but fast random-number generator.  Uses a linear congruential
+ * generator, with occasional help from cpu_clock().
+ */
+unsigned long
+torture_random(struct torture_random_state *trsp)
+{
+       if (--trsp->trs_count < 0) {
+               trsp->trs_state += (unsigned long)local_clock();
+               trsp->trs_count = TORTURE_RANDOM_REFRESH;
+       }
+       trsp->trs_state = trsp->trs_state * TORTURE_RANDOM_MULT +
+               TORTURE_RANDOM_ADD;
+       return swahw32(trsp->trs_state);
+}
+EXPORT_SYMBOL_GPL(torture_random);
+
+/*
+ * Variables for shuffling.  The idea is to ensure that each CPU stays
+ * idle for an extended period to test interactions with dyntick idle,
+ * as well as interactions with any per-CPU varibles.
+ */
+struct shuffle_task {
+       struct list_head st_l;
+       struct task_struct *st_t;
+};
+
+static long shuffle_interval;  /* In jiffies. */
+static struct task_struct *shuffler_task;
+static cpumask_var_t shuffle_tmp_mask;
+static int shuffle_idle_cpu;   /* Force all torture tasks off this CPU */
+static struct list_head shuffle_task_list = LIST_HEAD_INIT(shuffle_task_list);
+static DEFINE_MUTEX(shuffle_task_mutex);
+
+/*
+ * Register a task to be shuffled.  If there is no memory, just splat
+ * and don't bother registering.
+ */
+void torture_shuffle_task_register(struct task_struct *tp)
+{
+       struct shuffle_task *stp;
+
+       if (WARN_ON_ONCE(tp == NULL))
+               return;
+       stp = kmalloc(sizeof(*stp), GFP_KERNEL);
+       if (WARN_ON_ONCE(stp == NULL))
+               return;
+       stp->st_t = tp;
+       mutex_lock(&shuffle_task_mutex);
+       list_add(&stp->st_l, &shuffle_task_list);
+       mutex_unlock(&shuffle_task_mutex);
+}
+EXPORT_SYMBOL_GPL(torture_shuffle_task_register);
+
+/*
+ * Unregister all tasks, for example, at the end of the torture run.
+ */
+static void torture_shuffle_task_unregister_all(void)
+{
+       struct shuffle_task *stp;
+       struct shuffle_task *p;
+
+       mutex_lock(&shuffle_task_mutex);
+       list_for_each_entry_safe(stp, p, &shuffle_task_list, st_l) {
+               list_del(&stp->st_l);
+               kfree(stp);
+       }
+       mutex_unlock(&shuffle_task_mutex);
+}
+
+/* Shuffle tasks such that we allow shuffle_idle_cpu to become idle.
+ * A special case is when shuffle_idle_cpu = -1, in which case we allow
+ * the tasks to run on all CPUs.
+ */
+static void torture_shuffle_tasks(void)
+{
+       struct shuffle_task *stp;
+
+       cpumask_setall(shuffle_tmp_mask);
+       get_online_cpus();
+
+       /* No point in shuffling if there is only one online CPU (ex: UP) */
+       if (num_online_cpus() == 1) {
+               put_online_cpus();
+               return;
+       }
+
+       /* Advance to the next CPU.  Upon overflow, don't idle any CPUs. */
+       shuffle_idle_cpu = cpumask_next(shuffle_idle_cpu, shuffle_tmp_mask);
+       if (shuffle_idle_cpu >= nr_cpu_ids)
+               shuffle_idle_cpu = -1;
+       if (shuffle_idle_cpu != -1) {
+               cpumask_clear_cpu(shuffle_idle_cpu, shuffle_tmp_mask);
+               if (cpumask_empty(shuffle_tmp_mask)) {
+                       put_online_cpus();
+                       return;
+               }
+       }
+
+       mutex_lock(&shuffle_task_mutex);
+       list_for_each_entry(stp, &shuffle_task_list, st_l)
+               set_cpus_allowed_ptr(stp->st_t, shuffle_tmp_mask);
+       mutex_unlock(&shuffle_task_mutex);
+
+       put_online_cpus();
+}
+
+/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
+ * system to become idle at a time and cut off its timer ticks. This is meant
+ * to test the support for such tickless idle CPU in RCU.
+ */
+static int torture_shuffle(void *arg)
+{
+       VERBOSE_TOROUT_STRING("torture_shuffle task started");
+       do {
+               schedule_timeout_interruptible(shuffle_interval);
+               torture_shuffle_tasks();
+               torture_shutdown_absorb("torture_shuffle");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("torture_shuffle");
+       return 0;
+}
+
+/*
+ * Start the shuffler, with shuffint in jiffies.
+ */
+int torture_shuffle_init(long shuffint)
+{
+       shuffle_interval = shuffint;
+
+       shuffle_idle_cpu = -1;
+
+       if (!alloc_cpumask_var(&shuffle_tmp_mask, GFP_KERNEL)) {
+               VERBOSE_TOROUT_ERRSTRING("Failed to alloc mask");
+               return -ENOMEM;
+       }
+
+       /* Create the shuffler thread */
+       return torture_create_kthread(torture_shuffle, NULL, shuffler_task);
+}
+EXPORT_SYMBOL_GPL(torture_shuffle_init);
+
+/*
+ * Stop the shuffling.
+ */
+static void torture_shuffle_cleanup(void)
+{
+       torture_shuffle_task_unregister_all();
+       if (shuffler_task) {
+               VERBOSE_TOROUT_STRING("Stopping torture_shuffle task");
+               kthread_stop(shuffler_task);
+               free_cpumask_var(shuffle_tmp_mask);
+       }
+       shuffler_task = NULL;
+}
+EXPORT_SYMBOL_GPL(torture_shuffle_cleanup);
+
+/*
+ * Variables for auto-shutdown.  This allows "lights out" torture runs
+ * to be fully scripted.
+ */
+static int shutdown_secs;              /* desired test duration in seconds. */
+static struct task_struct *shutdown_task;
+static unsigned long shutdown_time;    /* jiffies to system shutdown. */
+static void (*torture_shutdown_hook)(void);
+
+/*
+ * Absorb kthreads into a kernel function that won't return, so that
+ * they won't ever access module text or data again.
+ */
+void torture_shutdown_absorb(const char *title)
+{
+       while (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
+               pr_notice("torture thread %s parking due to system shutdown\n",
+                         title);
+               schedule_timeout_uninterruptible(MAX_SCHEDULE_TIMEOUT);
+       }
+}
+EXPORT_SYMBOL_GPL(torture_shutdown_absorb);
+
+/*
+ * Cause the torture test to shutdown the system after the test has
+ * run for the time specified by the shutdown_secs parameter.
+ */
+static int torture_shutdown(void *arg)
+{
+       long delta;
+       unsigned long jiffies_snap;
+
+       VERBOSE_TOROUT_STRING("torture_shutdown task started");
+       jiffies_snap = jiffies;
+       while (ULONG_CMP_LT(jiffies_snap, shutdown_time) &&
+              !torture_must_stop()) {
+               delta = shutdown_time - jiffies_snap;
+               if (verbose)
+                       pr_alert("%s" TORTURE_FLAG
+                                "torture_shutdown task: %lu jiffies remaining\n",
+                                torture_type, delta);
+               schedule_timeout_interruptible(delta);
+               jiffies_snap = jiffies;
+       }
+       if (torture_must_stop()) {
+               torture_kthread_stopping("torture_shutdown");
+               return 0;
+       }
+
+       /* OK, shut down the system. */
+
+       VERBOSE_TOROUT_STRING("torture_shutdown task shutting down system");
+       shutdown_task = NULL;   /* Avoid self-kill deadlock. */
+       if (torture_shutdown_hook)
+               torture_shutdown_hook();
+       else
+               VERBOSE_TOROUT_STRING("No torture_shutdown_hook(), skipping.");
+       kernel_power_off();     /* Shut down the system. */
+       return 0;
+}
+
+/*
+ * Start up the shutdown task.
+ */
+int torture_shutdown_init(int ssecs, void (*cleanup)(void))
+{
+       int ret = 0;
+
+       shutdown_secs = ssecs;
+       torture_shutdown_hook = cleanup;
+       if (shutdown_secs > 0) {
+               shutdown_time = jiffies + shutdown_secs * HZ;
+               ret = torture_create_kthread(torture_shutdown, NULL,
+                                            shutdown_task);
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(torture_shutdown_init);
+
+/*
+ * Detect and respond to a system shutdown.
+ */
+static int torture_shutdown_notify(struct notifier_block *unused1,
+                                  unsigned long unused2, void *unused3)
+{
+       mutex_lock(&fullstop_mutex);
+       if (ACCESS_ONCE(fullstop) == FULLSTOP_DONTSTOP) {
+               VERBOSE_TOROUT_STRING("Unscheduled system shutdown detected");
+               ACCESS_ONCE(fullstop) = FULLSTOP_SHUTDOWN;
+       } else {
+               pr_warn("Concurrent rmmod and shutdown illegal!\n");
+       }
+       mutex_unlock(&fullstop_mutex);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block torture_shutdown_nb = {
+       .notifier_call = torture_shutdown_notify,
+};
+
+/*
+ * Shut down the shutdown task.  Say what???  Heh!  This can happen if
+ * the torture module gets an rmmod before the shutdown time arrives.  ;-)
+ */
+static void torture_shutdown_cleanup(void)
+{
+       unregister_reboot_notifier(&torture_shutdown_nb);
+       if (shutdown_task != NULL) {
+               VERBOSE_TOROUT_STRING("Stopping torture_shutdown task");
+               kthread_stop(shutdown_task);
+       }
+       shutdown_task = NULL;
+}
+
+/*
+ * Variables for stuttering, which means to periodically pause and
+ * restart testing in order to catch bugs that appear when load is
+ * suddenly applied to or removed from the system.
+ */
+static struct task_struct *stutter_task;
+static int stutter_pause_test;
+static int stutter;
+
+/*
+ * Block until the stutter interval ends.  This must be called periodically
+ * by all running kthreads that need to be subject to stuttering.
+ */
+void stutter_wait(const char *title)
+{
+       while (ACCESS_ONCE(stutter_pause_test) ||
+              (torture_runnable && !ACCESS_ONCE(*torture_runnable))) {
+               if (stutter_pause_test)
+                       schedule_timeout_interruptible(1);
+               else
+                       schedule_timeout_interruptible(round_jiffies_relative(HZ));
+               torture_shutdown_absorb(title);
+       }
+}
+EXPORT_SYMBOL_GPL(stutter_wait);
+
+/*
+ * Cause the torture test to "stutter", starting and stopping all
+ * threads periodically.
+ */
+static int torture_stutter(void *arg)
+{
+       VERBOSE_TOROUT_STRING("torture_stutter task started");
+       do {
+               if (!torture_must_stop()) {
+                       schedule_timeout_interruptible(stutter);
+                       ACCESS_ONCE(stutter_pause_test) = 1;
+               }
+               if (!torture_must_stop())
+                       schedule_timeout_interruptible(stutter);
+               ACCESS_ONCE(stutter_pause_test) = 0;
+               torture_shutdown_absorb("torture_stutter");
+       } while (!torture_must_stop());
+       torture_kthread_stopping("torture_stutter");
+       return 0;
+}
+
+/*
+ * Initialize and kick off the torture_stutter kthread.
+ */
+int torture_stutter_init(int s)
+{
+       int ret;
+
+       stutter = s;
+       ret = torture_create_kthread(torture_stutter, NULL, stutter_task);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(torture_stutter_init);
+
+/*
+ * Cleanup after the torture_stutter kthread.
+ */
+static void torture_stutter_cleanup(void)
+{
+       if (!stutter_task)
+               return;
+       VERBOSE_TOROUT_STRING("Stopping torture_stutter task");
+       kthread_stop(stutter_task);
+       stutter_task = NULL;
+}
+
+/*
+ * Initialize torture module.  Please note that this is -not- invoked via
+ * the usual module_init() mechanism, but rather by an explicit call from
+ * the client torture module.  This call must be paired with a later
+ * torture_init_end().
+ *
+ * The runnable parameter points to a flag that controls whether or not
+ * the test is currently runnable.  If there is no such flag, pass in NULL.
+ */
+void __init torture_init_begin(char *ttype, bool v, int *runnable)
+{
+       mutex_lock(&fullstop_mutex);
+       torture_type = ttype;
+       verbose = v;
+       torture_runnable = runnable;
+       fullstop = FULLSTOP_DONTSTOP;
+
+}
+EXPORT_SYMBOL_GPL(torture_init_begin);
+
+/*
+ * Tell the torture module that initialization is complete.
+ */
+void __init torture_init_end(void)
+{
+       mutex_unlock(&fullstop_mutex);
+       register_reboot_notifier(&torture_shutdown_nb);
+}
+EXPORT_SYMBOL_GPL(torture_init_end);
+
+/*
+ * Clean up torture module.  Please note that this is -not- invoked via
+ * the usual module_exit() mechanism, but rather by an explicit call from
+ * the client torture module.  Returns true if a race with system shutdown
+ * is detected, otherwise, all kthreads started by functions in this file
+ * will be shut down.
+ *
+ * This must be called before the caller starts shutting down its own
+ * kthreads.
+ */
+bool torture_cleanup(void)
+{
+       mutex_lock(&fullstop_mutex);
+       if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) {
+               pr_warn("Concurrent rmmod and shutdown illegal!\n");
+               mutex_unlock(&fullstop_mutex);
+               schedule_timeout_uninterruptible(10);
+               return true;
+       }
+       ACCESS_ONCE(fullstop) = FULLSTOP_RMMOD;
+       mutex_unlock(&fullstop_mutex);
+       torture_shutdown_cleanup();
+       torture_shuffle_cleanup();
+       torture_stutter_cleanup();
+       torture_onoff_cleanup();
+       return false;
+}
+EXPORT_SYMBOL_GPL(torture_cleanup);
+
+/*
+ * Is it time for the current torture test to stop?
+ */
+bool torture_must_stop(void)
+{
+       return torture_must_stop_irq() || kthread_should_stop();
+}
+EXPORT_SYMBOL_GPL(torture_must_stop);
+
+/*
+ * Is it time for the current torture test to stop?  This is the irq-safe
+ * version, hence no check for kthread_should_stop().
+ */
+bool torture_must_stop_irq(void)
+{
+       return ACCESS_ONCE(fullstop) != FULLSTOP_DONTSTOP;
+}
+EXPORT_SYMBOL_GPL(torture_must_stop_irq);
+
+/*
+ * Each kthread must wait for kthread_should_stop() before returning from
+ * its top-level function, otherwise segfaults ensue.  This function
+ * prints a "stopping" message and waits for kthread_should_stop(), and
+ * should be called from all torture kthreads immediately prior to
+ * returning.
+ */
+void torture_kthread_stopping(char *title)
+{
+       if (verbose)
+               VERBOSE_TOROUT_STRING(title);
+       while (!kthread_should_stop()) {
+               torture_shutdown_absorb(title);
+               schedule_timeout_uninterruptible(1);
+       }
+}
+EXPORT_SYMBOL_GPL(torture_kthread_stopping);
+
+/*
+ * Create a generic torture kthread that is immediately runnable.  If you
+ * need the kthread to be stopped so that you can do something to it before
+ * it starts, you will need to open-code your own.
+ */
+int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m,
+                           char *f, struct task_struct **tp)
+{
+       int ret = 0;
+
+       VERBOSE_TOROUT_STRING(m);
+       *tp = kthread_run(fn, arg, s);
+       if (IS_ERR(*tp)) {
+               ret = PTR_ERR(*tp);
+               VERBOSE_TOROUT_ERRSTRING(f);
+               *tp = NULL;
+       }
+       torture_shuffle_task_register(*tp);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(_torture_create_kthread);
+
+/*
+ * Stop a generic kthread, emitting a message.
+ */
+void _torture_stop_kthread(char *m, struct task_struct **tp)
+{
+       if (*tp == NULL)
+               return;
+       VERBOSE_TOROUT_STRING(m);
+       kthread_stop(*tp);
+       *tp = NULL;
+}
+EXPORT_SYMBOL_GPL(_torture_stop_kthread);
index 294b8a271a04223786827b6fffb58fd7e90fbcaf..fc4da2d97f9b6e280b2e29a525e478958cb495d4 100644 (file)
@@ -2397,6 +2397,13 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
        write &= RB_WRITE_MASK;
        tail = write - length;
 
+       /*
+        * If this is the first commit on the page, then it has the same
+        * timestamp as the page itself.
+        */
+       if (!tail)
+               delta = 0;
+
        /* See if we shot pass the end of this buffer page */
        if (unlikely(write > BUF_PAGE_SIZE))
                return rb_move_tail(cpu_buffer, length, tail,
index a5457d577b98313b1ca8b1670ad32a2140001498..0434ff1b808e92c539b70828185c8fa1c44c865a 100644 (file)
@@ -40,8 +40,8 @@ static int write_iteration = 50;
 module_param(write_iteration, uint, 0644);
 MODULE_PARM_DESC(write_iteration, "# of writes between timestamp readings");
 
-static int producer_nice = 19;
-static int consumer_nice = 19;
+static int producer_nice = MAX_NICE;
+static int consumer_nice = MAX_NICE;
 
 static int producer_fifo = -1;
 static int consumer_fifo = -1;
@@ -308,7 +308,7 @@ static void ring_buffer_producer(void)
 
        /* Let the user know that the test is running at low priority */
        if (producer_fifo < 0 && consumer_fifo < 0 &&
-           producer_nice == 19 && consumer_nice == 19)
+           producer_nice == MAX_NICE && consumer_nice == MAX_NICE)
                trace_printk("WARNING!!! This test is running at lowest priority.\n");
 
        trace_printk("Time:     %lld (usecs)\n", time);
index 815c878f409bd94e08777d1b9f83b1553f4a2e24..24c1f23825579df4f2bf46e2dca98e6af8fb4abd 100644 (file)
@@ -1600,15 +1600,31 @@ void trace_buffer_unlock_commit(struct ring_buffer *buffer,
 }
 EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit);
 
+static struct ring_buffer *temp_buffer;
+
 struct ring_buffer_event *
 trace_event_buffer_lock_reserve(struct ring_buffer **current_rb,
                          struct ftrace_event_file *ftrace_file,
                          int type, unsigned long len,
                          unsigned long flags, int pc)
 {
+       struct ring_buffer_event *entry;
+
        *current_rb = ftrace_file->tr->trace_buffer.buffer;
-       return trace_buffer_lock_reserve(*current_rb,
+       entry = trace_buffer_lock_reserve(*current_rb,
                                         type, len, flags, pc);
+       /*
+        * If tracing is off, but we have triggers enabled
+        * we still need to look at the event data. Use the temp_buffer
+        * to store the trace event for the tigger to use. It's recusive
+        * safe and will not be recorded anywhere.
+        */
+       if (!entry && ftrace_file->flags & FTRACE_EVENT_FL_TRIGGER_COND) {
+               *current_rb = temp_buffer;
+               entry = trace_buffer_lock_reserve(*current_rb,
+                                                 type, len, flags, pc);
+       }
+       return entry;
 }
 EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve);
 
@@ -6494,11 +6510,16 @@ __init static int tracer_alloc_buffers(void)
 
        raw_spin_lock_init(&global_trace.start_lock);
 
+       /* Used for event triggers */
+       temp_buffer = ring_buffer_alloc(PAGE_SIZE, RB_FL_OVERWRITE);
+       if (!temp_buffer)
+               goto out_free_cpumask;
+
        /* TODO: make the number of buffers hot pluggable with CPUS */
        if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) {
                printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
                WARN_ON(1);
-               goto out_free_cpumask;
+               goto out_free_temp_buffer;
        }
 
        if (global_trace.buffer_disabled)
@@ -6540,6 +6561,8 @@ __init static int tracer_alloc_buffers(void)
 
        return 0;
 
+out_free_temp_buffer:
+       ring_buffer_free(temp_buffer);
 out_free_cpumask:
        free_percpu(global_trace.trace_buffer.data);
 #ifdef CONFIG_TRACER_MAX_TRACE
index e854f420e033eb65a2bca233bb8df2e42778faf7..c894614de14d8efdbbc145141d19f9a56af9a984 100644 (file)
@@ -31,9 +31,25 @@ static int perf_trace_event_perm(struct ftrace_event_call *tp_event,
        }
 
        /* The ftrace function trace is allowed only for root. */
-       if (ftrace_event_is_function(tp_event) &&
-           perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
-               return -EPERM;
+       if (ftrace_event_is_function(tp_event)) {
+               if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               /*
+                * We don't allow user space callchains for  function trace
+                * event, due to issues with page faults while tracing page
+                * fault handler and its overall trickiness nature.
+                */
+               if (!p_event->attr.exclude_callchain_user)
+                       return -EINVAL;
+
+               /*
+                * Same reason to disable user stack dump as for user space
+                * callchains above.
+                */
+               if (p_event->attr.sample_type & PERF_SAMPLE_STACK_USER)
+                       return -EINVAL;
+       }
 
        /* No tracing, just counting, so no obvious leak */
        if (!(p_event->attr.sample_type & PERF_SAMPLE_RAW))
index e71ffd4eccb5b4d7a7b0234dd72e525b1c647550..7b16d40bd64d934d2be40e146bf8baa8e074487d 100644 (file)
 
 DEFINE_MUTEX(event_mutex);
 
-DEFINE_MUTEX(event_storage_mutex);
-EXPORT_SYMBOL_GPL(event_storage_mutex);
-
-char event_storage[EVENT_STORAGE_SIZE];
-EXPORT_SYMBOL_GPL(event_storage);
-
 LIST_HEAD(ftrace_events);
 static LIST_HEAD(ftrace_common_fields);
 
@@ -1777,6 +1771,16 @@ static void trace_module_add_events(struct module *mod)
 {
        struct ftrace_event_call **call, **start, **end;
 
+       if (!mod->num_trace_events)
+               return;
+
+       /* Don't add infrastructure for mods without tracepoints */
+       if (trace_module_has_bad_taint(mod)) {
+               pr_err("%s: module has bad taint, not creating trace events\n",
+                      mod->name);
+               return;
+       }
+
        start = mod->trace_events;
        end = mod->trace_events + mod->num_trace_events;
 
index 7c3e3e72e2b6bd2f0a6bd929ff67526497281b4a..ee0a5098ac43adca42f1631450f6f8330782cd5c 100644 (file)
@@ -95,15 +95,12 @@ static void __always_unused ____ftrace_check_##name(void)           \
 #undef __array
 #define __array(type, item, len)                                       \
        do {                                                            \
+               char *type_str = #type"["__stringify(len)"]";           \
                BUILD_BUG_ON(len > MAX_FILTER_STR_VAL);                 \
-               mutex_lock(&event_storage_mutex);                       \
-               snprintf(event_storage, sizeof(event_storage),          \
-                        "%s[%d]", #type, len);                         \
-               ret = trace_define_field(event_call, event_storage, #item, \
+               ret = trace_define_field(event_call, type_str, #item,   \
                                 offsetof(typeof(field), item),         \
                                 sizeof(field.item),                    \
                                 is_signed_type(type), filter_type);    \
-               mutex_unlock(&event_storage_mutex);                     \
                if (ret)                                                \
                        return ret;                                     \
        } while (0);
index 2aefbee93a6d574a0ea082632788a1d5c7791474..887ef88b0bc70e10463a37da502e1718385e35ca 100644 (file)
@@ -498,14 +498,14 @@ void trace_hardirqs_off(void)
 }
 EXPORT_SYMBOL(trace_hardirqs_off);
 
-void trace_hardirqs_on_caller(unsigned long caller_addr)
+__visible void trace_hardirqs_on_caller(unsigned long caller_addr)
 {
        if (!preempt_trace() && irq_trace())
                stop_critical_timing(CALLER_ADDR0, caller_addr);
 }
 EXPORT_SYMBOL(trace_hardirqs_on_caller);
 
-void trace_hardirqs_off_caller(unsigned long caller_addr)
+__visible void trace_hardirqs_off_caller(unsigned long caller_addr)
 {
        if (!preempt_trace() && irq_trace())
                start_critical_timing(CALLER_ADDR0, caller_addr);
index 29f26540e9c9550fd1c099512e7b20beb21ce234..031cc5655a514d2bcf89f930388dcddda396986f 100644 (file)
@@ -631,6 +631,11 @@ void tracepoint_iter_reset(struct tracepoint_iter *iter)
 EXPORT_SYMBOL_GPL(tracepoint_iter_reset);
 
 #ifdef CONFIG_MODULES
+bool trace_module_has_bad_taint(struct module *mod)
+{
+       return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP));
+}
+
 static int tracepoint_module_coming(struct module *mod)
 {
        struct tp_module *tp_mod, *iter;
@@ -641,7 +646,7 @@ static int tracepoint_module_coming(struct module *mod)
         * module headers (for forced load), to make sure we don't cause a crash.
         * Staging and out-of-tree GPL modules are fine.
         */
-       if (mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP)))
+       if (trace_module_has_bad_taint(mod))
                return 0;
        mutex_lock(&tracepoints_mutex);
        tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL);
index 240fb62cf3945aa0f7b601b343db65312a42f345..dd06439b9c84fe80463121905339c41493710998 100644 (file)
@@ -225,7 +225,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id)
  *
  *     When there is no mapping defined for the user-namespace uid
  *     pair INVALID_UID is returned.  Callers are expected to test
- *     for and handle handle INVALID_UID being returned.  INVALID_UID
+ *     for and handle INVALID_UID being returned.  INVALID_UID
  *     may be tested for using uid_valid().
  */
 kuid_t make_kuid(struct user_namespace *ns, uid_t uid)
index 5b690b5a9e745ba569609836dc01cc4518d167ad..0ee63af30bd14a4ad7f4b8f846d19b100fd596b3 100644 (file)
@@ -1858,6 +1858,12 @@ static void destroy_worker(struct worker *worker)
        if (worker->flags & WORKER_IDLE)
                pool->nr_idle--;
 
+       /*
+        * Once WORKER_DIE is set, the kworker may destroy itself at any
+        * point.  Pin to ensure the task stays until we're done with it.
+        */
+       get_task_struct(worker->task);
+
        list_del_init(&worker->entry);
        worker->flags |= WORKER_DIE;
 
@@ -1866,6 +1872,7 @@ static void destroy_worker(struct worker *worker)
        spin_unlock_irq(&pool->lock);
 
        kthread_stop(worker->task);
+       put_task_struct(worker->task);
        kfree(worker);
 
        spin_lock_irq(&pool->lock);
@@ -3225,7 +3232,7 @@ static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
                return -ENOMEM;
 
        if (sscanf(buf, "%d", &attrs->nice) == 1 &&
-           attrs->nice >= -20 && attrs->nice <= 19)
+           attrs->nice >= MIN_NICE && attrs->nice <= MAX_NICE)
                ret = apply_workqueue_attrs(wq, attrs);
        else
                ret = -EINVAL;
index dbf94a7d25a8a1c7be60d62f29680e69e1261f1b..dd7f8858188a6ac92ac19bb7ae032d62786ee612 100644 (file)
@@ -119,7 +119,7 @@ menu "Compile-time checks and compiler options"
 
 config DEBUG_INFO
        bool "Compile the kernel with debug info"
-       depends on DEBUG_KERNEL
+       depends on DEBUG_KERNEL && !COMPILE_TEST
        help
           If you say Y here the resulting kernel image will include
          debugging info resulting in a larger kernel image.
@@ -980,6 +980,21 @@ config DEBUG_LOCKING_API_SELFTESTS
          The following locking APIs are covered: spinlocks, rwlocks,
          mutexes and rwsems.
 
+config LOCK_TORTURE_TEST
+       tristate "torture tests for locking"
+       depends on DEBUG_KERNEL
+       select TORTURE_TEST
+       default n
+       help
+         This option provides a kernel module that runs torture tests
+         on kernel locking primitives.  The kernel module may be built
+         after the fact on the running kernel to be tested, if desired.
+
+         Say Y here if you want kernel locking-primitive torture tests
+         to be built into the kernel.
+         Say M if you want these torture tests to build as a module.
+         Say N if you are unsure.
+
 endmenu # lock debugging
 
 config TRACE_IRQFLAGS
@@ -1141,9 +1156,14 @@ config SPARSE_RCU_POINTER
 
         Say N if you are unsure.
 
+config TORTURE_TEST
+       tristate
+       default n
+
 config RCU_TORTURE_TEST
        tristate "torture tests for RCU"
        depends on DEBUG_KERNEL
+       select TORTURE_TEST
        default n
        help
          This option provides a kernel module that runs torture tests
index 126b34f2eb1663dcc9636ca71647e05736708689..48140e3ba73f5864a734edb3032be01745b2c678 100644 (file)
@@ -45,6 +45,7 @@ obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 
+GCOV_PROFILE_hweight.o := n
 CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
index 2defd1308b045c46389a6232391999914573deb6..98f2d7e91a9114e5e124e42bef00d7935708e521 100644 (file)
@@ -424,111 +424,134 @@ void debug_dma_dump_mappings(struct device *dev)
 EXPORT_SYMBOL(debug_dma_dump_mappings);
 
 /*
- * For each page mapped (initial page in the case of
- * dma_alloc_coherent/dma_map_{single|page}, or each page in a
- * scatterlist) insert into this tree using the pfn as the key. At
+ * For each mapping (initial cacheline in the case of
+ * dma_alloc_coherent/dma_map_page, initial cacheline in each page of a
+ * scatterlist, or the cacheline specified in dma_map_single) insert
+ * into this tree using the cacheline as the key. At
  * dma_unmap_{single|sg|page} or dma_free_coherent delete the entry.  If
- * the pfn already exists at insertion time add a tag as a reference
+ * the entry already exists at insertion time add a tag as a reference
  * count for the overlapping mappings.  For now, the overlap tracking
- * just ensures that 'unmaps' balance 'maps' before marking the pfn
- * idle, but we should also be flagging overlaps as an API violation.
+ * just ensures that 'unmaps' balance 'maps' before marking the
+ * cacheline idle, but we should also be flagging overlaps as an API
+ * violation.
  *
  * Memory usage is mostly constrained by the maximum number of available
  * dma-debug entries in that we need a free dma_debug_entry before
- * inserting into the tree.  In the case of dma_map_{single|page} and
- * dma_alloc_coherent there is only one dma_debug_entry and one pfn to
- * track per event.  dma_map_sg(), on the other hand,
- * consumes a single dma_debug_entry, but inserts 'nents' entries into
- * the tree.
+ * inserting into the tree.  In the case of dma_map_page and
+ * dma_alloc_coherent there is only one dma_debug_entry and one
+ * dma_active_cacheline entry to track per event.  dma_map_sg(), on the
+ * other hand, consumes a single dma_debug_entry, but inserts 'nents'
+ * entries into the tree.
  *
  * At any time debug_dma_assert_idle() can be called to trigger a
- * warning if the given page is in the active set.
+ * warning if any cachelines in the given page are in the active set.
  */
-static RADIX_TREE(dma_active_pfn, GFP_NOWAIT);
+static RADIX_TREE(dma_active_cacheline, GFP_NOWAIT);
 static DEFINE_SPINLOCK(radix_lock);
-#define ACTIVE_PFN_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
+#define ACTIVE_CACHELINE_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
+#define CACHELINE_PER_PAGE_SHIFT (PAGE_SHIFT - L1_CACHE_SHIFT)
+#define CACHELINES_PER_PAGE (1 << CACHELINE_PER_PAGE_SHIFT)
 
-static int active_pfn_read_overlap(unsigned long pfn)
+static phys_addr_t to_cacheline_number(struct dma_debug_entry *entry)
+{
+       return (entry->pfn << CACHELINE_PER_PAGE_SHIFT) +
+               (entry->offset >> L1_CACHE_SHIFT);
+}
+
+static int active_cacheline_read_overlap(phys_addr_t cln)
 {
        int overlap = 0, i;
 
        for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
-               if (radix_tree_tag_get(&dma_active_pfn, pfn, i))
+               if (radix_tree_tag_get(&dma_active_cacheline, cln, i))
                        overlap |= 1 << i;
        return overlap;
 }
 
-static int active_pfn_set_overlap(unsigned long pfn, int overlap)
+static int active_cacheline_set_overlap(phys_addr_t cln, int overlap)
 {
        int i;
 
-       if (overlap > ACTIVE_PFN_MAX_OVERLAP || overlap < 0)
+       if (overlap > ACTIVE_CACHELINE_MAX_OVERLAP || overlap < 0)
                return overlap;
 
        for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
                if (overlap & 1 << i)
-                       radix_tree_tag_set(&dma_active_pfn, pfn, i);
+                       radix_tree_tag_set(&dma_active_cacheline, cln, i);
                else
-                       radix_tree_tag_clear(&dma_active_pfn, pfn, i);
+                       radix_tree_tag_clear(&dma_active_cacheline, cln, i);
 
        return overlap;
 }
 
-static void active_pfn_inc_overlap(unsigned long pfn)
+static void active_cacheline_inc_overlap(phys_addr_t cln)
 {
-       int overlap = active_pfn_read_overlap(pfn);
+       int overlap = active_cacheline_read_overlap(cln);
 
-       overlap = active_pfn_set_overlap(pfn, ++overlap);
+       overlap = active_cacheline_set_overlap(cln, ++overlap);
 
        /* If we overflowed the overlap counter then we're potentially
         * leaking dma-mappings.  Otherwise, if maps and unmaps are
         * balanced then this overflow may cause false negatives in
-        * debug_dma_assert_idle() as the pfn may be marked idle
+        * debug_dma_assert_idle() as the cacheline may be marked idle
         * prematurely.
         */
-       WARN_ONCE(overlap > ACTIVE_PFN_MAX_OVERLAP,
-                 "DMA-API: exceeded %d overlapping mappings of pfn %lx\n",
-                 ACTIVE_PFN_MAX_OVERLAP, pfn);
+       WARN_ONCE(overlap > ACTIVE_CACHELINE_MAX_OVERLAP,
+                 "DMA-API: exceeded %d overlapping mappings of cacheline %pa\n",
+                 ACTIVE_CACHELINE_MAX_OVERLAP, &cln);
 }
 
-static int active_pfn_dec_overlap(unsigned long pfn)
+static int active_cacheline_dec_overlap(phys_addr_t cln)
 {
-       int overlap = active_pfn_read_overlap(pfn);
+       int overlap = active_cacheline_read_overlap(cln);
 
-       return active_pfn_set_overlap(pfn, --overlap);
+       return active_cacheline_set_overlap(cln, --overlap);
 }
 
-static int active_pfn_insert(struct dma_debug_entry *entry)
+static int active_cacheline_insert(struct dma_debug_entry *entry)
 {
+       phys_addr_t cln = to_cacheline_number(entry);
        unsigned long flags;
        int rc;
 
+       /* If the device is not writing memory then we don't have any
+        * concerns about the cpu consuming stale data.  This mitigates
+        * legitimate usages of overlapping mappings.
+        */
+       if (entry->direction == DMA_TO_DEVICE)
+               return 0;
+
        spin_lock_irqsave(&radix_lock, flags);
-       rc = radix_tree_insert(&dma_active_pfn, entry->pfn, entry);
+       rc = radix_tree_insert(&dma_active_cacheline, cln, entry);
        if (rc == -EEXIST)
-               active_pfn_inc_overlap(entry->pfn);
+               active_cacheline_inc_overlap(cln);
        spin_unlock_irqrestore(&radix_lock, flags);
 
        return rc;
 }
 
-static void active_pfn_remove(struct dma_debug_entry *entry)
+static void active_cacheline_remove(struct dma_debug_entry *entry)
 {
+       phys_addr_t cln = to_cacheline_number(entry);
        unsigned long flags;
 
+       /* ...mirror the insert case */
+       if (entry->direction == DMA_TO_DEVICE)
+               return;
+
        spin_lock_irqsave(&radix_lock, flags);
        /* since we are counting overlaps the final put of the
-        * entry->pfn will occur when the overlap count is 0.
-        * active_pfn_dec_overlap() returns -1 in that case
+        * cacheline will occur when the overlap count is 0.
+        * active_cacheline_dec_overlap() returns -1 in that case
         */
-       if (active_pfn_dec_overlap(entry->pfn) < 0)
-               radix_tree_delete(&dma_active_pfn, entry->pfn);
+       if (active_cacheline_dec_overlap(cln) < 0)
+               radix_tree_delete(&dma_active_cacheline, cln);
        spin_unlock_irqrestore(&radix_lock, flags);
 }
 
 /**
  * debug_dma_assert_idle() - assert that a page is not undergoing dma
- * @page: page to lookup in the dma_active_pfn tree
+ * @page: page to lookup in the dma_active_cacheline tree
  *
  * Place a call to this routine in cases where the cpu touching the page
  * before the dma completes (page is dma_unmapped) will lead to data
@@ -536,22 +559,38 @@ static void active_pfn_remove(struct dma_debug_entry *entry)
  */
 void debug_dma_assert_idle(struct page *page)
 {
+       static struct dma_debug_entry *ents[CACHELINES_PER_PAGE];
+       struct dma_debug_entry *entry = NULL;
+       void **results = (void **) &ents;
+       unsigned int nents, i;
        unsigned long flags;
-       struct dma_debug_entry *entry;
+       phys_addr_t cln;
 
        if (!page)
                return;
 
+       cln = (phys_addr_t) page_to_pfn(page) << CACHELINE_PER_PAGE_SHIFT;
        spin_lock_irqsave(&radix_lock, flags);
-       entry = radix_tree_lookup(&dma_active_pfn, page_to_pfn(page));
+       nents = radix_tree_gang_lookup(&dma_active_cacheline, results, cln,
+                                      CACHELINES_PER_PAGE);
+       for (i = 0; i < nents; i++) {
+               phys_addr_t ent_cln = to_cacheline_number(ents[i]);
+
+               if (ent_cln == cln) {
+                       entry = ents[i];
+                       break;
+               } else if (ent_cln >= cln + CACHELINES_PER_PAGE)
+                       break;
+       }
        spin_unlock_irqrestore(&radix_lock, flags);
 
        if (!entry)
                return;
 
+       cln = to_cacheline_number(entry);
        err_printk(entry->dev, entry,
-                  "DMA-API: cpu touching an active dma mapped page "
-                  "[pfn=0x%lx]\n", entry->pfn);
+                  "DMA-API: cpu touching an active dma mapped cacheline [cln=%pa]\n",
+                  &cln);
 }
 
 /*
@@ -568,9 +607,9 @@ static void add_dma_entry(struct dma_debug_entry *entry)
        hash_bucket_add(bucket, entry);
        put_hash_bucket(bucket, &flags);
 
-       rc = active_pfn_insert(entry);
+       rc = active_cacheline_insert(entry);
        if (rc == -ENOMEM) {
-               pr_err("DMA-API: pfn tracking ENOMEM, dma-debug disabled\n");
+               pr_err("DMA-API: cacheline tracking ENOMEM, dma-debug disabled\n");
                global_disable = true;
        }
 
@@ -631,7 +670,7 @@ static void dma_entry_free(struct dma_debug_entry *entry)
 {
        unsigned long flags;
 
-       active_pfn_remove(entry);
+       active_cacheline_remove(entry);
 
        /*
         * add to beginning of the list - this way the entries are
index 4dc1b990aa2339b572bd31d18b917dc3a1e161df..34fd931b54b53ac10c64d1320b2f54c299679ff1 100644 (file)
@@ -9,7 +9,7 @@ if FONT_SUPPORT
 
 config FONTS
        bool "Select compiled-in fonts"
-       depends on FRAMEBUFFER_CONSOLE
+       depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
        help
          Say Y here if you would like to use fonts other than the default
          your frame buffer console usually use.
@@ -22,7 +22,7 @@ config FONTS
 
 config FONT_8x8
        bool "VGA 8x8 font" if FONTS
-       depends on FRAMEBUFFER_CONSOLE
+       depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
        default y if !SPARC && !FONTS
        help
          This is the "high resolution" font for the VGA frame buffer (the one
@@ -45,7 +45,7 @@ config FONT_8x16
 
 config FONT_6x11
        bool "Mac console 6x11 font (not supported by all drivers)" if FONTS
-       depends on FRAMEBUFFER_CONSOLE
+       depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
        default y if !SPARC && !FONTS && MAC
        help
          Small console font with Macintosh-style high-half glyphs.  Some Mac
index 7be235f1a70bed4c0e4b5c54b7af566e095a4396..93d145e5539c2e1bd0a9e8fc014739c178e6d0fc 100644 (file)
@@ -54,9 +54,7 @@ static inline void move_tags(unsigned *dst, unsigned *dst_nr,
 /*
  * Try to steal tags from a remote cpu's percpu freelist.
  *
- * We first check how many percpu freelists have tags - we don't steal tags
- * unless enough percpu freelists have tags on them that it's possible more than
- * half the total tags could be stuck on remote percpu freelists.
+ * We first check how many percpu freelists have tags
  *
  * Then we iterate through the cpus until we find some tags - we don't attempt
  * to find the "best" cpu to steal from, to keep cacheline bouncing to a
@@ -69,8 +67,7 @@ static inline void steal_tags(struct percpu_ida *pool,
        struct percpu_ida_cpu *remote;
 
        for (cpus_have_tags = cpumask_weight(&pool->cpus_have_tags);
-            cpus_have_tags * pool->percpu_max_size > pool->nr_tags / 2;
-            cpus_have_tags--) {
+            cpus_have_tags; cpus_have_tags--) {
                cpu = cpumask_next(cpu, &pool->cpus_have_tags);
 
                if (cpu >= nr_cpu_ids) {
index 7811ed3b4e701c2e0d82368a8bae457279ca3246..bd4a8dfdf0b8052cdaedd0b3478eea4138ac100a 100644 (file)
@@ -1253,8 +1253,10 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
 
                node = indirect_to_ptr(node);
                max_index = radix_tree_maxindex(node->height);
-               if (cur_index > max_index)
+               if (cur_index > max_index) {
+                       rcu_read_unlock();
                        break;
+               }
 
                cur_index = __locate(node, item, cur_index, &found_index);
                rcu_read_unlock();
index 1e5b2df442916de82ef497f844c068724f8cd555..61489677870007e273301209438ac4913562b140 100644 (file)
@@ -244,8 +244,19 @@ static void __prandom_reseed(bool late)
        static bool latch = false;
        static DEFINE_SPINLOCK(lock);
 
+       /* Asking for random bytes might result in bytes getting
+        * moved into the nonblocking pool and thus marking it
+        * as initialized. In this case we would double back into
+        * this function and attempt to do a late reseed.
+        * Ignore the pointless attempt to reseed again if we're
+        * already waiting for bytes when the nonblocking pool
+        * got initialized.
+        */
+
        /* only allow initial seeding (late == false) once */
-       spin_lock_irqsave(&lock, flags);
+       if (!spin_trylock_irqsave(&lock, flags))
+               return;
+
        if (latch && !late)
                goto out;
        latch = true;
index e5878de4f1013ddbdd3db07d1fca2bcc3a692a7c..9b1f9062a202fc243bef05853e5b965e91f96182 100644 (file)
@@ -648,7 +648,7 @@ EXPORT_SYMBOL(memmove);
  * @count: The size of the area.
  */
 #undef memcmp
-int memcmp(const void *cs, const void *ct, size_t count)
+__visible int memcmp(const void *cs, const void *ct, size_t count)
 {
        const unsigned char *su1, *su2;
        int res = 0;
index 2d9f1504d75e26d45ddf58fe2db8c048ecbc8d83..2888024e0b0abea6b6f37f4531ad0f8dfec5c7b3 100644 (file)
@@ -575,5 +575,5 @@ config PGTABLE_MAPPING
          then you should select this. This causes zsmalloc to use page table
          mapping rather than copying for object mapping.
 
-         You can check speed with zsmalloc benchmark[1].
-         [1] https://github.com/spartacus06/zsmalloc
+         You can check speed with zsmalloc benchmark:
+         https://github.com/spartacus06/zsmapbench
index b48c5259ea33dfed9e4c08c956d8e30a36480c42..918577595ea8695298cd21ecab7acaca35b1eb92 100644 (file)
@@ -251,7 +251,6 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 {
        int nr_scanned = 0, total_isolated = 0;
        struct page *cursor, *valid_page = NULL;
-       unsigned long nr_strict_required = end_pfn - blockpfn;
        unsigned long flags;
        bool locked = false;
 
@@ -264,11 +263,12 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 
                nr_scanned++;
                if (!pfn_valid_within(blockpfn))
-                       continue;
+                       goto isolate_fail;
+
                if (!valid_page)
                        valid_page = page;
                if (!PageBuddy(page))
-                       continue;
+                       goto isolate_fail;
 
                /*
                 * The zone lock must be held to isolate freepages.
@@ -289,12 +289,10 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 
                /* Recheck this is a buddy page under lock */
                if (!PageBuddy(page))
-                       continue;
+                       goto isolate_fail;
 
                /* Found a free page, break it into order-0 pages */
                isolated = split_free_page(page);
-               if (!isolated && strict)
-                       break;
                total_isolated += isolated;
                for (i = 0; i < isolated; i++) {
                        list_add(&page->lru, freelist);
@@ -305,7 +303,15 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
                if (isolated) {
                        blockpfn += isolated - 1;
                        cursor += isolated - 1;
+                       continue;
                }
+
+isolate_fail:
+               if (strict)
+                       break;
+               else
+                       continue;
+
        }
 
        trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
@@ -315,7 +321,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
         * pages requested were isolated. If there were any failures, 0 is
         * returned and CMA will fail.
         */
-       if (strict && nr_strict_required > total_isolated)
+       if (strict && blockpfn < end_pfn)
                total_isolated = 0;
 
        if (locked)
index d56d3c145b9f26d3210ec8ad17430be6c46af2a9..7a13f6ac5421b9fead7729df856556b12269ad8c 100644 (file)
@@ -2553,8 +2553,8 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (ret > 0) {
                ssize_t err;
 
-               err = generic_write_sync(file, pos, ret);
-               if (err < 0 && ret > 0)
+               err = generic_write_sync(file, iocb->ki_pos - ret, ret);
+               if (err < 0)
                        ret = err;
        }
        return ret;
index bbc4d660221ac4e514e24d49ce140b25ad5364d2..34feba60a17e6dce30b2cdfa929926ad5a450bee 100644 (file)
 
 #include "internal.h"
 
+static int mm_counter(struct page *page)
+{
+       return PageAnon(page) ? MM_ANONPAGES : MM_FILEPAGES;
+}
+
 static void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long addr, pte_t *ptep)
 {
        pte_t pte = *ptep;
+       struct page *page;
+       swp_entry_t entry;
 
        if (pte_present(pte)) {
-               struct page *page;
-
                flush_cache_page(vma, addr, pte_pfn(pte));
                pte = ptep_clear_flush(vma, addr, ptep);
                page = vm_normal_page(vma, addr, pte);
                if (page) {
                        if (pte_dirty(pte))
                                set_page_dirty(page);
+                       update_hiwater_rss(mm);
+                       dec_mm_counter(mm, mm_counter(page));
                        page_remove_rmap(page);
                        page_cache_release(page);
+               }
+       } else {        /* zap_pte() is not called when pte_none() */
+               if (!pte_file(pte)) {
                        update_hiwater_rss(mm);
-                       dec_mm_counter(mm, MM_FILEPAGES);
+                       entry = pte_to_swp_entry(pte);
+                       if (non_swap_entry(entry)) {
+                               if (is_migration_entry(entry)) {
+                                       page = migration_entry_to_page(entry);
+                                       dec_mm_counter(mm, mm_counter(page));
+                               }
+                       } else {
+                               free_swap_and_cache(entry);
+                               dec_mm_counter(mm, MM_SWAPENTS);
+                       }
                }
-       } else {
-               if (!pte_file(pte))
-                       free_swap_and_cache(pte_to_swp_entry(pte));
                pte_clear_not_present_full(mm, addr, ptep, 0);
        }
 }
index 82166bf974e14262ecfb064ea7c173d006d3ab98..1546655a2d78afe4dc1c954b5e0ccff77ba3437f 100644 (file)
@@ -1166,8 +1166,10 @@ alloc:
                } else {
                        ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
                                        pmd, orig_pmd, page, haddr);
-                       if (ret & VM_FAULT_OOM)
+                       if (ret & VM_FAULT_OOM) {
                                split_huge_page(page);
+                               ret |= VM_FAULT_FALLBACK;
+                       }
                        put_page(page);
                }
                count_vm_event(THP_FAULT_FALLBACK);
@@ -1179,9 +1181,10 @@ alloc:
                if (page) {
                        split_huge_page(page);
                        put_page(page);
-               }
+               } else
+                       split_huge_page_pmd(vma, address, pmd);
+               ret |= VM_FAULT_FALLBACK;
                count_vm_event(THP_FAULT_FALLBACK);
-               ret |= VM_FAULT_OOM;
                goto out;
        }
 
@@ -1545,6 +1548,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                                entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
+                       set_pmd_at(mm, addr, pmd, entry);
                        BUG_ON(pmd_write(entry));
                } else {
                        struct page *page = pmd_page(*pmd);
@@ -1557,16 +1561,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                         */
                        if (!is_huge_zero_page(page) &&
                            !pmd_numa(*pmd)) {
-                               entry = *pmd;
-                               entry = pmd_mknuma(entry);
+                               pmdp_set_numa(mm, addr, pmd);
                                ret = HPAGE_PMD_NR;
                        }
                }
-
-               /* Set PMD if cleared earlier */
-               if (ret == HPAGE_PMD_NR)
-                       set_pmd_at(mm, addr, pmd, entry);
-
                spin_unlock(ptl);
        }
 
@@ -1963,7 +1961,7 @@ out:
        return ret;
 }
 
-#define VM_NO_THP (VM_SPECIAL|VM_MIXEDMAP|VM_HUGETLB|VM_SHARED|VM_MAYSHARE)
+#define VM_NO_THP (VM_SPECIAL | VM_HUGETLB | VM_SHARED | VM_MAYSHARE)
 
 int hugepage_madvise(struct vm_area_struct *vma,
                     unsigned long *vm_flags, int advice)
index aa4c7c7250c11a95b9676b70c7cc38f987d88717..68710e80994afed815c58b59a1a3cf421df8101f 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -444,7 +444,7 @@ static void break_cow(struct rmap_item *rmap_item)
 static struct page *page_trans_compound_anon(struct page *page)
 {
        if (PageTransCompound(page)) {
-               struct page *head = compound_trans_head(page);
+               struct page *head = compound_head(page);
                /*
                 * head may actually be splitted and freed from under
                 * us but it's ok here.
index 53385cd4e6f02cfae85f99a2629f735094130c78..5b6b0039f725032de5d63376aa0388e49bd3192d 100644 (file)
@@ -1127,8 +1127,8 @@ skip_node:
         * skipping css reference should be safe.
         */
        if (next_css) {
-               if ((next_css->flags & CSS_ONLINE) &&
-                               (next_css == &root->css || css_tryget(next_css)))
+               if ((next_css == &root->css) ||
+                   ((next_css->flags & CSS_ONLINE) && css_tryget(next_css)))
                        return mem_cgroup_from_css(next_css);
 
                prev_css = next_css;
@@ -1687,7 +1687,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
         * protects memcg_name and makes sure that parallel ooms do not
         * interleave
         */
-       static DEFINE_SPINLOCK(oom_info_lock);
+       static DEFINE_MUTEX(oom_info_lock);
        struct cgroup *task_cgrp;
        struct cgroup *mem_cgrp;
        static char memcg_name[PATH_MAX];
@@ -1698,7 +1698,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
        if (!p)
                return;
 
-       spin_lock(&oom_info_lock);
+       mutex_lock(&oom_info_lock);
        rcu_read_lock();
 
        mem_cgrp = memcg->css.cgroup;
@@ -1767,7 +1767,7 @@ done:
 
                pr_cont("\n");
        }
-       spin_unlock(&oom_info_lock);
+       mutex_unlock(&oom_info_lock);
 }
 
 /*
@@ -6595,6 +6595,7 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct mem_cgroup_event *event, *tmp;
+       struct cgroup_subsys_state *iter;
 
        /*
         * Unregister events and notify userspace.
@@ -6611,7 +6612,14 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
        kmem_cgroup_css_offline(memcg);
 
        mem_cgroup_invalidate_reclaim_iterators(memcg);
-       mem_cgroup_reparent_charges(memcg);
+
+       /*
+        * This requires that offlining is serialized.  Right now that is
+        * guaranteed because css_killed_work_fn() holds the cgroup_mutex.
+        */
+       css_for_each_descendant_post(iter, css)
+               mem_cgroup_reparent_charges(mem_cgroup_from_css(iter));
+
        mem_cgroup_destroy_all_caches(memcg);
        vmpressure_cleanup(&memcg->vmpressure);
 }
index 4f08a2d61487f3c45dc01638c31b6aff689ce6e7..90002ea43638cd0dd669d12092837714ec3113f3 100644 (file)
@@ -945,8 +945,10 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
                         * to it. Similarly, page lock is shifted.
                         */
                        if (hpage != p) {
-                               put_page(hpage);
-                               get_page(p);
+                               if (!(flags & MF_COUNT_INCREASED)) {
+                                       put_page(hpage);
+                                       get_page(p);
+                               }
                                lock_page(p);
                                unlock_page(hpage);
                                *hpagep = p;
@@ -1649,7 +1651,7 @@ int soft_offline_page(struct page *page, int flags)
 {
        int ret;
        unsigned long pfn = page_to_pfn(page);
-       struct page *hpage = compound_trans_head(page);
+       struct page *hpage = compound_head(page);
 
        if (PageHWPoison(page)) {
                pr_info("soft offline: %#lx page already poisoned\n", pfn);
index be6a0c0d4ae081d48edd26f09d37f67cc70b1c52..22dfa617bddb69af777298c45739a0113f965b13 100644 (file)
@@ -3348,6 +3348,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                if (ret & VM_FAULT_LOCKED)
                        unlock_page(vmf.page);
                ret = VM_FAULT_HWPOISON;
+               page_cache_release(vmf.page);
                goto uncharge_out;
        }
 
@@ -3703,7 +3704,6 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(is_vm_hugetlb_page(vma)))
                return hugetlb_fault(mm, vma, address, flags);
 
-retry:
        pgd = pgd_offset(mm, address);
        pud = pud_alloc(mm, pgd, address);
        if (!pud)
@@ -3741,20 +3741,13 @@ retry:
                        if (dirty && !pmd_write(orig_pmd)) {
                                ret = do_huge_pmd_wp_page(mm, vma, address, pmd,
                                                          orig_pmd);
-                               /*
-                                * If COW results in an oom, the huge pmd will
-                                * have been split, so retry the fault on the
-                                * pte for a smaller charge.
-                                */
-                               if (unlikely(ret & VM_FAULT_OOM))
-                                       goto retry;
-                               return ret;
+                               if (!(ret & VM_FAULT_FALLBACK))
+                                       return ret;
                        } else {
                                huge_pmd_set_accessed(mm, vma, address, pmd,
                                                      orig_pmd, dirty);
+                               return 0;
                        }
-
-                       return 0;
                }
        }
 
index ae3c8f3595d4ff522f0427b05ace2f7e041da8ad..4755c857694246ca6365a382931bcd431af9bda2 100644 (file)
@@ -1556,10 +1556,10 @@ SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
 
 #ifdef CONFIG_COMPAT
 
-asmlinkage long compat_sys_get_mempolicy(int __user *policy,
-                                    compat_ulong_t __user *nmask,
-                                    compat_ulong_t maxnode,
-                                    compat_ulong_t addr, compat_ulong_t flags)
+COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
+                      compat_ulong_t __user *, nmask,
+                      compat_ulong_t, maxnode,
+                      compat_ulong_t, addr, compat_ulong_t, flags)
 {
        long err;
        unsigned long __user *nm = NULL;
@@ -1586,8 +1586,8 @@ asmlinkage long compat_sys_get_mempolicy(int __user *policy,
        return err;
 }
 
-asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
-                                    compat_ulong_t maxnode)
+COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask,
+                      compat_ulong_t, maxnode)
 {
        long err = 0;
        unsigned long __user *nm = NULL;
@@ -1609,9 +1609,9 @@ asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
        return sys_set_mempolicy(mode, nm, nr_bits+1);
 }
 
-asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
-                            compat_ulong_t mode, compat_ulong_t __user *nmask,
-                            compat_ulong_t maxnode, compat_ulong_t flags)
+COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len,
+                      compat_ulong_t, mode, compat_ulong_t __user *, nmask,
+                      compat_ulong_t, maxnode, compat_ulong_t, flags)
 {
        long err = 0;
        unsigned long __user *nm = NULL;
@@ -2301,35 +2301,6 @@ static void sp_free(struct sp_node *n)
        kmem_cache_free(sn_cache, n);
 }
 
-#ifdef CONFIG_NUMA_BALANCING
-static bool numa_migrate_deferred(struct task_struct *p, int last_cpupid)
-{
-       /* Never defer a private fault */
-       if (cpupid_match_pid(p, last_cpupid))
-               return false;
-
-       if (p->numa_migrate_deferred) {
-               p->numa_migrate_deferred--;
-               return true;
-       }
-       return false;
-}
-
-static inline void defer_numa_migrate(struct task_struct *p)
-{
-       p->numa_migrate_deferred = sysctl_numa_balancing_migrate_deferred;
-}
-#else
-static inline bool numa_migrate_deferred(struct task_struct *p, int last_cpupid)
-{
-       return false;
-}
-
-static inline void defer_numa_migrate(struct task_struct *p)
-{
-}
-#endif /* CONFIG_NUMA_BALANCING */
-
 /**
  * mpol_misplaced - check whether current page node is valid in policy
  *
@@ -2403,52 +2374,9 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
 
        /* Migrate the page towards the node whose CPU is referencing it */
        if (pol->flags & MPOL_F_MORON) {
-               int last_cpupid;
-               int this_cpupid;
-
                polnid = thisnid;
-               this_cpupid = cpu_pid_to_cpupid(thiscpu, current->pid);
-
-               /*
-                * Multi-stage node selection is used in conjunction
-                * with a periodic migration fault to build a temporal
-                * task<->page relation. By using a two-stage filter we
-                * remove short/unlikely relations.
-                *
-                * Using P(p) ~ n_p / n_t as per frequentist
-                * probability, we can equate a task's usage of a
-                * particular page (n_p) per total usage of this
-                * page (n_t) (in a given time-span) to a probability.
-                *
-                * Our periodic faults will sample this probability and
-                * getting the same result twice in a row, given these
-                * samples are fully independent, is then given by
-                * P(n)^2, provided our sample period is sufficiently
-                * short compared to the usage pattern.
-                *
-                * This quadric squishes small probabilities, making
-                * it less likely we act on an unlikely task<->page
-                * relation.
-                */
-               last_cpupid = page_cpupid_xchg_last(page, this_cpupid);
-               if (!cpupid_pid_unset(last_cpupid) && cpupid_to_nid(last_cpupid) != thisnid) {
 
-                       /* See sysctl_numa_balancing_migrate_deferred comment */
-                       if (!cpupid_match_pid(current, last_cpupid))
-                               defer_numa_migrate(current);
-
-                       goto out;
-               }
-
-               /*
-                * The quadratic filter above reduces extraneous migration
-                * of shared pages somewhat. This code reduces it even more,
-                * reducing the overhead of page migrations of shared pages.
-                * This makes workloads with shared pages rely more on
-                * "move task near its memory", and less on "move memory
-                * towards its task", which is exactly what we want.
-                */
-               if (numa_migrate_deferred(current, last_cpupid))
+               if (!should_numa_migrate_memory(current, page, curnid, thiscpu))
                        goto out;
        }
 
index 482a33d89134fd83e15d5f6863dae57f5cb05aac..bed48809e5d01c14513a1395a12a3c4098341755 100644 (file)
@@ -177,6 +177,37 @@ out:
        return SWAP_AGAIN;
 }
 
+/*
+ * Congratulations to trinity for discovering this bug.
+ * mm/fremap.c's remap_file_pages() accepts any range within a single vma to
+ * convert that vma to VM_NONLINEAR; and generic_file_remap_pages() will then
+ * replace the specified range by file ptes throughout (maybe populated after).
+ * If page migration finds a page within that range, while it's still located
+ * by vma_interval_tree rather than lost to i_mmap_nonlinear list, no problem:
+ * zap_pte() clears the temporary migration entry before mmap_sem is dropped.
+ * But if the migrating page is in a part of the vma outside the range to be
+ * remapped, then it will not be cleared, and remove_migration_ptes() needs to
+ * deal with it.  Fortunately, this part of the vma is of course still linear,
+ * so we just need to use linear location on the nonlinear list.
+ */
+static int remove_linear_migration_ptes_from_nonlinear(struct page *page,
+               struct address_space *mapping, void *arg)
+{
+       struct vm_area_struct *vma;
+       /* hugetlbfs does not support remap_pages, so no huge pgoff worries */
+       pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+       unsigned long addr;
+
+       list_for_each_entry(vma,
+               &mapping->i_mmap_nonlinear, shared.nonlinear) {
+
+               addr = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
+               if (addr >= vma->vm_start && addr < vma->vm_end)
+                       remove_migration_pte(page, vma, addr, arg);
+       }
+       return SWAP_AGAIN;
+}
+
 /*
  * Get rid of all migration entries and replace them by
  * references to the indicated page.
@@ -186,6 +217,7 @@ static void remove_migration_ptes(struct page *old, struct page *new)
        struct rmap_walk_control rwc = {
                .rmap_one = remove_migration_pte,
                .arg = old,
+               .file_nonlinear = remove_linear_migration_ptes_from_nonlinear,
        };
 
        rmap_walk(new, &rwc);
@@ -1158,7 +1190,7 @@ static struct page *new_page_node(struct page *p, unsigned long private,
                                        pm->node);
        else
                return alloc_pages_exact_node(pm->node,
-                               GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0);
+                               GFP_HIGHUSER_MOVABLE | __GFP_THISNODE, 0);
 }
 
 /*
@@ -1544,9 +1576,9 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
        struct page *newpage;
 
        newpage = alloc_pages_exact_node(nid,
-                                        (GFP_HIGHUSER_MOVABLE | GFP_THISNODE |
-                                         __GFP_NOMEMALLOC | __GFP_NORETRY |
-                                         __GFP_NOWARN) &
+                                        (GFP_HIGHUSER_MOVABLE |
+                                         __GFP_THISNODE | __GFP_NOMEMALLOC |
+                                         __GFP_NORETRY | __GFP_NOWARN) &
                                         ~GFP_IOFS, 0);
 
        return newpage;
@@ -1747,7 +1779,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                goto out_dropref;
 
        new_page = alloc_pages_node(node,
-               (GFP_TRANSHUGE | GFP_THISNODE) & ~__GFP_WAIT, HPAGE_PMD_ORDER);
+               (GFP_TRANSHUGE | __GFP_THISNODE) & ~__GFP_WAIT,
+               HPAGE_PMD_ORDER);
        if (!new_page)
                goto out_fail;
 
index 8a8cd0265e523b54909e456881a00d497fa456d3..f802c2d216a7d28bf76c5c911d83d10d213fd474 100644 (file)
@@ -31,6 +31,9 @@ void use_mm(struct mm_struct *mm)
        tsk->mm = mm;
        switch_mm(active_mm, mm, tsk);
        task_unlock(tsk);
+#ifdef finish_arch_post_lock_switch
+       finish_arch_post_lock_switch();
+#endif
 
        if (active_mm != mm)
                mmdrop(active_mm);
index 7332c1785744fa0517a213b489e9c5b6bf350937..769a67a158037197341742104d2a9023cb1e03a0 100644 (file)
@@ -58,36 +58,27 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                                if (pte_numa(ptent))
                                        ptent = pte_mknonnuma(ptent);
                                ptent = pte_modify(ptent, newprot);
+                               /*
+                                * Avoid taking write faults for pages we
+                                * know to be dirty.
+                                */
+                               if (dirty_accountable && pte_dirty(ptent))
+                                       ptent = pte_mkwrite(ptent);
+                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                                updated = true;
                        } else {
                                struct page *page;
 
-                               ptent = *pte;
                                page = vm_normal_page(vma, addr, oldpte);
                                if (page && !PageKsm(page)) {
                                        if (!pte_numa(oldpte)) {
-                                               ptent = pte_mknuma(ptent);
-                                               set_pte_at(mm, addr, pte, ptent);
+                                               ptep_set_numa(mm, addr, pte);
                                                updated = true;
                                        }
                                }
                        }
-
-                       /*
-                        * Avoid taking write faults for pages we know to be
-                        * dirty.
-                        */
-                       if (dirty_accountable && pte_dirty(ptent)) {
-                               ptent = pte_mkwrite(ptent);
-                               updated = true;
-                       }
-
                        if (updated)
                                pages++;
-
-                       /* Only !prot_numa always clears the pte */
-                       if (!prot_numa)
-                               ptep_modify_prot_commit(mm, addr, pte, ptent);
                } else if (IS_ENABLED(CONFIG_MIGRATION) && !pte_file(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
 
index 2d30e2cfe8047606064f117fbaca4675540e00dd..7106cb1aca8e3733059b344a773310aa4bf0fcd7 100644 (file)
@@ -2173,11 +2173,12 @@ int __set_page_dirty_nobuffers(struct page *page)
        if (!TestSetPageDirty(page)) {
                struct address_space *mapping = page_mapping(page);
                struct address_space *mapping2;
+               unsigned long flags;
 
                if (!mapping)
                        return 1;
 
-               spin_lock_irq(&mapping->tree_lock);
+               spin_lock_irqsave(&mapping->tree_lock, flags);
                mapping2 = page_mapping(page);
                if (mapping2) { /* Race with truncate? */
                        BUG_ON(mapping2 != mapping);
@@ -2186,7 +2187,7 @@ int __set_page_dirty_nobuffers(struct page *page)
                        radix_tree_tag_set(&mapping->page_tree,
                                page_index(page), PAGECACHE_TAG_DIRTY);
                }
-               spin_unlock_irq(&mapping->tree_lock);
+               spin_unlock_irqrestore(&mapping->tree_lock, flags);
                if (mapping->host) {
                        /* !PageAnon && !swapper_space */
                        __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
index e3758a09a009747bd17cb75442d0fcae69a74cc4..3bac76ae4b30ec8a62042bdff9644e87ee181d3c 100644 (file)
@@ -369,9 +369,11 @@ void prep_compound_page(struct page *page, unsigned long order)
        __SetPageHead(page);
        for (i = 1; i < nr_pages; i++) {
                struct page *p = page + i;
-               __SetPageTail(p);
                set_page_count(p, 0);
                p->first_page = page;
+               /* Make sure p->first_page is always valid for PageTail() */
+               smp_wmb();
+               __SetPageTail(p);
        }
 }
 
@@ -1236,6 +1238,15 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
        }
        local_irq_restore(flags);
 }
+static bool gfp_thisnode_allocation(gfp_t gfp_mask)
+{
+       return (gfp_mask & GFP_THISNODE) == GFP_THISNODE;
+}
+#else
+static bool gfp_thisnode_allocation(gfp_t gfp_mask)
+{
+       return false;
+}
 #endif
 
 /*
@@ -1572,7 +1583,13 @@ again:
                                          get_pageblock_migratetype(page));
        }
 
-       __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order));
+       /*
+        * NOTE: GFP_THISNODE allocations do not partake in the kswapd
+        * aging protocol, so they can't be fair.
+        */
+       if (!gfp_thisnode_allocation(gfp_flags))
+               __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order));
+
        __count_zone_vm_events(PGALLOC, zone, 1 << order);
        zone_statistics(preferred_zone, zone, gfp_flags);
        local_irq_restore(flags);
@@ -1944,8 +1961,12 @@ zonelist_scan:
                 * ultimately fall back to remote zones that do not
                 * partake in the fairness round-robin cycle of this
                 * zonelist.
+                *
+                * NOTE: GFP_THISNODE allocations do not partake in
+                * the kswapd aging protocol, so they can't be fair.
                 */
-               if (alloc_flags & ALLOC_WMARK_LOW) {
+               if ((alloc_flags & ALLOC_WMARK_LOW) &&
+                   !gfp_thisnode_allocation(gfp_mask)) {
                        if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0)
                                continue;
                        if (!zone_local(preferred_zone, zone))
@@ -2501,8 +2522,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
         * allowed per node queues are empty and that nodes are
         * over allocated.
         */
-       if (IS_ENABLED(CONFIG_NUMA) &&
-                       (gfp_mask & GFP_THISNODE) == GFP_THISNODE)
+       if (gfp_thisnode_allocation(gfp_mask))
                goto nopage;
 
 restart:
index 036cfe07050f65eee962f51e6223321f9e01e132..63e24fb4387b6d305960f9e7ba8c0554e6818ca5 100644 (file)
@@ -102,10 +102,11 @@ struct pcpu_chunk {
        int                     free_size;      /* free bytes in the chunk */
        int                     contig_hint;    /* max contiguous size hint */
        void                    *base_addr;     /* base address of this chunk */
-       int                     map_used;       /* # of map entries used */
+       int                     map_used;       /* # of map entries used before the sentry */
        int                     map_alloc;      /* # of map entries allocated */
        int                     *map;           /* allocation map */
        void                    *data;          /* chunk data */
+       int                     first_free;     /* no free below this */
        bool                    immutable;      /* no [de]population allowed */
        unsigned long           populated[];    /* populated bitmap */
 };
@@ -356,11 +357,11 @@ static int pcpu_need_to_extend(struct pcpu_chunk *chunk)
 {
        int new_alloc;
 
-       if (chunk->map_alloc >= chunk->map_used + 2)
+       if (chunk->map_alloc >= chunk->map_used + 3)
                return 0;
 
        new_alloc = PCPU_DFL_MAP_ALLOC;
-       while (new_alloc < chunk->map_used + 2)
+       while (new_alloc < chunk->map_used + 3)
                new_alloc *= 2;
 
        return new_alloc;
@@ -417,48 +418,6 @@ out_unlock:
        return 0;
 }
 
-/**
- * pcpu_split_block - split a map block
- * @chunk: chunk of interest
- * @i: index of map block to split
- * @head: head size in bytes (can be 0)
- * @tail: tail size in bytes (can be 0)
- *
- * Split the @i'th map block into two or three blocks.  If @head is
- * non-zero, @head bytes block is inserted before block @i moving it
- * to @i+1 and reducing its size by @head bytes.
- *
- * If @tail is non-zero, the target block, which can be @i or @i+1
- * depending on @head, is reduced by @tail bytes and @tail byte block
- * is inserted after the target block.
- *
- * @chunk->map must have enough free slots to accommodate the split.
- *
- * CONTEXT:
- * pcpu_lock.
- */
-static void pcpu_split_block(struct pcpu_chunk *chunk, int i,
-                            int head, int tail)
-{
-       int nr_extra = !!head + !!tail;
-
-       BUG_ON(chunk->map_alloc < chunk->map_used + nr_extra);
-
-       /* insert new subblocks */
-       memmove(&chunk->map[i + nr_extra], &chunk->map[i],
-               sizeof(chunk->map[0]) * (chunk->map_used - i));
-       chunk->map_used += nr_extra;
-
-       if (head) {
-               chunk->map[i + 1] = chunk->map[i] - head;
-               chunk->map[i++] = head;
-       }
-       if (tail) {
-               chunk->map[i++] -= tail;
-               chunk->map[i] = tail;
-       }
-}
-
 /**
  * pcpu_alloc_area - allocate area from a pcpu_chunk
  * @chunk: chunk of interest
@@ -483,19 +442,27 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align)
        int oslot = pcpu_chunk_slot(chunk);
        int max_contig = 0;
        int i, off;
+       bool seen_free = false;
+       int *p;
 
-       for (i = 0, off = 0; i < chunk->map_used; off += abs(chunk->map[i++])) {
-               bool is_last = i + 1 == chunk->map_used;
+       for (i = chunk->first_free, p = chunk->map + i; i < chunk->map_used; i++, p++) {
                int head, tail;
+               int this_size;
+
+               off = *p;
+               if (off & 1)
+                       continue;
 
                /* extra for alignment requirement */
                head = ALIGN(off, align) - off;
-               BUG_ON(i == 0 && head != 0);
 
-               if (chunk->map[i] < 0)
-                       continue;
-               if (chunk->map[i] < head + size) {
-                       max_contig = max(chunk->map[i], max_contig);
+               this_size = (p[1] & ~1) - off;
+               if (this_size < head + size) {
+                       if (!seen_free) {
+                               chunk->first_free = i;
+                               seen_free = true;
+                       }
+                       max_contig = max(this_size, max_contig);
                        continue;
                }
 
@@ -505,44 +472,59 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align)
                 * than sizeof(int), which is very small but isn't too
                 * uncommon for percpu allocations.
                 */
-               if (head && (head < sizeof(int) || chunk->map[i - 1] > 0)) {
-                       if (chunk->map[i - 1] > 0)
-                               chunk->map[i - 1] += head;
-                       else {
-                               chunk->map[i - 1] -= head;
+               if (head && (head < sizeof(int) || !(p[-1] & 1))) {
+                       *p = off += head;
+                       if (p[-1] & 1)
                                chunk->free_size -= head;
-                       }
-                       chunk->map[i] -= head;
-                       off += head;
+                       else
+                               max_contig = max(*p - p[-1], max_contig);
+                       this_size -= head;
                        head = 0;
                }
 
                /* if tail is small, just keep it around */
-               tail = chunk->map[i] - head - size;
-               if (tail < sizeof(int))
+               tail = this_size - head - size;
+               if (tail < sizeof(int)) {
                        tail = 0;
+                       size = this_size - head;
+               }
 
                /* split if warranted */
                if (head || tail) {
-                       pcpu_split_block(chunk, i, head, tail);
+                       int nr_extra = !!head + !!tail;
+
+                       /* insert new subblocks */
+                       memmove(p + nr_extra + 1, p + 1,
+                               sizeof(chunk->map[0]) * (chunk->map_used - i));
+                       chunk->map_used += nr_extra;
+
                        if (head) {
-                               i++;
-                               off += head;
-                               max_contig = max(chunk->map[i - 1], max_contig);
+                               if (!seen_free) {
+                                       chunk->first_free = i;
+                                       seen_free = true;
+                               }
+                               *++p = off += head;
+                               ++i;
+                               max_contig = max(head, max_contig);
+                       }
+                       if (tail) {
+                               p[1] = off + size;
+                               max_contig = max(tail, max_contig);
                        }
-                       if (tail)
-                               max_contig = max(chunk->map[i + 1], max_contig);
                }
 
+               if (!seen_free)
+                       chunk->first_free = i + 1;
+
                /* update hint and mark allocated */
-               if (is_last)
+               if (i + 1 == chunk->map_used)
                        chunk->contig_hint = max_contig; /* fully scanned */
                else
                        chunk->contig_hint = max(chunk->contig_hint,
                                                 max_contig);
 
-               chunk->free_size -= chunk->map[i];
-               chunk->map[i] = -chunk->map[i];
+               chunk->free_size -= size;
+               *p |= 1;
 
                pcpu_chunk_relocate(chunk, oslot);
                return off;
@@ -570,34 +552,50 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int size, int align)
 static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme)
 {
        int oslot = pcpu_chunk_slot(chunk);
-       int i, off;
-
-       for (i = 0, off = 0; i < chunk->map_used; off += abs(chunk->map[i++]))
-               if (off == freeme)
-                       break;
+       int off = 0;
+       unsigned i, j;
+       int to_free = 0;
+       int *p;
+
+       freeme |= 1;    /* we are searching for <given offset, in use> pair */
+
+       i = 0;
+       j = chunk->map_used;
+       while (i != j) {
+               unsigned k = (i + j) / 2;
+               off = chunk->map[k];
+               if (off < freeme)
+                       i = k + 1;
+               else if (off > freeme)
+                       j = k;
+               else
+                       i = j = k;
+       }
        BUG_ON(off != freeme);
-       BUG_ON(chunk->map[i] > 0);
 
-       chunk->map[i] = -chunk->map[i];
-       chunk->free_size += chunk->map[i];
+       if (i < chunk->first_free)
+               chunk->first_free = i;
 
+       p = chunk->map + i;
+       *p = off &= ~1;
+       chunk->free_size += (p[1] & ~1) - off;
+
+       /* merge with next? */
+       if (!(p[1] & 1))
+               to_free++;
        /* merge with previous? */
-       if (i > 0 && chunk->map[i - 1] >= 0) {
-               chunk->map[i - 1] += chunk->map[i];
-               chunk->map_used--;
-               memmove(&chunk->map[i], &chunk->map[i + 1],
-                       (chunk->map_used - i) * sizeof(chunk->map[0]));
+       if (i > 0 && !(p[-1] & 1)) {
+               to_free++;
                i--;
+               p--;
        }
-       /* merge with next? */
-       if (i + 1 < chunk->map_used && chunk->map[i + 1] >= 0) {
-               chunk->map[i] += chunk->map[i + 1];
-               chunk->map_used--;
-               memmove(&chunk->map[i + 1], &chunk->map[i + 2],
-                       (chunk->map_used - (i + 1)) * sizeof(chunk->map[0]));
+       if (to_free) {
+               chunk->map_used -= to_free;
+               memmove(p + 1, p + 1 + to_free,
+                       (chunk->map_used - i) * sizeof(chunk->map[0]));
        }
 
-       chunk->contig_hint = max(chunk->map[i], chunk->contig_hint);
+       chunk->contig_hint = max(chunk->map[i + 1] - chunk->map[i] - 1, chunk->contig_hint);
        pcpu_chunk_relocate(chunk, oslot);
 }
 
@@ -617,7 +615,9 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
        }
 
        chunk->map_alloc = PCPU_DFL_MAP_ALLOC;
-       chunk->map[chunk->map_used++] = pcpu_unit_size;
+       chunk->map[0] = 0;
+       chunk->map[1] = pcpu_unit_size | 1;
+       chunk->map_used = 1;
 
        INIT_LIST_HEAD(&chunk->list);
        chunk->free_size = pcpu_unit_size;
@@ -713,6 +713,16 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
        unsigned long flags;
        void __percpu *ptr;
 
+       /*
+        * We want the lowest bit of offset available for in-use/free
+        * indicator, so force >= 16bit alignment and make size even.
+        */
+       if (unlikely(align < 2))
+               align = 2;
+
+       if (unlikely(size & 1))
+               size++;
+
        if (unlikely(!size || size > PCPU_MIN_UNIT_SIZE || align > PAGE_SIZE)) {
                WARN(true, "illegal size (%zu) or align (%zu) for "
                     "percpu allocation\n", size, align);
@@ -1343,9 +1353,13 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        }
        schunk->contig_hint = schunk->free_size;
 
-       schunk->map[schunk->map_used++] = -ai->static_size;
+       schunk->map[0] = 1;
+       schunk->map[1] = ai->static_size;
+       schunk->map_used = 1;
        if (schunk->free_size)
-               schunk->map[schunk->map_used++] = schunk->free_size;
+               schunk->map[++schunk->map_used] = 1 | (ai->static_size + schunk->free_size);
+       else
+               schunk->map[1] |= 1;
 
        /* init dynamic chunk if necessary */
        if (dyn_size) {
@@ -1358,8 +1372,10 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
                bitmap_fill(dchunk->populated, pcpu_unit_pages);
 
                dchunk->contig_hint = dchunk->free_size = dyn_size;
-               dchunk->map[dchunk->map_used++] = -pcpu_reserved_chunk_limit;
-               dchunk->map[dchunk->map_used++] = dchunk->free_size;
+               dchunk->map[0] = 1;
+               dchunk->map[1] = pcpu_reserved_chunk_limit;
+               dchunk->map[2] = (pcpu_reserved_chunk_limit + dchunk->free_size) | 1;
+               dchunk->map_used = 2;
        }
 
        /* link the first chunk in */
index fd26d0433509e2b5885c74249a9eb04828285180..3c5cf68566ec1375ff4d4deedc09db4c540e4b37 100644 (file)
@@ -456,25 +456,23 @@ free_iovecs:
        return rc;
 }
 
-asmlinkage ssize_t
-compat_sys_process_vm_readv(compat_pid_t pid,
-                           const struct compat_iovec __user *lvec,
-                           unsigned long liovcnt,
-                           const struct compat_iovec __user *rvec,
-                           unsigned long riovcnt,
-                           unsigned long flags)
+COMPAT_SYSCALL_DEFINE6(process_vm_readv, compat_pid_t, pid,
+                      const struct compat_iovec __user *, lvec,
+                      compat_ulong_t, liovcnt,
+                      const struct compat_iovec __user *, rvec,
+                      compat_ulong_t, riovcnt,
+                      compat_ulong_t, flags)
 {
        return compat_process_vm_rw(pid, lvec, liovcnt, rvec,
                                    riovcnt, flags, 0);
 }
 
-asmlinkage ssize_t
-compat_sys_process_vm_writev(compat_pid_t pid,
-                            const struct compat_iovec __user *lvec,
-                            unsigned long liovcnt,
-                            const struct compat_iovec __user *rvec,
-                            unsigned long riovcnt,
-                            unsigned long flags)
+COMPAT_SYSCALL_DEFINE6(process_vm_writev, compat_pid_t, pid,
+                      const struct compat_iovec __user *, lvec,
+                      compat_ulong_t, liovcnt,
+                      const struct compat_iovec __user *, rvec,
+                      compat_ulong_t, riovcnt,
+                      compat_ulong_t, flags)
 {
        return compat_process_vm_rw(pid, lvec, liovcnt, rvec,
                                    riovcnt, flags, 1);
index d9d42316a99a917ff6562c7cbc54dd50a085a1f6..11cf322f8133d7048d414c6f0eed227f6b12d3ac 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1165,6 +1165,16 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                }
                set_pte_at(mm, address, pte,
                           swp_entry_to_pte(make_hwpoison_entry(page)));
+       } else if (pte_unused(pteval)) {
+               /*
+                * The guest indicated that the page content is of no
+                * interest anymore. Simply discard the pte, vmscan
+                * will take care of the rest.
+                */
+               if (PageAnon(page))
+                       dec_mm_counter(mm, MM_ANONPAGES);
+               else
+                       dec_mm_counter(mm, MM_FILEPAGES);
        } else if (PageAnon(page)) {
                swp_entry_t entry = { .val = page_private(page) };
                pte_t swp_pte;
@@ -1360,8 +1370,9 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
 }
 
 static int try_to_unmap_nonlinear(struct page *page,
-               struct address_space *mapping, struct vm_area_struct *vma)
+               struct address_space *mapping, void *arg)
 {
+       struct vm_area_struct *vma;
        int ret = SWAP_AGAIN;
        unsigned long cursor;
        unsigned long max_nl_cursor = 0;
@@ -1663,7 +1674,7 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
        if (list_empty(&mapping->i_mmap_nonlinear))
                goto done;
 
-       ret = rwc->file_nonlinear(page, mapping, vma);
+       ret = rwc->file_nonlinear(page, mapping, rwc->arg);
 
 done:
        mutex_unlock(&mapping->i_mmap_mutex);
index 7e3e0458bce4180d115469b8ce622afef9b1e367..25f14ad8f817443bda93901aa8ab0b626280f297 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1004,21 +1004,19 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x)
 static void add_full(struct kmem_cache *s,
        struct kmem_cache_node *n, struct page *page)
 {
-       lockdep_assert_held(&n->list_lock);
-
        if (!(s->flags & SLAB_STORE_USER))
                return;
 
+       lockdep_assert_held(&n->list_lock);
        list_add(&page->lru, &n->full);
 }
 
 static void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page)
 {
-       lockdep_assert_held(&n->list_lock);
-
        if (!(s->flags & SLAB_STORE_USER))
                return;
 
+       lockdep_assert_held(&n->list_lock);
        list_del(&page->lru);
 }
 
@@ -1520,11 +1518,9 @@ static void discard_slab(struct kmem_cache *s, struct page *page)
 /*
  * Management of partially allocated slabs.
  */
-static inline void add_partial(struct kmem_cache_node *n,
-                               struct page *page, int tail)
+static inline void
+__add_partial(struct kmem_cache_node *n, struct page *page, int tail)
 {
-       lockdep_assert_held(&n->list_lock);
-
        n->nr_partial++;
        if (tail == DEACTIVATE_TO_TAIL)
                list_add_tail(&page->lru, &n->partial);
@@ -1532,15 +1528,27 @@ static inline void add_partial(struct kmem_cache_node *n,
                list_add(&page->lru, &n->partial);
 }
 
-static inline void remove_partial(struct kmem_cache_node *n,
-                                       struct page *page)
+static inline void add_partial(struct kmem_cache_node *n,
+                               struct page *page, int tail)
 {
        lockdep_assert_held(&n->list_lock);
+       __add_partial(n, page, tail);
+}
 
+static inline void
+__remove_partial(struct kmem_cache_node *n, struct page *page)
+{
        list_del(&page->lru);
        n->nr_partial--;
 }
 
+static inline void remove_partial(struct kmem_cache_node *n,
+                                       struct page *page)
+{
+       lockdep_assert_held(&n->list_lock);
+       __remove_partial(n, page);
+}
+
 /*
  * Remove slab from the partial list, freeze it and
  * return the pointer to the freelist.
@@ -2906,12 +2914,10 @@ static void early_kmem_cache_node_alloc(int node)
        inc_slabs_node(kmem_cache_node, node, page->objects);
 
        /*
-        * the lock is for lockdep's sake, not for any actual
-        * race protection
+        * No locks need to be taken here as it has just been
+        * initialized and there is no concurrent access.
         */
-       spin_lock(&n->list_lock);
-       add_partial(n, page, DEACTIVATE_TO_HEAD);
-       spin_unlock(&n->list_lock);
+       __add_partial(n, page, DEACTIVATE_TO_HEAD);
 }
 
 static void free_kmem_cache_nodes(struct kmem_cache *s)
@@ -3197,7 +3203,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
 
        list_for_each_entry_safe(page, h, &n->partial, lru) {
                if (!page->inuse) {
-                       remove_partial(n, page);
+                       __remove_partial(n, page);
                        discard_slab(s, page);
                } else {
                        list_slab_objects(s, page,
index b31ba67d440ac997a05de372e831046bf98d9070..0092097b3f4ce5e22844759a9e264ef143d05c7c 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -98,7 +98,7 @@ static void put_compound_page(struct page *page)
        }
 
        /* __split_huge_page_refcount can run under us */
-       page_head = compound_trans_head(page);
+       page_head = compound_head(page);
 
        /*
         * THP can not break up slab pages so avoid taking
@@ -253,7 +253,7 @@ bool __get_page_tail(struct page *page)
         */
        unsigned long flags;
        bool got;
-       struct page *page_head = compound_trans_head(page);
+       struct page *page_head = compound_head(page);
 
        /* Ref to put_compound_page() comment. */
        if (!__compound_tail_refcounted(page_head)) {
index 98e85e9c2b2dcd080d7efdc4bfb7521eac0d0b38..e76ace30d4364e99e2311adc73e8fff87dfe6f5a 100644 (file)
@@ -63,6 +63,8 @@ unsigned long total_swapcache_pages(void)
        return ret;
 }
 
+static atomic_t swapin_readahead_hits = ATOMIC_INIT(4);
+
 void show_swap_cache_info(void)
 {
        printk("%lu pages in swap cache\n", total_swapcache_pages());
@@ -286,8 +288,11 @@ struct page * lookup_swap_cache(swp_entry_t entry)
 
        page = find_get_page(swap_address_space(entry), entry.val);
 
-       if (page)
+       if (page) {
                INC_CACHE_INFO(find_success);
+               if (TestClearPageReadahead(page))
+                       atomic_inc(&swapin_readahead_hits);
+       }
 
        INC_CACHE_INFO(find_total);
        return page;
@@ -389,6 +394,50 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
        return found_page;
 }
 
+static unsigned long swapin_nr_pages(unsigned long offset)
+{
+       static unsigned long prev_offset;
+       unsigned int pages, max_pages, last_ra;
+       static atomic_t last_readahead_pages;
+
+       max_pages = 1 << ACCESS_ONCE(page_cluster);
+       if (max_pages <= 1)
+               return 1;
+
+       /*
+        * This heuristic has been found to work well on both sequential and
+        * random loads, swapping to hard disk or to SSD: please don't ask
+        * what the "+ 2" means, it just happens to work well, that's all.
+        */
+       pages = atomic_xchg(&swapin_readahead_hits, 0) + 2;
+       if (pages == 2) {
+               /*
+                * We can have no readahead hits to judge by: but must not get
+                * stuck here forever, so check for an adjacent offset instead
+                * (and don't even bother to check whether swap type is same).
+                */
+               if (offset != prev_offset + 1 && offset != prev_offset - 1)
+                       pages = 1;
+               prev_offset = offset;
+       } else {
+               unsigned int roundup = 4;
+               while (roundup < pages)
+                       roundup <<= 1;
+               pages = roundup;
+       }
+
+       if (pages > max_pages)
+               pages = max_pages;
+
+       /* Don't shrink readahead too fast */
+       last_ra = atomic_read(&last_readahead_pages) / 2;
+       if (pages < last_ra)
+               pages = last_ra;
+       atomic_set(&last_readahead_pages, pages);
+
+       return pages;
+}
+
 /**
  * swapin_readahead - swap in pages in hope we need them soon
  * @entry: swap entry of this memory
@@ -412,11 +461,16 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
                        struct vm_area_struct *vma, unsigned long addr)
 {
        struct page *page;
-       unsigned long offset = swp_offset(entry);
+       unsigned long entry_offset = swp_offset(entry);
+       unsigned long offset = entry_offset;
        unsigned long start_offset, end_offset;
-       unsigned long mask = (1UL << page_cluster) - 1;
+       unsigned long mask;
        struct blk_plug plug;
 
+       mask = swapin_nr_pages(offset) - 1;
+       if (!mask)
+               goto skip;
+
        /* Read a page_cluster sized and aligned cluster around offset. */
        start_offset = offset & ~mask;
        end_offset = offset | mask;
@@ -430,10 +484,13 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
                                                gfp_mask, vma, addr);
                if (!page)
                        continue;
+               if (offset != entry_offset)
+                       SetPageReadahead(page);
                page_cache_release(page);
        }
        blk_finish_plug(&plug);
 
        lru_add_drain();        /* Push any new pages onto the LRU now */
+skip:
        return read_swap_cache_async(entry, gfp_mask, vma, addr);
 }
index c6c13b050a58c4223464221a61e93a9944aec9f5..4a7f7e6992b665b64052ea77bbb1cd9be0aa00b4 100644 (file)
@@ -1923,7 +1923,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        p->swap_map = NULL;
        cluster_info = p->cluster_info;
        p->cluster_info = NULL;
-       p->flags = 0;
        frontswap_map = frontswap_map_get(p);
        spin_unlock(&p->lock);
        spin_unlock(&swap_lock);
@@ -1949,6 +1948,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
                mutex_unlock(&inode->i_mutex);
        }
        filp_close(swap_file, NULL);
+
+       /*
+        * Clear the SWP_USED flag after all resources are freed so that swapon
+        * can reuse this swap_info in alloc_swap_info() safely.  It is ok to
+        * not hold p->lock after we cleared its SWP_WRITEOK.
+        */
+       spin_lock(&swap_lock);
+       p->flags = 0;
+       spin_unlock(&swap_lock);
+
        err = 0;
        atomic_inc(&proc_poll_event);
        wake_up_interruptible(&proc_poll_wait);
index 196970a4541f0c07108eff49b7cb8d12fd930b06..d4042e75f7c7e7c7d498c4fcc33c90f1d1de2bff 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/vmstat.h>
 #include <linux/eventfd.h>
+#include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/printk.h>
 #include <linux/vmpressure.h>
index 72496140ac0843e54c086c18ace843189b47ffda..def5dd2fbe6124401e392a0438a062acf0140f81 100644 (file)
@@ -851,12 +851,14 @@ const char * const vmstat_text[] = {
        "thp_zero_page_alloc",
        "thp_zero_page_alloc_failed",
 #endif
+#ifdef CONFIG_DEBUG_TLBFLUSH
 #ifdef CONFIG_SMP
        "nr_tlb_remote_flush",
        "nr_tlb_remote_flush_received",
-#endif
+#endif /* CONFIG_SMP */
        "nr_tlb_local_flush_all",
        "nr_tlb_local_flush_one",
+#endif /* CONFIG_DEBUG_TLBFLUSH */
 
 #endif /* CONFIG_VM_EVENTS_COUNTERS */
 };
index ec9909935fb60850ed3635e1636f568c8c88bbf0..175273f38cb1bd59f5aeb88cb8c815033475dfe8 100644 (file)
@@ -307,9 +307,11 @@ static void vlan_sync_address(struct net_device *dev,
 static void vlan_transfer_features(struct net_device *dev,
                                   struct net_device *vlandev)
 {
+       struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
+
        vlandev->gso_max_size = dev->gso_max_size;
 
-       if (dev->features & NETIF_F_HW_VLAN_CTAG_TX)
+       if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
                vlandev->hard_header_len = dev->hard_header_len;
        else
                vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
index de51c48c439382db712761747188dc72061c82b0..27bfe2f8e2de71bee3f873106d88498765d36e93 100644 (file)
@@ -538,6 +538,9 @@ static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev
        struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
        struct net_device *real_dev = vlan->real_dev;
 
+       if (saddr == NULL)
+               saddr = dev->dev_addr;
+
        return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
 }
 
@@ -575,6 +578,9 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->features |= real_dev->vlan_features | NETIF_F_LLTX;
        dev->gso_max_size = real_dev->gso_max_size;
+       if (dev->features & NETIF_F_VLAN_FEATURES)
+               netdev_warn(real_dev, "VLAN features are set incorrectly.  Q-in-Q configurations may not work correctly.\n");
+
 
        /* ipv6 shared card related stuff */
        dev->dev_id = real_dev->dev_id;
@@ -589,7 +595,8 @@ static int vlan_dev_init(struct net_device *dev)
 #endif
 
        dev->needed_headroom = real_dev->needed_headroom;
-       if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
+       if (vlan_hw_offload_capable(real_dev->features,
+                                   vlan_dev_priv(dev)->vlan_proto)) {
                dev->header_ops      = &vlan_passthru_header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
        } else {
index a5e4d2dcb03e8c98eae243e1dd1b82cea68bd227..9186550d77a61b84c8f310ad7cd8e602ed116980 100644 (file)
@@ -204,7 +204,7 @@ free_and_return:
        return ret;
 }
 
-struct p9_fcall *p9_fcall_alloc(int alloc_msize)
+static struct p9_fcall *p9_fcall_alloc(int alloc_msize)
 {
        struct p9_fcall *fc;
        fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS);
index cd1e1ede73a45c2516091263c937f45024616c4e..ac2666c1d01127ab5ac73946377c6edd1a3ffb67 100644 (file)
@@ -340,7 +340,10 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
                int count = nr_pages;
                while (nr_pages) {
                        s = rest_of_page(data);
-                       pages[index++] = kmap_to_page(data);
+                       if (is_vmalloc_addr(data))
+                               pages[index++] = vmalloc_to_page(data);
+                       else
+                               pages[index++] = kmap_to_page(data);
                        data += s;
                        nr_pages--;
                }
index 512159bf607f0d4a3b09eae9af101775a8b56441..8323bced8e5bc9e8e1f6d552f7e94222c3f218ab 100644 (file)
@@ -241,19 +241,19 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr)
        size = bat_priv->num_ifaces * sizeof(uint8_t);
        orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC);
        if (!orig_node->bat_iv.bcast_own_sum)
-               goto free_bcast_own;
+               goto free_orig_node;
 
        hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
                                     batadv_choose_orig, orig_node,
                                     &orig_node->hash_entry);
        if (hash_added != 0)
-               goto free_bcast_own;
+               goto free_orig_node;
 
        return orig_node;
 
-free_bcast_own:
-       kfree(orig_node->bat_iv.bcast_own);
 free_orig_node:
+       /* free twice, as batadv_orig_node_new sets refcount to 2 */
+       batadv_orig_node_free_ref(orig_node);
        batadv_orig_node_free_ref(orig_node);
 
        return NULL;
@@ -266,7 +266,7 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
                        struct batadv_orig_node *orig_neigh)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
-       struct batadv_neigh_node *neigh_node;
+       struct batadv_neigh_node *neigh_node, *tmp_neigh_node;
 
        neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, orig_node);
        if (!neigh_node)
@@ -281,14 +281,24 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
        neigh_node->orig_node = orig_neigh;
        neigh_node->if_incoming = hard_iface;
 
-       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                  "Creating new neighbor %pM for orig_node %pM on interface %s\n",
-                  neigh_addr, orig_node->orig, hard_iface->net_dev->name);
-
        spin_lock_bh(&orig_node->neigh_list_lock);
-       hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+       tmp_neigh_node = batadv_neigh_node_get(orig_node, hard_iface,
+                                              neigh_addr);
+       if (!tmp_neigh_node) {
+               hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+       } else {
+               kfree(neigh_node);
+               batadv_hardif_free_ref(hard_iface);
+               neigh_node = tmp_neigh_node;
+       }
        spin_unlock_bh(&orig_node->neigh_list_lock);
 
+       if (!tmp_neigh_node)
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Creating new neighbor %pM for orig_node %pM on interface %s\n",
+                          neigh_addr, orig_node->orig,
+                          hard_iface->net_dev->name);
+
 out:
        return neigh_node;
 }
index 3d417d3641c6d83a4ecb4f87bdf48d4f26d48242..b851cc58085330acbab02848fedf3cb01751a060 100644 (file)
@@ -241,7 +241,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        const struct batadv_hard_iface *hard_iface;
-       int min_mtu = ETH_DATA_LEN;
+       int min_mtu = INT_MAX;
 
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -256,8 +256,6 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
        }
        rcu_read_unlock();
 
-       atomic_set(&bat_priv->packet_size_max, min_mtu);
-
        if (atomic_read(&bat_priv->fragmentation) == 0)
                goto out;
 
@@ -268,13 +266,21 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
        min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE);
        min_mtu -= sizeof(struct batadv_frag_packet);
        min_mtu *= BATADV_FRAG_MAX_FRAGMENTS;
-       atomic_set(&bat_priv->packet_size_max, min_mtu);
-
-       /* with fragmentation enabled we can fragment external packets easily */
-       min_mtu = min_t(int, min_mtu, ETH_DATA_LEN);
 
 out:
-       return min_mtu - batadv_max_header_len();
+       /* report to the other components the maximum amount of bytes that
+        * batman-adv can send over the wire (without considering the payload
+        * overhead). For example, this value is used by TT to compute the
+        * maximum local table table size
+        */
+       atomic_set(&bat_priv->packet_size_max, min_mtu);
+
+       /* the real soft-interface MTU is computed by removing the payload
+        * overhead from the maximum amount of bytes that was just computed.
+        *
+        * However batman-adv does not support MTUs bigger than ETH_DATA_LEN
+        */
+       return min_t(int, min_mtu - batadv_max_header_len(), ETH_DATA_LEN);
 }
 
 /* adjusts the MTU if a new interface with a smaller MTU appeared. */
index 6df12a2e36052b7f8a07dea276565c362890863f..853941629dc15a3c60b569d315815aee4987fe08 100644 (file)
@@ -457,6 +457,42 @@ out:
        return neigh_node;
 }
 
+/**
+ * batadv_neigh_node_get - retrieve a neighbour from the list
+ * @orig_node: originator which the neighbour belongs to
+ * @hard_iface: the interface where this neighbour is connected to
+ * @addr: the address of the neighbour
+ *
+ * Looks for and possibly returns a neighbour belonging to this originator list
+ * which is connected through the provided hard interface.
+ * Returns NULL if the neighbour is not found.
+ */
+struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+                     const struct batadv_hard_iface *hard_iface,
+                     const uint8_t *addr)
+{
+       struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
+               if (!batadv_compare_eth(tmp_neigh_node->addr, addr))
+                       continue;
+
+               if (tmp_neigh_node->if_incoming != hard_iface)
+                       continue;
+
+               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+                       continue;
+
+               res = tmp_neigh_node;
+               break;
+       }
+       rcu_read_unlock();
+
+       return res;
+}
+
 /**
  * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
  * @rcu: rcu pointer of the orig_ifinfo object
index 37be290f63f6e603cb849e1484311389464682b3..db3a9ed734cb7c858c28d00e53250fd22d15f828 100644 (file)
@@ -29,6 +29,10 @@ void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node);
 struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
                                              const uint8_t *addr);
 struct batadv_neigh_node *
+batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
+                     const struct batadv_hard_iface *hard_iface,
+                     const uint8_t *addr);
+struct batadv_neigh_node *
 batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
                      const uint8_t *neigh_addr,
                      struct batadv_orig_node *orig_node);
index 1ed9f7c9ecea4108f00d7beb6c2cb056f5ff87ed..a953d5b196a3825020ba306c8df42130a0d26eda 100644 (file)
@@ -688,7 +688,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
        int is_old_ttvn;
 
        /* check if there is enough data before accessing it */
-       if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0)
+       if (!pskb_may_pull(skb, hdr_len + ETH_HLEN))
                return 0;
 
        /* create a copy of the skb (in case of for re-routing) to modify it. */
@@ -918,6 +918,8 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
 
        if (ret != NET_RX_SUCCESS)
                ret = batadv_route_unicast_packet(skb, recv_if);
+       else
+               consume_skb(skb);
 
        return ret;
 }
index 579f5f00a385689f29a60ac111adf8b8682e1aa6..843febd1e5198914a398215037cd2d926f167738 100644 (file)
@@ -254,9 +254,9 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
                                   struct batadv_orig_node *orig_node,
                                   unsigned short vid)
 {
-       struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+       struct ethhdr *ethhdr;
        struct batadv_unicast_packet *unicast_packet;
-       int ret = NET_XMIT_DROP;
+       int ret = NET_XMIT_DROP, hdr_size;
 
        if (!orig_node)
                goto out;
@@ -265,12 +265,16 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
        case BATADV_UNICAST:
                if (!batadv_send_skb_prepare_unicast(skb, orig_node))
                        goto out;
+
+               hdr_size = sizeof(*unicast_packet);
                break;
        case BATADV_UNICAST_4ADDR:
                if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb,
                                                           orig_node,
                                                           packet_subtype))
                        goto out;
+
+               hdr_size = sizeof(struct batadv_unicast_4addr_packet);
                break;
        default:
                /* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -279,6 +283,7 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
                goto out;
        }
 
+       ethhdr = (struct ethhdr *)(skb->data + hdr_size);
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* inform the destination node that we are still missing a correct route
index b6071f675a3e57e159a99dec0c24f88603af9042..959dde721c46d057e23c494ba0b55175338466dc 100644 (file)
@@ -1975,6 +1975,7 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
        struct hlist_head *head;
        uint32_t i, crc_tmp, crc = 0;
        uint8_t flags;
+       __be16 tmp_vid;
 
        for (i = 0; i < hash->size; i++) {
                head = &hash->table[i];
@@ -2011,8 +2012,11 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
                                                             orig_node))
                                continue;
 
-                       crc_tmp = crc32c(0, &tt_common->vid,
-                                        sizeof(tt_common->vid));
+                       /* use network order to read the VID: this ensures that
+                        * every node reads the bytes in the same order.
+                        */
+                       tmp_vid = htons(tt_common->vid);
+                       crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
 
                        /* compute the CRC on flags that have to be kept in sync
                         * among nodes
@@ -2046,6 +2050,7 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
        struct hlist_head *head;
        uint32_t i, crc_tmp, crc = 0;
        uint8_t flags;
+       __be16 tmp_vid;
 
        for (i = 0; i < hash->size; i++) {
                head = &hash->table[i];
@@ -2064,8 +2069,11 @@ static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
                        if (tt_common->flags & BATADV_TT_CLIENT_NEW)
                                continue;
 
-                       crc_tmp = crc32c(0, &tt_common->vid,
-                                        sizeof(tt_common->vid));
+                       /* use network order to read the VID: this ensures that
+                        * every node reads the bytes in the same order.
+                        */
+                       tmp_vid = htons(tt_common->vid);
+                       crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
 
                        /* compute the CRC on flags that have to be kept in sync
                         * among nodes
@@ -2262,6 +2270,7 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
 {
        struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
        struct batadv_orig_node_vlan *vlan;
+       uint32_t crc;
        int i;
 
        /* check if each received CRC matches the locally stored one */
@@ -2281,7 +2290,10 @@ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
                if (!vlan)
                        return false;
 
-               if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc))
+               crc = vlan->tt.crc;
+               batadv_orig_node_vlan_free_ref(vlan);
+
+               if (crc != ntohl(tt_vlan_tmp->crc))
                        return false;
        }
 
@@ -3218,7 +3230,6 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
 
                spin_lock_bh(&orig_node->tt_lock);
 
-               tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
                batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
                                         ttvn, tt_change);
 
index 292e619db8961c82e7c3aa7f3280cb4236176ab8..d9fb9345144238f61372fdb21ca57c08b9471efd 100644 (file)
@@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session)
                del_timer(&session->timer);
 }
 
+static void hidp_process_report(struct hidp_session *session,
+                               int type, const u8 *data, int len, int intr)
+{
+       if (len > HID_MAX_BUFFER_SIZE)
+               len = HID_MAX_BUFFER_SIZE;
+
+       memcpy(session->input_buf, data, len);
+       hid_input_report(session->hid, type, session->input_buf, len, intr);
+}
+
 static void hidp_process_handshake(struct hidp_session *session,
                                        unsigned char param)
 {
@@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
                        hidp_input_report(session, skb);
 
                if (session->hid)
-                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
+                       hidp_process_report(session, HID_INPUT_REPORT,
+                                           skb->data, skb->len, 0);
                break;
 
        case HIDP_DATA_RTYPE_OTHER:
@@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session,
                        hidp_input_report(session, skb);
 
                if (session->hid) {
-                       hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
+                       hidp_process_report(session, HID_INPUT_REPORT,
+                                           skb->data, skb->len, 1);
                        BT_DBG("report len %d", skb->len);
                }
        } else {
index ab5241400cf78a9d7371d7a866d58aeba0d8043a..8798492a6e9971fff198344b580fa5ec3f17b8be 100644 (file)
@@ -24,6 +24,7 @@
 #define __HIDP_H
 
 #include <linux/types.h>
+#include <linux/hid.h>
 #include <linux/kref.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/l2cap.h>
@@ -179,6 +180,9 @@ struct hidp_session {
 
        /* Used in hidp_output_raw_report() */
        int output_report_success; /* boolean */
+
+       /* temporary input buffer */
+       u8 input_buf[HID_MAX_BUFFER_SIZE];
 };
 
 /* HIDP init defines */
index e4401a531afbd4bc1b22819282ff1a6d1b539bb0..8fe8b71b487add263a711d39e52f683675708dd6 100644 (file)
@@ -49,14 +49,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        brstats->tx_bytes += skb->len;
        u64_stats_update_end(&brstats->syncp);
 
-       if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
-               goto out;
-
        BR_INPUT_SKB_CB(skb)->brdev = dev;
 
        skb_reset_mac_header(skb);
        skb_pull(skb, ETH_HLEN);
 
+       if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
+               goto out;
+
        if (is_broadcast_ether_addr(dest))
                br_flood_deliver(br, skb, false);
        else if (is_multicast_ether_addr(dest)) {
@@ -187,8 +187,7 @@ static int br_set_mac_address(struct net_device *dev, void *p)
 
        spin_lock_bh(&br->lock);
        if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) {
-               memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-               br_fdb_change_mac_address(br, addr->sa_data);
+               /* Mac address will be changed in br_stp_change_bridge_id(). */
                br_stp_change_bridge_id(br, addr->sa_data);
        }
        spin_unlock_bh(&br->lock);
@@ -226,6 +225,33 @@ static void br_netpoll_cleanup(struct net_device *dev)
                br_netpoll_disable(p);
 }
 
+static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
+{
+       struct netpoll *np;
+       int err;
+
+       np = kzalloc(sizeof(*p->np), gfp);
+       if (!np)
+               return -ENOMEM;
+
+       err = __netpoll_setup(np, p->dev, gfp);
+       if (err) {
+               kfree(np);
+               return err;
+       }
+
+       p->np = np;
+       return err;
+}
+
+int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
+{
+       if (!p->br->dev->npinfo)
+               return 0;
+
+       return __br_netpoll_enable(p, gfp);
+}
+
 static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
                            gfp_t gfp)
 {
@@ -236,7 +262,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
        list_for_each_entry(p, &br->port_list, list) {
                if (!p->dev)
                        continue;
-               err = br_netpoll_enable(p, gfp);
+               err = __br_netpoll_enable(p, gfp);
                if (err)
                        goto fail;
        }
@@ -249,28 +275,6 @@ fail:
        goto out;
 }
 
-int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)
-{
-       struct netpoll *np;
-       int err;
-
-       if (!p->br->dev->npinfo)
-               return 0;
-
-       np = kzalloc(sizeof(*p->np), gfp);
-       if (!np)
-               return -ENOMEM;
-
-       err = __netpoll_setup(np, p->dev, gfp);
-       if (err) {
-               kfree(np);
-               return err;
-       }
-
-       p->np = np;
-       return err;
-}
-
 void br_netpoll_disable(struct net_bridge_port *p)
 {
        struct netpoll *np = p->np;
index c5f5a4a933f4302d34fd35abff160287af496919..9203d5a1943fbd4ba272ae38e742d8692093f7f1 100644 (file)
@@ -27,6 +27,9 @@
 #include "br_private.h"
 
 static struct kmem_cache *br_fdb_cache __read_mostly;
+static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
+                                            const unsigned char *addr,
+                                            __u16 vid);
 static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
                      const unsigned char *addr, u16 vid);
 static void fdb_notify(struct net_bridge *br,
@@ -89,11 +92,57 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
        call_rcu(&f->rcu, fdb_rcu_free);
 }
 
+/* Delete a local entry if no other port had the same address. */
+static void fdb_delete_local(struct net_bridge *br,
+                            const struct net_bridge_port *p,
+                            struct net_bridge_fdb_entry *f)
+{
+       const unsigned char *addr = f->addr.addr;
+       u16 vid = f->vlan_id;
+       struct net_bridge_port *op;
+
+       /* Maybe another port has same hw addr? */
+       list_for_each_entry(op, &br->port_list, list) {
+               if (op != p && ether_addr_equal(op->dev->dev_addr, addr) &&
+                   (!vid || nbp_vlan_find(op, vid))) {
+                       f->dst = op;
+                       f->added_by_user = 0;
+                       return;
+               }
+       }
+
+       /* Maybe bridge device has same hw addr? */
+       if (p && ether_addr_equal(br->dev->dev_addr, addr) &&
+           (!vid || br_vlan_find(br, vid))) {
+               f->dst = NULL;
+               f->added_by_user = 0;
+               return;
+       }
+
+       fdb_delete(br, f);
+}
+
+void br_fdb_find_delete_local(struct net_bridge *br,
+                             const struct net_bridge_port *p,
+                             const unsigned char *addr, u16 vid)
+{
+       struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
+       struct net_bridge_fdb_entry *f;
+
+       spin_lock_bh(&br->hash_lock);
+       f = fdb_find(head, addr, vid);
+       if (f && f->is_local && !f->added_by_user && f->dst == p)
+               fdb_delete_local(br, p, f);
+       spin_unlock_bh(&br->hash_lock);
+}
+
 void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
 {
        struct net_bridge *br = p->br;
-       bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false;
+       struct net_port_vlans *pv = nbp_get_vlan_info(p);
+       bool no_vlan = !pv;
        int i;
+       u16 vid;
 
        spin_lock_bh(&br->hash_lock);
 
@@ -104,38 +153,34 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
                        struct net_bridge_fdb_entry *f;
 
                        f = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
-                       if (f->dst == p && f->is_local) {
-                               /* maybe another port has same hw addr? */
-                               struct net_bridge_port *op;
-                               u16 vid = f->vlan_id;
-                               list_for_each_entry(op, &br->port_list, list) {
-                                       if (op != p &&
-                                           ether_addr_equal(op->dev->dev_addr,
-                                                            f->addr.addr) &&
-                                           nbp_vlan_find(op, vid)) {
-                                               f->dst = op;
-                                               goto insert;
-                                       }
-                               }
-
+                       if (f->dst == p && f->is_local && !f->added_by_user) {
                                /* delete old one */
-                               fdb_delete(br, f);
-insert:
-                               /* insert new address,  may fail if invalid
-                                * address or dup.
-                                */
-                               fdb_insert(br, p, newaddr, vid);
+                               fdb_delete_local(br, p, f);
 
                                /* if this port has no vlan information
                                 * configured, we can safely be done at
                                 * this point.
                                 */
                                if (no_vlan)
-                                       goto done;
+                                       goto insert;
                        }
                }
        }
 
+insert:
+       /* insert new address,  may fail if invalid address or dup. */
+       fdb_insert(br, p, newaddr, 0);
+
+       if (no_vlan)
+               goto done;
+
+       /* Now add entries for every VLAN configured on the port.
+        * This function runs under RTNL so the bitmap will not change
+        * from under us.
+        */
+       for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID)
+               fdb_insert(br, p, newaddr, vid);
+
 done:
        spin_unlock_bh(&br->hash_lock);
 }
@@ -146,10 +191,12 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
        struct net_port_vlans *pv;
        u16 vid = 0;
 
+       spin_lock_bh(&br->hash_lock);
+
        /* If old entry was unassociated with any port, then delete it. */
        f = __br_fdb_get(br, br->dev->dev_addr, 0);
        if (f && f->is_local && !f->dst)
-               fdb_delete(br, f);
+               fdb_delete_local(br, NULL, f);
 
        fdb_insert(br, NULL, newaddr, 0);
 
@@ -159,14 +206,16 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
         */
        pv = br_get_vlan_info(br);
        if (!pv)
-               return;
+               goto out;
 
        for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
                f = __br_fdb_get(br, br->dev->dev_addr, vid);
                if (f && f->is_local && !f->dst)
-                       fdb_delete(br, f);
+                       fdb_delete_local(br, NULL, f);
                fdb_insert(br, NULL, newaddr, vid);
        }
+out:
+       spin_unlock_bh(&br->hash_lock);
 }
 
 void br_fdb_cleanup(unsigned long _data)
@@ -235,25 +284,11 @@ void br_fdb_delete_by_port(struct net_bridge *br,
 
                        if (f->is_static && !do_all)
                                continue;
-                       /*
-                        * if multiple ports all have the same device address
-                        * then when one port is deleted, assign
-                        * the local entry to other port
-                        */
-                       if (f->is_local) {
-                               struct net_bridge_port *op;
-                               list_for_each_entry(op, &br->port_list, list) {
-                                       if (op != p &&
-                                           ether_addr_equal(op->dev->dev_addr,
-                                                            f->addr.addr)) {
-                                               f->dst = op;
-                                               goto skip_delete;
-                                       }
-                               }
-                       }
 
-                       fdb_delete(br, f);
-               skip_delete: ;
+                       if (f->is_local)
+                               fdb_delete_local(br, p, f);
+                       else
+                               fdb_delete(br, f);
                }
        }
        spin_unlock_bh(&br->hash_lock);
@@ -397,6 +432,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
                fdb->vlan_id = vid;
                fdb->is_local = 0;
                fdb->is_static = 0;
+               fdb->added_by_user = 0;
                fdb->updated = fdb->used = jiffies;
                hlist_add_head_rcu(&fdb->hlist, head);
        }
@@ -447,7 +483,7 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 }
 
 void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
-                  const unsigned char *addr, u16 vid)
+                  const unsigned char *addr, u16 vid, bool added_by_user)
 {
        struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
        struct net_bridge_fdb_entry *fdb;
@@ -473,13 +509,18 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
                        /* fastpath: update of existing entry */
                        fdb->dst = source;
                        fdb->updated = jiffies;
+                       if (unlikely(added_by_user))
+                               fdb->added_by_user = 1;
                }
        } else {
                spin_lock(&br->hash_lock);
                if (likely(!fdb_find(head, addr, vid))) {
                        fdb = fdb_create(head, source, addr, vid);
-                       if (fdb)
+                       if (fdb) {
+                               if (unlikely(added_by_user))
+                                       fdb->added_by_user = 1;
                                fdb_notify(br, fdb, RTM_NEWNEIGH);
+                       }
                }
                /* else  we lose race and someone else inserts
                 * it first, don't bother updating
@@ -647,6 +688,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
 
                modified = true;
        }
+       fdb->added_by_user = 1;
 
        fdb->used = jiffies;
        if (modified) {
@@ -664,7 +706,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p,
 
        if (ndm->ndm_flags & NTF_USE) {
                rcu_read_lock();
-               br_fdb_update(p->br, p, addr, vid);
+               br_fdb_update(p->br, p, addr, vid, true);
                rcu_read_unlock();
        } else {
                spin_lock_bh(&p->br->hash_lock);
@@ -749,8 +791,7 @@ out:
        return err;
 }
 
-int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr,
-                      u16 vlan)
+static int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vlan)
 {
        struct hlist_head *head = &br->hash[br_mac_hash(addr, vlan)];
        struct net_bridge_fdb_entry *fdb;
index cffe1d666ba11636cc7e3d374018edf7ac31535b..54d207d3a31ced4e2d23e0e4fba132f52bb9dc6c 100644 (file)
@@ -389,6 +389,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
        if (br->dev->needed_headroom < dev->needed_headroom)
                br->dev->needed_headroom = dev->needed_headroom;
 
+       if (br_fdb_insert(br, p, dev->dev_addr, 0))
+               netdev_err(dev, "failed insert local address bridge forwarding table\n");
+
        spin_lock_bh(&br->lock);
        changed_addr = br_stp_recalculate_bridge_id(br);
 
@@ -404,9 +407,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        dev_set_mtu(br->dev, br_min_mtu(br));
 
-       if (br_fdb_insert(br, p, dev->dev_addr, 0))
-               netdev_err(dev, "failed insert local address bridge forwarding table\n");
-
        kobject_uevent(&p->kobj, KOBJ_ADD);
 
        return 0;
index bf8dc7d308d6d0b0a092d080723118d327a19b10..d0cca3c65f0174ab8c6522b5f54ab2ad33b66dca 100644 (file)
@@ -29,6 +29,7 @@ static int br_pass_frame_up(struct sk_buff *skb)
        struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
        struct net_bridge *br = netdev_priv(brdev);
        struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);
+       struct net_port_vlans *pv;
 
        u64_stats_update_begin(&brstats->syncp);
        brstats->rx_packets++;
@@ -39,18 +40,18 @@ static int br_pass_frame_up(struct sk_buff *skb)
         * packet is allowed except in promisc modue when someone
         * may be running packet capture.
         */
+       pv = br_get_vlan_info(br);
        if (!(brdev->flags & IFF_PROMISC) &&
-           !br_allowed_egress(br, br_get_vlan_info(br), skb)) {
+           !br_allowed_egress(br, pv, skb)) {
                kfree_skb(skb);
                return NET_RX_DROP;
        }
 
-       skb = br_handle_vlan(br, br_get_vlan_info(br), skb);
-       if (!skb)
-               return NET_RX_DROP;
-
        indev = skb->dev;
        skb->dev = brdev;
+       skb = br_handle_vlan(br, pv, skb);
+       if (!skb)
+               return NET_RX_DROP;
 
        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
                       netif_receive_skb);
@@ -77,7 +78,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
        /* insert into forwarding database after filtering to avoid spoofing */
        br = p->br;
        if (p->flags & BR_LEARNING)
-               br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
+               br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);
 
        if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
            br_multicast_rcv(br, p, skb, vid))
@@ -148,7 +149,7 @@ static int br_handle_local_finish(struct sk_buff *skb)
 
        br_vlan_get_tag(skb, &vid);
        if (p->flags & BR_LEARNING)
-               br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid);
+               br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
        return 0;        /* process further */
 }
 
index ef66365b7354da9f2fe2c4d87d2056d9a781f3c8..93067ecdb9a212321c8780bd65153d60e8203907 100644 (file)
@@ -1127,9 +1127,10 @@ static void br_multicast_query_received(struct net_bridge *br,
                                        struct net_bridge_port *port,
                                        struct bridge_mcast_querier *querier,
                                        int saddr,
+                                       bool is_general_query,
                                        unsigned long max_delay)
 {
-       if (saddr)
+       if (saddr && is_general_query)
                br_multicast_update_querier_timer(br, querier, max_delay);
        else if (timer_pending(&querier->timer))
                return;
@@ -1181,8 +1182,16 @@ static int br_ip4_multicast_query(struct net_bridge *br,
                            IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
        }
 
+       /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer
+        * all-systems destination addresses (224.0.0.1) for general queries
+        */
+       if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) {
+               err = -EINVAL;
+               goto out;
+       }
+
        br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
-                                   max_delay);
+                                   !group, max_delay);
 
        if (!group)
                goto out;
@@ -1228,6 +1237,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
        unsigned long max_delay;
        unsigned long now = jiffies;
        const struct in6_addr *group = NULL;
+       bool is_general_query;
        int err = 0;
 
        spin_lock(&br->multicast_lock);
@@ -1235,6 +1245,12 @@ static int br_ip6_multicast_query(struct net_bridge *br,
            (port && port->state == BR_STATE_DISABLED))
                goto out;
 
+       /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */
+       if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
+               err = -EINVAL;
+               goto out;
+       }
+
        if (skb->len == sizeof(*mld)) {
                if (!pskb_may_pull(skb, sizeof(*mld))) {
                        err = -EINVAL;
@@ -1256,8 +1272,19 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
        }
 
+       is_general_query = group && ipv6_addr_any(group);
+
+       /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
+        * all-nodes destination address (ff02::1) for general queries
+        */
+       if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) {
+               err = -EINVAL;
+               goto out;
+       }
+
        br_multicast_query_received(br, port, &br->ip6_querier,
-                                   !ipv6_addr_any(&ip6h->saddr), max_delay);
+                                   !ipv6_addr_any(&ip6h->saddr),
+                                   is_general_query, max_delay);
 
        if (!group)
                goto out;
index fcd12333c59b319de7c11c1ddc86214195725e46..3ba11bc99b65db2b14754dc84deeed5274623f6f 100644 (file)
@@ -104,6 +104,7 @@ struct net_bridge_fdb_entry
        mac_addr                        addr;
        unsigned char                   is_local;
        unsigned char                   is_static;
+       unsigned char                   added_by_user;
        __u16                           vlan_id;
 };
 
@@ -370,6 +371,9 @@ static inline void br_netpoll_disable(struct net_bridge_port *p)
 int br_fdb_init(void);
 void br_fdb_fini(void);
 void br_fdb_flush(struct net_bridge *br);
+void br_fdb_find_delete_local(struct net_bridge *br,
+                             const struct net_bridge_port *p,
+                             const unsigned char *addr, u16 vid);
 void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr);
 void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr);
 void br_fdb_cleanup(unsigned long arg);
@@ -383,8 +387,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, unsigned long count,
 int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
                  const unsigned char *addr, u16 vid);
 void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
-                  const unsigned char *addr, u16 vid);
-int fdb_delete_by_addr(struct net_bridge *br, const u8 *addr, u16 vid);
+                  const unsigned char *addr, u16 vid, bool added_by_user);
 
 int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
                  struct net_device *dev, const unsigned char *addr);
@@ -584,6 +587,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
 int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags);
 int br_vlan_delete(struct net_bridge *br, u16 vid);
 void br_vlan_flush(struct net_bridge *br);
+bool br_vlan_find(struct net_bridge *br, u16 vid);
 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
@@ -665,6 +669,11 @@ static inline void br_vlan_flush(struct net_bridge *br)
 {
 }
 
+static inline bool br_vlan_find(struct net_bridge *br, u16 vid)
+{
+       return false;
+}
+
 static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
 {
        return -EOPNOTSUPP;
index 656a6f3e40de1b13b9ea7a89373da5d5615e5bb2..189ba1e7d8515945db5593c053b7751d36a02d3b 100644 (file)
@@ -194,6 +194,8 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
 
        wasroot = br_is_root_bridge(br);
 
+       br_fdb_change_mac_address(br, addr);
+
        memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
        memcpy(br->bridge_id.addr, addr, ETH_ALEN);
        memcpy(br->dev->dev_addr, addr, ETH_ALEN);
index 4ca4d0a0151c49926dd7e47c6ac5bc8f6b5d28f0..f23c74b3a95327722916405cee92d5d61048c8a2 100644 (file)
@@ -119,22 +119,6 @@ static void __vlan_flush(struct net_port_vlans *v)
        kfree_rcu(v, rcu);
 }
 
-/* Strip the tag from the packet.  Will return skb with tci set 0.  */
-static struct sk_buff *br_vlan_untag(struct sk_buff *skb)
-{
-       if (skb->protocol != htons(ETH_P_8021Q)) {
-               skb->vlan_tci = 0;
-               return skb;
-       }
-
-       skb->vlan_tci = 0;
-       skb = vlan_untag(skb);
-       if (skb)
-               skb->vlan_tci = 0;
-
-       return skb;
-}
-
 struct sk_buff *br_handle_vlan(struct net_bridge *br,
                               const struct net_port_vlans *pv,
                               struct sk_buff *skb)
@@ -144,13 +128,27 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
        if (!br->vlan_enabled)
                goto out;
 
+       /* Vlan filter table must be configured at this point.  The
+        * only exception is the bridge is set in promisc mode and the
+        * packet is destined for the bridge device.  In this case
+        * pass the packet as is.
+        */
+       if (!pv) {
+               if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) {
+                       goto out;
+               } else {
+                       kfree_skb(skb);
+                       return NULL;
+               }
+       }
+
        /* At this point, we know that the frame was filtered and contains
         * a valid vlan id.  If the vlan id is set in the untagged bitmap,
         * send untagged; otherwise, send tagged.
         */
        br_vlan_get_tag(skb, &vid);
        if (test_bit(vid, pv->untagged_bitmap))
-               skb = br_vlan_untag(skb);
+               skb->vlan_tci = 0;
 
 out:
        return skb;
@@ -174,6 +172,18 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
        if (!v)
                return false;
 
+       /* If vlan tx offload is disabled on bridge device and frame was
+        * sent from vlan device on the bridge device, it does not have
+        * HW accelerated vlan tag.
+        */
+       if (unlikely(!vlan_tx_tag_present(skb) &&
+                    (skb->protocol == htons(ETH_P_8021Q) ||
+                     skb->protocol == htons(ETH_P_8021AD)))) {
+               skb = vlan_untag(skb);
+               if (unlikely(!skb))
+                       return false;
+       }
+
        err = br_vlan_get_tag(skb, vid);
        if (!*vid) {
                u16 pvid = br_get_pvid(v);
@@ -275,9 +285,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
        if (!pv)
                return -EINVAL;
 
-       spin_lock_bh(&br->hash_lock);
-       fdb_delete_by_addr(br, br->dev->dev_addr, vid);
-       spin_unlock_bh(&br->hash_lock);
+       br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid);
 
        __vlan_del(pv, vid);
        return 0;
@@ -295,6 +303,25 @@ void br_vlan_flush(struct net_bridge *br)
        __vlan_flush(pv);
 }
 
+bool br_vlan_find(struct net_bridge *br, u16 vid)
+{
+       struct net_port_vlans *pv;
+       bool found = false;
+
+       rcu_read_lock();
+       pv = rcu_dereference(br->vlan_info);
+
+       if (!pv)
+               goto out;
+
+       if (test_bit(vid, pv->vlan_bitmap))
+               found = true;
+
+out:
+       rcu_read_unlock();
+       return found;
+}
+
 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
 {
        if (!rtnl_trylock())
@@ -359,9 +386,7 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
        if (!pv)
                return -EINVAL;
 
-       spin_lock_bh(&port->br->hash_lock);
-       fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
-       spin_unlock_bh(&port->br->hash_lock);
+       br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid);
 
        return __vlan_del(pv, vid);
 }
index 4dca159435cfe17dcc09fadccfebee7ca49b1075..edbca468fa73cc29b31703bd4fe4d70925f21bd5 100644 (file)
@@ -22,6 +22,7 @@
 #include <net/pkt_sched.h>
 #include <net/caif/caif_device.h>
 #include <net/caif/caif_layer.h>
+#include <net/caif/caif_dev.h>
 #include <net/caif/cfpkt.h>
 #include <net/caif/cfcnfg.h>
 #include <net/caif/cfserl.h>
index 353f793d1b3bb7285d466f0f67f3bc6023e10e49..a6e115463052ac72431fb8680bcedb3969dd1aff 100644 (file)
@@ -15,6 +15,7 @@
 #include <net/caif/caif_layer.h>
 #include <net/caif/cfsrvl.h>
 #include <net/caif/cfpkt.h>
+#include <net/caif/caif_dev.h>
 
 #define SRVL_CTRL_PKT_SIZE 1
 #define SRVL_FLOW_OFF 0x81
index d249874a366d363edfc94adc47df54dde6bdba0e..a27f8aad9e991f95cc5366bce3e975bff4f16bdd 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/skbuff.h>
 #include <linux/can.h>
 #include <linux/can/core.h>
+#include <linux/can/skb.h>
 #include <linux/ratelimit.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
@@ -290,7 +291,7 @@ int can_send(struct sk_buff *skb, int loop)
                                return -ENOMEM;
                        }
 
-                       newskb->sk = skb->sk;
+                       can_skb_set_owner(newskb, skb->sk);
                        newskb->ip_summed = CHECKSUM_UNNECESSARY;
                        newskb->pkt_type = PACKET_BROADCAST;
                }
index 3fc737b214c78effe8b83a4fed649d8109274737..dcb75c0e66c1b69979a88c65efe43084046f8bc2 100644 (file)
@@ -268,7 +268,7 @@ static void bcm_can_tx(struct bcm_op *op)
 
        /* send with loopback */
        skb->dev = dev;
-       skb->sk = op->sk;
+       can_skb_set_owner(skb, op->sk);
        can_send(skb, 1);
 
        /* update statistics */
@@ -1223,7 +1223,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
 
        can_skb_prv(skb)->ifindex = dev->ifindex;
        skb->dev = dev;
-       skb->sk  = sk;
+       can_skb_set_owner(skb, sk);
        err = can_send(skb, 1); /* send with loopback */
        dev_put(dev);
 
index 07d72d852324f23a8fffdc71798e89602b861977..081e81fd017fa53f7a6ed3afd341601b43377531 100644 (file)
@@ -121,13 +121,9 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
        if (!ro->recv_own_msgs && oskb->sk == sk)
                return;
 
-       /* do not pass frames with DLC > 8 to a legacy socket */
-       if (!ro->fd_frames) {
-               struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
-
-               if (unlikely(cfd->len > CAN_MAX_DLEN))
-                       return;
-       }
+       /* do not pass non-CAN2.0 frames to a legacy socket */
+       if (!ro->fd_frames && oskb->len != CAN_MTU)
+               return;
 
        /* clone the given skb to be able to enqueue it into the rcv queue */
        skb = skb_clone(oskb, GFP_ATOMIC);
@@ -715,6 +711,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
 
        skb->dev = dev;
        skb->sk  = sk;
+       skb->priority = sk->sk_priority;
 
        err = can_send(skb, ro->loopback);
 
@@ -737,9 +734,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
                       struct msghdr *msg, size_t size, int flags)
 {
        struct sock *sk = sock->sk;
-       struct raw_sock *ro = raw_sk(sk);
        struct sk_buff *skb;
-       int rxmtu;
        int err = 0;
        int noblock;
 
@@ -750,20 +745,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
        if (!skb)
                return err;
 
-       /*
-        * when serving a legacy socket the DLC <= 8 is already checked inside
-        * raw_rcv(). Now check if we need to pass a canfd_frame to a legacy
-        * socket and cut the possible CANFD_MTU/CAN_MTU length to CAN_MTU
-        */
-       if (!ro->fd_frames)
-               rxmtu = CAN_MTU;
-       else
-               rxmtu = skb->len;
-
-       if (size < rxmtu)
+       if (size < skb->len)
                msg->msg_flags |= MSG_TRUNC;
        else
-               size = rxmtu;
+               size = skb->len;
 
        err = memcpy_toiovec(msg->msg_iov, skb->data, size);
        if (err < 0) {
index 0e478a0f4204b72ed19ae49c349d632cda009e02..30efc5c186222c64ea3d7d21b194f8ce9f4e0f47 100644 (file)
@@ -840,9 +840,13 @@ static bool ceph_msg_data_bio_advance(struct ceph_msg_data_cursor *cursor,
 
        if (!cursor->bvec_iter.bi_size) {
                bio = bio->bi_next;
-               cursor->bvec_iter = bio->bi_iter;
+               cursor->bio = bio;
+               if (bio)
+                       cursor->bvec_iter = bio->bi_iter;
+               else
+                       memset(&cursor->bvec_iter, 0,
+                              sizeof(cursor->bvec_iter));
        }
-       cursor->bio = bio;
 
        if (!cursor->last_piece) {
                BUG_ON(!cursor->resid);
index 010ff3bd58ade67373c0db7531a2ec8ea9bb1460..0676f2b199d672eaf61157cdf78b75ee74afb434 100644 (file)
@@ -1426,6 +1426,40 @@ static void __send_queued(struct ceph_osd_client *osdc)
                __send_request(osdc, req);
 }
 
+/*
+ * Caller should hold map_sem for read and request_mutex.
+ */
+static int __ceph_osdc_start_request(struct ceph_osd_client *osdc,
+                                    struct ceph_osd_request *req,
+                                    bool nofail)
+{
+       int rc;
+
+       __register_request(osdc, req);
+       req->r_sent = 0;
+       req->r_got_reply = 0;
+       rc = __map_request(osdc, req, 0);
+       if (rc < 0) {
+               if (nofail) {
+                       dout("osdc_start_request failed map, "
+                               " will retry %lld\n", req->r_tid);
+                       rc = 0;
+               } else {
+                       __unregister_request(osdc, req);
+               }
+               return rc;
+       }
+
+       if (req->r_osd == NULL) {
+               dout("send_request %p no up osds in pg\n", req);
+               ceph_monc_request_next_osdmap(&osdc->client->monc);
+       } else {
+               __send_queued(osdc);
+       }
+
+       return 0;
+}
+
 /*
  * Timeout callback, called every N seconds when 1 or more osd
  * requests has been active for more than N seconds.  When this
@@ -1653,6 +1687,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
        osdmap_epoch = ceph_decode_32(&p);
 
        /* lookup */
+       down_read(&osdc->map_sem);
        mutex_lock(&osdc->request_mutex);
        req = __lookup_request(osdc, tid);
        if (req == NULL) {
@@ -1709,7 +1744,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
                dout("redirect pool %lld\n", redir.oloc.pool);
 
                __unregister_request(osdc, req);
-               mutex_unlock(&osdc->request_mutex);
 
                req->r_target_oloc = redir.oloc; /* struct */
 
@@ -1721,10 +1755,10 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
                 * successfully.  In the future we might want to follow
                 * original request's nofail setting here.
                 */
-               err = ceph_osdc_start_request(osdc, req, true);
+               err = __ceph_osdc_start_request(osdc, req, true);
                BUG_ON(err);
 
-               goto done;
+               goto out_unlock;
        }
 
        already_completed = req->r_got_reply;
@@ -1742,8 +1776,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
                req->r_got_reply = 1;
        } else if ((flags & CEPH_OSD_FLAG_ONDISK) == 0) {
                dout("handle_reply tid %llu dup ack\n", tid);
-               mutex_unlock(&osdc->request_mutex);
-               goto done;
+               goto out_unlock;
        }
 
        dout("handle_reply tid %llu flags %d\n", tid, flags);
@@ -1758,6 +1791,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
                __unregister_request(osdc, req);
 
        mutex_unlock(&osdc->request_mutex);
+       up_read(&osdc->map_sem);
 
        if (!already_completed) {
                if (req->r_unsafe_callback &&
@@ -1775,10 +1809,14 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
                complete_request(req);
        }
 
-done:
+out:
        dout("req=%p req->r_linger=%d\n", req, req->r_linger);
        ceph_osdc_put_request(req);
        return;
+out_unlock:
+       mutex_unlock(&osdc->request_mutex);
+       up_read(&osdc->map_sem);
+       goto out;
 
 bad_put:
        req->r_result = -EIO;
@@ -1791,6 +1829,7 @@ bad_put:
        ceph_osdc_put_request(req);
 bad_mutex:
        mutex_unlock(&osdc->request_mutex);
+       up_read(&osdc->map_sem);
 bad:
        pr_err("corrupt osd_op_reply got %d %d\n",
               (int)msg->front.iov_len, le32_to_cpu(msg->hdr.front_len));
@@ -2351,34 +2390,16 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
                            struct ceph_osd_request *req,
                            bool nofail)
 {
-       int rc = 0;
+       int rc;
 
        down_read(&osdc->map_sem);
        mutex_lock(&osdc->request_mutex);
-       __register_request(osdc, req);
-       req->r_sent = 0;
-       req->r_got_reply = 0;
-       rc = __map_request(osdc, req, 0);
-       if (rc < 0) {
-               if (nofail) {
-                       dout("osdc_start_request failed map, "
-                               " will retry %lld\n", req->r_tid);
-                       rc = 0;
-               } else {
-                       __unregister_request(osdc, req);
-               }
-               goto out_unlock;
-       }
-       if (req->r_osd == NULL) {
-               dout("send_request %p no up osds in pg\n", req);
-               ceph_monc_request_next_osdmap(&osdc->client->monc);
-       } else {
-               __send_queued(osdc);
-       }
-       rc = 0;
-out_unlock:
+
+       rc = __ceph_osdc_start_request(osdc, req, nofail);
+
        mutex_unlock(&osdc->request_mutex);
        up_read(&osdc->map_sem);
+
        return rc;
 }
 EXPORT_SYMBOL(ceph_osdc_start_request);
@@ -2504,9 +2525,12 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
        err = -ENOMEM;
        osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify");
        if (!osdc->notify_wq)
-               goto out_msgpool;
+               goto out_msgpool_reply;
+
        return 0;
 
+out_msgpool_reply:
+       ceph_msgpool_destroy(&osdc->msgpool_op_reply);
 out_msgpool:
        ceph_msgpool_destroy(&osdc->msgpool_op);
 out_mempool:
index f50161fb812eace2eb659ae78bf12062c608b5b6..9a76eaf63184753d6020eb1f3a9ab51299b1ae02 100644 (file)
@@ -384,8 +384,8 @@ static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
        return sock_setsockopt(sock, level, optname, optval, optlen);
 }
 
-asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
-                               char __user *optval, unsigned int optlen)
+COMPAT_SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
+                      char __user *, optval, unsigned int, optlen)
 {
        int err;
        struct socket *sock = sockfd_lookup(fd, &err);
@@ -504,8 +504,8 @@ int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *usersta
 }
 EXPORT_SYMBOL(compat_sock_get_timestampns);
 
-asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
-                               char __user *optval, int __user *optlen)
+COMPAT_SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
+                      char __user *, optval, int __user *, optlen)
 {
        int err;
        struct socket *sock = sockfd_lookup(fd, &err);
@@ -735,15 +735,15 @@ static unsigned char nas[21] = {
 };
 #undef AL
 
-asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
+COMPAT_SYSCALL_DEFINE3(sendmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags)
 {
        if (flags & MSG_CMSG_COMPAT)
                return -EINVAL;
        return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
-asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
-                                   unsigned int vlen, unsigned int flags)
+COMPAT_SYSCALL_DEFINE4(sendmmsg, int, fd, struct compat_mmsghdr __user *, mmsg,
+                      unsigned int, vlen, unsigned int, flags)
 {
        if (flags & MSG_CMSG_COMPAT)
                return -EINVAL;
@@ -751,28 +751,28 @@ asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
                              flags | MSG_CMSG_COMPAT);
 }
 
-asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
+COMPAT_SYSCALL_DEFINE3(recvmsg, int, fd, struct compat_msghdr __user *, msg, unsigned int, flags)
 {
        if (flags & MSG_CMSG_COMPAT)
                return -EINVAL;
        return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
-asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags)
+COMPAT_SYSCALL_DEFINE4(recv, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags)
 {
        return sys_recv(fd, buf, len, flags | MSG_CMSG_COMPAT);
 }
 
-asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len,
-                                   unsigned int flags, struct sockaddr __user *addr,
-                                   int __user *addrlen)
+COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len,
+                      unsigned int, flags, struct sockaddr __user *, addr,
+                      int __user *, addrlen)
 {
        return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen);
 }
 
-asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
-                                   unsigned int vlen, unsigned int flags,
-                                   struct compat_timespec __user *timeout)
+COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg,
+                      unsigned int, vlen, unsigned int, flags,
+                      struct compat_timespec __user *, timeout)
 {
        int datagrams;
        struct timespec ktspec;
@@ -795,7 +795,7 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
        return datagrams;
 }
 
-asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
+COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args)
 {
        int ret;
        u32 a[6];
index 3721db71635051f82a4ace0d24e669156c1a8783..45fa2f11f84dcc7f0efe12711c2d51526360a08d 100644 (file)
@@ -2286,7 +2286,7 @@ out:
 }
 EXPORT_SYMBOL(skb_checksum_help);
 
-__be16 skb_network_protocol(struct sk_buff *skb)
+__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
 {
        __be16 type = skb->protocol;
        int vlan_depth = ETH_HLEN;
@@ -2313,6 +2313,8 @@ __be16 skb_network_protocol(struct sk_buff *skb)
                vlan_depth += VLAN_HLEN;
        }
 
+       *depth = vlan_depth;
+
        return type;
 }
 
@@ -2326,12 +2328,13 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
        struct packet_offload *ptype;
-       __be16 type = skb_network_protocol(skb);
+       int vlan_depth = skb->mac_len;
+       __be16 type = skb_network_protocol(skb, &vlan_depth);
 
        if (unlikely(!type))
                return ERR_PTR(-EINVAL);
 
-       __skb_pull(skb, skb->mac_len);
+       __skb_pull(skb, vlan_depth);
 
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, &offload_base, list) {
@@ -2420,7 +2423,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault);
  * 2. No high memory really exists on this machine.
  */
 
-static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
+static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_HIGHMEM
        int i;
@@ -2495,34 +2498,38 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)
 }
 
 static netdev_features_t harmonize_features(struct sk_buff *skb,
-       netdev_features_t features)
+                                           const struct net_device *dev,
+                                           netdev_features_t features)
 {
+       int tmp;
+
        if (skb->ip_summed != CHECKSUM_NONE &&
-           !can_checksum_protocol(features, skb_network_protocol(skb))) {
+           !can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) {
                features &= ~NETIF_F_ALL_CSUM;
-       } else if (illegal_highdma(skb->dev, skb)) {
+       } else if (illegal_highdma(dev, skb)) {
                features &= ~NETIF_F_SG;
        }
 
        return features;
 }
 
-netdev_features_t netif_skb_features(struct sk_buff *skb)
+netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+                                        const struct net_device *dev)
 {
        __be16 protocol = skb->protocol;
-       netdev_features_t features = skb->dev->features;
+       netdev_features_t features = dev->features;
 
-       if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
+       if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs)
                features &= ~NETIF_F_GSO_MASK;
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
                struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
                protocol = veh->h_vlan_encapsulated_proto;
        } else if (!vlan_tx_tag_present(skb)) {
-               return harmonize_features(skb, features);
+               return harmonize_features(skb, dev, features);
        }
 
-       features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
+       features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
                                               NETIF_F_HW_VLAN_STAG_TX);
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
@@ -2530,9 +2537,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
                                NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
                                NETIF_F_HW_VLAN_STAG_TX;
 
-       return harmonize_features(skb, features);
+       return harmonize_features(skb, dev, features);
 }
-EXPORT_SYMBOL(netif_skb_features);
+EXPORT_SYMBOL(netif_skb_dev_features);
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq)
@@ -2803,7 +2810,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);
  *      the BH enable code must have IRQs enabled so that it will not deadlock.
  *          --BLG
  */
-int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
+static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 {
        struct net_device *dev = skb->dev;
        struct netdev_queue *txq;
@@ -4637,7 +4644,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
 
-int netdev_adjacent_sysfs_add(struct net_device *dev,
+static int netdev_adjacent_sysfs_add(struct net_device *dev,
                              struct net_device *adj_dev,
                              struct list_head *dev_list)
 {
@@ -4647,7 +4654,7 @@ int netdev_adjacent_sysfs_add(struct net_device *dev,
        return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj),
                                 linkname);
 }
-void netdev_adjacent_sysfs_del(struct net_device *dev,
+static void netdev_adjacent_sysfs_del(struct net_device *dev,
                               char *name,
                               struct list_head *dev_list)
 {
index f409e0bd35c06456f4877d10d98c342f52362d84..185c341fafbd079714fe3a563b8209d5c5f7ead4 100644 (file)
@@ -745,6 +745,13 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
                        attach_rules(&ops->rules_list, dev);
                break;
 
+       case NETDEV_CHANGENAME:
+               list_for_each_entry(ops, &net->rules_ops, list) {
+                       detach_rules(&ops->rules_list, dev);
+                       attach_rules(&ops->rules_list, dev);
+               }
+               break;
+
        case NETDEV_UNREGISTER:
                list_for_each_entry(ops, &net->rules_ops, list)
                        detach_rules(&ops->rules_list, dev);
index 87577d447554336b33067ab6e2373c6bdd25b93d..e29e810663d777ecee281b61fda8ec8dbdcbfb92 100644 (file)
@@ -323,17 +323,6 @@ u32 __skb_get_poff(const struct sk_buff *skb)
        return poff;
 }
 
-static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
-{
-       if (unlikely(queue_index >= dev->real_num_tx_queues)) {
-               net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
-                                    dev->name, queue_index,
-                                    dev->real_num_tx_queues);
-               return 0;
-       }
-       return queue_index;
-}
-
 static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_XPS
@@ -372,7 +361,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 #endif
 }
 
-u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
+static u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 {
        struct sock *sk = skb->sk;
        int queue_index = sk_tx_queue_get(sk);
@@ -392,7 +381,6 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 
        return queue_index;
 }
-EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
                                    struct sk_buff *skb,
@@ -403,13 +391,13 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev,
        if (dev->real_num_tx_queues != 1) {
                const struct net_device_ops *ops = dev->netdev_ops;
                if (ops->ndo_select_queue)
-                       queue_index = ops->ndo_select_queue(dev, skb,
-                                                           accel_priv);
+                       queue_index = ops->ndo_select_queue(dev, skb, accel_priv,
+                                                           __netdev_pick_tx);
                else
                        queue_index = __netdev_pick_tx(dev, skb);
 
                if (!accel_priv)
-                       queue_index = dev_cap_txqueue(dev, queue_index);
+                       queue_index = netdev_cap_txqueue(dev, queue_index);
        }
 
        skb_set_queue_mapping(skb, queue_index);
index b9e9e0d38672a8ca9a17f8d6ec8daf88b8a09a65..e16129019c6658ae7b1ab697692f8e6484c8cd90 100644 (file)
@@ -766,9 +766,6 @@ static void neigh_periodic_work(struct work_struct *work)
        nht = rcu_dereference_protected(tbl->nht,
                                        lockdep_is_held(&tbl->lock));
 
-       if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
-               goto out;
-
        /*
         *      periodically recompute ReachableTime from random function
         */
@@ -781,6 +778,9 @@ static void neigh_periodic_work(struct work_struct *work)
                                neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
        }
 
+       if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
+               goto out;
+
        for (i = 0 ; i < (1 << nht->hash_shift); i++) {
                np = &nht->hash_buckets[i];
 
@@ -3046,7 +3046,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
        if (!t)
                goto err;
 
-       for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
+       for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
                t->neigh_vars[i].data += (long) p;
                t->neigh_vars[i].extra1 = dev;
                t->neigh_vars[i].extra2 = p;
index c03f3dec4763fc507edc56167cd8e88a209fb197..df9e6b1a975920f47fbd68b540ccb4d7f8511759 100644 (file)
@@ -742,7 +742,7 @@ static bool pkt_is_ns(struct sk_buff *skb)
        struct nd_msg *msg;
        struct ipv6hdr *hdr;
 
-       if (skb->protocol != htons(ETH_P_ARP))
+       if (skb->protocol != htons(ETH_P_IPV6))
                return false;
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)))
                return false;
@@ -948,6 +948,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
 {
        char *cur=opt, *delim;
        int ipv6;
+       bool ipversion_set = false;
 
        if (*cur != '@') {
                if ((delim = strchr(cur, '@')) == NULL)
@@ -960,6 +961,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
        cur++;
 
        if (*cur != '/') {
+               ipversion_set = true;
                if ((delim = strchr(cur, '/')) == NULL)
                        goto parse_failed;
                *delim = 0;
@@ -1002,7 +1004,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
        ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
        if (ipv6 < 0)
                goto parse_failed;
-       else if (np->ipv6 != (bool)ipv6)
+       else if (ipversion_set && np->ipv6 != (bool)ipv6)
                goto parse_failed;
        else
                np->ipv6 = (bool)ipv6;
index 393b1bc9a618e5dee70105614772ad692e09bb7e..120eecc0f5a471f0157894f48ee33f1d1f6a9af5 100644 (file)
@@ -374,7 +374,7 @@ static size_t rtnl_link_get_slave_info_data_size(const struct net_device *dev)
        if (!master_dev)
                return 0;
        ops = master_dev->rtnl_link_ops;
-       if (!ops->get_slave_size)
+       if (!ops || !ops->get_slave_size)
                return 0;
        /* IFLA_INFO_SLAVE_DATA + nested data */
        return nla_total_size(sizeof(struct nlattr)) +
@@ -1963,16 +1963,21 @@ replay:
 
                dev->ifindex = ifm->ifi_index;
 
-               if (ops->newlink)
+               if (ops->newlink) {
                        err = ops->newlink(net, dev, tb, data);
-               else
+                       /* Drivers should call free_netdev() in ->destructor
+                        * and unregister it on failure so that device could be
+                        * finally freed in rtnl_unlock.
+                        */
+                       if (err < 0)
+                               goto out;
+               } else {
                        err = register_netdevice(dev);
-
-               if (err < 0) {
-                       free_netdev(dev);
-                       goto out;
+                       if (err < 0) {
+                               free_netdev(dev);
+                               goto out;
+                       }
                }
-
                err = rtnl_configure_link(dev, ifm);
                if (err < 0)
                        unregister_netdevice(dev);
@@ -2116,12 +2121,13 @@ EXPORT_SYMBOL(rtmsg_ifinfo);
 static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
                                   struct net_device *dev,
                                   u8 *addr, u32 pid, u32 seq,
-                                  int type, unsigned int flags)
+                                  int type, unsigned int flags,
+                                  int nlflags)
 {
        struct nlmsghdr *nlh;
        struct ndmsg *ndm;
 
-       nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), nlflags);
        if (!nlh)
                return -EMSGSIZE;
 
@@ -2159,7 +2165,7 @@ static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
        if (!skb)
                goto errout;
 
-       err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF);
+       err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF, 0);
        if (err < 0) {
                kfree_skb(skb);
                goto errout;
@@ -2384,7 +2390,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
 
                err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
                                              portid, seq,
-                                             RTM_NEWNEIGH, NTF_SELF);
+                                             RTM_NEWNEIGH, NTF_SELF,
+                                             NLM_F_MULTI);
                if (err < 0)
                        return err;
 skip:
index 5976ef0846bdda08db6289bb91f05a63b85e6e3a..90b96a11b974d2697defcc9ccf4b14b65d704c49 100644 (file)
@@ -707,9 +707,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->mark               = old->mark;
        new->skb_iif            = old->skb_iif;
        __nf_copy(new, old);
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
-       new->nf_trace           = old->nf_trace;
-#endif
 #ifdef CONFIG_NET_SCHED
        new->tc_index           = old->tc_index;
 #ifdef CONFIG_NET_CLS_ACT
@@ -2130,25 +2127,31 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
  *
  *     The `hlen` as calculated by skb_zerocopy_headlen() specifies the
  *     headroom in the `to` buffer.
+ *
+ *     Return value:
+ *     0: everything is OK
+ *     -ENOMEM: couldn't orphan frags of @from due to lack of memory
+ *     -EFAULT: skb_copy_bits() found some problem with skb geometry
  */
-void
-skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
+int
+skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
 {
        int i, j = 0;
        int plen = 0; /* length of skb->head fragment */
+       int ret;
        struct page *page;
        unsigned int offset;
 
        BUG_ON(!from->head_frag && !hlen);
 
        /* dont bother with small payloads */
-       if (len <= skb_tailroom(to)) {
-               skb_copy_bits(from, 0, skb_put(to, len), len);
-               return;
-       }
+       if (len <= skb_tailroom(to))
+               return skb_copy_bits(from, 0, skb_put(to, len), len);
 
        if (hlen) {
-               skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+               ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+               if (unlikely(ret))
+                       return ret;
                len -= hlen;
        } else {
                plen = min_t(int, skb_headlen(from), len);
@@ -2166,6 +2169,11 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
        to->len += len + plen;
        to->data_len += len + plen;
 
+       if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
+               skb_tx_error(from);
+               return -ENOMEM;
+       }
+
        for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
                if (!len)
                        break;
@@ -2176,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
                j++;
        }
        skb_shinfo(to)->nr_frags = j;
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(skb_zerocopy);
 
@@ -2841,81 +2851,85 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 
 /**
  *     skb_segment - Perform protocol segmentation on skb.
- *     @skb: buffer to segment
+ *     @head_skb: buffer to segment
  *     @features: features for the output path (see dev->features)
  *
  *     This function performs segmentation on the given skb.  It returns
  *     a pointer to the first in a list of new skbs for the segments.
  *     In case of error it returns ERR_PTR(err).
  */
-struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
+struct sk_buff *skb_segment(struct sk_buff *head_skb,
+                           netdev_features_t features)
 {
        struct sk_buff *segs = NULL;
        struct sk_buff *tail = NULL;
-       struct sk_buff *fskb = skb_shinfo(skb)->frag_list;
-       skb_frag_t *skb_frag = skb_shinfo(skb)->frags;
-       unsigned int mss = skb_shinfo(skb)->gso_size;
-       unsigned int doffset = skb->data - skb_mac_header(skb);
+       struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
+       skb_frag_t *frag = skb_shinfo(head_skb)->frags;
+       unsigned int mss = skb_shinfo(head_skb)->gso_size;
+       unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
+       struct sk_buff *frag_skb = head_skb;
        unsigned int offset = doffset;
-       unsigned int tnl_hlen = skb_tnl_header_len(skb);
+       unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
        unsigned int headroom;
        unsigned int len;
        __be16 proto;
        bool csum;
        int sg = !!(features & NETIF_F_SG);
-       int nfrags = skb_shinfo(skb)->nr_frags;
+       int nfrags = skb_shinfo(head_skb)->nr_frags;
        int err = -ENOMEM;
        int i = 0;
        int pos;
+       int dummy;
 
-       proto = skb_network_protocol(skb);
+       proto = skb_network_protocol(head_skb, &dummy);
        if (unlikely(!proto))
                return ERR_PTR(-EINVAL);
 
        csum = !!can_checksum_protocol(features, proto);
-       __skb_push(skb, doffset);
-       headroom = skb_headroom(skb);
-       pos = skb_headlen(skb);
+       __skb_push(head_skb, doffset);
+       headroom = skb_headroom(head_skb);
+       pos = skb_headlen(head_skb);
 
        do {
                struct sk_buff *nskb;
-               skb_frag_t *frag;
+               skb_frag_t *nskb_frag;
                int hsize;
                int size;
 
-               len = skb->len - offset;
+               len = head_skb->len - offset;
                if (len > mss)
                        len = mss;
 
-               hsize = skb_headlen(skb) - offset;
+               hsize = skb_headlen(head_skb) - offset;
                if (hsize < 0)
                        hsize = 0;
                if (hsize > len || !sg)
                        hsize = len;
 
-               if (!hsize && i >= nfrags && skb_headlen(fskb) &&
-                   (skb_headlen(fskb) == len || sg)) {
-                       BUG_ON(skb_headlen(fskb) > len);
+               if (!hsize && i >= nfrags && skb_headlen(list_skb) &&
+                   (skb_headlen(list_skb) == len || sg)) {
+                       BUG_ON(skb_headlen(list_skb) > len);
 
                        i = 0;
-                       nfrags = skb_shinfo(fskb)->nr_frags;
-                       skb_frag = skb_shinfo(fskb)->frags;
-                       pos += skb_headlen(fskb);
+                       nfrags = skb_shinfo(list_skb)->nr_frags;
+                       frag = skb_shinfo(list_skb)->frags;
+                       frag_skb = list_skb;
+                       pos += skb_headlen(list_skb);
 
                        while (pos < offset + len) {
                                BUG_ON(i >= nfrags);
 
-                               size = skb_frag_size(skb_frag);
+                               size = skb_frag_size(frag);
                                if (pos + size > offset + len)
                                        break;
 
                                i++;
                                pos += size;
-                               skb_frag++;
+                               frag++;
                        }
 
-                       nskb = skb_clone(fskb, GFP_ATOMIC);
-                       fskb = fskb->next;
+                       nskb = skb_clone(list_skb, GFP_ATOMIC);
+                       list_skb = list_skb->next;
 
                        if (unlikely(!nskb))
                                goto err;
@@ -2936,7 +2950,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
                        __skb_push(nskb, doffset);
                } else {
                        nskb = __alloc_skb(hsize + doffset + headroom,
-                                          GFP_ATOMIC, skb_alloc_rx_flag(skb),
+                                          GFP_ATOMIC, skb_alloc_rx_flag(head_skb),
                                           NUMA_NO_NODE);
 
                        if (unlikely(!nskb))
@@ -2952,12 +2966,12 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
                        segs = nskb;
                tail = nskb;
 
-               __copy_skb_header(nskb, skb);
-               nskb->mac_len = skb->mac_len;
+               __copy_skb_header(nskb, head_skb);
+               nskb->mac_len = head_skb->mac_len;
 
                skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
 
-               skb_copy_from_linear_data_offset(skb, -tnl_hlen,
+               skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
                                                 nskb->data - tnl_hlen,
                                                 doffset + tnl_hlen);
 
@@ -2966,30 +2980,32 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
 
                if (!sg) {
                        nskb->ip_summed = CHECKSUM_NONE;
-                       nskb->csum = skb_copy_and_csum_bits(skb, offset,
+                       nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
                                                            skb_put(nskb, len),
                                                            len, 0);
                        continue;
                }
 
-               frag = skb_shinfo(nskb)->frags;
+               nskb_frag = skb_shinfo(nskb)->frags;
 
-               skb_copy_from_linear_data_offset(skb, offset,
+               skb_copy_from_linear_data_offset(head_skb, offset,
                                                 skb_put(nskb, hsize), hsize);
 
-               skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
+               skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags &
+                       SKBTX_SHARED_FRAG;
 
                while (pos < offset + len) {
                        if (i >= nfrags) {
-                               BUG_ON(skb_headlen(fskb));
+                               BUG_ON(skb_headlen(list_skb));
 
                                i = 0;
-                               nfrags = skb_shinfo(fskb)->nr_frags;
-                               skb_frag = skb_shinfo(fskb)->frags;
+                               nfrags = skb_shinfo(list_skb)->nr_frags;
+                               frag = skb_shinfo(list_skb)->frags;
+                               frag_skb = list_skb;
 
                                BUG_ON(!nfrags);
 
-                               fskb = fskb->next;
+                               list_skb = list_skb->next;
                        }
 
                        if (unlikely(skb_shinfo(nskb)->nr_frags >=
@@ -3000,27 +3016,30 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
                                goto err;
                        }
 
-                       *frag = *skb_frag;
-                       __skb_frag_ref(frag);
-                       size = skb_frag_size(frag);
+                       if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC)))
+                               goto err;
+
+                       *nskb_frag = *frag;
+                       __skb_frag_ref(nskb_frag);
+                       size = skb_frag_size(nskb_frag);
 
                        if (pos < offset) {
-                               frag->page_offset += offset - pos;
-                               skb_frag_size_sub(frag, offset - pos);
+                               nskb_frag->page_offset += offset - pos;
+                               skb_frag_size_sub(nskb_frag, offset - pos);
                        }
 
                        skb_shinfo(nskb)->nr_frags++;
 
                        if (pos + size <= offset + len) {
                                i++;
-                               skb_frag++;
+                               frag++;
                                pos += size;
                        } else {
-                               skb_frag_size_sub(frag, pos + size - (offset + len));
+                               skb_frag_size_sub(nskb_frag, pos + size - (offset + len));
                                goto skip_fraglist;
                        }
 
-                       frag++;
+                       nskb_frag++;
                }
 
 skip_fraglist:
@@ -3034,7 +3053,7 @@ perform_csum_check:
                                                  nskb->len - doffset, 0);
                        nskb->ip_summed = CHECKSUM_NONE;
                }
-       } while ((offset += len) < skb->len);
+       } while ((offset += len) < head_skb->len);
 
        return segs;
 
index 0c127dcdf6a8ba9d25d544b02bf798d25fd67f6e..c0fc6bdad1e3629f123244d6d7c77805c9b5f0bd 100644 (file)
@@ -1775,7 +1775,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
                        while (order) {
                                if (npages >= 1 << order) {
                                        page = alloc_pages(sk->sk_allocation |
-                                                          __GFP_COMP | __GFP_NOWARN,
+                                                          __GFP_COMP |
+                                                          __GFP_NOWARN |
+                                                          __GFP_NORETRY,
                                                           order);
                                        if (page)
                                                goto fill_page;
@@ -1845,7 +1847,7 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
                gfp_t gfp = prio;
 
                if (order)
-                       gfp |= __GFP_COMP | __GFP_NOWARN;
+                       gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY;
                pfrag->page = alloc_pages(gfp, order);
                if (likely(pfrag->page)) {
                        pfrag->offset = 0;
@@ -2355,10 +2357,13 @@ void release_sock(struct sock *sk)
        if (sk->sk_backlog.tail)
                __release_sock(sk);
 
+       /* Warning : release_cb() might need to release sk ownership,
+        * ie call sock_release_ownership(sk) before us.
+        */
        if (sk->sk_prot->release_cb)
                sk->sk_prot->release_cb(sk);
 
-       sk->sk_lock.owned = 0;
+       sock_release_ownership(sk);
        if (waitqueue_active(&sk->sk_lock.wq))
                wake_up(&sk->sk_lock.wq);
        spin_unlock_bh(&sk->sk_lock.slock);
index c073b81a1f3e74887783dbd6096b77629d12fbe0..62b5828acde0906b71fc39955c9f2b36582d395a 100644 (file)
@@ -8,7 +8,7 @@
 #include "tfrc.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
-static bool tfrc_debug;
+bool tfrc_debug;
 module_param(tfrc_debug, bool, 0644);
 MODULE_PARM_DESC(tfrc_debug, "Enable TFRC debug messages");
 #endif
index a3d8f7c76ae091ba92704a3e6a70186c53b3b0f5..40ee7d62b6520d7daf2a1a8f3b54bda9cfbedfc2 100644 (file)
@@ -21,6 +21,7 @@
 #include "packet_history.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
+extern bool tfrc_debug;
 #define tfrc_pr_debug(format, a...)    DCCP_PR_DEBUG(tfrc_debug, format, ##a)
 #else
 #define tfrc_pr_debug(format, a...)
index 2954dcbca8325d81cab149613554d380bc607469..4c04848953bdb4caddeae9debd195ea3d004ee0d 100644 (file)
@@ -2104,8 +2104,6 @@ static struct notifier_block dn_dev_notifier = {
        .notifier_call = dn_device_event,
 };
 
-extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
-
 static struct packet_type dn_dix_packet_type __read_mostly = {
        .type =         cpu_to_be16(ETH_P_DNA_RT),
        .func =         dn_route_rcv,
@@ -2353,9 +2351,6 @@ static const struct proto_ops dn_proto_ops = {
        .sendpage =     sock_no_sendpage,
 };
 
-void dn_register_sysctl(void);
-void dn_unregister_sysctl(void);
-
 MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
 MODULE_AUTHOR("Linux DECnet Project Team");
 MODULE_LICENSE("GPL");
index 327060c6c874b337cf6edf9bd37c5b8181c0beee..7ae0d7f6dbd0bff10516e9415050d7aa41a07da0 100644 (file)
@@ -297,7 +297,7 @@ static bool seq_nr_after(u16 a, u16 b)
 
 void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx)
 {
-       if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
+       if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) {
                WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
                return;
        }
index 48b25c0af4d082a5c3256f9844f62e12e1cc6f3c..8edfea5da5729b7e02dacfe820f9c0eb97d4c5ee 100644 (file)
@@ -106,7 +106,6 @@ static int lowpan_header_create(struct sk_buff *skb,
                           unsigned short type, const void *_daddr,
                           const void *_saddr, unsigned int len)
 {
-       struct ipv6hdr *hdr;
        const u8 *saddr = _saddr;
        const u8 *daddr = _daddr;
        struct ieee802154_addr sa, da;
@@ -117,8 +116,6 @@ static int lowpan_header_create(struct sk_buff *skb,
        if (type != ETH_P_IPV6)
                return 0;
 
-       hdr = ipv6_hdr(skb);
-
        if (!saddr)
                saddr = dev->dev_addr;
 
@@ -533,7 +530,27 @@ static struct header_ops lowpan_header_ops = {
        .create = lowpan_header_create,
 };
 
+static struct lock_class_key lowpan_tx_busylock;
+static struct lock_class_key lowpan_netdev_xmit_lock_key;
+
+static void lowpan_set_lockdep_class_one(struct net_device *dev,
+                                        struct netdev_queue *txq,
+                                        void *_unused)
+{
+       lockdep_set_class(&txq->_xmit_lock,
+                         &lowpan_netdev_xmit_lock_key);
+}
+
+
+static int lowpan_dev_init(struct net_device *dev)
+{
+       netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL);
+       dev->qdisc_tx_busylock = &lowpan_tx_busylock;
+       return 0;
+}
+
 static const struct net_device_ops lowpan_netdev_ops = {
+       .ndo_init               = lowpan_dev_init,
        .ndo_start_xmit         = lowpan_xmit,
        .ndo_set_mac_address    = lowpan_set_address,
 };
index ecd2c3f245ce2b2e0b79f17417c5e6ad8c70abf6..19ab78aca547fc7fb45e56607e7adafd0036d947 100644 (file)
@@ -1296,8 +1296,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 
        segs = ERR_PTR(-EPROTONOSUPPORT);
 
-       /* Note : following gso_segment() might change skb->encapsulation */
-       udpfrag = !skb->encapsulation && proto == IPPROTO_UDP;
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
+               udpfrag = proto == IPPROTO_UDP && encap;
+       else
+               udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
 
        ops = rcu_dereference(inet_offloads[proto]);
        if (likely(ops && ops->callbacks.gso_segment))
index ac2dff3c2c1cf053cce19edf5179daf750dc2732..bdbf68bb2e2d194fcdf94553bd41a4ac9f184d7c 100644 (file)
@@ -1443,7 +1443,8 @@ static size_t inet_nlmsg_size(void)
               + nla_total_size(4) /* IFA_LOCAL */
               + nla_total_size(4) /* IFA_BROADCAST */
               + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
-              + nla_total_size(4);  /* IFA_FLAGS */
+              + nla_total_size(4)  /* IFA_FLAGS */
+              + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */
 }
 
 static inline u32 cstamp_delta(unsigned long cstamp)
index 1863422fb7d553340151b1402ee30d4be1fcde29..250be7421ab36c50ce00a25dcd3c659ca1c97f18 100644 (file)
@@ -182,6 +182,14 @@ static int gre_cisco_rcv(struct sk_buff *skb)
        int i;
        bool csum_err = false;
 
+#ifdef CONFIG_NET_IPGRE_BROADCAST
+       if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
+               /* Looped back packet, drop it! */
+               if (rt_is_output_route(skb_rtable(skb)))
+                       goto drop;
+       }
+#endif
+
        if (parse_gre_header(skb, &tpi, &csum_err) < 0)
                goto drop;
 
index bb075fc9a14f25169c175c7fcdcb86d56c709627..3b01959bf4bb0bbc208d8d564c8595c67eedd179 100644 (file)
@@ -208,7 +208,7 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force)
        }
 
        work = frag_mem_limit(nf) - nf->low_thresh;
-       while (work > 0) {
+       while (work > 0 || force) {
                spin_lock(&nf->lru_lock);
 
                if (list_empty(&nf->lru_list)) {
@@ -278,9 +278,10 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
 
        atomic_inc(&qp->refcnt);
        hlist_add_head(&qp->list, &hb->chain);
+       inet_frag_lru_add(nf, qp);
        spin_unlock(&hb->chain_lock);
        read_unlock(&f->lock);
-       inet_frag_lru_add(nf, qp);
+
        return qp;
 }
 
index e9f1217a8afdaf2559ce3fd7d134489994faf440..f3869c186d975e5a0f80f067fb461069f9ba2689 100644 (file)
 #include <net/route.h>
 #include <net/xfrm.h>
 
+static bool ip_may_fragment(const struct sk_buff *skb)
+{
+       return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ||
+              !skb->local_df;
+}
+
+static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
+{
+       if (skb->len <= mtu || skb->local_df)
+               return false;
+
+       if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+               return false;
+
+       return true;
+}
+
+static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb)
+{
+       unsigned int mtu;
+
+       if (skb->local_df || !skb_is_gso(skb))
+               return false;
+
+       mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true);
+
+       /* if seglen > mtu, do software segmentation for IP fragmentation on
+        * output.  DF bit cannot be set since ip_forward would have sent
+        * icmp error.
+        */
+       return skb_gso_network_seglen(skb) > mtu;
+}
+
+/* called if GSO skb needs to be fragmented on forward */
+static int ip_forward_finish_gso(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb_dst(skb);
+       netdev_features_t features;
+       struct sk_buff *segs;
+       int ret = 0;
+
+       features = netif_skb_dev_features(skb, dst->dev);
+       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+       if (IS_ERR(segs)) {
+               kfree_skb(skb);
+               return -ENOMEM;
+       }
+
+       consume_skb(skb);
+
+       do {
+               struct sk_buff *nskb = segs->next;
+               int err;
+
+               segs->next = NULL;
+               err = dst_output(segs);
+
+               if (err && ret == 0)
+                       ret = err;
+               segs = nskb;
+       } while (segs);
+
+       return ret;
+}
+
 static int ip_forward_finish(struct sk_buff *skb)
 {
        struct ip_options *opt  = &(IPCB(skb)->opt);
@@ -49,6 +114,9 @@ static int ip_forward_finish(struct sk_buff *skb)
        if (unlikely(opt->optlen))
                ip_forward_options(skb);
 
+       if (ip_gso_exceeds_dst_mtu(skb))
+               return ip_forward_finish_gso(skb);
+
        return dst_output(skb);
 }
 
@@ -91,8 +159,7 @@ int ip_forward(struct sk_buff *skb)
 
        IPCB(skb)->flags |= IPSKB_FORWARDED;
        mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
-       if (unlikely(skb->len > mtu && !skb_is_gso(skb) &&
-                    (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
+       if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) {
                IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
                          htonl(mtu));
index 8971780aec7c5fadb4223c0391b05aa9c881ba34..73c6b63bba74e57b70589ff548fccf0db79cc9a4 100644 (file)
@@ -422,9 +422,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        to->tc_index = from->tc_index;
 #endif
        nf_copy(to, from);
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
-       to->nf_trace = from->nf_trace;
-#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
        to->ipvs_property = from->ipvs_property;
 #endif
index bd28f386bd02020ef3adc4295a90021d6d43a0f7..a82a22d8f77fdca5f496e9d7cb45f40b70d194ca 100644 (file)
@@ -93,83 +93,32 @@ static void tunnel_dst_reset(struct ip_tunnel *t)
        tunnel_dst_set(t, NULL);
 }
 
-static void tunnel_dst_reset_all(struct ip_tunnel *t)
+void ip_tunnel_dst_reset_all(struct ip_tunnel *t)
 {
        int i;
 
        for_each_possible_cpu(i)
                __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL);
 }
+EXPORT_SYMBOL(ip_tunnel_dst_reset_all);
 
-static struct dst_entry *tunnel_dst_get(struct ip_tunnel *t)
+static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie)
 {
        struct dst_entry *dst;
 
        rcu_read_lock();
        dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst);
-       if (dst)
+       if (dst) {
+               if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
+                       rcu_read_unlock();
+                       tunnel_dst_reset(t);
+                       return NULL;
+               }
                dst_hold(dst);
-       rcu_read_unlock();
-       return dst;
-}
-
-static struct dst_entry *tunnel_dst_check(struct ip_tunnel *t, u32 cookie)
-{
-       struct dst_entry *dst = tunnel_dst_get(t);
-
-       if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
-               tunnel_dst_reset(t);
-               return NULL;
        }
-
-       return dst;
-}
-
-/* Often modified stats are per cpu, other are shared (netdev->stats) */
-struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
-                                               struct rtnl_link_stats64 *tot)
-{
-       int i;
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_sw_netstats *tstats =
-                                                  per_cpu_ptr(dev->tstats, i);
-               u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
-               unsigned int start;
-
-               do {
-                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
-                       rx_packets = tstats->rx_packets;
-                       tx_packets = tstats->tx_packets;
-                       rx_bytes = tstats->rx_bytes;
-                       tx_bytes = tstats->tx_bytes;
-               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
-
-               tot->rx_packets += rx_packets;
-               tot->tx_packets += tx_packets;
-               tot->rx_bytes   += rx_bytes;
-               tot->tx_bytes   += tx_bytes;
-       }
-
-       tot->multicast = dev->stats.multicast;
-
-       tot->rx_crc_errors = dev->stats.rx_crc_errors;
-       tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
-       tot->rx_length_errors = dev->stats.rx_length_errors;
-       tot->rx_frame_errors = dev->stats.rx_frame_errors;
-       tot->rx_errors = dev->stats.rx_errors;
-
-       tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
-       tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
-       tot->tx_dropped = dev->stats.tx_dropped;
-       tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
-       tot->tx_errors = dev->stats.tx_errors;
-
-       tot->collisions  = dev->stats.collisions;
-
-       return tot;
+       rcu_read_unlock();
+       return (struct rtable *)dst;
 }
-EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
 
 static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
                                __be16 flags, __be32 key)
@@ -467,9 +416,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
 
 #ifdef CONFIG_NET_IPGRE_BROADCAST
        if (ipv4_is_multicast(iph->daddr)) {
-               /* Looped back packet, drop it! */
-               if (rt_is_output_route(skb_rtable(skb)))
-                       goto drop;
                tunnel->dev->stats.multicast++;
                skb->pkt_type = PACKET_BROADCAST;
        }
@@ -584,7 +530,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        struct flowi4 fl4;
        u8     tos, ttl;
        __be16 df;
-       struct rtable *rt = NULL;       /* Route to the other host */
+       struct rtable *rt;              /* Route to the other host */
        unsigned int max_headroom;      /* The extra header space needed */
        __be32 dst;
        int err;
@@ -657,8 +603,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
                         tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);
 
-       if (connected)
-               rt = (struct rtable *)tunnel_dst_check(tunnel, 0);
+       rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL;
 
        if (!rt) {
                rt = ip_route_output_key(tunnel->net, &fl4);
@@ -766,7 +711,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
                if (set_mtu)
                        dev->mtu = mtu;
        }
-       tunnel_dst_reset_all(t);
+       ip_tunnel_dst_reset_all(t);
        netdev_state_change(dev);
 }
 
@@ -1095,7 +1040,7 @@ void ip_tunnel_uninit(struct net_device *dev)
        if (itn->fb_tunnel_dev != dev)
                ip_tunnel_del(netdev_priv(dev));
 
-       tunnel_dst_reset_all(tunnel);
+       ip_tunnel_dst_reset_all(tunnel);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_uninit);
 
index 6156f4ef5e919ccdc470f8cdb5a27593dedbe2c3..8d69626f2206900dfbb336063034875743a3936e 100644 (file)
@@ -148,3 +148,49 @@ error:
        return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+
+/* Often modified stats are per cpu, other are shared (netdev->stats) */
+struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
+                                               struct rtnl_link_stats64 *tot)
+{
+       int i;
+
+       for_each_possible_cpu(i) {
+               const struct pcpu_sw_netstats *tstats =
+                                                  per_cpu_ptr(dev->tstats, i);
+               u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+               unsigned int start;
+
+               do {
+                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
+                       rx_packets = tstats->rx_packets;
+                       tx_packets = tstats->tx_packets;
+                       rx_bytes = tstats->rx_bytes;
+                       tx_bytes = tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+               tot->rx_packets += rx_packets;
+               tot->tx_packets += tx_packets;
+               tot->rx_bytes   += rx_bytes;
+               tot->tx_bytes   += tx_bytes;
+       }
+
+       tot->multicast = dev->stats.multicast;
+
+       tot->rx_crc_errors = dev->stats.rx_crc_errors;
+       tot->rx_fifo_errors = dev->stats.rx_fifo_errors;
+       tot->rx_length_errors = dev->stats.rx_length_errors;
+       tot->rx_frame_errors = dev->stats.rx_frame_errors;
+       tot->rx_errors = dev->stats.rx_errors;
+
+       tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
+       tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
+       tot->tx_dropped = dev->stats.tx_dropped;
+       tot->tx_aborted_errors = dev->stats.tx_aborted_errors;
+       tot->tx_errors = dev->stats.tx_errors;
+
+       tot->collisions  = dev->stats.collisions;
+
+       return tot;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
index efa1138fa523be1ed228b66accbfa9ed75920265..b3e86ea7b71b7e480ce64d243e3c1951484a7cbb 100644 (file)
@@ -273,7 +273,7 @@ static int __init ic_open_devs(void)
 
                msleep(1);
 
-               if time_before(jiffies, next_msg)
+               if (time_before(jiffies, next_msg))
                        continue;
 
                elapsed = jiffies_to_msecs(jiffies - start);
index b9b3472975ba31a646502dcd8c76046869be4e98..28863570dd60557ca27d8c73c7590b926c7dcf57 100644 (file)
@@ -2255,13 +2255,14 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
 }
 
 static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
-                           u32 portid, u32 seq, struct mfc_cache *c, int cmd)
+                           u32 portid, u32 seq, struct mfc_cache *c, int cmd,
+                           int flags)
 {
        struct nlmsghdr *nlh;
        struct rtmsg *rtm;
        int err;
 
-       nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
        if (nlh == NULL)
                return -EMSGSIZE;
 
@@ -2329,7 +2330,7 @@ static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
        if (skb == NULL)
                goto errout;
 
-       err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+       err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
        if (err < 0)
                goto errout;
 
@@ -2368,7 +2369,8 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
                                if (ipmr_fill_mroute(mrt, skb,
                                                     NETLINK_CB(cb->skb).portid,
                                                     cb->nlh->nlmsg_seq,
-                                                    mfc, RTM_NEWROUTE) < 0)
+                                                    mfc, RTM_NEWROUTE,
+                                                    NLM_F_MULTI) < 0)
                                        goto done;
 next_entry:
                                e++;
@@ -2382,7 +2384,8 @@ next_entry:
                        if (ipmr_fill_mroute(mrt, skb,
                                             NETLINK_CB(cb->skb).portid,
                                             cb->nlh->nlmsg_seq,
-                                            mfc, RTM_NEWROUTE) < 0) {
+                                            mfc, RTM_NEWROUTE,
+                                            NLM_F_MULTI) < 0) {
                                spin_unlock_bh(&mfc_unres_lock);
                                goto done;
                        }
index 81c6910cfa925b315c8efda5e3d79af817c82c88..a26ce035e3fad076a1d76fae0c377771300c7a04 100644 (file)
@@ -61,6 +61,11 @@ config NFT_CHAIN_NAT_IPV4
          packet transformations such as the source, destination address and
          source and destination ports.
 
+config NFT_REJECT_IPV4
+       depends on NF_TABLES_IPV4
+       default NFT_REJECT
+       tristate
+
 config NF_TABLES_ARP
        depends on NF_TABLES
        tristate "ARP nf_tables support"
index c16be9d58420dad15b4218ec119b34d184a7ea7e..90b82405331e1736c8bb4f0d4cacfd3c8fd4e783 100644 (file)
@@ -30,6 +30,7 @@ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
 obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
+obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
 obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
 
 # generic IP tables 
index 9eea059dd6216225950428819104bfcae77d10ba..574f7ebba0b6238d8e61ffd08dead06a07a619c5 100644 (file)
@@ -229,7 +229,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
                        ret = nf_ct_expect_related(rtcp_exp);
                        if (ret == 0)
                                break;
-                       else if (ret != -EBUSY) {
+                       else if (ret == -EBUSY) {
+                               nf_ct_unexpect_related(rtp_exp);
+                               continue;
+                       } else if (ret < 0) {
                                nf_ct_unexpect_related(rtp_exp);
                                nated_port = 0;
                                break;
index d551e31b416e02e728a433293d25317e9c930dcb..7c676671329d9432eb2392f6b4fc649ebcdae97f 100644 (file)
@@ -1198,8 +1198,8 @@ static int snmp_translate(struct nf_conn *ct,
                map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
        } else {
                /* DNAT replies */
-               map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
-               map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
+               map.from = NOCT1(&ct->tuplehash[!dir].tuple.src.u3.ip);
+               map.to = NOCT1(&ct->tuplehash[dir].tuple.dst.u3.ip);
        }
 
        if (map.from == map.to)
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
new file mode 100644 (file)
index 0000000..e79718a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * 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.
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/icmp.h>
+#include <net/netfilter/ipv4/nf_reject.h>
+#include <net/netfilter/nft_reject.h>
+
+void nft_reject_ipv4_eval(const struct nft_expr *expr,
+                         struct nft_data data[NFT_REG_MAX + 1],
+                         const struct nft_pktinfo *pkt)
+{
+       struct nft_reject *priv = nft_expr_priv(expr);
+
+       switch (priv->type) {
+       case NFT_REJECT_ICMP_UNREACH:
+               nf_send_unreach(pkt->skb, priv->icmp_code);
+               break;
+       case NFT_REJECT_TCP_RST:
+               nf_send_reset(pkt->skb, pkt->ops->hooknum);
+               break;
+       }
+
+       data[NFT_REG_VERDICT].verdict = NF_DROP;
+}
+EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval);
+
+static struct nft_expr_type nft_reject_ipv4_type;
+static const struct nft_expr_ops nft_reject_ipv4_ops = {
+       .type           = &nft_reject_ipv4_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
+       .eval           = nft_reject_ipv4_eval,
+       .init           = nft_reject_init,
+       .dump           = nft_reject_dump,
+};
+
+static struct nft_expr_type nft_reject_ipv4_type __read_mostly = {
+       .family         = NFPROTO_IPV4,
+       .name           = "reject",
+       .ops            = &nft_reject_ipv4_ops,
+       .policy         = nft_reject_policy,
+       .maxattr        = NFTA_REJECT_MAX,
+       .owner          = THIS_MODULE,
+};
+
+static int __init nft_reject_ipv4_module_init(void)
+{
+       return nft_register_expr(&nft_reject_ipv4_type);
+}
+
+static void __exit nft_reject_ipv4_module_exit(void)
+{
+       nft_unregister_expr(&nft_reject_ipv4_type);
+}
+
+module_init(nft_reject_ipv4_module_init);
+module_exit(nft_reject_ipv4_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "reject");
index 25071b48921cebc4788a1f4b0b5fa118832f5910..4c011ec69ed43efacdf692592a849d691ca93d2d 100644 (file)
@@ -1597,6 +1597,7 @@ static int __mkroute_input(struct sk_buff *skb,
        rth->rt_gateway = 0;
        rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
+       RT_CACHE_STAT_INC(in_slow_tot);
 
        rth->dst.input = ip_forward;
        rth->dst.output = ip_output;
@@ -1695,10 +1696,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        err = fib_lookup(net, &fl4, &res);
-       if (err != 0)
+       if (err != 0) {
+               if (!IN_DEV_FORWARD(in_dev))
+                       err = -EHOSTUNREACH;
                goto no_route;
-
-       RT_CACHE_STAT_INC(in_slow_tot);
+       }
 
        if (res.type == RTN_BROADCAST)
                goto brd_input;
@@ -1712,8 +1714,10 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                goto local_input;
        }
 
-       if (!IN_DEV_FORWARD(in_dev))
+       if (!IN_DEV_FORWARD(in_dev)) {
+               err = -EHOSTUNREACH;
                goto no_route;
+       }
        if (res.type != RTN_UNICAST)
                goto martian_destination;
 
@@ -1768,6 +1772,7 @@ local_input:
        rth->rt_gateway = 0;
        rth->rt_uses_gateway = 0;
        INIT_LIST_HEAD(&rth->rt_uncached);
+       RT_CACHE_STAT_INC(in_slow_tot);
        if (res.type == RTN_UNREACHABLE) {
                rth->dst.input= ip_error;
                rth->dst.error= -err;
index 4475b3bb494d5d126dd844b0159629cd672afbdc..97c8f5620c430930c0b9c7958db079a968bd807b 100644 (file)
@@ -1044,7 +1044,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp)
        }
 }
 
-static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
+static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
+                               int *copied, size_t size)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        int err, flags;
@@ -1059,11 +1060,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
        if (unlikely(tp->fastopen_req == NULL))
                return -ENOBUFS;
        tp->fastopen_req->data = msg;
+       tp->fastopen_req->size = size;
 
        flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
        err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
                                    msg->msg_namelen, flags);
-       *size = tp->fastopen_req->copied;
+       *copied = tp->fastopen_req->copied;
        tcp_free_fastopen_req(tp);
        return err;
 }
@@ -1083,7 +1085,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        flags = msg->msg_flags;
        if (flags & MSG_FASTOPEN) {
-               err = tcp_sendmsg_fastopen(sk, msg, &copied_syn);
+               err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
                if (err == -EINPROGRESS && copied_syn > 0)
                        goto out;
                else if (err)
@@ -2229,7 +2231,7 @@ adjudge_to_death:
        /*      This is a (useful) BSD violating of the RFC. There is a
         *      problem with TCP as specified in that the other end could
         *      keep a socket open forever with no application left this end.
-        *      We use a 3 minute timeout (about the same as BSD) then kill
+        *      We use a 1 minute timeout (about the same as BSD) then kill
         *      our end. If they send after that then tough - BUT: long enough
         *      that we won't make the old 4*rto = almost no time - whoops
         *      reset mistake.
index ad37bf18ae4b95a6870a8019ecc3ca9ff55d7679..2388275adb9bd0fcfb8ea7a97a22ac661b4df745 100644 (file)
@@ -290,8 +290,7 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
        left = tp->snd_cwnd - in_flight;
        if (sk_can_gso(sk) &&
            left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd &&
-           left * tp->mss_cache < sk->sk_gso_max_size &&
-           left < sk->sk_gso_max_segs)
+           left < tp->xmit_size_goal_segs)
                return true;
        return left <= tcp_max_tso_deferred_mss(tp);
 }
index 65cf90e063d5adcc98f15b044e35b20e1668352a..eeaac399420de043bb466603fcb03ff83076438a 100644 (file)
@@ -671,6 +671,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        long m = mrtt; /* RTT */
+       u32 srtt = tp->srtt;
 
        /*      The following amusing code comes from Jacobson's
         *      article in SIGCOMM '88.  Note that rtt and mdev
@@ -688,11 +689,9 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
         * does not matter how to _calculate_ it. Seems, it was trap
         * that VJ failed to avoid. 8)
         */
-       if (m == 0)
-               m = 1;
-       if (tp->srtt != 0) {
-               m -= (tp->srtt >> 3);   /* m is now error in rtt est */
-               tp->srtt += m;          /* rtt = 7/8 rtt + 1/8 new */
+       if (srtt != 0) {
+               m -= (srtt >> 3);       /* m is now error in rtt est */
+               srtt += m;              /* rtt = 7/8 rtt + 1/8 new */
                if (m < 0) {
                        m = -m;         /* m is now abs(error) */
                        m -= (tp->mdev >> 2);   /* similar update on mdev */
@@ -723,11 +722,12 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
                }
        } else {
                /* no previous measure. */
-               tp->srtt = m << 3;      /* take the measured time to be rtt */
+               srtt = m << 3;          /* take the measured time to be rtt */
                tp->mdev = m << 1;      /* make sure rto = 3*rtt */
                tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
                tp->rtt_seq = tp->snd_nxt;
        }
+       tp->srtt = max(1U, srtt);
 }
 
 /* Set the sk_pacing_rate to allow proper sizing of TSO packets.
@@ -746,8 +746,10 @@ static void tcp_update_pacing_rate(struct sock *sk)
 
        rate *= max(tp->snd_cwnd, tp->packets_out);
 
-       /* Correction for small srtt : minimum srtt being 8 (1 jiffy << 3),
-        * be conservative and assume srtt = 1 (125 us instead of 1.25 ms)
+       /* Correction for small srtt and scheduling constraints.
+        * For small rtt, consider noise is too high, and use
+        * the minimal value (srtt = 1 -> 125 us for HZ=1000)
+        *
         * We probably need usec resolution in the future.
         * Note: This also takes care of possible srtt=0 case,
         * when tcp_rtt_estimator() was not yet called.
@@ -1943,8 +1945,9 @@ void tcp_enter_loss(struct sock *sk, int how)
                if (skb == tcp_send_head(sk))
                        break;
 
-               if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
+               if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
                        tp->undo_marker = 0;
+
                TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
                if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) {
                        TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
index 3cf9765104978cbf8ed49d184f926f23130cd4fd..1e4eac779f51c81bf5472d13ed446fefb0827753 100644 (file)
@@ -2628,7 +2628,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw,
 {
        __be32 dest, src;
        __u16 destp, srcp;
-       long delta = tw->tw_ttd - jiffies;
+       s32 delta = tw->tw_ttd - inet_tw_time_stamp();
 
        dest  = tw->tw_daddr;
        src   = tw->tw_rcv_saddr;
index 03d26b85eab8520c552040f527d37323be91bd68..17a11e65e57fea3fa3728ce905df6130c580c48a 100644 (file)
@@ -698,7 +698,8 @@ static void tcp_tsq_handler(struct sock *sk)
        if ((1 << sk->sk_state) &
            (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_CLOSING |
             TCPF_CLOSE_WAIT  | TCPF_LAST_ACK))
-               tcp_write_xmit(sk, tcp_current_mss(sk), 0, 0, GFP_ATOMIC);
+               tcp_write_xmit(sk, tcp_current_mss(sk), tcp_sk(sk)->nonagle,
+                              0, GFP_ATOMIC);
 }
 /*
  * One tasklet per cpu tries to send more skbs.
@@ -766,6 +767,17 @@ void tcp_release_cb(struct sock *sk)
        if (flags & (1UL << TCP_TSQ_DEFERRED))
                tcp_tsq_handler(sk);
 
+       /* Here begins the tricky part :
+        * We are called from release_sock() with :
+        * 1) BH disabled
+        * 2) sk_lock.slock spinlock held
+        * 3) socket owned by us (sk->sk_lock.owned == 1)
+        *
+        * But following code is meant to be called from BH handlers,
+        * so we should keep BH disabled, but early release socket ownership
+        */
+       sock_release_ownership(sk);
+
        if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) {
                tcp_write_timer_handler(sk);
                __sock_put(sk);
@@ -863,8 +875,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
 
                if (unlikely(skb->fclone == SKB_FCLONE_ORIG &&
                             fclone->fclone == SKB_FCLONE_CLONE))
-                       NET_INC_STATS_BH(sock_net(sk),
-                                        LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
+                       NET_INC_STATS(sock_net(sk),
+                                     LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
 
                if (unlikely(skb_cloned(skb)))
                        skb = pskb_copy(skb, gfp_mask);
@@ -1904,7 +1916,15 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 
                if (atomic_read(&sk->sk_wmem_alloc) > limit) {
                        set_bit(TSQ_THROTTLED, &tp->tsq_flags);
-                       break;
+                       /* It is possible TX completion already happened
+                        * before we set TSQ_THROTTLED, so we must
+                        * test again the condition.
+                        * We abuse smp_mb__after_clear_bit() because
+                        * there is no smp_mb__after_set_bit() yet
+                        */
+                       smp_mb__after_clear_bit();
+                       if (atomic_read(&sk->sk_wmem_alloc) > limit)
+                               break;
                }
 
                limit = mss_now;
@@ -1977,7 +1997,7 @@ bool tcp_schedule_loss_probe(struct sock *sk)
        /* Schedule a loss probe in 2*RTT for SACK capable connections
         * in Open state, that are either limited by cwnd or application.
         */
-       if (sysctl_tcp_early_retrans < 3 || !rtt || !tp->packets_out ||
+       if (sysctl_tcp_early_retrans < 3 || !tp->srtt || !tp->packets_out ||
            !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open)
                return false;
 
@@ -2328,6 +2348,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
        struct tcp_sock *tp = tcp_sk(sk);
        struct inet_connection_sock *icsk = inet_csk(sk);
        unsigned int cur_mss;
+       int err;
 
        /* Inconslusive MTU probe */
        if (icsk->icsk_mtup.probe_size) {
@@ -2391,11 +2412,15 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
                     skb_headroom(skb) >= 0xFFFF)) {
                struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
                                                   GFP_ATOMIC);
-               return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
-                             -ENOBUFS;
+               err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
+                            -ENOBUFS;
        } else {
-               return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
+               err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
        }
+
+       if (likely(!err))
+               TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS;
+       return err;
 }
 
 int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
@@ -2899,7 +2924,12 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
        space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
                MAX_TCP_OPTION_SPACE;
 
-       syn_data = skb_copy_expand(syn, skb_headroom(syn), space,
+       space = min_t(size_t, space, fo->size);
+
+       /* limit to order-0 allocations */
+       space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER));
+
+       syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space,
                                   sk->sk_allocation);
        if (syn_data == NULL)
                goto fallback;
index 25f5cee3a08a3ea22f2b30ef15809da73af44f08..88b4023ecfcfc85df907ff7472354084b3b16264 100644 (file)
@@ -17,6 +17,8 @@
 static DEFINE_SPINLOCK(udp_offload_lock);
 static struct udp_offload_priv __rcu *udp_offload_base __read_mostly;
 
+#define udp_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&udp_offload_lock))
+
 struct udp_offload_priv {
        struct udp_offload      *offload;
        struct rcu_head         rcu;
@@ -100,8 +102,7 @@ out:
 
 int udp_add_offload(struct udp_offload *uo)
 {
-       struct udp_offload_priv __rcu **head = &udp_offload_base;
-       struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_KERNEL);
+       struct udp_offload_priv *new_offload = kzalloc(sizeof(*new_offload), GFP_ATOMIC);
 
        if (!new_offload)
                return -ENOMEM;
@@ -109,8 +110,8 @@ int udp_add_offload(struct udp_offload *uo)
        new_offload->offload = uo;
 
        spin_lock(&udp_offload_lock);
-       rcu_assign_pointer(new_offload->next, rcu_dereference(*head));
-       rcu_assign_pointer(*head, new_offload);
+       new_offload->next = udp_offload_base;
+       rcu_assign_pointer(udp_offload_base, new_offload);
        spin_unlock(&udp_offload_lock);
 
        return 0;
@@ -130,12 +131,12 @@ void udp_del_offload(struct udp_offload *uo)
 
        spin_lock(&udp_offload_lock);
 
-       uo_priv = rcu_dereference(*head);
+       uo_priv = udp_deref_protected(*head);
        for (; uo_priv != NULL;
-               uo_priv = rcu_dereference(*head)) {
-
+            uo_priv = udp_deref_protected(*head)) {
                if (uo_priv->offload == uo) {
-                       rcu_assign_pointer(*head, rcu_dereference(uo_priv->next));
+                       rcu_assign_pointer(*head,
+                                          udp_deref_protected(uo_priv->next));
                        goto unlock;
                }
                head = &uo_priv->next;
index d92e5586783e518c1f5db2b1bd3261766ff7a913..438a73aa777cf560f38a87801b03b8ce20a315b1 100644 (file)
@@ -138,6 +138,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
 config IPV6_VTI
 tristate "Virtual (secure) IPv6: tunneling"
        select IPV6_TUNNEL
+       select NET_IP_TUNNEL
        depends on INET6_XFRM_MODE_TUNNEL
        ---help---
        Tunneling means encapsulating data of one protocol type within
index ad235690684c97f873e0c24b774d5184055fe7e2..6c7fa0853fc74ef179b00de52d78aecee342e18b 100644 (file)
@@ -133,10 +133,12 @@ static int ipv6_count_addresses(struct inet6_dev *idev);
 static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE];
 static DEFINE_SPINLOCK(addrconf_hash_lock);
 
-static void addrconf_verify(unsigned long);
+static void addrconf_verify(void);
+static void addrconf_verify_rtnl(void);
+static void addrconf_verify_work(struct work_struct *);
 
-static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
-static DEFINE_SPINLOCK(addrconf_verify_lock);
+static struct workqueue_struct *addrconf_wq;
+static DECLARE_DELAYED_WORK(addr_chk_work, addrconf_verify_work);
 
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
@@ -151,7 +153,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
                                                  u32 flags, u32 noflags);
 
 static void addrconf_dad_start(struct inet6_ifaddr *ifp);
-static void addrconf_dad_timer(unsigned long data);
+static void addrconf_dad_work(struct work_struct *w);
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
 static void addrconf_dad_run(struct inet6_dev *idev);
 static void addrconf_rs_timer(unsigned long data);
@@ -247,9 +249,9 @@ static void addrconf_del_rs_timer(struct inet6_dev *idev)
                __in6_dev_put(idev);
 }
 
-static void addrconf_del_dad_timer(struct inet6_ifaddr *ifp)
+static void addrconf_del_dad_work(struct inet6_ifaddr *ifp)
 {
-       if (del_timer(&ifp->dad_timer))
+       if (cancel_delayed_work(&ifp->dad_work))
                __in6_ifa_put(ifp);
 }
 
@@ -261,12 +263,12 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev,
        mod_timer(&idev->rs_timer, jiffies + when);
 }
 
-static void addrconf_mod_dad_timer(struct inet6_ifaddr *ifp,
-                                  unsigned long when)
+static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
+                                  unsigned long delay)
 {
-       if (!timer_pending(&ifp->dad_timer))
+       if (!delayed_work_pending(&ifp->dad_work))
                in6_ifa_hold(ifp);
-       mod_timer(&ifp->dad_timer, jiffies + when);
+       mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
 }
 
 static int snmp6_alloc_dev(struct inet6_dev *idev)
@@ -751,8 +753,9 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
 
        in6_dev_put(ifp->idev);
 
-       if (del_timer(&ifp->dad_timer))
-               pr_notice("Timer is still running, when freeing ifa=%p\n", ifp);
+       if (cancel_delayed_work(&ifp->dad_work))
+               pr_notice("delayed DAD work was pending while freeing ifa=%p\n",
+                         ifp);
 
        if (ifp->state != INET6_IFADDR_STATE_DEAD) {
                pr_warn("Freeing alive inet6 address %p\n", ifp);
@@ -849,8 +852,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
 
        spin_lock_init(&ifa->lock);
        spin_lock_init(&ifa->state_lock);
-       setup_timer(&ifa->dad_timer, addrconf_dad_timer,
-                   (unsigned long)ifa);
+       INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work);
        INIT_HLIST_NODE(&ifa->addr_lst);
        ifa->scope = scope;
        ifa->prefix_len = pfxlen;
@@ -990,6 +992,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
        enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP;
        unsigned long expires;
 
+       ASSERT_RTNL();
+
        spin_lock_bh(&ifp->state_lock);
        state = ifp->state;
        ifp->state = INET6_IFADDR_STATE_DEAD;
@@ -1021,7 +1025,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 
        write_unlock_bh(&ifp->idev->lock);
 
-       addrconf_del_dad_timer(ifp);
+       addrconf_del_dad_work(ifp);
 
        ipv6_ifa_notify(RTM_DELADDR, ifp);
 
@@ -1103,8 +1107,11 @@ retry:
         * Lifetime is greater than REGEN_ADVANCE time units.  In particular,
         * an implementation must not create a temporary address with a zero
         * Preferred Lifetime.
+        * Use age calculation as in addrconf_verify to avoid unnecessary
+        * temporary addresses being generated.
         */
-       if (tmp_prefered_lft <= regen_advance) {
+       age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
+       if (tmp_prefered_lft <= regen_advance + age) {
                in6_ifa_put(ifp);
                in6_dev_put(idev);
                ret = -1;
@@ -1601,7 +1608,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
 {
        if (ifp->flags&IFA_F_PERMANENT) {
                spin_lock_bh(&ifp->lock);
-               addrconf_del_dad_timer(ifp);
+               addrconf_del_dad_work(ifp);
                ifp->flags |= IFA_F_TENTATIVE;
                if (dad_failed)
                        ifp->flags |= IFA_F_DADFAILED;
@@ -1622,20 +1629,21 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed)
                        spin_unlock_bh(&ifp->lock);
                }
                ipv6_del_addr(ifp);
-       } else
+       } else {
                ipv6_del_addr(ifp);
+       }
 }
 
 static int addrconf_dad_end(struct inet6_ifaddr *ifp)
 {
        int err = -ENOENT;
 
-       spin_lock(&ifp->state_lock);
+       spin_lock_bh(&ifp->state_lock);
        if (ifp->state == INET6_IFADDR_STATE_DAD) {
                ifp->state = INET6_IFADDR_STATE_POSTDAD;
                err = 0;
        }
-       spin_unlock(&ifp->state_lock);
+       spin_unlock_bh(&ifp->state_lock);
 
        return err;
 }
@@ -1668,7 +1676,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
                }
        }
 
-       addrconf_dad_stop(ifp, 1);
+       spin_lock_bh(&ifp->state_lock);
+       /* transition from _POSTDAD to _ERRDAD */
+       ifp->state = INET6_IFADDR_STATE_ERRDAD;
+       spin_unlock_bh(&ifp->state_lock);
+
+       addrconf_mod_dad_work(ifp, 0);
 }
 
 /* Join to solicited addr multicast group. */
@@ -1677,6 +1690,8 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr)
 {
        struct in6_addr maddr;
 
+       ASSERT_RTNL();
+
        if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
                return;
 
@@ -1688,6 +1703,8 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 {
        struct in6_addr maddr;
 
+       ASSERT_RTNL();
+
        if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
                return;
 
@@ -1698,6 +1715,9 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
+
+       ASSERT_RTNL();
+
        if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
@@ -1709,6 +1729,9 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
+
+       ASSERT_RTNL();
+
        if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
@@ -2268,11 +2291,13 @@ ok:
                                return;
                        }
 
-                       ifp->flags |= IFA_F_MANAGETEMPADDR;
                        update_lft = 0;
                        create = 1;
+                       spin_lock_bh(&ifp->lock);
+                       ifp->flags |= IFA_F_MANAGETEMPADDR;
                        ifp->cstamp = jiffies;
                        ifp->tokenized = tokenized;
+                       spin_unlock_bh(&ifp->lock);
                        addrconf_dad_start(ifp);
                }
 
@@ -2323,7 +2348,7 @@ ok:
                                         create, now);
 
                        in6_ifa_put(ifp);
-                       addrconf_verify(0);
+                       addrconf_verify();
                }
        }
        inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo);
@@ -2472,7 +2497,7 @@ static int inet6_addr_add(struct net *net, int ifindex,
                        manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
                                         true, jiffies);
                in6_ifa_put(ifp);
-               addrconf_verify(0);
+               addrconf_verify_rtnl();
                return 0;
        }
 
@@ -2783,6 +2808,8 @@ static void addrconf_gre_config(struct net_device *dev)
        ipv6_addr_set(&addr,  htonl(0xFE800000), 0, 0, 0);
        if (!ipv6_generate_eui64(addr.s6_addr + 8, dev))
                addrconf_add_linklocal(idev, &addr);
+       else
+               addrconf_prefix_route(&addr, 64, dev, 0, 0);
 }
 #endif
 
@@ -3006,7 +3033,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
                hlist_for_each_entry_rcu(ifa, h, addr_lst) {
                        if (ifa->idev == idev) {
                                hlist_del_init_rcu(&ifa->addr_lst);
-                               addrconf_del_dad_timer(ifa);
+                               addrconf_del_dad_work(ifa);
                                goto restart;
                        }
                }
@@ -3044,7 +3071,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
        while (!list_empty(&idev->addr_list)) {
                ifa = list_first_entry(&idev->addr_list,
                                       struct inet6_ifaddr, if_list);
-               addrconf_del_dad_timer(ifa);
+               addrconf_del_dad_work(ifa);
 
                list_del(&ifa->if_list);
 
@@ -3143,10 +3170,10 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
                rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
 
        ifp->dad_probes = idev->cnf.dad_transmits;
-       addrconf_mod_dad_timer(ifp, rand_num);
+       addrconf_mod_dad_work(ifp, rand_num);
 }
 
-static void addrconf_dad_start(struct inet6_ifaddr *ifp)
+static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
 {
        struct inet6_dev *idev = ifp->idev;
        struct net_device *dev = idev->dev;
@@ -3198,25 +3225,68 @@ out:
        read_unlock_bh(&idev->lock);
 }
 
-static void addrconf_dad_timer(unsigned long data)
+static void addrconf_dad_start(struct inet6_ifaddr *ifp)
+{
+       bool begin_dad = false;
+
+       spin_lock_bh(&ifp->state_lock);
+       if (ifp->state != INET6_IFADDR_STATE_DEAD) {
+               ifp->state = INET6_IFADDR_STATE_PREDAD;
+               begin_dad = true;
+       }
+       spin_unlock_bh(&ifp->state_lock);
+
+       if (begin_dad)
+               addrconf_mod_dad_work(ifp, 0);
+}
+
+static void addrconf_dad_work(struct work_struct *w)
 {
-       struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
+       struct inet6_ifaddr *ifp = container_of(to_delayed_work(w),
+                                               struct inet6_ifaddr,
+                                               dad_work);
        struct inet6_dev *idev = ifp->idev;
        struct in6_addr mcaddr;
 
+       enum {
+               DAD_PROCESS,
+               DAD_BEGIN,
+               DAD_ABORT,
+       } action = DAD_PROCESS;
+
+       rtnl_lock();
+
+       spin_lock_bh(&ifp->state_lock);
+       if (ifp->state == INET6_IFADDR_STATE_PREDAD) {
+               action = DAD_BEGIN;
+               ifp->state = INET6_IFADDR_STATE_DAD;
+       } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) {
+               action = DAD_ABORT;
+               ifp->state = INET6_IFADDR_STATE_POSTDAD;
+       }
+       spin_unlock_bh(&ifp->state_lock);
+
+       if (action == DAD_BEGIN) {
+               addrconf_dad_begin(ifp);
+               goto out;
+       } else if (action == DAD_ABORT) {
+               addrconf_dad_stop(ifp, 1);
+               goto out;
+       }
+
        if (!ifp->dad_probes && addrconf_dad_end(ifp))
                goto out;
 
-       write_lock(&idev->lock);
+       write_lock_bh(&idev->lock);
        if (idev->dead || !(idev->if_flags & IF_READY)) {
-               write_unlock(&idev->lock);
+               write_unlock_bh(&idev->lock);
                goto out;
        }
 
        spin_lock(&ifp->lock);
        if (ifp->state == INET6_IFADDR_STATE_DEAD) {
                spin_unlock(&ifp->lock);
-               write_unlock(&idev->lock);
+               write_unlock_bh(&idev->lock);
                goto out;
        }
 
@@ -3227,7 +3297,7 @@ static void addrconf_dad_timer(unsigned long data)
 
                ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
                spin_unlock(&ifp->lock);
-               write_unlock(&idev->lock);
+               write_unlock_bh(&idev->lock);
 
                addrconf_dad_completed(ifp);
 
@@ -3235,16 +3305,17 @@ static void addrconf_dad_timer(unsigned long data)
        }
 
        ifp->dad_probes--;
-       addrconf_mod_dad_timer(ifp,
-                              NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
+       addrconf_mod_dad_work(ifp,
+                             NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
        spin_unlock(&ifp->lock);
-       write_unlock(&idev->lock);
+       write_unlock_bh(&idev->lock);
 
        /* send a neighbour solicitation for our addr */
        addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
        ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any);
 out:
        in6_ifa_put(ifp);
+       rtnl_unlock();
 }
 
 /* ifp->idev must be at least read locked */
@@ -3271,7 +3342,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
        struct in6_addr lladdr;
        bool send_rs, send_mld;
 
-       addrconf_del_dad_timer(ifp);
+       addrconf_del_dad_work(ifp);
 
        /*
         *      Configure the address for reception. Now it is valid.
@@ -3512,23 +3583,23 @@ int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
  *     Periodic address status verification
  */
 
-static void addrconf_verify(unsigned long foo)
+static void addrconf_verify_rtnl(void)
 {
        unsigned long now, next, next_sec, next_sched;
        struct inet6_ifaddr *ifp;
        int i;
 
+       ASSERT_RTNL();
+
        rcu_read_lock_bh();
-       spin_lock(&addrconf_verify_lock);
        now = jiffies;
        next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
 
-       del_timer(&addr_chk_timer);
+       cancel_delayed_work(&addr_chk_work);
 
        for (i = 0; i < IN6_ADDR_HSIZE; i++) {
 restart:
-               hlist_for_each_entry_rcu_bh(ifp,
-                                        &inet6_addr_lst[i], addr_lst) {
+               hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[i], addr_lst) {
                        unsigned long age;
 
                        /* When setting preferred_lft to a value not zero or
@@ -3623,13 +3694,22 @@ restart:
 
        ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n",
              now, next, next_sec, next_sched);
-
-       addr_chk_timer.expires = next_sched;
-       add_timer(&addr_chk_timer);
-       spin_unlock(&addrconf_verify_lock);
+       mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now);
        rcu_read_unlock_bh();
 }
 
+static void addrconf_verify_work(struct work_struct *w)
+{
+       rtnl_lock();
+       addrconf_verify_rtnl();
+       rtnl_unlock();
+}
+
+static void addrconf_verify(void)
+{
+       mod_delayed_work(addrconf_wq, &addr_chk_work, 0);
+}
+
 static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local,
                                     struct in6_addr **peer_pfx)
 {
@@ -3686,6 +3766,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
        bool was_managetempaddr;
        bool had_prefixroute;
 
+       ASSERT_RTNL();
+
        if (!valid_lft || (prefered_lft > valid_lft))
                return -EINVAL;
 
@@ -3751,7 +3833,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
                                 !was_managetempaddr, jiffies);
        }
 
-       addrconf_verify(0);
+       addrconf_verify_rtnl();
 
        return 0;
 }
@@ -4381,6 +4463,8 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
        bool update_rs = false;
        struct in6_addr ll_addr;
 
+       ASSERT_RTNL();
+
        if (token == NULL)
                return -EINVAL;
        if (ipv6_addr_any(token))
@@ -4429,7 +4513,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
        }
 
        write_unlock_bh(&idev->lock);
-       addrconf_verify(0);
+       addrconf_verify_rtnl();
        return 0;
 }
 
@@ -4631,6 +4715,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 {
        struct net *net = dev_net(ifp->idev->dev);
 
+       if (event)
+               ASSERT_RTNL();
+
        inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
 
        switch (event) {
@@ -5239,6 +5326,12 @@ int __init addrconf_init(void)
        if (err < 0)
                goto out_addrlabel;
 
+       addrconf_wq = create_workqueue("ipv6_addrconf");
+       if (!addrconf_wq) {
+               err = -ENOMEM;
+               goto out_nowq;
+       }
+
        /* The addrconf netdev notifier requires that loopback_dev
         * has it's ipv6 private information allocated and setup
         * before it can bring up and give link-local addresses
@@ -5269,7 +5362,7 @@ int __init addrconf_init(void)
 
        register_netdevice_notifier(&ipv6_dev_notf);
 
-       addrconf_verify(0);
+       addrconf_verify();
 
        rtnl_af_register(&inet6_ops);
 
@@ -5297,6 +5390,8 @@ errout:
        rtnl_af_unregister(&inet6_ops);
        unregister_netdevice_notifier(&ipv6_dev_notf);
 errlo:
+       destroy_workqueue(addrconf_wq);
+out_nowq:
        unregister_pernet_subsys(&addrconf_ops);
 out_addrlabel:
        ipv6_addr_label_cleanup();
@@ -5332,7 +5427,8 @@ void addrconf_cleanup(void)
        for (i = 0; i < IN6_ADDR_HSIZE; i++)
                WARN_ON(!hlist_empty(&inet6_addr_lst[i]));
        spin_unlock_bh(&addrconf_hash_lock);
-
-       del_timer(&addr_chk_timer);
+       cancel_delayed_work(&addr_chk_work);
        rtnl_unlock();
+
+       destroy_workqueue(addrconf_wq);
 }
index 140748debc4ade194e5e179636e94264da7e65a1..8af3eb57f4380fd7de7497ff98f40c88f2040e50 100644 (file)
@@ -212,7 +212,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                found = (nexthdr == target);
 
                if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
-                       if (target < 0)
+                       if (target < 0 || found)
                                break;
                        return -ENOENT;
                }
index cf77f3abfd061280f6a211deb4a24bcd247c944a..447a7fbd1bb6f28dc78203ef4f4254705dc68c99 100644 (file)
@@ -25,11 +25,11 @@ int __init ipv6_exthdrs_offload_init(void)
        int ret;
 
        ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING);
-       if (!ret)
+       if (ret)
                goto out;
 
        ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS);
-       if (!ret)
+       if (ret)
                goto out_rt;
 
 out:
index f81f59686f21b222047793f0c72c99ce3ceaa82d..f2610e15766027ce3a7408862d03f4c427c555ea 100644 (file)
@@ -414,7 +414,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        addr_type = ipv6_addr_type(&hdr->daddr);
 
        if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) ||
-           ipv6_anycast_destination(skb))
+           ipv6_chk_acast_addr_src(net, skb->dev, &hdr->daddr))
                saddr = &hdr->daddr;
 
        /*
index 1e8683b135bb7b503d9ab97d5c3c165af2453fa1..59f95affceb0773d052184bdf5fec9f276433d63 100644 (file)
@@ -89,7 +89,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        unsigned int unfrag_ip6hlen;
        u8 *prevhdr;
        int offset = 0;
-       bool tunnel;
+       bool encap, udpfrag;
        int nhoff;
 
        if (unlikely(skb_shinfo(skb)->gso_type &
@@ -110,8 +110,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
                goto out;
 
-       tunnel = SKB_GSO_CB(skb)->encap_level > 0;
-       if (tunnel)
+       encap = SKB_GSO_CB(skb)->encap_level > 0;
+       if (encap)
                features = skb->dev->hw_enc_features & netif_skb_features(skb);
        SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h);
 
@@ -121,6 +121,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 
        proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
 
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
+               udpfrag = proto == IPPROTO_UDP && encap;
+       else
+               udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
+
        ops = rcu_dereference(inet6_offloads[proto]);
        if (likely(ops && ops->callbacks.gso_segment)) {
                skb_reset_transport_header(skb);
@@ -133,13 +139,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        for (skb = segs; skb; skb = skb->next) {
                ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff);
                ipv6h->payload_len = htons(skb->len - nhoff - sizeof(*ipv6h));
-               if (tunnel) {
-                       skb_reset_inner_headers(skb);
-                       skb->encapsulation = 1;
-               }
                skb->network_header = (u8 *)ipv6h - skb->head;
 
-               if (!tunnel && proto == IPPROTO_UDP) {
+               if (udpfrag) {
                        unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
                        fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
                        fptr->frag_off = htons(offset);
@@ -148,6 +150,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
                        offset += (ntohs(ipv6h->payload_len) -
                                   sizeof(struct frag_hdr));
                }
+               if (encap)
+                       skb_reset_inner_headers(skb);
        }
 
 out:
index ef02b26ccf812e57e794e9b151746600bcb9a8f0..64d6073731d368e54073f9ca97ac6ad0cecdd415 100644 (file)
@@ -342,6 +342,20 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
        return mtu;
 }
 
+static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
+{
+       if (skb->len <= mtu || skb->local_df)
+               return false;
+
+       if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)
+               return true;
+
+       if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+               return false;
+
+       return true;
+}
+
 int ip6_forward(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
@@ -466,8 +480,7 @@ int ip6_forward(struct sk_buff *skb)
        if (mtu < IPV6_MIN_MTU)
                mtu = IPV6_MIN_MTU;
 
-       if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) ||
-           (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) {
+       if (ip6_pkt_too_big(skb, mtu)) {
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
@@ -517,9 +530,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        to->tc_index = from->tc_index;
 #endif
        nf_copy(to, from);
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
-       to->nf_trace = from->nf_trace;
-#endif
        skb_copy_secmark(to, from);
 }
 
@@ -1091,21 +1101,19 @@ static void ip6_append_data_mtu(unsigned int *mtu,
                                unsigned int fragheaderlen,
                                struct sk_buff *skb,
                                struct rt6_info *rt,
-                               bool pmtuprobe)
+                               unsigned int orig_mtu)
 {
        if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
                if (skb == NULL) {
                        /* first fragment, reserve header_len */
-                       *mtu = *mtu - rt->dst.header_len;
+                       *mtu = orig_mtu - rt->dst.header_len;
 
                } else {
                        /*
                         * this fragment is not first, the headers
                         * space is regarded as data space.
                         */
-                       *mtu = min(*mtu, pmtuprobe ?
-                                  rt->dst.dev->mtu :
-                                  dst_mtu(rt->dst.path));
+                       *mtu = orig_mtu;
                }
                *maxfraglen = ((*mtu - fragheaderlen) & ~7)
                              + fragheaderlen - sizeof(struct frag_hdr);
@@ -1122,7 +1130,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct inet_cork *cork;
        struct sk_buff *skb, *skb_prev = NULL;
-       unsigned int maxfraglen, fragheaderlen, mtu;
+       unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
        int exthdrlen;
        int dst_exthdrlen;
        int hh_len;
@@ -1204,6 +1212,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                dst_exthdrlen = 0;
                mtu = cork->fragsize;
        }
+       orig_mtu = mtu;
 
        hh_len = LL_RESERVED_SPACE(rt->dst.dev);
 
@@ -1301,8 +1310,7 @@ alloc_new_skb:
                        if (skb == NULL || skb_prev == NULL)
                                ip6_append_data_mtu(&mtu, &maxfraglen,
                                                    fragheaderlen, skb, rt,
-                                                   np->pmtudisc >=
-                                                   IPV6_PMTUDISC_PROBE);
+                                                   orig_mtu);
 
                        skb_prev = skb;
 
index 0eb4038a4d63434738e938113b37bfe6611e07c3..8737400af0a095cac6666112cb8dcd4d60518823 100644 (file)
@@ -2349,13 +2349,14 @@ int ip6mr_get_route(struct net *net,
 }
 
 static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
-                            u32 portid, u32 seq, struct mfc6_cache *c, int cmd)
+                            u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
+                            int flags)
 {
        struct nlmsghdr *nlh;
        struct rtmsg *rtm;
        int err;
 
-       nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
        if (nlh == NULL)
                return -EMSGSIZE;
 
@@ -2423,7 +2424,7 @@ static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
        if (skb == NULL)
                goto errout;
 
-       err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+       err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
        if (err < 0)
                goto errout;
 
@@ -2462,7 +2463,8 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
                                if (ip6mr_fill_mroute(mrt, skb,
                                                      NETLINK_CB(cb->skb).portid,
                                                      cb->nlh->nlmsg_seq,
-                                                     mfc, RTM_NEWROUTE) < 0)
+                                                     mfc, RTM_NEWROUTE,
+                                                     NLM_F_MULTI) < 0)
                                        goto done;
 next_entry:
                                e++;
@@ -2476,7 +2478,8 @@ next_entry:
                        if (ip6mr_fill_mroute(mrt, skb,
                                              NETLINK_CB(cb->skb).portid,
                                              cb->nlh->nlmsg_seq,
-                                             mfc, RTM_NEWROUTE) < 0) {
+                                             mfc, RTM_NEWROUTE,
+                                             NLM_F_MULTI) < 0) {
                                spin_unlock_bh(&mfc_unres_lock);
                                goto done;
                        }
index 35750df744dc9ce92c3b98dcfd5dab27dcf73e85..4bff1f297e39a4affcf82e6b7aca2e6078b4dc50 100644 (file)
@@ -50,6 +50,11 @@ config NFT_CHAIN_NAT_IPV6
          packet transformations such as the source, destination address and
          source and destination ports.
 
+config NFT_REJECT_IPV6
+       depends on NF_TABLES_IPV6
+       default NFT_REJECT
+       tristate
+
 config IP6_NF_IPTABLES
        tristate "IP6 tables support (required for filtering)"
        depends on INET && IPV6
index d1b4928f34f7ba3f80200ec0b9db67c12d47715b..70d3dd66f2cdbf1408d328fd06104671446d5bc9 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
 obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o
 obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
 obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o
+obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
 
 # matches
 obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c
new file mode 100644 (file)
index 0000000..0bc19fa
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2013 Eric Leblond <eric@regit.org>
+ *
+ * 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.
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nft_reject.h>
+#include <net/netfilter/ipv6/nf_reject.h>
+
+void nft_reject_ipv6_eval(const struct nft_expr *expr,
+                         struct nft_data data[NFT_REG_MAX + 1],
+                         const struct nft_pktinfo *pkt)
+{
+       struct nft_reject *priv = nft_expr_priv(expr);
+       struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
+
+       switch (priv->type) {
+       case NFT_REJECT_ICMP_UNREACH:
+               nf_send_unreach6(net, pkt->skb, priv->icmp_code,
+                                pkt->ops->hooknum);
+               break;
+       case NFT_REJECT_TCP_RST:
+               nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
+               break;
+       }
+
+       data[NFT_REG_VERDICT].verdict = NF_DROP;
+}
+EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval);
+
+static struct nft_expr_type nft_reject_ipv6_type;
+static const struct nft_expr_ops nft_reject_ipv6_ops = {
+       .type           = &nft_reject_ipv6_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
+       .eval           = nft_reject_ipv6_eval,
+       .init           = nft_reject_init,
+       .dump           = nft_reject_dump,
+};
+
+static struct nft_expr_type nft_reject_ipv6_type __read_mostly = {
+       .family         = NFPROTO_IPV6,
+       .name           = "reject",
+       .ops            = &nft_reject_ipv6_ops,
+       .policy         = nft_reject_policy,
+       .maxattr        = NFTA_REJECT_MAX,
+       .owner          = THIS_MODULE,
+};
+
+static int __init nft_reject_ipv6_module_init(void)
+{
+       return nft_register_expr(&nft_reject_ipv6_type);
+}
+
+static void __exit nft_reject_ipv6_module_exit(void)
+{
+       nft_unregister_expr(&nft_reject_ipv6_type);
+}
+
+module_init(nft_reject_ipv6_module_init);
+module_exit(nft_reject_ipv6_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject");
index fb9beb78f00b23fc307384bf6aef21adf2ab6895..587bbdcb22b4c04c0186932d463bce29ca32b38e 100644 (file)
@@ -135,6 +135,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        fl6.flowi6_proto = IPPROTO_ICMPV6;
        fl6.saddr = np->saddr;
        fl6.daddr = *daddr;
+       fl6.flowi6_mark = sk->sk_mark;
        fl6.fl6_icmp_type = user_icmph.icmp6_type;
        fl6.fl6_icmp_code = user_icmph.icmp6_code;
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
index 11dac21e658690cdf01d7eb41c7e653d142ad9d4..fba54a407bb2b7c2aae62ac2d03df806bc1a794a 100644 (file)
@@ -1513,7 +1513,7 @@ int ip6_route_add(struct fib6_config *cfg)
        if (!table)
                goto out;
 
-       rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table);
+       rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table);
 
        if (!rt) {
                err = -ENOMEM;
index 3dfbcf1dcb1cbdb38a2a0b17a328bb424b139eb0..b4d74c86586cd1a0256afb59870e32ebbebd56e8 100644 (file)
@@ -475,6 +475,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
                ipip6_tunnel_unlink(sitn, tunnel);
                ipip6_tunnel_del_prl(tunnel, NULL);
        }
+       ip_tunnel_dst_reset_all(tunnel);
        dev_put(dev);
 }
 
@@ -1082,6 +1083,7 @@ static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
                t->parms.link = p->link;
                ipip6_tunnel_bind_dev(t->dev);
        }
+       ip_tunnel_dst_reset_all(t);
        netdev_state_change(t->dev);
 }
 
@@ -1112,6 +1114,7 @@ static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
        t->ip6rd.relay_prefix = relay_prefix;
        t->ip6rd.prefixlen = ip6rd->prefixlen;
        t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
+       ip_tunnel_dst_reset_all(t);
        netdev_state_change(t->dev);
        return 0;
 }
@@ -1271,6 +1274,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
                        err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
                        break;
                }
+               ip_tunnel_dst_reset_all(t);
                netdev_state_change(dev);
                break;
 
@@ -1326,6 +1330,9 @@ static const struct net_device_ops ipip6_netdev_ops = {
 
 static void ipip6_dev_free(struct net_device *dev)
 {
+       struct ip_tunnel *tunnel = netdev_priv(dev);
+
+       free_percpu(tunnel->dst_cache);
        free_percpu(dev->tstats);
        free_netdev(dev);
 }
@@ -1375,6 +1382,12 @@ static int ipip6_tunnel_init(struct net_device *dev)
                u64_stats_init(&ipip6_tunnel_stats->syncp);
        }
 
+       tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
+       if (!tunnel->dst_cache) {
+               free_percpu(dev->tstats);
+               return -ENOMEM;
+       }
+
        return 0;
 }
 
@@ -1405,6 +1418,12 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
                u64_stats_init(&ipip6_fb_stats->syncp);
        }
 
+       tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
+       if (!tunnel->dst_cache) {
+               free_percpu(dev->tstats);
+               return -ENOMEM;
+       }
+
        dev_hold(dev);
        rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
        return 0;
index e7359f9eaa8d4dd14b706afc9c7241c85e52d056..b261ee8b83fc87ddabcb447d1235ea8b67429de2 100644 (file)
@@ -113,7 +113,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
                fptr->nexthdr = nexthdr;
                fptr->reserved = 0;
-               ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
+               fptr->identification = skb_shinfo(skb)->ip6_frag_id;
 
                /* Fragment the skb. ipv6 header and the remaining fields of the
                 * fragment header are updated in ipv6_gso_segment()
index 994e28bfb32e14ba9e4ab833c5491683824a149e..00b2a6d1c0092a7d0ec668b0b657f520637f31cd 100644 (file)
 #include <net/p8022.h>
 #include <net/psnap.h>
 #include <net/sock.h>
+#include <net/datalink.h>
 #include <net/tcp_states.h>
+#include <net/net_namespace.h>
 
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_SYSCTL
-extern void ipx_register_sysctl(void);
-extern void ipx_unregister_sysctl(void);
-#else
-#define ipx_register_sysctl()
-#define ipx_unregister_sysctl()
-#endif
-
 /* Configuration Variables */
 static unsigned char ipxcfg_max_hops = 16;
 static char ipxcfg_auto_select_primary;
@@ -84,15 +78,6 @@ DEFINE_SPINLOCK(ipx_interfaces_lock);
 struct ipx_interface *ipx_primary_net;
 struct ipx_interface *ipx_internal_net;
 
-extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc,
-                           unsigned char *node);
-extern void ipxrtr_del_routes(struct ipx_interface *intrfc);
-extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
-                              struct iovec *iov, size_t len, int noblock);
-extern int ipxrtr_route_skb(struct sk_buff *skb);
-extern struct ipx_route *ipxrtr_lookup(__be32 net);
-extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
-
 struct ipx_interface *ipx_interfaces_head(void)
 {
        struct ipx_interface *rc = NULL;
@@ -1986,9 +1971,6 @@ static struct notifier_block ipx_dev_notifier = {
        .notifier_call  = ipxitf_device_event,
 };
 
-extern struct datalink_proto *make_EII_client(void);
-extern void destroy_EII_client(struct datalink_proto *);
-
 static const unsigned char ipx_8022_type = 0xE0;
 static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
 static const char ipx_EII_err_msg[] __initconst =
index 30f4519b092f546aad806520280bec883165a9c2..c1f03185c5e115ffe359e39a0bfb17efe8d4c38a 100644 (file)
@@ -20,15 +20,11 @@ DEFINE_RWLOCK(ipx_routes_lock);
 
 extern struct ipx_interface *ipx_internal_net;
 
-extern __be16 ipx_cksum(struct ipxhdr *packet, int length);
 extern struct ipx_interface *ipxitf_find_using_net(__be32 net);
 extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
                               struct sk_buff *skb, int copy);
 extern int ipxitf_demux_socket(struct ipx_interface *intrfc,
                               struct sk_buff *skb, int copy);
-extern int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb,
-                      char *node);
-extern struct ipx_interface *ipxitf_find_using_net(__be32 net);
 
 struct ipx_route *ipxrtr_lookup(__be32 net)
 {
index 1a04c13293628eb420088717dce841266328b09f..79326978517a6842b8538b6a45b95309b8e37d4f 100644 (file)
@@ -433,12 +433,13 @@ static inline int verify_sec_ctx_len(const void *p)
        return 0;
 }
 
-static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx)
+static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx,
+                                                                    gfp_t gfp)
 {
        struct xfrm_user_sec_ctx *uctx = NULL;
        int ctx_size = sec_ctx->sadb_x_ctx_len;
 
-       uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL);
+       uctx = kmalloc((sizeof(*uctx)+ctx_size), gfp);
 
        if (!uctx)
                return NULL;
@@ -1124,7 +1125,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 
        sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
        if (sec_ctx != NULL) {
-               struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+               struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL);
 
                if (!uctx)
                        goto out;
@@ -2231,14 +2232,14 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
 
        sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
        if (sec_ctx != NULL) {
-               struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+               struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL);
 
                if (!uctx) {
                        err = -ENOBUFS;
                        goto out;
                }
 
-               err = security_xfrm_policy_alloc(&xp->security, uctx);
+               err = security_xfrm_policy_alloc(&xp->security, uctx, GFP_KERNEL);
                kfree(uctx);
 
                if (err)
@@ -2335,12 +2336,12 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
 
        sec_ctx = ext_hdrs[SADB_X_EXT_SEC_CTX - 1];
        if (sec_ctx != NULL) {
-               struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+               struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_KERNEL);
 
                if (!uctx)
                        return -ENOMEM;
 
-               err = security_xfrm_policy_alloc(&pol_ctx, uctx);
+               err = security_xfrm_policy_alloc(&pol_ctx, uctx, GFP_KERNEL);
                kfree(uctx);
                if (err)
                        return err;
@@ -3239,8 +3240,8 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
                }
                if ((*dir = verify_sec_ctx_len(p)))
                        goto out;
-               uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
-               *dir = security_xfrm_policy_alloc(&xp->security, uctx);
+               uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx, GFP_ATOMIC);
+               *dir = security_xfrm_policy_alloc(&xp->security, uctx, GFP_ATOMIC);
                kfree(uctx);
 
                if (*dir)
index 735d0f60c83a126683b599d1e967eb9ca18b0471..c83827e7c3248ad493b576ca565f21b485aa0453 100644 (file)
@@ -112,7 +112,6 @@ struct l2tp_net {
        spinlock_t l2tp_session_hlist_lock;
 };
 
-static void l2tp_session_set_header_len(struct l2tp_session *session, int version);
 static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel);
 
 static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk)
@@ -1863,7 +1862,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_delete);
 /* We come here whenever a session's send_seq, cookie_len or
  * l2specific_len parameters are set.
  */
-static void l2tp_session_set_header_len(struct l2tp_session *session, int version)
+void l2tp_session_set_header_len(struct l2tp_session *session, int version)
 {
        if (version == L2TP_HDR_VER_2) {
                session->hdr_len = 6;
@@ -1876,6 +1875,7 @@ static void l2tp_session_set_header_len(struct l2tp_session *session, int versio
        }
 
 }
+EXPORT_SYMBOL_GPL(l2tp_session_set_header_len);
 
 struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
 {
@@ -2016,7 +2016,7 @@ static int __init l2tp_init(void)
        if (rc)
                goto out;
 
-       l2tp_wq = alloc_workqueue("l2tp", WQ_NON_REENTRANT | WQ_UNBOUND, 0);
+       l2tp_wq = alloc_workqueue("l2tp", WQ_UNBOUND, 0);
        if (!l2tp_wq) {
                pr_err("alloc_workqueue failed\n");
                rc = -ENOMEM;
index 1f01ba3435bcf0889a79e510567f19f248b7eef5..3f93ccd6ba9768fe171f4e35e79d613226c1dbc7 100644 (file)
@@ -263,6 +263,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                      int length, int (*payload_hook)(struct sk_buff *skb));
 int l2tp_session_queue_purge(struct l2tp_session *session);
 int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb);
+void l2tp_session_set_header_len(struct l2tp_session *session, int version);
 
 int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb,
                  int hdr_len);
index 4cfd722e91536c1de137ec64f1e33bbc7fc5e1ea..bd7387adea9eff25ce7ffd0683589dcdcc020ad0 100644 (file)
@@ -578,8 +578,10 @@ static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *inf
        if (info->attrs[L2TP_ATTR_RECV_SEQ])
                session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]);
 
-       if (info->attrs[L2TP_ATTR_SEND_SEQ])
+       if (info->attrs[L2TP_ATTR_SEND_SEQ]) {
                session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]);
+               l2tp_session_set_header_len(session, session->tunnel->version);
+       }
 
        if (info->attrs[L2TP_ATTR_LNS_MODE])
                session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]);
index be5fadf3473946a3b7ef886eeadcb2d219e867aa..5990919356a5d7c7573d8cbd0f6c899f28eb7f67 100644 (file)
@@ -254,12 +254,14 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
                po = pppox_sk(sk);
                ppp_input(&po->chan, skb);
        } else {
-               l2tp_info(session, PPPOL2TP_MSG_DATA, "%s: socket not bound\n",
-                         session->name);
+               l2tp_dbg(session, PPPOL2TP_MSG_DATA,
+                        "%s: recv %d byte data frame, passing to L2TP socket\n",
+                        session->name, data_len);
 
-               /* Not bound. Nothing we can do, so discard. */
-               atomic_long_inc(&session->stats.rx_errors);
-               kfree_skb(skb);
+               if (sock_queue_rcv_skb(sk, skb) < 0) {
+                       atomic_long_inc(&session->stats.rx_errors);
+                       kfree_skb(skb);
+               }
        }
 
        return;
@@ -1312,6 +1314,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk,
                        po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ :
                                PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
                }
+               l2tp_session_set_header_len(session, session->tunnel->version);
                l2tp_info(session, PPPOL2TP_MSG_CONTROL,
                          "%s: set send_seq=%d\n",
                          session->name, session->send_seq);
index f9ae9b85d4c1bf297f3008e0f0693d6305c69824..453e974287d19b52971116bca5e0e401746f3ffb 100644 (file)
@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                                        IEEE80211_P2P_OPPPS_ENABLE_BIT;
 
        err = ieee80211_assign_beacon(sdata, &params->beacon);
-       if (err < 0)
+       if (err < 0) {
+               ieee80211_vif_release_channel(sdata);
                return err;
+       }
        changed |= err;
 
        err = drv_start_ap(sdata->local, sdata);
@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                if (old)
                        kfree_rcu(old, rcu_head);
                RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
+               ieee80211_vif_release_channel(sdata);
                return err;
        }
 
@@ -1090,8 +1093,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        kfree(sdata->u.ap.next_beacon);
        sdata->u.ap.next_beacon = NULL;
 
-       cancel_work_sync(&sdata->u.ap.request_smps_work);
-
        /* turn off carrier for this interface and dependent VLANs */
        list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
                netif_carrier_off(vlan->dev);
@@ -1103,6 +1104,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        kfree_rcu(old_beacon, rcu_head);
        if (old_probe_resp)
                kfree_rcu(old_probe_resp, rcu_head);
+       sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
 
        __sta_info_flush(sdata, true);
        ieee80211_free_keys(sdata, true);
@@ -2638,6 +2640,24 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
        INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
        INIT_LIST_HEAD(&roc->dependents);
 
+       /*
+        * cookie is either the roc cookie (for normal roc)
+        * or the SKB (for mgmt TX)
+        */
+       if (!txskb) {
+               /* local->mtx protects this */
+               local->roc_cookie_counter++;
+               roc->cookie = local->roc_cookie_counter;
+               /* wow, you wrapped 64 bits ... more likely a bug */
+               if (WARN_ON(roc->cookie == 0)) {
+                       roc->cookie = 1;
+                       local->roc_cookie_counter++;
+               }
+               *cookie = roc->cookie;
+       } else {
+               *cookie = (unsigned long)txskb;
+       }
+
        /* if there's one pending or we're scanning, queue this one */
        if (!list_empty(&local->roc_list) ||
            local->scanning || local->radar_detect_enabled)
@@ -2772,24 +2792,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
        if (!queued)
                list_add_tail(&roc->list, &local->roc_list);
 
-       /*
-        * cookie is either the roc cookie (for normal roc)
-        * or the SKB (for mgmt TX)
-        */
-       if (!txskb) {
-               /* local->mtx protects this */
-               local->roc_cookie_counter++;
-               roc->cookie = local->roc_cookie_counter;
-               /* wow, you wrapped 64 bits ... more likely a bug */
-               if (WARN_ON(roc->cookie == 0)) {
-                       roc->cookie = 1;
-                       local->roc_cookie_counter++;
-               }
-               *cookie = roc->cookie;
-       } else {
-               *cookie = (unsigned long)txskb;
-       }
-
        return 0;
 }
 
index f43613a97dd664e2daf1856b001d7bdee5708d4f..0c1ecfdf9a128b05f76e545d3e0b95de50123176 100644 (file)
@@ -100,6 +100,12 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
                }
                max_bw = max(max_bw, width);
        }
+
+       /* use the configured bandwidth in case of monitor interface */
+       sdata = rcu_dereference(local->monitor_sdata);
+       if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf)
+               max_bw = max(max_bw, conf->def.width);
+
        rcu_read_unlock();
 
        return max_bw;
index fab7b91923e0a8b93313797b53a469234ce83506..70dd013de8361e39c95264eeae967e193fe240e5 100644 (file)
@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(struct work_struct *work)
                             u.ap.request_smps_work);
 
        sdata_lock(sdata);
-       __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
+       if (sdata_dereference(sdata->u.ap.beacon, sdata))
+               __ieee80211_request_smps_ap(sdata,
+                                           sdata->u.ap.driver_smps_mode);
        sdata_unlock(sdata);
 }
 
index 771080ec7212a43b5e3bb151a7e17ab392fe5557..2796a198728fd12bab4625ae1b112123988794f0 100644 (file)
@@ -695,12 +695,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
        struct cfg80211_bss *cbss;
        struct beacon_data *presp;
        struct sta_info *sta;
-       int active_ibss;
        u16 capability;
 
-       active_ibss = ieee80211_sta_active_ibss(sdata);
-
-       if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
+       if (!is_zero_ether_addr(ifibss->bssid)) {
                capability = WLAN_CAPABILITY_IBSS;
 
                if (ifibss->privacy)
index 3701930c66493af53461a4f0c1849ad26450e092..5e44e3179e02aabaea7b6d455ec5ed656e3691b0 100644 (file)
@@ -1692,14 +1692,8 @@ void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
 void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
 void ieee80211_add_pending_skb(struct ieee80211_local *local,
                               struct sk_buff *skb);
-void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
-                                  struct sk_buff_head *skbs,
-                                  void (*fn)(void *data), void *data);
-static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
-                                             struct sk_buff_head *skbs)
-{
-       ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
-}
+void ieee80211_add_pending_skbs(struct ieee80211_local *local,
+                               struct sk_buff_head *skbs);
 void ieee80211_flush_queues(struct ieee80211_local *local,
                            struct ieee80211_sub_if_data *sdata);
 
index 3dfd20a453aba250fff726d1733f0dac6c763b3c..ce1c4437061049a8ebea8d5d08e77995217b2a0d 100644 (file)
@@ -418,20 +418,24 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                return ret;
        }
 
+       mutex_lock(&local->iflist_mtx);
+       rcu_assign_pointer(local->monitor_sdata, sdata);
+       mutex_unlock(&local->iflist_mtx);
+
        mutex_lock(&local->mtx);
        ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
                                        IEEE80211_CHANCTX_EXCLUSIVE);
        mutex_unlock(&local->mtx);
        if (ret) {
+               mutex_lock(&local->iflist_mtx);
+               rcu_assign_pointer(local->monitor_sdata, NULL);
+               mutex_unlock(&local->iflist_mtx);
+               synchronize_net();
                drv_remove_interface(local, sdata);
                kfree(sdata);
                return ret;
        }
 
-       mutex_lock(&local->iflist_mtx);
-       rcu_assign_pointer(local->monitor_sdata, sdata);
-       mutex_unlock(&local->iflist_mtx);
-
        return 0;
 }
 
@@ -770,12 +774,19 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_roc_purge(local, sdata);
 
-       if (sdata->vif.type == NL80211_IFTYPE_STATION)
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_STATION:
                ieee80211_mgd_stop(sdata);
-
-       if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+               break;
+       case NL80211_IFTYPE_ADHOC:
                ieee80211_ibss_stop(sdata);
-
+               break;
+       case NL80211_IFTYPE_AP:
+               cancel_work_sync(&sdata->u.ap.request_smps_work);
+               break;
+       default:
+               break;
+       }
 
        /*
         * Remove all stations associated with this interface.
@@ -1046,7 +1057,8 @@ static void ieee80211_uninit(struct net_device *dev)
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
                                         struct sk_buff *skb,
-                                        void *accel_priv)
+                                        void *accel_priv,
+                                        select_queue_fallback_t fallback)
 {
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1064,7 +1076,8 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
                                          struct sk_buff *skb,
-                                         void *accel_priv)
+                                         void *accel_priv,
+                                         select_queue_fallback_t fallback)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
index 2802f9d9279de1527927a88bc731489cc22613c7..ad8b377b4b9f6cfa5d5e222a3c0aff169f4d72d1 100644 (file)
@@ -36,6 +36,7 @@ static struct sk_buff *mps_qos_null_get(struct sta_info *sta)
                                      sdata->vif.addr);
        nullfunc->frame_control = fc;
        nullfunc->duration_id = 0;
+       nullfunc->seq_ctrl = 0;
        /* no address resolution for this frame -> set addr 1 immediately */
        memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
        memset(skb_put(skb, 2), 0, 2); /* append QoS control field */
index fc1d82465b3ce1b1cdcc9edb4f5157618b70e8ce..245dce969b31165078c04fca9a5fc963457e9d68 100644 (file)
@@ -222,6 +222,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        switch (vht_oper->chan_width) {
        case IEEE80211_VHT_CHANWIDTH_USE_HT:
                vht_chandef.width = chandef->width;
+               vht_chandef.center_freq1 = chandef->center_freq1;
                break;
        case IEEE80211_VHT_CHANWIDTH_80MHZ:
                vht_chandef.width = NL80211_CHAN_WIDTH_80;
@@ -271,6 +272,28 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        ret = 0;
 
 out:
+       /*
+        * When tracking the current AP, don't do any further checks if the
+        * new chandef is identical to the one we're currently using for the
+        * connection. This keeps us from playing ping-pong with regulatory,
+        * without it the following can happen (for example):
+        *  - connect to an AP with 80 MHz, world regdom allows 80 MHz
+        *  - AP advertises regdom US
+        *  - CRDA loads regdom US with 80 MHz prohibited (old database)
+        *  - the code below detects an unsupported channel, downgrades, and
+        *    we disconnect from the AP in the caller
+        *  - disconnect causes CRDA to reload world regdomain and the game
+        *    starts anew.
+        * (see https://bugzilla.kernel.org/show_bug.cgi?id=70881)
+        *
+        * It seems possible that there are still scenarios with CSA or real
+        * bandwidth changes where a this could happen, but those cases are
+        * less common and wouldn't completely prevent using the AP.
+        */
+       if (tracking &&
+           cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef))
+               return ret;
+
        /* don't print the message below for VHT mismatch if VHT is disabled */
        if (ret & IEEE80211_STA_DISABLE_VHT)
                vht_chandef = *chandef;
@@ -3753,6 +3776,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
                chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
                if (WARN_ON(!chanctx_conf)) {
                        rcu_read_unlock();
+                       sta_info_free(local, new_sta);
                        return -EINVAL;
                }
                rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
index c24ca0d0f4697ea7040c813dbf24d1c32f707329..3e57f96c9666daf4b420cfd663864878bef34204 100644 (file)
@@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *sta)
               sta->sta.addr, sta->sta.aid);
 
        if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
+               /*
+                * Clear the flag only if the other one is still set
+                * so that the TX path won't start TX'ing new frames
+                * directly ... In the case that the driver flag isn't
+                * set ieee80211_sta_ps_deliver_wakeup() will clear it.
+                */
+               clear_sta_flag(sta, WLAN_STA_PS_STA);
                ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
                       sta->sta.addr, sta->sta.aid);
                return;
index decd30c1e29053d9a5e3ea56c7ccb66a7407578d..137a192e64bc3c2aa61cc9c5912a89bd3008cbe3 100644 (file)
@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
        return -ENOENT;
 }
 
-static void cleanup_single_sta(struct sta_info *sta)
+static void __cleanup_single_sta(struct sta_info *sta)
 {
        int ac, i;
        struct tid_ampdu_tx *tid_tx;
@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        struct ps_data *ps;
 
-       if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
+       if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
+           test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
                if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
                    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                        ps = &sdata->bss->ps;
@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct sta_info *sta)
                        return;
 
                clear_sta_flag(sta, WLAN_STA_PS_STA);
+               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 
                atomic_dec(&ps->num_sta_ps);
                sta_info_recalc_tim(sta);
@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct sta_info *sta)
                ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
                kfree(tid_tx);
        }
+}
 
+static void cleanup_single_sta(struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ieee80211_local *local = sdata->local;
+
+       __cleanup_single_sta(sta);
        sta_info_free(local, sta);
 }
 
@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        rcu_read_unlock();
 
        spin_lock_init(&sta->lock);
+       spin_lock_init(&sta->ps_lock);
        INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
        INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
        mutex_init(&sta->ampdu_mlme.mtx);
@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
                goto out_err;
        }
 
-       /* notify driver */
-       err = sta_info_insert_drv_state(local, sdata, sta);
-       if (err)
-               goto out_err;
-
        local->num_sta++;
        local->sta_generation++;
        smp_mb();
 
+       /* simplify things and don't accept BA sessions yet */
+       set_sta_flag(sta, WLAN_STA_BLOCK_BA);
+
        /* make the station visible */
        sta_info_hash_add(local, sta);
 
        list_add_rcu(&sta->list, &local->sta_list);
 
+       /* notify driver */
+       err = sta_info_insert_drv_state(local, sdata, sta);
+       if (err)
+               goto out_remove;
+
        set_sta_flag(sta, WLAN_STA_INSERTED);
+       /* accept BA sessions now */
+       clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
 
        ieee80211_recalc_min_chandef(sdata);
        ieee80211_sta_debugfs_add(sta);
@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
                mesh_accept_plinks_update(sdata);
 
        return 0;
+ out_remove:
+       sta_info_hash_del(local, sta);
+       list_del_rcu(&sta->list);
+       local->num_sta--;
+       synchronize_net();
+       __cleanup_single_sta(sta);
  out_err:
        mutex_unlock(&local->sta_mtx);
        rcu_read_lock();
@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
 }
 EXPORT_SYMBOL(ieee80211_find_sta);
 
-static void clear_sta_ps_flags(void *_sta)
+/* powersave support code */
+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
 {
-       struct sta_info *sta = _sta;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct sk_buff_head pending;
+       int filtered = 0, buffered = 0, ac;
+       unsigned long flags;
        struct ps_data *ps;
 
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_sta)
        else
                return;
 
-       clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-       if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
-               atomic_dec(&ps->num_sta_ps);
-}
-
-/* powersave support code */
-void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
-{
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-       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);
 
        BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
 
        skb_queue_head_init(&pending);
 
+       /* sync with ieee80211_tx_h_unicast_ps_buf */
+       spin_lock(&sta->ps_lock);
        /* Send all buffered frames to the station */
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                int count = skb_queue_len(&pending), tmp;
@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
                buffered += tmp - count;
        }
 
-       ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
+       ieee80211_add_pending_skbs(local, &pending);
+       clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+       clear_sta_flag(sta, WLAN_STA_PS_STA);
+       spin_unlock(&sta->ps_lock);
+
+       atomic_dec(&ps->num_sta_ps);
 
        /* This station just woke up and isn't aware of our SMPS state */
        if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
@@ -1188,6 +1206,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
        memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
        memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
        memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
+       nullfunc->seq_ctrl = 0;
 
        skb->priority = tid;
        skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]);
index d77ff70906303855458734a5bfac0526460056eb..d3a6d8208f2f85f7db331238f41c0da2938f0f8d 100644 (file)
@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat {
  * @drv_unblock_wk: used for driver PS unblocking
  * @listen_interval: listen interval of this station, when we're acting as AP
  * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
+ * @ps_lock: used for powersave (when mac80211 is the AP) related locking
  * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
  *     when it leaves power saving state or polls
  * @tx_filtered: buffers (per AC) of frames we already tried to
@@ -356,10 +357,8 @@ struct sta_info {
        /* use the accessors defined below */
        unsigned long _flags;
 
-       /*
-        * STA powersave frame queues, no more than the internal
-        * locking required.
-        */
+       /* STA powersave lock and frame queues */
+       spinlock_t ps_lock;
        struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
        struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
        unsigned long driver_buffered_tids;
index 27c990bf2320237aa3c3124e25d0b0bc9508fb40..4080c615636fabf3d430ecd898d4349ccd213464 100644 (file)
@@ -478,6 +478,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                       sta->sta.addr, sta->sta.aid, ac);
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
                        purge_old_ps_buffers(tx->local);
+
+               /* sync with ieee80211_sta_ps_deliver_wakeup */
+               spin_lock(&sta->ps_lock);
+               /*
+                * STA woke up the meantime and all the frames on ps_tx_buf have
+                * been queued to pending queue. No reordering can happen, go
+                * ahead and Tx the packet.
+                */
+               if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
+                   !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
+                       spin_unlock(&sta->ps_lock);
+                       return TX_CONTINUE;
+               }
+
                if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
                        struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
                        ps_dbg(tx->sdata,
@@ -492,6 +506,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
                info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
                skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
+               spin_unlock(&sta->ps_lock);
 
                if (!timer_pending(&local->sta_cleanup))
                        mod_timer(&local->sta_cleanup,
@@ -878,7 +893,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
        }
 
        /* adjust first fragment's length */
-       skb->len = hdrlen + per_fragm;
+       skb_trim(skb, hdrlen + per_fragm);
        return 0;
 }
 
index 676dc0967f377f1251a761bf2dff0c35c8e92346..b8700d417a9cf26735a581fe25eb2619cf4a37da 100644 (file)
@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
        spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 }
 
-void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
-                                  struct sk_buff_head *skbs,
-                                  void (*fn)(void *data), void *data)
+void ieee80211_add_pending_skbs(struct ieee80211_local *local,
+                               struct sk_buff_head *skbs)
 {
        struct ieee80211_hw *hw = &local->hw;
        struct sk_buff *skb;
@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
                __skb_queue_tail(&local->pending[queue], skb);
        }
 
-       if (fn)
-               fn(data);
-
        for (i = 0; i < hw->queues; i++)
                __ieee80211_wake_queue(hw, i,
                        IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
@@ -1740,6 +1736,26 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
+       /*
+        * Reconfigure sched scan if it was interrupted by FW restart or
+        * suspend.
+        */
+       mutex_lock(&local->mtx);
+       sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
+                                               lockdep_is_held(&local->mtx));
+       if (sched_scan_sdata && local->sched_scan_req)
+               /*
+                * Sched scan stopped, but we don't want to report it. Instead,
+                * we're trying to reschedule.
+                */
+               if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
+                                                        local->sched_scan_req))
+                       sched_scan_stopped = true;
+       mutex_unlock(&local->mtx);
+
+       if (sched_scan_stopped)
+               cfg80211_sched_scan_stopped(local->hw.wiphy);
+
        /*
         * If this is for hw restart things are still running.
         * We may want to change that later, however.
@@ -1768,26 +1784,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        WARN_ON(1);
 #endif
 
-       /*
-        * Reconfigure sched scan if it was interrupted by FW restart or
-        * suspend.
-        */
-       mutex_lock(&local->mtx);
-       sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
-                                               lockdep_is_held(&local->mtx));
-       if (sched_scan_sdata && local->sched_scan_req)
-               /*
-                * Sched scan stopped, but we don't want to report it. Instead,
-                * we're trying to reschedule.
-                */
-               if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
-                                                        local->sched_scan_req))
-                       sched_scan_stopped = true;
-       mutex_unlock(&local->mtx);
-
-       if (sched_scan_stopped)
-               cfg80211_sched_scan_stopped(local->hw.wiphy);
-
        return 0;
 }
 
index 21211c60ca988992034bfc330977e846c3fc7010..d51422c778dee359bec450c75b77bfb24ca712f4 100644 (file)
@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                return IEEE80211_AC_BE;
        }
 
+       if (skb->protocol == sdata->control_port_protocol) {
+               skb->priority = 7;
+               return ieee80211_downgrade_queue(sdata, skb);
+       }
+
        /* use the data classifier to determine what 802.1d tag the
         * data frame has */
        rcu_read_lock();
index c37467562fd04ebd5bf7ac1a02bef56e3bd9017a..e9410d17619df52b76620e6a81a51e3c9a549f33 100644 (file)
@@ -513,7 +513,6 @@ config NFT_QUEUE
 
 config NFT_REJECT
        depends on NF_TABLES
-       depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6
        default m if NETFILTER_ADVANCED=n
        tristate "Netfilter nf_tables reject support"
        help
@@ -521,6 +520,11 @@ config NFT_REJECT
          explicitly deny and notify via TCP reset/ICMP informational errors
          unallowed traffic.
 
+config NFT_REJECT_INET
+       depends on NF_TABLES_INET
+       default NFT_REJECT
+       tristate
+
 config NFT_COMPAT
        depends on NF_TABLES
        depends on NETFILTER_XTABLES
index ee9c4de5f8eded2b7e545eea47dfbd1f42edfafc..bffdad774da753131937d53ba1693af8f25b83a0 100644 (file)
@@ -79,6 +79,7 @@ obj-$(CONFIG_NFT_LIMIT)               += nft_limit.o
 obj-$(CONFIG_NFT_NAT)          += nft_nat.o
 obj-$(CONFIG_NFT_QUEUE)                += nft_queue.o
 obj-$(CONFIG_NFT_REJECT)       += nft_reject.o
+obj-$(CONFIG_NFT_REJECT_INET)  += nft_reject_inet.o
 obj-$(CONFIG_NFT_RBTREE)       += nft_rbtree.o
 obj-$(CONFIG_NFT_HASH)         += nft_hash.o
 obj-$(CONFIG_NFT_COUNTER)      += nft_counter.o
index 59a1a85bcb3eb888348cbc818789ebb16aa01cc9..a8eb0a89326ab504ec83421ea7b66aba3ab3a057 100644 (file)
@@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
        cp->protocol       = p->protocol;
        ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
        cp->cport          = p->cport;
-       ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr);
-       cp->vport          = p->vport;
-       /* proto should only be IPPROTO_IP if d_addr is a fwmark */
+       /* proto should only be IPPROTO_IP if p->vaddr is a fwmark */
        ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
-                      &cp->daddr, daddr);
+                      &cp->vaddr, p->vaddr);
+       cp->vport          = p->vport;
+       ip_vs_addr_set(p->af, &cp->daddr, daddr);
        cp->dport          = dport;
        cp->flags          = flags;
        cp->fwmark         = fwmark;
index 8824ed0ccc9cd544e4799484ea7158f1f8db9c67..356bef519fe5b781f6225557f64186c0075852a1 100644 (file)
@@ -312,6 +312,21 @@ static void death_by_timeout(unsigned long ul_conntrack)
        nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0);
 }
 
+static inline bool
+nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
+                       const struct nf_conntrack_tuple *tuple,
+                       u16 zone)
+{
+       struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+
+       /* A conntrack can be recreated with the equal tuple,
+        * so we need to check that the conntrack is confirmed
+        */
+       return nf_ct_tuple_equal(tuple, &h->tuple) &&
+               nf_ct_zone(ct) == zone &&
+               nf_ct_is_confirmed(ct);
+}
+
 /*
  * Warning :
  * - Caller must take a reference on returned object
@@ -333,8 +348,7 @@ ____nf_conntrack_find(struct net *net, u16 zone,
        local_bh_disable();
 begin:
        hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) {
-               if (nf_ct_tuple_equal(tuple, &h->tuple) &&
-                   nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {
+               if (nf_ct_key_equal(h, tuple, zone)) {
                        NF_CT_STAT_INC(net, found);
                        local_bh_enable();
                        return h;
@@ -372,8 +386,7 @@ begin:
                             !atomic_inc_not_zero(&ct->ct_general.use)))
                        h = NULL;
                else {
-                       if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) ||
-                                    nf_ct_zone(ct) != zone)) {
+                       if (unlikely(!nf_ct_key_equal(h, tuple, zone))) {
                                nf_ct_put(ct);
                                goto begin;
                        }
@@ -435,7 +448,9 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
                        goto out;
 
        add_timer(&ct->timeout);
-       nf_conntrack_get(&ct->ct_general);
+       smp_wmb();
+       /* The caller holds a reference to this object */
+       atomic_set(&ct->ct_general.use, 2);
        __nf_conntrack_hash_insert(ct, hash, repl_hash);
        NF_CT_STAT_INC(net, insert);
        spin_unlock_bh(&nf_conntrack_lock);
@@ -449,6 +464,21 @@ out:
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert);
 
+/* deletion from this larval template list happens via nf_ct_put() */
+void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl)
+{
+       __set_bit(IPS_TEMPLATE_BIT, &tmpl->status);
+       __set_bit(IPS_CONFIRMED_BIT, &tmpl->status);
+       nf_conntrack_get(&tmpl->ct_general);
+
+       spin_lock_bh(&nf_conntrack_lock);
+       /* Overload tuple linked list to put us in template list. */
+       hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+                                &net->ct.tmpl);
+       spin_unlock_bh(&nf_conntrack_lock);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert);
+
 /* Confirm a connection given skb; places it in hash table */
 int
 __nf_conntrack_confirm(struct sk_buff *skb)
@@ -720,11 +750,10 @@ __nf_conntrack_alloc(struct net *net, u16 zone,
                nf_ct_zone->id = zone;
        }
 #endif
-       /*
-        * changes to lookup keys must be done before setting refcnt to 1
+       /* Because we use RCU lookups, we set ct_general.use to zero before
+        * this is inserted in any list.
         */
-       smp_wmb();
-       atomic_set(&ct->ct_general.use, 1);
+       atomic_set(&ct->ct_general.use, 0);
        return ct;
 
 #ifdef CONFIG_NF_CONNTRACK_ZONES
@@ -748,6 +777,11 @@ void nf_conntrack_free(struct nf_conn *ct)
 {
        struct net *net = nf_ct_net(ct);
 
+       /* A freed object has refcnt == 0, that's
+        * the golden rule for SLAB_DESTROY_BY_RCU
+        */
+       NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0);
+
        nf_ct_ext_destroy(ct);
        nf_ct_ext_free(ct);
        kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
@@ -843,6 +877,9 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
                NF_CT_STAT_INC(net, new);
        }
 
+       /* Now it is inserted into the unconfirmed list, bump refcount */
+       nf_conntrack_get(&ct->ct_general);
+
        /* Overload tuple linked list to put us in unconfirmed list. */
        hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
                       &net->ct.unconfirmed);
index bb322d0beb484f3c66a334a5e0b24651f2a1ffca..b9f0e03743228ec852eee97eb6bb9ef1e0ab73e9 100644 (file)
@@ -1310,27 +1310,22 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
 }
 
 static int
-ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[])
+ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
 {
 #ifdef CONFIG_NF_NAT_NEEDED
        int ret;
 
-       if (cda[CTA_NAT_DST]) {
-               ret = ctnetlink_parse_nat_setup(ct,
-                                               NF_NAT_MANIP_DST,
-                                               cda[CTA_NAT_DST]);
-               if (ret < 0)
-                       return ret;
-       }
-       if (cda[CTA_NAT_SRC]) {
-               ret = ctnetlink_parse_nat_setup(ct,
-                                               NF_NAT_MANIP_SRC,
-                                               cda[CTA_NAT_SRC]);
-               if (ret < 0)
-                       return ret;
-       }
-       return 0;
+       ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST,
+                                       cda[CTA_NAT_DST]);
+       if (ret < 0)
+               return ret;
+
+       ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_SRC,
+                                       cda[CTA_NAT_SRC]);
+       return ret;
 #else
+       if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
+               return 0;
        return -EOPNOTSUPP;
 #endif
 }
@@ -1659,11 +1654,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
                        goto err2;
        }
 
-       if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
-               err = ctnetlink_change_nat(ct, cda);
-               if (err < 0)
-                       goto err2;
-       }
+       err = ctnetlink_setup_nat(ct, cda);
+       if (err < 0)
+               goto err2;
 
        nf_ct_acct_ext_add(ct, GFP_ATOMIC);
        nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
index d3f5cd6dd962b195ea85775cd0432cf204e697b2..52ca952b802c5e3ea41c83823b90f74365b8fc76 100644 (file)
@@ -432,15 +432,15 @@ nf_nat_setup_info(struct nf_conn *ct,
 }
 EXPORT_SYMBOL(nf_nat_setup_info);
 
-unsigned int
-nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
+static unsigned int
+__nf_nat_alloc_null_binding(struct nf_conn *ct, enum nf_nat_manip_type manip)
 {
        /* Force range to this IP; let proto decide mapping for
         * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
         * Use reply in case it's already been mangled (eg local packet).
         */
        union nf_inet_addr ip =
-               (HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
+               (manip == NF_NAT_MANIP_SRC ?
                ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3 :
                ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3);
        struct nf_nat_range range = {
@@ -448,7 +448,13 @@ nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
                .min_addr       = ip,
                .max_addr       = ip,
        };
-       return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
+       return nf_nat_setup_info(ct, &range, manip);
+}
+
+unsigned int
+nf_nat_alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
+{
+       return __nf_nat_alloc_null_binding(ct, HOOK2MANIP(hooknum));
 }
 EXPORT_SYMBOL_GPL(nf_nat_alloc_null_binding);
 
@@ -702,9 +708,9 @@ static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
 
 static int
 nfnetlink_parse_nat(const struct nlattr *nat,
-                   const struct nf_conn *ct, struct nf_nat_range *range)
+                   const struct nf_conn *ct, struct nf_nat_range *range,
+                   const struct nf_nat_l3proto *l3proto)
 {
-       const struct nf_nat_l3proto *l3proto;
        struct nlattr *tb[CTA_NAT_MAX+1];
        int err;
 
@@ -714,38 +720,46 @@ nfnetlink_parse_nat(const struct nlattr *nat,
        if (err < 0)
                return err;
 
-       rcu_read_lock();
-       l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct));
-       if (l3proto == NULL) {
-               err = -EAGAIN;
-               goto out;
-       }
        err = l3proto->nlattr_to_range(tb, range);
        if (err < 0)
-               goto out;
+               return err;
 
        if (!tb[CTA_NAT_PROTO])
-               goto out;
+               return 0;
 
-       err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
-out:
-       rcu_read_unlock();
-       return err;
+       return nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
 }
 
+/* This function is called under rcu_read_lock() */
 static int
 nfnetlink_parse_nat_setup(struct nf_conn *ct,
                          enum nf_nat_manip_type manip,
                          const struct nlattr *attr)
 {
        struct nf_nat_range range;
+       const struct nf_nat_l3proto *l3proto;
        int err;
 
-       err = nfnetlink_parse_nat(attr, ct, &range);
+       /* Should not happen, restricted to creating new conntracks
+        * via ctnetlink.
+        */
+       if (WARN_ON_ONCE(nf_nat_initialized(ct, manip)))
+               return -EEXIST;
+
+       /* Make sure that L3 NAT is there by when we call nf_nat_setup_info to
+        * attach the null binding, otherwise this may oops.
+        */
+       l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct));
+       if (l3proto == NULL)
+               return -EAGAIN;
+
+       /* No NAT information has been passed, allocate the null-binding */
+       if (attr == NULL)
+               return __nf_nat_alloc_null_binding(ct, manip);
+
+       err = nfnetlink_parse_nat(attr, ct, &range, l3proto);
        if (err < 0)
                return err;
-       if (nf_nat_initialized(ct, manip))
-               return -EEXIST;
 
        return nf_nat_setup_info(ct, &range, manip);
 }
index 9858e3e51a3a049ce796b3ed625e3d3ad8bbe5cc..52e20c9a46a58be4328276964c1bb255c51a423c 100644 (file)
@@ -363,9 +363,8 @@ static int __net_init synproxy_net_init(struct net *net)
                goto err2;
        if (!nfct_synproxy_ext_add(ct))
                goto err2;
-       __set_bit(IPS_TEMPLATE_BIT, &ct->status);
-       __set_bit(IPS_CONFIRMED_BIT, &ct->status);
 
+       nf_conntrack_tmpl_insert(net, ct);
        snet->tmpl = ct;
 
        snet->stats = alloc_percpu(struct synproxy_stats);
@@ -390,7 +389,7 @@ static void __net_exit synproxy_net_exit(struct net *net)
 {
        struct synproxy_net *snet = synproxy_pernet(net);
 
-       nf_conntrack_free(snet->tmpl);
+       nf_ct_put(snet->tmpl);
        synproxy_proc_exit(net);
        free_percpu(snet->stats);
 }
index 117bbaaddde636a7b5cbf754012ab2f696898e71..adce01e8bb57e7fb9794eebceae274707d96899e 100644 (file)
@@ -1008,10 +1008,8 @@ notify:
        return 0;
 }
 
-static void nf_tables_rcu_chain_destroy(struct rcu_head *head)
+static void nf_tables_chain_destroy(struct nft_chain *chain)
 {
-       struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head);
-
        BUG_ON(chain->use > 0);
 
        if (chain->flags & NFT_BASE_CHAIN) {
@@ -1045,7 +1043,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(chain))
                return PTR_ERR(chain);
 
-       if (!list_empty(&chain->rules))
+       if (!list_empty(&chain->rules) || chain->use > 0)
                return -EBUSY;
 
        list_del(&chain->list);
@@ -1059,7 +1057,9 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
                               family);
 
        /* Make sure all rule references are gone before this is released */
-       call_rcu(&chain->rcu_head, nf_tables_rcu_chain_destroy);
+       synchronize_rcu();
+
+       nf_tables_chain_destroy(chain);
        return 0;
 }
 
@@ -1114,35 +1114,45 @@ void nft_unregister_expr(struct nft_expr_type *type)
 }
 EXPORT_SYMBOL_GPL(nft_unregister_expr);
 
-static const struct nft_expr_type *__nft_expr_type_get(struct nlattr *nla)
+static const struct nft_expr_type *__nft_expr_type_get(u8 family,
+                                                      struct nlattr *nla)
 {
        const struct nft_expr_type *type;
 
        list_for_each_entry(type, &nf_tables_expressions, list) {
-               if (!nla_strcmp(nla, type->name))
+               if (!nla_strcmp(nla, type->name) &&
+                   (!type->family || type->family == family))
                        return type;
        }
        return NULL;
 }
 
-static const struct nft_expr_type *nft_expr_type_get(struct nlattr *nla)
+static const struct nft_expr_type *nft_expr_type_get(u8 family,
+                                                    struct nlattr *nla)
 {
        const struct nft_expr_type *type;
 
        if (nla == NULL)
                return ERR_PTR(-EINVAL);
 
-       type = __nft_expr_type_get(nla);
+       type = __nft_expr_type_get(family, nla);
        if (type != NULL && try_module_get(type->owner))
                return type;
 
 #ifdef CONFIG_MODULES
        if (type == NULL) {
+               nfnl_unlock(NFNL_SUBSYS_NFTABLES);
+               request_module("nft-expr-%u-%.*s", family,
+                              nla_len(nla), (char *)nla_data(nla));
+               nfnl_lock(NFNL_SUBSYS_NFTABLES);
+               if (__nft_expr_type_get(family, nla))
+                       return ERR_PTR(-EAGAIN);
+
                nfnl_unlock(NFNL_SUBSYS_NFTABLES);
                request_module("nft-expr-%.*s",
                               nla_len(nla), (char *)nla_data(nla));
                nfnl_lock(NFNL_SUBSYS_NFTABLES);
-               if (__nft_expr_type_get(nla))
+               if (__nft_expr_type_get(family, nla))
                        return ERR_PTR(-EAGAIN);
        }
 #endif
@@ -1193,7 +1203,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
        if (err < 0)
                return err;
 
-       type = nft_expr_type_get(tb[NFTA_EXPR_NAME]);
+       type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]);
        if (IS_ERR(type))
                return PTR_ERR(type);
 
@@ -1521,9 +1531,8 @@ err:
        return err;
 }
 
-static void nf_tables_rcu_rule_destroy(struct rcu_head *head)
+static void nf_tables_rule_destroy(struct nft_rule *rule)
 {
-       struct nft_rule *rule = container_of(head, struct nft_rule, rcu_head);
        struct nft_expr *expr;
 
        /*
@@ -1538,11 +1547,6 @@ static void nf_tables_rcu_rule_destroy(struct rcu_head *head)
        kfree(rule);
 }
 
-static void nf_tables_rule_destroy(struct nft_rule *rule)
-{
-       call_rcu(&rule->rcu_head, nf_tables_rcu_rule_destroy);
-}
-
 #define NFT_RULE_MAXEXPRS      128
 
 static struct nft_expr_info *info;
@@ -1809,9 +1813,6 @@ static int nf_tables_commit(struct sk_buff *skb)
        synchronize_rcu();
 
        list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
-               /* Delete this rule from the dirty list */
-               list_del(&rupd->list);
-
                /* This rule was inactive in the past and just became active.
                 * Clear the next bit of the genmask since its meaning has
                 * changed, now it is the future.
@@ -1822,6 +1823,7 @@ static int nf_tables_commit(struct sk_buff *skb)
                                              rupd->chain, rupd->rule,
                                              NFT_MSG_NEWRULE, 0,
                                              rupd->family);
+                       list_del(&rupd->list);
                        kfree(rupd);
                        continue;
                }
@@ -1831,7 +1833,15 @@ static int nf_tables_commit(struct sk_buff *skb)
                nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain,
                                      rupd->rule, NFT_MSG_DELRULE, 0,
                                      rupd->family);
+       }
+
+       /* Make sure we don't see any packet traversing old rules */
+       synchronize_rcu();
+
+       /* Now we can safely release unused old rules */
+       list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
                nf_tables_rule_destroy(rupd->rule);
+               list_del(&rupd->list);
                kfree(rupd);
        }
 
@@ -1844,20 +1854,26 @@ static int nf_tables_abort(struct sk_buff *skb)
        struct nft_rule_trans *rupd, *tmp;
 
        list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
-               /* Delete all rules from the dirty list */
-               list_del(&rupd->list);
-
                if (!nft_rule_is_active_next(net, rupd->rule)) {
                        nft_rule_clear(net, rupd->rule);
+                       list_del(&rupd->list);
                        kfree(rupd);
                        continue;
                }
 
                /* This rule is inactive, get rid of it */
                list_del_rcu(&rupd->rule->list);
+       }
+
+       /* Make sure we don't see any packet accessing aborted rules */
+       synchronize_rcu();
+
+       list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
                nf_tables_rule_destroy(rupd->rule);
+               list_del(&rupd->list);
                kfree(rupd);
        }
+
        return 0;
 }
 
@@ -1943,6 +1959,9 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
        }
 
        if (nla[NFTA_SET_TABLE] != NULL) {
+               if (afi == NULL)
+                       return -EAFNOSUPPORT;
+
                table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
                if (IS_ERR(table))
                        return PTR_ERR(table);
@@ -1989,13 +2008,13 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
 
                        if (!sscanf(i->name, name, &tmp))
                                continue;
-                       if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE)
+                       if (tmp < 0 || tmp >= BITS_PER_BYTE * PAGE_SIZE)
                                continue;
 
                        set_bit(tmp, inuse);
                }
 
-               n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE);
+               n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE);
                free_page((unsigned long)inuse);
        }
 
@@ -2428,6 +2447,8 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
        struct nft_ctx ctx;
        int err;
 
+       if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
+               return -EAFNOSUPPORT;
        if (nla[NFTA_SET_TABLE] == NULL)
                return -EINVAL;
 
@@ -2435,9 +2456,6 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
        if (err < 0)
                return err;
 
-       if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
-               return -EAFNOSUPPORT;
-
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
        if (IS_ERR(set))
                return PTR_ERR(set);
@@ -2723,6 +2741,9 @@ static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set,
                if (nla[NFTA_SET_ELEM_DATA] == NULL &&
                    !(elem.flags & NFT_SET_ELEM_INTERVAL_END))
                        return -EINVAL;
+               if (nla[NFTA_SET_ELEM_DATA] != NULL &&
+                   elem.flags & NFT_SET_ELEM_INTERVAL_END)
+                       return -EINVAL;
        } else {
                if (nla[NFTA_SET_ELEM_DATA] != NULL)
                        return -EINVAL;
@@ -2977,6 +2998,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
                                        const struct nft_set_iter *iter,
                                        const struct nft_set_elem *elem)
 {
+       if (elem->flags & NFT_SET_ELEM_INTERVAL_END)
+               return 0;
+
        switch (elem->data.verdict) {
        case NFT_JUMP:
        case NFT_GOTO:
index 0d879fcb8763c043430d242d68524e0256c4411d..90998a6ff8b9c1f10712e07d9b753e7d7d1bb2fd 100644 (file)
@@ -103,9 +103,9 @@ static struct nf_loginfo trace_loginfo = {
        },
 };
 
-static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
-                                   const struct nft_chain *chain,
-                                   int rulenum, enum nft_trace type)
+static void nft_trace_packet(const struct nft_pktinfo *pkt,
+                            const struct nft_chain *chain,
+                            int rulenum, enum nft_trace type)
 {
        struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
 
index f072fe803510320f7210c31b1a08ccddea5ae5b6..108120f216b17671351cb492c86cb0ae928504f6 100644 (file)
@@ -354,13 +354,16 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 
        skb = nfnetlink_alloc_skb(net, size, queue->peer_portid,
                                  GFP_ATOMIC);
-       if (!skb)
+       if (!skb) {
+               skb_tx_error(entskb);
                return NULL;
+       }
 
        nlh = nlmsg_put(skb, 0, 0,
                        NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
                        sizeof(struct nfgenmsg), 0);
        if (!nlh) {
+               skb_tx_error(entskb);
                kfree_skb(skb);
                return NULL;
        }
@@ -488,13 +491,15 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                nla->nla_type = NFQA_PAYLOAD;
                nla->nla_len = nla_attr_size(data_len);
 
-               skb_zerocopy(skb, entskb, data_len, hlen);
+               if (skb_zerocopy(skb, entskb, data_len, hlen))
+                       goto nla_put_failure;
        }
 
        nlh->nlmsg_len = skb->len;
        return skb;
 
 nla_put_failure:
+       skb_tx_error(entskb);
        kfree_skb(skb);
        net_err_ratelimited("nf_queue: error creating packet message\n");
        return NULL;
index 917052e20602ea1b7cca286edfbe01e429703327..46e2754038387cf978679e2fd4f1032b30e40bd6 100644 (file)
@@ -226,6 +226,7 @@ static int nft_ct_init_validate_get(const struct nft_expr *expr,
                if (tb[NFTA_CT_DIRECTION] != NULL)
                        return -EINVAL;
                break;
+       case NFT_CT_L3PROTOCOL:
        case NFT_CT_PROTOCOL:
        case NFT_CT_SRC:
        case NFT_CT_DST:
@@ -311,8 +312,19 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
                goto nla_put_failure;
        if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
                goto nla_put_failure;
-       if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
-               goto nla_put_failure;
+
+       switch (priv->key) {
+       case NFT_CT_PROTOCOL:
+       case NFT_CT_SRC:
+       case NFT_CT_DST:
+       case NFT_CT_PROTO_SRC:
+       case NFT_CT_PROTO_DST:
+               if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
+                       goto nla_put_failure;
+       default:
+               break;
+       }
+
        return 0;
 
 nla_put_failure:
index 5af790123ad865dbb88c9e172ed4b9beb8590e01..26c5154e05f3fc09aae2ebdea968ce564a3d5eb9 100644 (file)
@@ -23,7 +23,6 @@ static const char *nft_log_null_prefix = "";
 struct nft_log {
        struct nf_loginfo       loginfo;
        char                    *prefix;
-       int                     family;
 };
 
 static void nft_log_eval(const struct nft_expr *expr,
@@ -33,7 +32,7 @@ static void nft_log_eval(const struct nft_expr *expr,
        const struct nft_log *priv = nft_expr_priv(expr);
        struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
 
-       nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in,
+       nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in,
                      pkt->out, &priv->loginfo, "%s", priv->prefix);
 }
 
@@ -52,8 +51,6 @@ static int nft_log_init(const struct nft_ctx *ctx,
        struct nf_loginfo *li = &priv->loginfo;
        const struct nlattr *nla;
 
-       priv->family = ctx->afi->family;
-
        nla = tb[NFTA_LOG_PREFIX];
        if (nla != NULL) {
                priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL);
index 8a6116b75b5a03181e3183d5090c23059dd5a09e..bb4ef4cccb6efcdf937bc3417eb8dbd6ccf0e22f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
 
 struct nft_lookup {
        struct nft_set                  *set;
index e8254ad2e5a9f37e84694293c8ba4069b5e5f35e..425cf39af8907f1d0618b0904121073ea4dc116a 100644 (file)
@@ -116,7 +116,7 @@ static void nft_meta_get_eval(const struct nft_expr *expr,
                                 skb->sk->sk_socket->file->f_cred->fsgid);
                read_unlock_bh(&skb->sk->sk_callback_lock);
                break;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
        case NFT_META_RTCLASSID: {
                const struct dst_entry *dst = skb_dst(skb);
 
@@ -199,7 +199,7 @@ static int nft_meta_init_validate_get(uint32_t key)
        case NFT_META_OIFTYPE:
        case NFT_META_SKUID:
        case NFT_META_SKGID:
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
        case NFT_META_RTCLASSID:
 #endif
 #ifdef CONFIG_NETWORK_SECMARK
index a2aeb318678f9e0e577801f6e42bda4df66ea805..85daa84bfdfee3d65296fb62c723a78e180c4497 100644 (file)
@@ -135,7 +135,8 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
        if (len == 0 || len > FIELD_SIZEOF(struct nft_data, data))
                return ERR_PTR(-EINVAL);
 
-       if (len <= 4 && IS_ALIGNED(offset, len) && base != NFT_PAYLOAD_LL_HEADER)
+       if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
+           base != NFT_PAYLOAD_LL_HEADER)
                return &nft_payload_fast_ops;
        else
                return &nft_payload_ops;
index cbea473d69e953e9ba9e9d36ec4962aa3af57c1e..e8ae2f6bf232d8ccef7379f9bb573291da5581b4 100644 (file)
@@ -25,7 +25,6 @@ struct nft_queue {
        u16     queuenum;
        u16     queues_total;
        u16     flags;
-       u8      family;
 };
 
 static void nft_queue_eval(const struct nft_expr *expr,
@@ -43,7 +42,7 @@ static void nft_queue_eval(const struct nft_expr *expr,
                        queue = priv->queuenum + cpu % priv->queues_total;
                } else {
                        queue = nfqueue_hash(pkt->skb, queue,
-                                            priv->queues_total, priv->family,
+                                            priv->queues_total, pkt->ops->pf,
                                             jhash_initval);
                }
        }
@@ -71,7 +70,6 @@ static int nft_queue_init(const struct nft_ctx *ctx,
                return -EINVAL;
 
        init_hashrandom(&jhash_initval);
-       priv->family = ctx->afi->family;
        priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
 
        if (tb[NFTA_QUEUE_TOTAL] != NULL)
index ca0c1b231bfe25cfe3c341c2aea8967f0dd4a4ec..e21d69d13506b95946820f24641fe7e48d885866 100644 (file)
@@ -69,8 +69,10 @@ static void nft_rbtree_elem_destroy(const struct nft_set *set,
                                    struct nft_rbtree_elem *rbe)
 {
        nft_data_uninit(&rbe->key, NFT_DATA_VALUE);
-       if (set->flags & NFT_SET_MAP)
+       if (set->flags & NFT_SET_MAP &&
+           !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
                nft_data_uninit(rbe->data, set->dtype);
+
        kfree(rbe);
 }
 
@@ -108,7 +110,8 @@ static int nft_rbtree_insert(const struct nft_set *set,
        int err;
 
        size = sizeof(*rbe);
-       if (set->flags & NFT_SET_MAP)
+       if (set->flags & NFT_SET_MAP &&
+           !(elem->flags & NFT_SET_ELEM_INTERVAL_END))
                size += sizeof(rbe->data[0]);
 
        rbe = kzalloc(size, GFP_KERNEL);
@@ -117,7 +120,8 @@ static int nft_rbtree_insert(const struct nft_set *set,
 
        rbe->flags = elem->flags;
        nft_data_copy(&rbe->key, &elem->key);
-       if (set->flags & NFT_SET_MAP)
+       if (set->flags & NFT_SET_MAP &&
+           !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
                nft_data_copy(rbe->data, &elem->data);
 
        err = __nft_rbtree_insert(set, rbe);
@@ -153,7 +157,8 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
                        parent = parent->rb_right;
                else {
                        elem->cookie = rbe;
-                       if (set->flags & NFT_SET_MAP)
+                       if (set->flags & NFT_SET_MAP &&
+                           !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
                                nft_data_copy(&elem->data, rbe->data);
                        elem->flags = rbe->flags;
                        return 0;
@@ -177,7 +182,8 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
 
                rbe = rb_entry(node, struct nft_rbtree_elem, node);
                nft_data_copy(&elem.key, &rbe->key);
-               if (set->flags & NFT_SET_MAP)
+               if (set->flags & NFT_SET_MAP &&
+                   !(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
                        nft_data_copy(&elem.data, rbe->data);
                elem.flags = rbe->flags;
 
index 5e204711d7049781052095ca317a4efd944ea07a..f3448c2964468abc08d2b3630be18953820e1aff 100644 (file)
 #include <linux/netfilter.h>
 #include <linux/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables.h>
-#include <net/icmp.h>
-#include <net/netfilter/ipv4/nf_reject.h>
+#include <net/netfilter/nft_reject.h>
 
-#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
-#include <net/netfilter/ipv6/nf_reject.h>
-#endif
-
-struct nft_reject {
-       enum nft_reject_types   type:8;
-       u8                      icmp_code;
-       u8                      family;
-};
-
-static void nft_reject_eval(const struct nft_expr *expr,
-                             struct nft_data data[NFT_REG_MAX + 1],
-                             const struct nft_pktinfo *pkt)
-{
-       struct nft_reject *priv = nft_expr_priv(expr);
-#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
-       struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
-#endif
-       switch (priv->type) {
-       case NFT_REJECT_ICMP_UNREACH:
-               if (priv->family == NFPROTO_IPV4)
-                       nf_send_unreach(pkt->skb, priv->icmp_code);
-#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
-               else if (priv->family == NFPROTO_IPV6)
-                       nf_send_unreach6(net, pkt->skb, priv->icmp_code,
-                                     pkt->ops->hooknum);
-#endif
-               break;
-       case NFT_REJECT_TCP_RST:
-               if (priv->family == NFPROTO_IPV4)
-                       nf_send_reset(pkt->skb, pkt->ops->hooknum);
-#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
-               else if (priv->family == NFPROTO_IPV6)
-                       nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
-#endif
-               break;
-       }
-
-       data[NFT_REG_VERDICT].verdict = NF_DROP;
-}
-
-static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
+const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
        [NFTA_REJECT_TYPE]              = { .type = NLA_U32 },
        [NFTA_REJECT_ICMP_CODE]         = { .type = NLA_U8 },
 };
+EXPORT_SYMBOL_GPL(nft_reject_policy);
 
-static int nft_reject_init(const struct nft_ctx *ctx,
-                          const struct nft_expr *expr,
-                          const struct nlattr * const tb[])
+int nft_reject_init(const struct nft_ctx *ctx,
+                   const struct nft_expr *expr,
+                   const struct nlattr * const tb[])
 {
        struct nft_reject *priv = nft_expr_priv(expr);
 
        if (tb[NFTA_REJECT_TYPE] == NULL)
                return -EINVAL;
 
-       priv->family = ctx->afi->family;
        priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
        switch (priv->type) {
        case NFT_REJECT_ICMP_UNREACH:
@@ -89,8 +47,9 @@ static int nft_reject_init(const struct nft_ctx *ctx,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(nft_reject_init);
 
-static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
+int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
        const struct nft_reject *priv = nft_expr_priv(expr);
 
@@ -109,37 +68,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
 nla_put_failure:
        return -1;
 }
-
-static struct nft_expr_type nft_reject_type;
-static const struct nft_expr_ops nft_reject_ops = {
-       .type           = &nft_reject_type,
-       .size           = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
-       .eval           = nft_reject_eval,
-       .init           = nft_reject_init,
-       .dump           = nft_reject_dump,
-};
-
-static struct nft_expr_type nft_reject_type __read_mostly = {
-       .name           = "reject",
-       .ops            = &nft_reject_ops,
-       .policy         = nft_reject_policy,
-       .maxattr        = NFTA_REJECT_MAX,
-       .owner          = THIS_MODULE,
-};
-
-static int __init nft_reject_module_init(void)
-{
-       return nft_register_expr(&nft_reject_type);
-}
-
-static void __exit nft_reject_module_exit(void)
-{
-       nft_unregister_expr(&nft_reject_type);
-}
-
-module_init(nft_reject_module_init);
-module_exit(nft_reject_module_exit);
+EXPORT_SYMBOL_GPL(nft_reject_dump);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_ALIAS_NFT_EXPR("reject");
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c
new file mode 100644 (file)
index 0000000..b718a52
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 Patrick McHardy <kaber@trash.net>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nft_reject.h>
+
+static void nft_reject_inet_eval(const struct nft_expr *expr,
+                                struct nft_data data[NFT_REG_MAX + 1],
+                                const struct nft_pktinfo *pkt)
+{
+       switch (pkt->ops->pf) {
+       case NFPROTO_IPV4:
+               return nft_reject_ipv4_eval(expr, data, pkt);
+       case NFPROTO_IPV6:
+               return nft_reject_ipv6_eval(expr, data, pkt);
+       }
+}
+
+static struct nft_expr_type nft_reject_inet_type;
+static const struct nft_expr_ops nft_reject_inet_ops = {
+       .type           = &nft_reject_inet_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
+       .eval           = nft_reject_inet_eval,
+       .init           = nft_reject_init,
+       .dump           = nft_reject_dump,
+};
+
+static struct nft_expr_type nft_reject_inet_type __read_mostly = {
+       .family         = NFPROTO_INET,
+       .name           = "reject",
+       .ops            = &nft_reject_inet_ops,
+       .policy         = nft_reject_policy,
+       .maxattr        = NFTA_REJECT_MAX,
+       .owner          = THIS_MODULE,
+};
+
+static int __init nft_reject_inet_module_init(void)
+{
+       return nft_register_expr(&nft_reject_inet_type);
+}
+
+static void __exit nft_reject_inet_module_exit(void)
+{
+       nft_unregister_expr(&nft_reject_inet_type);
+}
+
+module_init(nft_reject_inet_module_init);
+module_exit(nft_reject_inet_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS_NFT_AF_EXPR(1, "reject");
index 5929be622c5cd27b9e706811042c9e176a3c78f7..75747aecdebe6344ccbfcf178c299be013d8f763 100644 (file)
@@ -228,12 +228,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
                        goto err3;
        }
 
-       __set_bit(IPS_TEMPLATE_BIT, &ct->status);
-       __set_bit(IPS_CONFIRMED_BIT, &ct->status);
-
-       /* Overload tuple linked list to put us in template list. */
-       hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
-                                &par->net->ct.tmpl);
+       nf_conntrack_tmpl_insert(par->net, ct);
 out:
        info->ct = ct;
        return 0;
index fdf51353cf78ac80958cadfa0e58e159970aa8bf..04748ab649c25bbb2d2d7cee6fbc192fb267dfbc 100644 (file)
@@ -1489,8 +1489,8 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
        if (addr->sa_family != AF_NETLINK)
                return -EINVAL;
 
-       /* Only superuser is allowed to send multicasts */
-       if (nladdr->nl_groups && !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
+       if ((nladdr->nl_groups || nladdr->nl_pid) &&
+           !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
                return -EPERM;
 
        if (!nlk->portid)
index 46bda010bf11740c1a2fcd9002a193a7ab70801a..56db888b1cd56785e23f0e0272d4ae3af87e32e6 100644 (file)
@@ -301,7 +301,7 @@ static int nci_open_device(struct nci_dev *ndev)
        rc = __nci_request(ndev, nci_reset_req, 0,
                           msecs_to_jiffies(NCI_RESET_TIMEOUT));
 
-       if (ndev->ops->setup(ndev))
+       if (ndev->ops->setup)
                ndev->ops->setup(ndev);
 
        if (!rc) {
index df4692826ead9ef8b5761f58ef7218bf4b3f5119..270b77dfac304afea375d4a5999b88cca863da90 100644 (file)
@@ -55,6 +55,7 @@
 
 #include "datapath.h"
 #include "flow.h"
+#include "flow_table.h"
 #include "flow_netlink.h"
 #include "vport-internal_dev.h"
 #include "vport-netdev.h"
@@ -160,7 +161,6 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
 {
        struct datapath *dp = container_of(rcu, struct datapath, rcu);
 
-       ovs_flow_tbl_destroy(&dp->table);
        free_percpu(dp->stats_percpu);
        release_net(ovs_dp_get_net(dp));
        kfree(dp->ports);
@@ -464,12 +464,24 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
        }
        nla->nla_len = nla_attr_size(skb->len);
 
-       skb_zerocopy(user_skb, skb, skb->len, hlen);
+       err = skb_zerocopy(user_skb, skb, skb->len, hlen);
+       if (err)
+               goto out;
+
+       /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */
+       if (!(dp->user_features & OVS_DP_F_UNALIGNED)) {
+               size_t plen = NLA_ALIGN(user_skb->len) - user_skb->len;
+
+               if (plen > 0)
+                       memset(skb_put(user_skb, plen), 0, plen);
+       }
 
        ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len;
 
        err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
 out:
+       if (err)
+               skb_tx_error(skb);
        kfree_skb(nskb);
        return err;
 }
@@ -852,11 +864,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
                        goto err_unlock_ovs;
 
                /* The unmasked key has to be the same for flow updates. */
-               error = -EINVAL;
-               if (!ovs_flow_cmp_unmasked_key(flow, &match)) {
-                       OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n");
+               if (!ovs_flow_cmp_unmasked_key(flow, &match))
                        goto err_unlock_ovs;
-               }
 
                /* Update actions. */
                old_acts = ovsl_dereference(flow->sf_acts);
@@ -1079,6 +1088,7 @@ static size_t ovs_dp_cmd_msg_size(void)
        msgsize += nla_total_size(IFNAMSIZ);
        msgsize += nla_total_size(sizeof(struct ovs_dp_stats));
        msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats));
+       msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */
 
        return msgsize;
 }
@@ -1168,7 +1178,7 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *in
        struct datapath *dp;
 
        dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
-       if (!dp)
+       if (IS_ERR(dp))
                return;
 
        WARN(dp->user_features, "Dropping previously announced user features\n");
@@ -1279,7 +1289,7 @@ err_destroy_ports_array:
 err_destroy_percpu:
        free_percpu(dp->stats_percpu);
 err_destroy_table:
-       ovs_flow_tbl_destroy(&dp->table);
+       ovs_flow_tbl_destroy(&dp->table, false);
 err_free_dp:
        release_net(ovs_dp_get_net(dp));
        kfree(dp);
@@ -1306,10 +1316,13 @@ static void __dp_destroy(struct datapath *dp)
        list_del_rcu(&dp->list_node);
 
        /* OVSP_LOCAL is datapath internal port. We need to make sure that
-        * all port in datapath are destroyed first before freeing datapath.
+        * all ports in datapath are destroyed first before freeing datapath.
         */
        ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
 
+       /* RCU destroy the flow table */
+       ovs_flow_tbl_destroy(&dp->table, true);
+
        call_rcu(&dp->rcu, destroy_dp_rcu);
 }
 
@@ -1753,11 +1766,12 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
        int bucket = cb->args[0], skip = cb->args[1];
        int i, j = 0;
 
+       rcu_read_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
-       if (!dp)
+       if (!dp) {
+               rcu_read_unlock();
                return -ENODEV;
-
-       rcu_read_lock();
+       }
        for (i = bucket; i < DP_VPORT_HASH_BUCKETS; i++) {
                struct vport *vport;
 
index 16f4b46161d4fe2b806a46e895aa46922e2ce038..2998989e76db0a7ccb8e25ef11aa393180956593 100644 (file)
@@ -73,6 +73,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
 
        if ((flow->key.eth.type == htons(ETH_P_IP) ||
             flow->key.eth.type == htons(ETH_P_IPV6)) &&
+           flow->key.ip.frag != OVS_FRAG_TYPE_LATER &&
            flow->key.ip.proto == IPPROTO_TCP &&
            likely(skb->len >= skb_transport_offset(skb) + sizeof(struct tcphdr))) {
                tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
@@ -91,7 +92,7 @@ static void stats_read(struct flow_stats *stats,
                       unsigned long *used, __be16 *tcp_flags)
 {
        spin_lock(&stats->lock);
-       if (time_after(stats->used, *used))
+       if (!*used || time_after(stats->used, *used))
                *used = stats->used;
        *tcp_flags |= stats->tcp_flags;
        ovs_stats->n_packets += stats->packet_count;
@@ -102,30 +103,24 @@ static void stats_read(struct flow_stats *stats,
 void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
                        unsigned long *used, __be16 *tcp_flags)
 {
-       int cpu, cur_cpu;
+       int cpu;
 
        *used = 0;
        *tcp_flags = 0;
        memset(ovs_stats, 0, sizeof(*ovs_stats));
 
+       local_bh_disable();
        if (!flow->stats.is_percpu) {
                stats_read(flow->stats.stat, ovs_stats, used, tcp_flags);
        } else {
-               cur_cpu = get_cpu();
                for_each_possible_cpu(cpu) {
                        struct flow_stats *stats;
 
-                       if (cpu == cur_cpu)
-                               local_bh_disable();
-
                        stats = per_cpu_ptr(flow->stats.cpu_stats, cpu);
                        stats_read(stats, ovs_stats, used, tcp_flags);
-
-                       if (cpu == cur_cpu)
-                               local_bh_enable();
                }
-               put_cpu();
        }
+       local_bh_enable();
 }
 
 static void stats_reset(struct flow_stats *stats)
@@ -140,25 +135,17 @@ static void stats_reset(struct flow_stats *stats)
 
 void ovs_flow_stats_clear(struct sw_flow *flow)
 {
-       int cpu, cur_cpu;
+       int cpu;
 
+       local_bh_disable();
        if (!flow->stats.is_percpu) {
                stats_reset(flow->stats.stat);
        } else {
-               cur_cpu = get_cpu();
-
                for_each_possible_cpu(cpu) {
-
-                       if (cpu == cur_cpu)
-                               local_bh_disable();
-
                        stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu));
-
-                       if (cpu == cur_cpu)
-                               local_bh_enable();
                }
-               put_cpu();
        }
+       local_bh_enable();
 }
 
 static int check_header(struct sk_buff *skb, int len)
index c58a0fe3c8892d4e09eb7377b60a06ae469efb09..3c268b3d71c34baa0a8c70888823b37da454fffd 100644 (file)
@@ -153,29 +153,29 @@ static void rcu_free_flow_callback(struct rcu_head *rcu)
        flow_free(flow);
 }
 
-static void flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
-{
-       if (!mask)
-               return;
-
-       BUG_ON(!mask->ref_count);
-       mask->ref_count--;
-
-       if (!mask->ref_count) {
-               list_del_rcu(&mask->list);
-               if (deferred)
-                       kfree_rcu(mask, rcu);
-               else
-                       kfree(mask);
-       }
-}
-
 void ovs_flow_free(struct sw_flow *flow, bool deferred)
 {
        if (!flow)
                return;
 
-       flow_mask_del_ref(flow->mask, deferred);
+       if (flow->mask) {
+               struct sw_flow_mask *mask = flow->mask;
+
+               /* ovs-lock is required to protect mask-refcount and
+                * mask list.
+                */
+               ASSERT_OVSL();
+               BUG_ON(!mask->ref_count);
+               mask->ref_count--;
+
+               if (!mask->ref_count) {
+                       list_del_rcu(&mask->list);
+                       if (deferred)
+                               kfree_rcu(mask, rcu);
+                       else
+                               kfree(mask);
+               }
+       }
 
        if (deferred)
                call_rcu(&flow->rcu, rcu_free_flow_callback);
@@ -188,26 +188,9 @@ static void free_buckets(struct flex_array *buckets)
        flex_array_free(buckets);
 }
 
+
 static void __table_instance_destroy(struct table_instance *ti)
 {
-       int i;
-
-       if (ti->keep_flows)
-               goto skip_flows;
-
-       for (i = 0; i < ti->n_buckets; i++) {
-               struct sw_flow *flow;
-               struct hlist_head *head = flex_array_get(ti->buckets, i);
-               struct hlist_node *n;
-               int ver = ti->node_ver;
-
-               hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) {
-                       hlist_del(&flow->hash_node[ver]);
-                       ovs_flow_free(flow, false);
-               }
-       }
-
-skip_flows:
        free_buckets(ti->buckets);
        kfree(ti);
 }
@@ -258,20 +241,38 @@ static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu)
 
 static void table_instance_destroy(struct table_instance *ti, bool deferred)
 {
+       int i;
+
        if (!ti)
                return;
 
+       if (ti->keep_flows)
+               goto skip_flows;
+
+       for (i = 0; i < ti->n_buckets; i++) {
+               struct sw_flow *flow;
+               struct hlist_head *head = flex_array_get(ti->buckets, i);
+               struct hlist_node *n;
+               int ver = ti->node_ver;
+
+               hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) {
+                       hlist_del_rcu(&flow->hash_node[ver]);
+                       ovs_flow_free(flow, deferred);
+               }
+       }
+
+skip_flows:
        if (deferred)
                call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
        else
                __table_instance_destroy(ti);
 }
 
-void ovs_flow_tbl_destroy(struct flow_table *table)
+void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred)
 {
        struct table_instance *ti = ovsl_dereference(table->ti);
 
-       table_instance_destroy(ti, false);
+       table_instance_destroy(ti, deferred);
 }
 
 struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
@@ -504,16 +505,11 @@ static struct sw_flow_mask *mask_alloc(void)
 
        mask = kmalloc(sizeof(*mask), GFP_KERNEL);
        if (mask)
-               mask->ref_count = 0;
+               mask->ref_count = 1;
 
        return mask;
 }
 
-static void mask_add_ref(struct sw_flow_mask *mask)
-{
-       mask->ref_count++;
-}
-
 static bool mask_equal(const struct sw_flow_mask *a,
                       const struct sw_flow_mask *b)
 {
@@ -554,9 +550,11 @@ static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
                mask->key = new->key;
                mask->range = new->range;
                list_add_rcu(&mask->list, &tbl->mask_list);
+       } else {
+               BUG_ON(!mask->ref_count);
+               mask->ref_count++;
        }
 
-       mask_add_ref(mask);
        flow->mask = mask;
        return 0;
 }
index 1996e34c0fd85b1a9f88c3e328fe191146be5b51..baaeb101924d81a4beb373be93e07287ed9be020 100644 (file)
@@ -60,7 +60,7 @@ void ovs_flow_free(struct sw_flow *, bool deferred);
 
 int ovs_flow_tbl_init(struct flow_table *);
 int ovs_flow_tbl_count(struct flow_table *table);
-void ovs_flow_tbl_destroy(struct flow_table *table);
+void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred);
 int ovs_flow_tbl_flush(struct flow_table *flow_table);
 
 int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
index 6a2bb37506c567c1f03de74bf51eb8aa357e318e..48a6a93db29602c032fe254d4a1d41cbc7b3f051 100644 (file)
@@ -308,11 +308,27 @@ static bool packet_use_direct_xmit(const struct packet_sock *po)
        return po->xmit == packet_direct_xmit;
 }
 
-static u16 packet_pick_tx_queue(struct net_device *dev)
+static u16 __packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)
 {
        return (u16) raw_smp_processor_id() % dev->real_num_tx_queues;
 }
 
+static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+       u16 queue_index;
+
+       if (ops->ndo_select_queue) {
+               queue_index = ops->ndo_select_queue(dev, skb, NULL,
+                                                   __packet_pick_tx_queue);
+               queue_index = netdev_cap_txqueue(dev, queue_index);
+       } else {
+               queue_index = __packet_pick_tx_queue(dev, skb);
+       }
+
+       skb_set_queue_mapping(skb, queue_index);
+}
+
 /* register_prot_hook must be invoked with the po->bind_lock held,
  * or from a context in which asynchronous accesses to the packet
  * socket is not possible (packet_create()).
@@ -2285,7 +2301,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                        }
                }
 
-               skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
+               packet_pick_tx_queue(dev, skb);
+
                skb->destructor = tpacket_destruct_skb;
                __packet_set_status(po, ph, TP_STATUS_SENDING);
                packet_inc_pending(&po->tx_ring);
@@ -2499,7 +2516,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        skb->dev = dev;
        skb->priority = sk->sk_priority;
        skb->mark = sk->sk_mark;
-       skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
+
+       packet_pick_tx_queue(dev, skb);
 
        if (po->has_vnet_hdr) {
                if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
@@ -3786,7 +3804,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                 */
                        if (!tx_ring)
                                init_prb_bdqc(po, rb, pg_vec, req_u, tx_ring);
-                               break;
+                       break;
                default:
                        break;
                }
index 1313145e3b8650853514552a0ddb371b4000b788..a07d55e75698cf52068ebd54fb651a45d264817a 100644 (file)
@@ -273,11 +273,12 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
 
 void qdisc_list_add(struct Qdisc *q)
 {
-       struct Qdisc *root = qdisc_dev(q)->qdisc;
+       if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
+               struct Qdisc *root = qdisc_dev(q)->qdisc;
 
-       WARN_ON_ONCE(root == &noop_qdisc);
-       if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS))
+               WARN_ON_ONCE(root == &noop_qdisc);
                list_add_tail(&q->list, &root->list);
+       }
 }
 EXPORT_SYMBOL(qdisc_list_add);
 
index 08ef7a42c0e411657e789cb140fad522aef97ed1..21e251766eb1a099c8f603c1f7bb5d33ec5b04a2 100644 (file)
@@ -601,6 +601,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
 {
        struct fq_sched_data *q = qdisc_priv(sch);
        struct rb_root *array;
+       void *old_fq_root;
        u32 idx;
 
        if (q->fq_root && log == q->fq_trees_log)
@@ -615,13 +616,19 @@ static int fq_resize(struct Qdisc *sch, u32 log)
        for (idx = 0; idx < (1U << log); idx++)
                array[idx] = RB_ROOT;
 
-       if (q->fq_root) {
-               fq_rehash(q, q->fq_root, q->fq_trees_log, array, log);
-               fq_free(q->fq_root);
-       }
+       sch_tree_lock(sch);
+
+       old_fq_root = q->fq_root;
+       if (old_fq_root)
+               fq_rehash(q, old_fq_root, q->fq_trees_log, array, log);
+
        q->fq_root = array;
        q->fq_trees_log = log;
 
+       sch_tree_unlock(sch);
+
+       fq_free(old_fq_root);
+
        return 0;
 }
 
@@ -697,9 +704,11 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
                q->flow_refill_delay = usecs_to_jiffies(usecs_delay);
        }
 
-       if (!err)
+       if (!err) {
+               sch_tree_unlock(sch);
                err = fq_resize(sch, fq_log);
-
+               sch_tree_lock(sch);
+       }
        while (sch->q.qlen > sch->limit) {
                struct sk_buff *skb = fq_dequeue(sch);
 
index a255d0200a593a708a6f30f4e9dbb70fabb917c3..fefeeb73f15f18a84406ed686dc653ff3327ef45 100644 (file)
  *
  * ECN support is added by Naeem Khademi <naeemk@ifi.uio.no>
  * University of Oslo, Norway.
+ *
+ * References:
+ * IETF draft submission: http://tools.ietf.org/html/draft-pan-aqm-pie-00
+ * IEEE  Conference on High Performance Switching and Routing 2013 :
+ * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem"
  */
 
 #include <linux/module.h>
@@ -36,7 +41,7 @@ struct pie_params {
        psched_time_t target;   /* user specified target delay in pschedtime */
        u32 tupdate;            /* timer frequency (in jiffies) */
        u32 limit;              /* number of packets that can be enqueued */
-       u32 alpha;              /* alpha and beta are between -4 and 4 */
+       u32 alpha;              /* alpha and beta are between 0 and 32 */
        u32 beta;               /* and are used for shift relative to 1 */
        bool ecn;               /* true if ecn is enabled */
        bool bytemode;          /* to scale drop early prob based on pkt size */
@@ -326,10 +331,16 @@ static void calculate_probability(struct Qdisc *sch)
        if (qdelay == 0 && qlen != 0)
                update_prob = false;
 
-       /* Add ranges for alpha and beta, more aggressive for high dropping
-        * mode and gentle steps for light dropping mode
-        * In light dropping mode, take gentle steps; in medium dropping mode,
-        * take medium steps; in high dropping mode, take big steps.
+       /* In the algorithm, alpha and beta are between 0 and 2 with typical
+        * value for alpha as 0.125. In this implementation, we use values 0-32
+        * passed from user space to represent this. Also, alpha and beta have
+        * unit of HZ and need to be scaled before they can used to update
+        * probability. alpha/beta are updated locally below by 1) scaling them
+        * appropriately 2) scaling down by 16 to come to 0-2 range.
+        * Please see paper for details.
+        *
+        * We scale alpha and beta differently depending on whether we are in
+        * light, medium or high dropping mode.
         */
        if (q->vars.prob < MAX_PROB / 100) {
                alpha =
index 1cb413fead89522a64931a4e2472b39c4d6a720d..4f505a006896578ebdac1392af1dc064500665c9 100644 (file)
@@ -334,18 +334,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                        qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate,
                                                      tb[TCA_TBF_PTAB]));
 
-       if (q->qdisc != &noop_qdisc) {
-               err = fifo_set_limit(q->qdisc, qopt->limit);
-               if (err)
-                       goto done;
-       } else if (qopt->limit > 0) {
-               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
-               if (IS_ERR(child)) {
-                       err = PTR_ERR(child);
-                       goto done;
-               }
-       }
-
        buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
        mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
 
@@ -390,6 +378,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                goto done;
        }
 
+       if (q->qdisc != &noop_qdisc) {
+               err = fifo_set_limit(q->qdisc, qopt->limit);
+               if (err)
+                       goto done;
+       } else if (qopt->limit > 0) {
+               child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
+               if (IS_ERR(child)) {
+                       err = PTR_ERR(child);
+                       goto done;
+               }
+       }
+
        sch_tree_lock(sch);
        if (child) {
                qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
index 5ae60920067470463420f0b3aa879e7c0999f200..ee13d28d39d10702096f733ee8d88aa862459952 100644 (file)
@@ -1239,78 +1239,107 @@ void sctp_assoc_update(struct sctp_association *asoc,
 }
 
 /* Update the retran path for sending a retransmitted packet.
- * Round-robin through the active transports, else round-robin
- * through the inactive transports as this is the next best thing
- * we can try.
+ * See also RFC4960, 6.4. Multi-Homed SCTP Endpoints:
+ *
+ *   When there is outbound data to send and the primary path
+ *   becomes inactive (e.g., due to failures), or where the
+ *   SCTP user explicitly requests to send data to an
+ *   inactive destination transport address, before reporting
+ *   an error to its ULP, the SCTP endpoint should try to send
+ *   the data to an alternate active destination transport
+ *   address if one exists.
+ *
+ *   When retransmitting data that timed out, if the endpoint
+ *   is multihomed, it should consider each source-destination
+ *   address pair in its retransmission selection policy.
+ *   When retransmitting timed-out data, the endpoint should
+ *   attempt to pick the most divergent source-destination
+ *   pair from the original source-destination pair to which
+ *   the packet was transmitted.
+ *
+ *   Note: Rules for picking the most divergent source-destination
+ *   pair are an implementation decision and are not specified
+ *   within this document.
+ *
+ * Our basic strategy is to round-robin transports in priorities
+ * according to sctp_state_prio_map[] e.g., if no such
+ * transport with state SCTP_ACTIVE exists, round-robin through
+ * SCTP_UNKNOWN, etc. You get the picture.
  */
-void sctp_assoc_update_retran_path(struct sctp_association *asoc)
+static const u8 sctp_trans_state_to_prio_map[] = {
+       [SCTP_ACTIVE]   = 3,    /* best case */
+       [SCTP_UNKNOWN]  = 2,
+       [SCTP_PF]       = 1,
+       [SCTP_INACTIVE] = 0,    /* worst case */
+};
+
+static u8 sctp_trans_score(const struct sctp_transport *trans)
 {
-       struct sctp_transport *t, *next;
-       struct list_head *head = &asoc->peer.transport_addr_list;
-       struct list_head *pos;
+       return sctp_trans_state_to_prio_map[trans->state];
+}
 
-       if (asoc->peer.transport_count == 1)
-               return;
+static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr,
+                                                   struct sctp_transport *best)
+{
+       if (best == NULL)
+               return curr;
 
-       /* Find the next transport in a round-robin fashion. */
-       t = asoc->peer.retran_path;
-       pos = &t->transports;
-       next = NULL;
+       return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best;
+}
 
-       while (1) {
-               /* Skip the head. */
-               if (pos->next == head)
-                       pos = head->next;
-               else
-                       pos = pos->next;
+void sctp_assoc_update_retran_path(struct sctp_association *asoc)
+{
+       struct sctp_transport *trans = asoc->peer.retran_path;
+       struct sctp_transport *trans_next = NULL;
 
-               t = list_entry(pos, struct sctp_transport, transports);
+       /* We're done as we only have the one and only path. */
+       if (asoc->peer.transport_count == 1)
+               return;
+       /* If active_path and retran_path are the same and active,
+        * then this is the only active path. Use it.
+        */
+       if (asoc->peer.active_path == asoc->peer.retran_path &&
+           asoc->peer.active_path->state == SCTP_ACTIVE)
+               return;
 
-               /* We have exhausted the list, but didn't find any
-                * other active transports.  If so, use the next
-                * transport.
-                */
-               if (t == asoc->peer.retran_path) {
-                       t = next;
+       /* Iterate from retran_path's successor back to retran_path. */
+       for (trans = list_next_entry(trans, transports); 1;
+            trans = list_next_entry(trans, transports)) {
+               /* Manually skip the head element. */
+               if (&trans->transports == &asoc->peer.transport_addr_list)
+                       continue;
+               if (trans->state == SCTP_UNCONFIRMED)
+                       continue;
+               trans_next = sctp_trans_elect_best(trans, trans_next);
+               /* Active is good enough for immediate return. */
+               if (trans_next->state == SCTP_ACTIVE)
                        break;
-               }
-
-               /* Try to find an active transport. */
-
-               if ((t->state == SCTP_ACTIVE) ||
-                   (t->state == SCTP_UNKNOWN)) {
+               /* We've reached the end, time to update path. */
+               if (trans == asoc->peer.retran_path)
                        break;
-               } else {
-                       /* Keep track of the next transport in case
-                        * we don't find any active transport.
-                        */
-                       if (t->state != SCTP_UNCONFIRMED && !next)
-                               next = t;
-               }
        }
 
-       if (t)
-               asoc->peer.retran_path = t;
-       else
-               t = asoc->peer.retran_path;
+       if (trans_next != NULL)
+               asoc->peer.retran_path = trans_next;
 
-       pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc,
-                &t->ipaddr.sa);
+       pr_debug("%s: association:%p updated new path to addr:%pISpc\n",
+                __func__, asoc, &asoc->peer.retran_path->ipaddr.sa);
 }
 
-/* Choose the transport for sending retransmit packet.  */
-struct sctp_transport *sctp_assoc_choose_alter_transport(
-       struct sctp_association *asoc, struct sctp_transport *last_sent_to)
+struct sctp_transport *
+sctp_assoc_choose_alter_transport(struct sctp_association *asoc,
+                                 struct sctp_transport *last_sent_to)
 {
        /* If this is the first time packet is sent, use the active path,
         * else use the retran path. If the last packet was sent over the
         * retran path, update the retran path and use it.
         */
-       if (!last_sent_to)
+       if (last_sent_to == NULL) {
                return asoc->peer.active_path;
-       else {
+       else {
                if (last_sent_to == asoc->peer.retran_path)
                        sctp_assoc_update_retran_path(asoc);
+
                return asoc->peer.retran_path;
        }
 }
@@ -1367,44 +1396,35 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
        return false;
 }
 
-/* Increase asoc's rwnd by len and send any window update SACK if needed. */
-void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
+/* Update asoc's rwnd for the approximated state in the buffer,
+ * and check whether SACK needs to be sent.
+ */
+void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
 {
+       int rx_count;
        struct sctp_chunk *sack;
        struct timer_list *timer;
 
-       if (asoc->rwnd_over) {
-               if (asoc->rwnd_over >= len) {
-                       asoc->rwnd_over -= len;
-               } else {
-                       asoc->rwnd += (len - asoc->rwnd_over);
-                       asoc->rwnd_over = 0;
-               }
-       } else {
-               asoc->rwnd += len;
-       }
+       if (asoc->ep->rcvbuf_policy)
+               rx_count = atomic_read(&asoc->rmem_alloc);
+       else
+               rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
 
-       /* If we had window pressure, start recovering it
-        * once our rwnd had reached the accumulated pressure
-        * threshold.  The idea is to recover slowly, but up
-        * to the initial advertised window.
-        */
-       if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
-               int change = min(asoc->pathmtu, asoc->rwnd_press);
-               asoc->rwnd += change;
-               asoc->rwnd_press -= change;
-       }
+       if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0)
+               asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1;
+       else
+               asoc->rwnd = 0;
 
-       pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n",
-                __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
-                asoc->a_rwnd);
+       pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n",
+                __func__, asoc, asoc->rwnd, rx_count,
+                asoc->base.sk->sk_rcvbuf);
 
        /* Send a window update SACK if the rwnd has increased by at least the
         * minimum of the association's PMTU and half of the receive buffer.
         * The algorithm used is similar to the one described in
         * Section 4.2.3.3 of RFC 1122.
         */
-       if (sctp_peer_needs_update(asoc)) {
+       if (update_peer && sctp_peer_needs_update(asoc)) {
                asoc->a_rwnd = asoc->rwnd;
 
                pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u "
@@ -1426,45 +1446,6 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len)
        }
 }
 
-/* Decrease asoc's rwnd by len. */
-void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
-{
-       int rx_count;
-       int over = 0;
-
-       if (unlikely(!asoc->rwnd || asoc->rwnd_over))
-               pr_debug("%s: association:%p has asoc->rwnd:%u, "
-                        "asoc->rwnd_over:%u!\n", __func__, asoc,
-                        asoc->rwnd, asoc->rwnd_over);
-
-       if (asoc->ep->rcvbuf_policy)
-               rx_count = atomic_read(&asoc->rmem_alloc);
-       else
-               rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
-
-       /* If we've reached or overflowed our receive buffer, announce
-        * a 0 rwnd if rwnd would still be positive.  Store the
-        * the potential pressure overflow so that the window can be restored
-        * back to original value.
-        */
-       if (rx_count >= asoc->base.sk->sk_rcvbuf)
-               over = 1;
-
-       if (asoc->rwnd >= len) {
-               asoc->rwnd -= len;
-               if (over) {
-                       asoc->rwnd_press += asoc->rwnd;
-                       asoc->rwnd = 0;
-               }
-       } else {
-               asoc->rwnd_over = len - asoc->rwnd;
-               asoc->rwnd = 0;
-       }
-
-       pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n",
-                __func__, asoc, len, asoc->rwnd, asoc->rwnd_over,
-                asoc->rwnd_press);
-}
 
 /* Build the bind address list for the association based on info from the
  * local endpoint and the remote peer.
index 0f6259a6a932c583f4450a6fe79ef46b7d184996..2b1738ef9394537589b403f7d299181e18fb2315 100644 (file)
@@ -662,6 +662,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
         */
        sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
 
+       newsk->sk_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+
        sk_refcnt_debug_inc(newsk);
 
        if (newsk->sk_prot->init(newsk)) {
index 632090b961c331b78efa79664392c7626451926d..3a1767ef3201a6a1870f641ef29e3683ea6dcff7 100644 (file)
@@ -1421,8 +1421,8 @@ static void sctp_chunk_destroy(struct sctp_chunk *chunk)
        BUG_ON(!list_empty(&chunk->list));
        list_del_init(&chunk->transmitted_list);
 
-       /* Free the chunk skb data and the SCTP_chunk stub itself. */
-       dev_kfree_skb(chunk->skb);
+       consume_skb(chunk->skb);
+       consume_skb(chunk->auth_chunk);
 
        SCTP_DBG_OBJCNT_DEC(chunk);
        kmem_cache_free(sctp_chunk_cachep, chunk);
index bd859154000e47cccdae4f9f5e4353ba3cb83fd0..5d6883ff00c3b7056639f06254caffcb14349e27 100644 (file)
@@ -495,11 +495,12 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
        }
 
        /* If the transport error count is greater than the pf_retrans
-        * threshold, and less than pathmaxrtx, then mark this transport
-        * as Partially Failed, ee SCTP Quick Failover Draft, secon 5.1,
-        * point 1
+        * threshold, and less than pathmaxrtx, and if the current state
+        * is not SCTP_UNCONFIRMED, then mark this transport as Partially
+        * Failed, see SCTP Quick Failover Draft, section 5.1
         */
        if ((transport->state != SCTP_PF) &&
+          (transport->state != SCTP_UNCONFIRMED) &&
           (asoc->pf_retrans < transport->pathmaxrxt) &&
           (transport->error_count > asoc->pf_retrans)) {
 
index 483dcd71b3c5f76a17dc66aee156c0b6caf60bac..01e002430c858c293cdda11bd2962c3340043fb9 100644 (file)
@@ -758,6 +758,12 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
                struct sctp_chunk auth;
                sctp_ierror_t ret;
 
+               /* Make sure that we and the peer are AUTH capable */
+               if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
+                       sctp_association_free(new_asoc);
+                       return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+               }
+
                /* set-up our fake chunk so that we can process it */
                auth.skb = chunk->auth_chunk;
                auth.asoc = chunk->asoc;
@@ -768,10 +774,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
                auth.transport = chunk->transport;
 
                ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
-
-               /* We can now safely free the auth_chunk clone */
-               kfree_skb(chunk->auth_chunk);
-
                if (ret != SCTP_IERROR_NO_ERROR) {
                        sctp_association_free(new_asoc);
                        return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
@@ -6176,7 +6178,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
         * PMTU.  In cases, such as loopback, this might be a rather
         * large spill over.
         */
-       if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over ||
+       if ((!chunk->data_accepted) && (!asoc->rwnd ||
            (datalen > asoc->rwnd + asoc->frag_point))) {
 
                /* If this is the next TSN, consider reneging to make
index 9e91d6e5df63e4317eeeb367d55e734e5a62af2f..981aaf8b6ace45e55b80a235ebbb9dfcb693d64b 100644 (file)
@@ -64,6 +64,7 @@
 #include <linux/crypto.h>
 #include <linux/slab.h>
 #include <linux/file.h>
+#include <linux/compat.h>
 
 #include <net/ip.h>
 #include <net/icmp.h>
@@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk,
 /*
  * New (hopefully final) interface for the API.
  * We use the sctp_getaddrs_old structure so that use-space library
- * can avoid any unnecessary allocations.   The only defferent part
+ * can avoid any unnecessary allocations. The only different part
  * is that we store the actual length of the address buffer into the
- * addrs_num structure member.  That way we can re-use the existing
+ * addrs_num structure member. That way we can re-use the existing
  * code.
  */
+#ifdef CONFIG_COMPAT
+struct compat_sctp_getaddrs_old {
+       sctp_assoc_t    assoc_id;
+       s32             addr_num;
+       compat_uptr_t   addrs;          /* struct sockaddr * */
+};
+#endif
+
 static int sctp_getsockopt_connectx3(struct sock *sk, int len,
                                     char __user *optval,
                                     int __user *optlen)
@@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len,
        sctp_assoc_t assoc_id = 0;
        int err = 0;
 
-       if (len < sizeof(param))
-               return -EINVAL;
+#ifdef CONFIG_COMPAT
+       if (is_compat_task()) {
+               struct compat_sctp_getaddrs_old param32;
 
-       if (copy_from_user(&param, optval, sizeof(param)))
-               return -EFAULT;
+               if (len < sizeof(param32))
+                       return -EINVAL;
+               if (copy_from_user(&param32, optval, sizeof(param32)))
+                       return -EFAULT;
 
-       err = __sctp_setsockopt_connectx(sk,
-                       (struct sockaddr __user *)param.addrs,
-                       param.addr_num, &assoc_id);
+               param.assoc_id = param32.assoc_id;
+               param.addr_num = param32.addr_num;
+               param.addrs = compat_ptr(param32.addrs);
+       } else
+#endif
+       {
+               if (len < sizeof(param))
+                       return -EINVAL;
+               if (copy_from_user(&param, optval, sizeof(param)))
+                       return -EFAULT;
+       }
 
+       err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *)
+                                        param.addrs, param.addr_num,
+                                        &assoc_id);
        if (err == 0 || err == -EINPROGRESS) {
                if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
                        return -EFAULT;
@@ -2092,12 +2115,6 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
                sctp_skb_pull(skb, copied);
                skb_queue_head(&sk->sk_receive_queue, skb);
 
-               /* When only partial message is copied to the user, increase
-                * rwnd by that amount. If all the data in the skb is read,
-                * rwnd is updated when the event is freed.
-                */
-               if (!sctp_ulpevent_is_notification(event))
-                       sctp_assoc_rwnd_increase(event->asoc, copied);
                goto out;
        } else if ((event->msg_flags & MSG_NOTIFICATION) ||
                   (event->msg_flags & MSG_EOR))
index 7135e617ab0ffa7343a2d698e94c6a71d5334d9d..35c8923b5554aa33549eb872c8d2aaa292b34db1 100644 (file)
@@ -151,6 +151,7 @@ static struct ctl_table sctp_net_table[] = {
        },
        {
                .procname       = "cookie_hmac_alg",
+               .data           = &init_net.sctp.sctp_hmac_alg,
                .maxlen         = 8,
                .mode           = 0644,
                .proc_handler   = proc_sctp_do_hmac_alg,
@@ -401,15 +402,18 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
 
 int sctp_sysctl_net_register(struct net *net)
 {
-       struct ctl_table *table;
-       int i;
+       struct ctl_table *table = sctp_net_table;
+
+       if (!net_eq(net, &init_net)) {
+               int i;
 
-       table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
-       if (!table)
-               return -ENOMEM;
+               table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
+               if (!table)
+                       return -ENOMEM;
 
-       for (i = 0; table[i].data; i++)
-               table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+               for (i = 0; table[i].data; i++)
+                       table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
+       }
 
        net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table);
        return 0;
index 85c64658bd0b183df5c7a7fd8394df757cb0b4b0..8d198ae0360634d25d3e4cff8a56cf73e389bd2d 100644 (file)
@@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
        skb = sctp_event2skb(event);
        /* Set the owner and charge rwnd for bytes received.  */
        sctp_ulpevent_set_owner(event, asoc);
-       sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));
+       sctp_assoc_rwnd_update(asoc, false);
 
        if (!skb->data_len)
                return;
@@ -1011,6 +1011,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
        struct sk_buff *skb, *frag;
        unsigned int    len;
+       struct sctp_association *asoc;
 
        /* Current stack structures assume that the rcv buffer is
         * per socket.   For UDP style sockets this is not true as
@@ -1035,8 +1036,11 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
        }
 
 done:
-       sctp_assoc_rwnd_increase(event->asoc, len);
+       asoc = event->asoc;
+       sctp_association_hold(asoc);
        sctp_ulpevent_release_owner(event);
+       sctp_assoc_rwnd_update(asoc, true);
+       sctp_association_put(asoc);
 }
 
 static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
index 879933aaed4c07ecd9cdad1809939ff729a588a7..a19ae1968d379d70ad36e51039d79469cfe30d18 100644 (file)
@@ -450,16 +450,17 @@ EXPORT_SYMBOL(sockfd_lookup);
 
 static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
 {
-       struct file *file;
+       struct fd f = fdget(fd);
        struct socket *sock;
 
        *err = -EBADF;
-       file = fget_light(fd, fput_needed);
-       if (file) {
-               sock = sock_from_file(file, err);
-               if (sock)
+       if (f.file) {
+               sock = sock_from_file(f.file, err);
+               if (likely(sock)) {
+                       *fput_needed = f.flags;
                        return sock;
-               fput_light(file, *fput_needed);
+               }
+               fdput(f);
        }
        return NULL;
 }
@@ -1985,6 +1986,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
 {
        if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
                return -EFAULT;
+
+       if (kmsg->msg_namelen < 0)
+               return -EINVAL;
+
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
                kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        return 0;
index 6c0513a7f99232280f78067d56c5c369cb79630d..36e431ee1c902ef1c6ed777331cf97ceda0bdee4 100644 (file)
@@ -108,6 +108,7 @@ struct gss_auth {
 static DEFINE_SPINLOCK(pipe_version_lock);
 static struct rpc_wait_queue pipe_version_rpc_waitqueue;
 static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
+static void gss_put_auth(struct gss_auth *gss_auth);
 
 static void gss_free_ctx(struct gss_cl_ctx *);
 static const struct rpc_pipe_ops gss_upcall_ops_v0;
@@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
        if (gss_msg->ctx != NULL)
                gss_put_ctx(gss_msg->ctx);
        rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
+       gss_put_auth(gss_msg->auth);
        kfree(gss_msg);
 }
 
@@ -498,9 +500,12 @@ gss_alloc_msg(struct gss_auth *gss_auth,
        default:
                err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
                if (err)
-                       goto err_free_msg;
+                       goto err_put_pipe_version;
        };
+       kref_get(&gss_auth->kref);
        return gss_msg;
+err_put_pipe_version:
+       put_pipe_version(gss_auth->net);
 err_free_msg:
        kfree(gss_msg);
 err:
@@ -991,6 +996,8 @@ gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
        gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
        if (gss_auth->service == 0)
                goto err_put_mech;
+       if (!gssd_running(gss_auth->net))
+               goto err_put_mech;
        auth = &gss_auth->rpc_auth;
        auth->au_cslack = GSS_CRED_SLACK >> 2;
        auth->au_rslack = GSS_VERF_SLACK >> 2;
@@ -1061,6 +1068,12 @@ gss_free_callback(struct kref *kref)
        gss_free(gss_auth);
 }
 
+static void
+gss_put_auth(struct gss_auth *gss_auth)
+{
+       kref_put(&gss_auth->kref, gss_free_callback);
+}
+
 static void
 gss_destroy(struct rpc_auth *auth)
 {
@@ -1082,7 +1095,7 @@ gss_destroy(struct rpc_auth *auth)
        gss_auth->gss_pipe[1] = NULL;
        rpcauth_destroy_credcache(auth);
 
-       kref_put(&gss_auth->kref, gss_free_callback);
+       gss_put_auth(gss_auth);
 }
 
 /*
@@ -1253,7 +1266,7 @@ gss_destroy_nullcred(struct rpc_cred *cred)
        call_rcu(&cred->cr_rcu, gss_free_cred_callback);
        if (ctx)
                gss_put_ctx(ctx);
-       kref_put(&gss_auth->kref, gss_free_callback);
+       gss_put_auth(gss_auth);
 }
 
 static void
index 890a29912d5ab3f39d156891d4844ede04d367e8..e860d4f7ed2accd100c9ae9f715018daaae469a1 100644 (file)
@@ -64,7 +64,6 @@ static void xprt_free_allocation(struct rpc_rqst *req)
        free_page((unsigned long)xbufp->head[0].iov_base);
        xbufp = &req->rq_snd_buf;
        free_page((unsigned long)xbufp->head[0].iov_base);
-       list_del(&req->rq_bc_pa_list);
        kfree(req);
 }
 
@@ -168,8 +167,10 @@ out_free:
        /*
         * Memory allocation failed, free the temporary list
         */
-       list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
+       list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) {
+               list_del(&req->rq_bc_pa_list);
                xprt_free_allocation(req);
+       }
 
        dprintk("RPC:       setup backchannel transport failed\n");
        return -ENOMEM;
@@ -198,6 +199,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
        xprt_dec_alloc_count(xprt, max_reqs);
        list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
                dprintk("RPC:        req=%p\n", req);
+               list_del(&req->rq_bc_pa_list);
                xprt_free_allocation(req);
                if (--max_reqs == 0)
                        break;
index 80a6640f329bab991859e032fda658a871e65ca5..06c6ff0cb9114200d88cb85e0c98af35670932f8 100644 (file)
@@ -571,7 +571,7 @@ static void svc_check_conn_limits(struct svc_serv *serv)
        }
 }
 
-int svc_alloc_arg(struct svc_rqst *rqstp)
+static int svc_alloc_arg(struct svc_rqst *rqstp)
 {
        struct svc_serv *serv = rqstp->rq_server;
        struct xdr_buf *arg;
@@ -612,7 +612,7 @@ int svc_alloc_arg(struct svc_rqst *rqstp)
        return 0;
 }
 
-struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
+static struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
 {
        struct svc_xprt *xprt;
        struct svc_pool         *pool = rqstp->rq_pool;
@@ -691,7 +691,7 @@ struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout)
        return xprt;
 }
 
-void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt)
+static void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt)
 {
        spin_lock_bh(&serv->sv_lock);
        set_bit(XPT_TEMP, &newxpt->xpt_flags);
index 817a1e5239692e9fb3f5117f36eb0895d426ea5f..0addefca8e7757d78571928580d6f7473a1354ae 100644 (file)
@@ -510,6 +510,7 @@ static int xs_nospace(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct sock *sk = transport->inet;
        int ret = -EAGAIN;
 
        dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
@@ -527,7 +528,7 @@ static int xs_nospace(struct rpc_task *task)
                         * window size
                         */
                        set_bit(SOCK_NOSPACE, &transport->sock->flags);
-                       transport->inet->sk_write_pending++;
+                       sk->sk_write_pending++;
                        /* ...and wait for more buffer space */
                        xprt_wait_for_buffer_space(task, xs_nospace_callback);
                }
@@ -537,6 +538,9 @@ static int xs_nospace(struct rpc_task *task)
        }
 
        spin_unlock_bh(&xprt->transport_lock);
+
+       /* Race breaker in case memory is freed before above code is called */
+       sk->sk_write_space(sk);
        return ret;
 }
 
index a38c89969c686128df1a556598b248a70eec665f..574b86193b15a8251dc85555cc03a8e5f9af1768 100644 (file)
@@ -610,8 +610,13 @@ static struct notifier_block notifier = {
 
 int tipc_bearer_setup(void)
 {
+       int err;
+
+       err = register_netdevice_notifier(&notifier);
+       if (err)
+               return err;
        dev_add_pack(&tipc_packet_type);
-       return register_netdevice_notifier(&notifier);
+       return 0;
 }
 
 void tipc_bearer_cleanup(void)
index c301a9a592d82d570050116df07e54a4551da537..e6d721692ae016bbc900ac909406ca0a645848b0 100644 (file)
@@ -181,7 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void)
        if (tipc_own_addr)
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
                                                   " (cannot change node address once assigned)");
-       tipc_core_start_net(addr);
+       tipc_net_start(addr);
        return tipc_cfg_reply_none();
 }
 
@@ -376,7 +376,6 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,
        struct tipc_cfg_msg_hdr *req_hdr;
        struct tipc_cfg_msg_hdr *rep_hdr;
        struct sk_buff *rep_buf;
-       int ret;
 
        /* Validate configuration message header (ignore invalid message) */
        req_hdr = (struct tipc_cfg_msg_hdr *)buf;
@@ -398,12 +397,8 @@ static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr,
                memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
                rep_hdr->tcm_len = htonl(rep_buf->len);
                rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
-
-               ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
-                                       rep_buf->len);
-               if (ret < 0)
-                       pr_err("Sending cfg reply message failed, no memory\n");
-
+               tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
+                                 rep_buf->len);
                kfree_skb(rep_buf);
        }
 }
index f9e88d8b04ca182b2e8c217e579647fbf9581e4e..80c20647b3d29fd75d2ebb8c760c2aa75214c515 100644 (file)
@@ -76,38 +76,14 @@ struct sk_buff *tipc_buf_acquire(u32 size)
        return skb;
 }
 
-/**
- * tipc_core_stop_net - shut down TIPC networking sub-systems
- */
-static void tipc_core_stop_net(void)
-{
-       tipc_net_stop();
-       tipc_bearer_cleanup();
-}
-
-/**
- * start_net - start TIPC networking sub-systems
- */
-int tipc_core_start_net(unsigned long addr)
-{
-       int res;
-
-       tipc_net_start(addr);
-       res = tipc_bearer_setup();
-       if (res < 0)
-               goto err;
-       return res;
-
-err:
-       tipc_core_stop_net();
-       return res;
-}
-
 /**
  * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
  */
 static void tipc_core_stop(void)
 {
+       tipc_handler_stop();
+       tipc_net_stop();
+       tipc_bearer_cleanup();
        tipc_netlink_stop();
        tipc_cfg_stop();
        tipc_subscr_stop();
@@ -122,30 +98,65 @@ static void tipc_core_stop(void)
  */
 static int tipc_core_start(void)
 {
-       int res;
+       int err;
 
        get_random_bytes(&tipc_random, sizeof(tipc_random));
 
-       res = tipc_handler_start();
-       if (!res)
-               res = tipc_ref_table_init(tipc_max_ports, tipc_random);
-       if (!res)
-               res = tipc_nametbl_init();
-       if (!res)
-               res = tipc_netlink_start();
-       if (!res)
-               res = tipc_socket_init();
-       if (!res)
-               res = tipc_register_sysctl();
-       if (!res)
-               res = tipc_subscr_start();
-       if (!res)
-               res = tipc_cfg_init();
-       if (res) {
-               tipc_handler_stop();
-               tipc_core_stop();
-       }
-       return res;
+       err = tipc_handler_start();
+       if (err)
+               goto out_handler;
+
+       err = tipc_ref_table_init(tipc_max_ports, tipc_random);
+       if (err)
+               goto out_reftbl;
+
+       err = tipc_nametbl_init();
+       if (err)
+               goto out_nametbl;
+
+       err = tipc_netlink_start();
+       if (err)
+               goto out_netlink;
+
+       err = tipc_socket_init();
+       if (err)
+               goto out_socket;
+
+       err = tipc_register_sysctl();
+       if (err)
+               goto out_sysctl;
+
+       err = tipc_subscr_start();
+       if (err)
+               goto out_subscr;
+
+       err = tipc_cfg_init();
+       if (err)
+               goto out_cfg;
+
+       err = tipc_bearer_setup();
+       if (err)
+               goto out_bearer;
+
+       return 0;
+out_bearer:
+       tipc_cfg_stop();
+out_cfg:
+       tipc_subscr_stop();
+out_subscr:
+       tipc_unregister_sysctl();
+out_sysctl:
+       tipc_socket_stop();
+out_socket:
+       tipc_netlink_stop();
+out_netlink:
+       tipc_nametbl_stop();
+out_nametbl:
+       tipc_ref_table_stop();
+out_reftbl:
+       tipc_handler_stop();
+out_handler:
+       return err;
 }
 
 static int __init tipc_init(void)
@@ -174,8 +185,6 @@ static int __init tipc_init(void)
 
 static void __exit tipc_exit(void)
 {
-       tipc_handler_stop();
-       tipc_core_stop_net();
        tipc_core_stop();
        pr_info("Deactivated\n");
 }
index 1ff477b0450d78bacb9522105f638f6523d625f6..4dfe137587bbd35a519b87a107f4e665a625bdaa 100644 (file)
@@ -90,7 +90,6 @@ extern int tipc_random __read_mostly;
 /*
  * Routines available to privileged subsystems
  */
-int tipc_core_start_net(unsigned long);
 int tipc_handler_start(void);
 void tipc_handler_stop(void);
 int tipc_netlink_start(void);
@@ -192,6 +191,7 @@ static inline void k_term_timer(struct timer_list *timer)
 
 struct tipc_skb_cb {
        void *handle;
+       bool deferred;
 };
 
 #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
index e4bc8a2967447fbde1f39d0d19146f2c7848ac99..1fabf160501f4f7b8127ef8d8a7583076e9b2eb4 100644 (file)
@@ -58,7 +58,6 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument)
 
        spin_lock_bh(&qitem_lock);
        if (!handler_enabled) {
-               pr_err("Signal request ignored by handler\n");
                spin_unlock_bh(&qitem_lock);
                return -ENOPROTOOPT;
        }
index d4b5de41b682188f1cf3bcffb08a44f38a9f84ae..da6018beb6ebc149b72efd816f4d7154bc6cdfd7 100644 (file)
@@ -1391,6 +1391,12 @@ static int link_recv_buf_validate(struct sk_buff *buf)
        u32 hdr_size;
        u32 min_hdr_size;
 
+       /* If this packet comes from the defer queue, the skb has already
+        * been validated
+        */
+       if (unlikely(TIPC_SKB_CB(buf)->deferred))
+               return 1;
+
        if (unlikely(buf->len < MIN_H_SIZE))
                return 0;
 
@@ -1703,6 +1709,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
                                &l_ptr->newest_deferred_in, buf)) {
                l_ptr->deferred_inqueue_sz++;
                l_ptr->stats.deferred_recv++;
+               TIPC_SKB_CB(buf)->deferred = true;
                if ((l_ptr->deferred_inqueue_sz % 16) == 1)
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
        } else
index 92a1533af4e0a689f93f30c5b560368f1a548e37..042e8e3cabc09f84aa5dce626c57a30faf3ca32d 100644 (file)
@@ -941,20 +941,48 @@ int tipc_nametbl_init(void)
        return 0;
 }
 
-void tipc_nametbl_stop(void)
+/**
+ * tipc_purge_publications - remove all publications for a given type
+ *
+ * tipc_nametbl_lock must be held when calling this function
+ */
+static void tipc_purge_publications(struct name_seq *seq)
 {
-       u32 i;
+       struct publication *publ, *safe;
+       struct sub_seq *sseq;
+       struct name_info *info;
 
-       if (!table.types)
+       if (!seq->sseqs) {
+               nameseq_delete_empty(seq);
                return;
+       }
+       sseq = seq->sseqs;
+       info = sseq->info;
+       list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) {
+               tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node,
+                                        publ->ref, publ->key);
+       }
+}
+
+void tipc_nametbl_stop(void)
+{
+       u32 i;
+       struct name_seq *seq;
+       struct hlist_head *seq_head;
+       struct hlist_node *safe;
 
-       /* Verify name table is empty, then release it */
+       /* Verify name table is empty and purge any lingering
+        * publications, then release the name table
+        */
        write_lock_bh(&tipc_nametbl_lock);
        for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
                if (hlist_empty(&table.types[i]))
                        continue;
-               pr_err("nametbl_stop(): orphaned hash chain detected\n");
-               break;
+               seq_head = &table.types[i];
+               hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) {
+                       tipc_purge_publications(seq);
+               }
+               continue;
        }
        kfree(table.types);
        table.types = NULL;
index 9f72a6376362e613cb87185acbb3581174c45592..3aaf73de9e2d017e96b3cc1124d5c9420d827abd 100644 (file)
@@ -83,8 +83,6 @@ static struct genl_ops tipc_genl_ops[] = {
        },
 };
 
-static int tipc_genl_family_registered;
-
 int tipc_netlink_start(void)
 {
        int res;
@@ -94,16 +92,10 @@ int tipc_netlink_start(void)
                pr_err("Failed to register netlink interface\n");
                return res;
        }
-
-       tipc_genl_family_registered = 1;
        return 0;
 }
 
 void tipc_netlink_stop(void)
 {
-       if (!tipc_genl_family_registered)
-               return;
-
        genl_unregister_family(&tipc_genl_family);
-       tipc_genl_family_registered = 0;
 }
index 2a2a938dc22cb3c14def50169afffa37ea5bec86..de3d593e2fee08c384ca2970d7a0fc695ff4d5fc 100644 (file)
@@ -126,9 +126,6 @@ int tipc_ref_table_init(u32 requested_size, u32 start)
  */
 void tipc_ref_table_stop(void)
 {
-       if (!tipc_ref_table.entries)
-               return;
-
        vfree(tipc_ref_table.entries);
        tipc_ref_table.entries = NULL;
 }
index b635ca347a870dc55187c221b3df1f2dc295a333..646a930eefbf8fa9a86cfe7011848143aafa49b8 100644 (file)
@@ -87,7 +87,6 @@ static void tipc_clean_outqueues(struct tipc_conn *con);
 static void tipc_conn_kref_release(struct kref *kref)
 {
        struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
-       struct tipc_server *s = con->server;
 
        if (con->sock) {
                tipc_sock_release_local(con->sock);
@@ -95,10 +94,6 @@ static void tipc_conn_kref_release(struct kref *kref)
        }
 
        tipc_clean_outqueues(con);
-
-       if (con->conid)
-               s->tipc_conn_shutdown(con->conid, con->usr_data);
-
        kfree(con);
 }
 
@@ -181,6 +176,9 @@ static void tipc_close_conn(struct tipc_conn *con)
        struct tipc_server *s = con->server;
 
        if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
+               if (con->conid)
+                       s->tipc_conn_shutdown(con->conid, con->usr_data);
+
                spin_lock_bh(&s->idr_lock);
                idr_remove(&s->conn_idr, con->conid);
                s->idr_in_use--;
@@ -429,10 +427,12 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,
        list_add_tail(&e->list, &con->outqueue);
        spin_unlock_bh(&con->outqueue_lock);
 
-       if (test_bit(CF_CONNECTED, &con->flags))
+       if (test_bit(CF_CONNECTED, &con->flags)) {
                if (!queue_work(s->send_wq, &con->swork))
                        conn_put(con);
-
+       } else {
+               conn_put(con);
+       }
        return 0;
 }
 
@@ -573,7 +573,6 @@ int tipc_server_start(struct tipc_server *s)
                kmem_cache_destroy(s->rcvbuf_cache);
                return ret;
        }
-       s->enabled = 1;
        return ret;
 }
 
@@ -583,10 +582,6 @@ void tipc_server_stop(struct tipc_server *s)
        int total = 0;
        int id;
 
-       if (!s->enabled)
-               return;
-
-       s->enabled = 0;
        spin_lock_bh(&s->idr_lock);
        for (id = 0; total < s->idr_in_use; id++) {
                con = idr_find(&s->conn_idr, id);
index 98b23f20bc0f5cbb1631111177bd0d88adfcaa68..be817b0b547e87148a103284adc5285a66147c28 100644 (file)
@@ -56,7 +56,6 @@
  * @name: server name
  * @imp: message importance
  * @type: socket type
- * @enabled: identify whether server is launched or not
  */
 struct tipc_server {
        struct idr conn_idr;
@@ -74,7 +73,6 @@ struct tipc_server {
        const char name[TIPC_SERVER_NAME_LEN];
        int imp;
        int type;
-       int enabled;
 };
 
 int tipc_conn_sendmsg(struct tipc_server *s, int conid,
index aab4948f0affa995adc2603bd09db4b5d354b266..0ed0eaa62f29e7148052907892ff90ebd20d2fed 100644 (file)
@@ -70,8 +70,6 @@ static const struct proto_ops msg_ops;
 static struct proto tipc_proto;
 static struct proto tipc_proto_kern;
 
-static int sockets_enabled;
-
 /*
  * Revised TIPC socket locking policy:
  *
@@ -999,7 +997,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo)
 
        for (;;) {
                prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-               if (skb_queue_empty(&sk->sk_receive_queue)) {
+               if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
                        if (sock->state == SS_DISCONNECTING) {
                                err = -ENOTCONN;
                                break;
@@ -1625,7 +1623,7 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo)
        for (;;) {
                prepare_to_wait_exclusive(sk_sleep(sk), &wait,
                                          TASK_INTERRUPTIBLE);
-               if (skb_queue_empty(&sk->sk_receive_queue)) {
+               if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
                        release_sock(sk);
                        timeo = schedule_timeout(timeo);
                        lock_sock(sk);
@@ -2027,8 +2025,6 @@ int tipc_socket_init(void)
                proto_unregister(&tipc_proto);
                goto out;
        }
-
-       sockets_enabled = 1;
  out:
        return res;
 }
@@ -2038,10 +2034,6 @@ int tipc_socket_init(void)
  */
 void tipc_socket_stop(void)
 {
-       if (!sockets_enabled)
-               return;
-
-       sockets_enabled = 0;
        sock_unregister(tipc_family_ops.family);
        proto_unregister(&tipc_proto);
 }
index 7cb0bd5b1176872dcd09ca830a8a01c5b1ec37c6..642437231ad5d2da2e7c9de5bd4494b082f3472e 100644 (file)
@@ -96,20 +96,16 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower,
 {
        struct tipc_subscriber *subscriber = sub->subscriber;
        struct kvec msg_sect;
-       int ret;
 
        msg_sect.iov_base = (void *)&sub->evt;
        msg_sect.iov_len = sizeof(struct tipc_event);
-
        sub->evt.event = htohl(event, sub->swap);
        sub->evt.found_lower = htohl(found_lower, sub->swap);
        sub->evt.found_upper = htohl(found_upper, sub->swap);
        sub->evt.port.ref = htohl(port_ref, sub->swap);
        sub->evt.port.node = htohl(node, sub->swap);
-       ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL,
-                               msg_sect.iov_base, msg_sect.iov_len);
-       if (ret < 0)
-               pr_err("Sending subscription event failed, no memory\n");
+       tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base,
+                         msg_sect.iov_len);
 }
 
 /**
@@ -153,14 +149,6 @@ static void subscr_timeout(struct tipc_subscription *sub)
        /* The spin lock per subscriber is used to protect its members */
        spin_lock_bh(&subscriber->lock);
 
-       /* Validate if the connection related to the subscriber is
-        * closed (in case subscriber is terminating)
-        */
-       if (subscriber->conid == 0) {
-               spin_unlock_bh(&subscriber->lock);
-               return;
-       }
-
        /* Validate timeout (in case subscription is being cancelled) */
        if (sub->timeout == TIPC_WAIT_FOREVER) {
                spin_unlock_bh(&subscriber->lock);
@@ -215,9 +203,6 @@ static void subscr_release(struct tipc_subscriber *subscriber)
 
        spin_lock_bh(&subscriber->lock);
 
-       /* Invalidate subscriber reference */
-       subscriber->conid = 0;
-
        /* Destroy any existing subscriptions for subscriber */
        list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
                                 subscription_list) {
@@ -278,9 +263,9 @@ static void subscr_cancel(struct tipc_subscr *s,
  *
  * Called with subscriber lock held.
  */
-static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
-                                            struct tipc_subscriber *subscriber)
-{
+static int subscr_subscribe(struct tipc_subscr *s,
+                           struct tipc_subscriber *subscriber,
+                           struct tipc_subscription **sub_p) {
        struct tipc_subscription *sub;
        int swap;
 
@@ -291,23 +276,21 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
        if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
                s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
                subscr_cancel(s, subscriber);
-               return NULL;
+               return 0;
        }
 
        /* Refuse subscription if global limit exceeded */
        if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) {
                pr_warn("Subscription rejected, limit reached (%u)\n",
                        TIPC_MAX_SUBSCRIPTIONS);
-               subscr_terminate(subscriber);
-               return NULL;
+               return -EINVAL;
        }
 
        /* Allocate subscription object */
        sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
        if (!sub) {
                pr_warn("Subscription rejected, no memory\n");
-               subscr_terminate(subscriber);
-               return NULL;
+               return -ENOMEM;
        }
 
        /* Initialize subscription object */
@@ -321,8 +304,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
            (sub->seq.lower > sub->seq.upper)) {
                pr_warn("Subscription rejected, illegal request\n");
                kfree(sub);
-               subscr_terminate(subscriber);
-               return NULL;
+               return -EINVAL;
        }
        INIT_LIST_HEAD(&sub->nameseq_list);
        list_add(&sub->subscription_list, &subscriber->subscription_list);
@@ -335,8 +317,8 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
                             (Handler)subscr_timeout, (unsigned long)sub);
                k_start_timer(&sub->timer, sub->timeout);
        }
-
-       return sub;
+       *sub_p = sub;
+       return 0;
 }
 
 /* Handle one termination request for the subscriber */
@@ -350,10 +332,14 @@ static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr,
                                  void *usr_data, void *buf, size_t len)
 {
        struct tipc_subscriber *subscriber = usr_data;
-       struct tipc_subscription *sub;
+       struct tipc_subscription *sub = NULL;
 
        spin_lock_bh(&subscriber->lock);
-       sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber);
+       if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) {
+               spin_unlock_bh(&subscriber->lock);
+               subscr_terminate(subscriber);
+               return;
+       }
        if (sub)
                tipc_nametbl_subscribe(sub);
        spin_unlock_bh(&subscriber->lock);
index 29fc8bee97022f456f8b64b8ff6ff54a977962dd..94404f19f9deebbb7c55b7a1660dd011510ba3fd 100644 (file)
@@ -163,9 +163,8 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 
 static inline unsigned int unix_hash_fold(__wsum n)
 {
-       unsigned int hash = (__force unsigned int)n;
+       unsigned int hash = (__force unsigned int)csum_fold(n);
 
-       hash ^= hash>>16;
        hash ^= hash>>8;
        return hash&(UNIX_HASH_SIZE-1);
 }
@@ -1788,8 +1787,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
 
        err = mutex_lock_interruptible(&u->readlock);
-       if (err) {
-               err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
+       if (unlikely(err)) {
+               /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+                * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+                */
+               err = noblock ? -EAGAIN : -ERESTARTSYS;
                goto out;
        }
 
@@ -1914,6 +1916,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct unix_sock *u = unix_sk(sk);
        DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
        int copied = 0;
+       int noblock = flags & MSG_DONTWAIT;
        int check_creds = 0;
        int target;
        int err = 0;
@@ -1929,7 +1932,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
 
        target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
-       timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
+       timeo = sock_rcvtimeo(sk, noblock);
 
        /* Lock the socket to prevent queue disordering
         * while sleeps in memcpy_tomsg
@@ -1941,8 +1944,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
        }
 
        err = mutex_lock_interruptible(&u->readlock);
-       if (err) {
-               err = sock_intr_errno(timeo);
+       if (unlikely(err)) {
+               /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+                * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+                */
+               err = noblock ? -EAGAIN : -ERESTARTSYS;
                goto out;
        }
 
index d89dee2259b5994b9237100425aae0a3f21b20af..a3bf18d116095f14f4238bc792d22e5f51f2dd26 100644 (file)
@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
 
        rdev->opencount--;
 
-       WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
-               !rdev->scan_req->notified);
+       if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+               if (WARN_ON(!rdev->scan_req->notified))
+                       rdev->scan_req->aborted = true;
+               ___cfg80211_scan_done(rdev, false);
+       }
 }
 
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
@@ -440,9 +443,6 @@ int wiphy_register(struct wiphy *wiphy)
        int i;
        u16 ifmodes = wiphy->interface_modes;
 
-       /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
-       wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
-
        /*
         * There are major locking problems in nl80211/mac80211 for CSA,
         * disable for all drivers until this has been reworked.
@@ -788,8 +788,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
        default:
                break;
        }
-
-       wdev->beacon_interval = 0;
 }
 
 static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
@@ -859,8 +857,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                break;
        case NETDEV_DOWN:
                cfg80211_update_iface_num(rdev, wdev->iftype, -1);
-               WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
-                       !rdev->scan_req->notified);
+               if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+                       if (WARN_ON(!rdev->scan_req->notified))
+                               rdev->scan_req->aborted = true;
+                       ___cfg80211_scan_done(rdev, false);
+               }
 
                if (WARN_ON(rdev->sched_scan_req &&
                            rdev->sched_scan_req->dev == wdev->netdev)) {
index 37ec16d7bb1ab6bf6e4948259aad19eb6e5a58cf..f1d193b557b69a5c021b76130f04bf58655288dd 100644 (file)
@@ -62,6 +62,7 @@ struct cfg80211_registered_device {
        struct rb_root bss_tree;
        u32 bss_generation;
        struct cfg80211_scan_request *scan_req; /* protected by RTNL */
+       struct sk_buff *scan_msg;
        struct cfg80211_sched_scan_request *sched_scan_req;
        unsigned long suspend_at;
        struct work_struct scan_done_wk;
@@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
                                   struct key_params *params, int key_idx,
                                   bool pairwise, const u8 *mac_addr);
 void __cfg80211_scan_done(struct work_struct *wk);
-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
+                          bool send_message);
 void __cfg80211_sched_scan_results(struct work_struct *wk);
 int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
                               bool driver_initiated);
index 7a742594916e177461a5374693e78c07bcbce09b..4fe2e6e2bc7635daef9aee5752ed97eafb29012a 100644 (file)
@@ -1719,9 +1719,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
                                 * We can then retry with the larger buffer.
                                 */
                                if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
-                                   !skb->len &&
+                                   !skb->len && !state->split &&
                                    cb->min_dump_alloc < 4096) {
                                        cb->min_dump_alloc = 4096;
+                                       state->split_start = 0;
                                        rtnl_unlock();
                                        return 1;
                                }
@@ -5244,7 +5245,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->scan)
                return -EOPNOTSUPP;
 
-       if (rdev->scan_req) {
+       if (rdev->scan_req || rdev->scan_msg) {
                err = -EBUSY;
                goto unlock;
        }
@@ -10011,40 +10012,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
                                NL80211_MCGRP_SCAN, GFP_KERNEL);
 }
 
-void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
-                           struct wireless_dev *wdev)
+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
+                                      struct wireless_dev *wdev, bool aborted)
 {
        struct sk_buff *msg;
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg)
-               return;
+               return NULL;
 
        if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
-                                 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
+                                 aborted ? NL80211_CMD_SCAN_ABORTED :
+                                           NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
                nlmsg_free(msg);
-               return;
+               return NULL;
        }
 
-       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
-                               NL80211_MCGRP_SCAN, GFP_KERNEL);
+       return msg;
 }
 
-void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
-                              struct wireless_dev *wdev)
+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
+                             struct sk_buff *msg)
 {
-       struct sk_buff *msg;
-
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg)
                return;
 
-       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
-                                 NL80211_CMD_SCAN_ABORTED) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
-
        genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
                                NL80211_MCGRP_SCAN, GFP_KERNEL);
 }
index b1b231324e102a44218bcf2354e52662fac78f5a..75799746d845f6fea6dcfa6b6f0b84bdc20aa14e 100644 (file)
@@ -8,10 +8,10 @@ void nl80211_exit(void);
 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
 void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
                             struct wireless_dev *wdev);
-void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
-                           struct wireless_dev *wdev);
-void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
-                              struct wireless_dev *wdev);
+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
+                                      struct wireless_dev *wdev, bool aborted);
+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
+                             struct sk_buff *msg);
 void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
                             struct net_device *netdev, u32 cmd);
 void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
index 9b897fca7487dd4fe8d8364368e8516ab8f369c0..f0541370e68eb9071caa429772a0a55d952c27d4 100644 (file)
@@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
                return;
        case NL80211_REGDOM_SET_BY_USER:
                treatment = reg_process_hint_user(reg_request);
-               if (treatment == REG_REQ_OK ||
+               if (treatment == REG_REQ_IGNORE ||
                    treatment == REG_REQ_ALREADY_SET)
                        return;
                schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
@@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
 int set_regdom(const struct ieee80211_regdomain *rd)
 {
        struct regulatory_request *lr;
+       bool user_reset = false;
        int r;
 
        if (!reg_is_valid_request(rd->alpha2)) {
@@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd)
                break;
        case NL80211_REGDOM_SET_BY_USER:
                r = reg_set_rd_user(rd, lr);
+               user_reset = true;
                break;
        case NL80211_REGDOM_SET_BY_DRIVER:
                r = reg_set_rd_driver(rd, lr);
@@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd)
        }
 
        if (r) {
-               if (r == -EALREADY)
+               switch (r) {
+               case -EALREADY:
                        reg_set_request_processed();
+                       break;
+               default:
+                       /* Back to world regulatory in case of errors */
+                       restore_regulatory_settings(user_reset);
+               }
 
                kfree(rd);
                return r;
index b528e31da2cfc07ccf5826ce02f3014a61b808e4..d1ed4aebbbb7dcc6dca3fccea4222e3eb7eb2fb0 100644 (file)
@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
                dev->bss_generation++;
 }
 
-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
+                          bool send_message)
 {
        struct cfg80211_scan_request *request;
        struct wireless_dev *wdev;
+       struct sk_buff *msg;
 #ifdef CONFIG_CFG80211_WEXT
        union iwreq_data wrqu;
 #endif
 
        ASSERT_RTNL();
 
-       request = rdev->scan_req;
+       if (rdev->scan_msg) {
+               nl80211_send_scan_result(rdev, rdev->scan_msg);
+               rdev->scan_msg = NULL;
+               return;
+       }
 
+       request = rdev->scan_req;
        if (!request)
                return;
 
@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
        if (wdev->netdev)
                cfg80211_sme_scan_done(wdev->netdev);
 
-       if (request->aborted) {
-               nl80211_send_scan_aborted(rdev, wdev);
-       } else {
-               if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
-                       /* flush entries from previous scans */
-                       spin_lock_bh(&rdev->bss_lock);
-                       __cfg80211_bss_expire(rdev, request->scan_start);
-                       spin_unlock_bh(&rdev->bss_lock);
-               }
-               nl80211_send_scan_done(rdev, wdev);
+       if (!request->aborted &&
+           request->flags & NL80211_SCAN_FLAG_FLUSH) {
+               /* flush entries from previous scans */
+               spin_lock_bh(&rdev->bss_lock);
+               __cfg80211_bss_expire(rdev, request->scan_start);
+               spin_unlock_bh(&rdev->bss_lock);
        }
 
+       msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
+
 #ifdef CONFIG_CFG80211_WEXT
        if (wdev->netdev && !request->aborted) {
                memset(&wrqu, 0, sizeof(wrqu));
@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
 
        rdev->scan_req = NULL;
        kfree(request);
+
+       if (!send_message)
+               rdev->scan_msg = msg;
+       else
+               nl80211_send_scan_result(rdev, msg);
 }
 
 void __cfg80211_scan_done(struct work_struct *wk)
@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_struct *wk)
                            scan_done_wk);
 
        rtnl_lock();
-       ___cfg80211_scan_done(rdev);
+       ___cfg80211_scan_done(rdev, true);
        rtnl_unlock();
 }
 
@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
-       if (rdev->scan_req) {
+       if (rdev->scan_req || rdev->scan_msg) {
                err = -EBUSY;
                goto out;
        }
@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_device *dev,
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
-       if (rdev->scan_req)
+       if (rdev->scan_req || rdev->scan_msg)
                return -EAGAIN;
 
        res = ieee80211_scan_results(rdev, info, extra, data->length);
index a6350911850890dc40fdcd6326345866ffc342a9..f04d4c32e96e144d37b49de5d1be69add8a55b2c 100644 (file)
@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
        ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
 
-       if (rdev->scan_req)
+       if (rdev->scan_req || rdev->scan_msg)
                return -EBUSY;
 
        if (wdev->conn->params.channel)
index 4b98b25793c5c23fa1799463b45ad71a030fceb9..1d5c7bf29938231fa06428dc6236e36c1719860e 100644 (file)
@@ -1158,7 +1158,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
        if (hlist_unhashed(&pol->bydst))
                return NULL;
 
-       hlist_del(&pol->bydst);
+       hlist_del_init(&pol->bydst);
        hlist_del(&pol->byidx);
        list_del(&pol->walk.all);
        net->xfrm.policy_count[dir]--;
index a26b7aa794755f970756cadb3c817bfc500956d2..40f1b3e92e7812e83127064237db07f18048b0a5 100644 (file)
@@ -1159,6 +1159,11 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
        }
        x->props.aalgo = orig->props.aalgo;
 
+       if (orig->aead) {
+               x->aead = xfrm_algo_aead_clone(orig->aead);
+               if (!x->aead)
+                       goto error;
+       }
        if (orig->ealg) {
                x->ealg = xfrm_algo_clone(orig->ealg);
                if (!x->ealg)
@@ -1201,6 +1206,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
        x->props.flags = orig->props.flags;
        x->props.extra_flags = orig->props.extra_flags;
 
+       x->tfcpad = orig->tfcpad;
+       x->replay_maxdiff = orig->replay_maxdiff;
+       x->replay_maxage = orig->replay_maxage;
        x->curlft.add_time = orig->curlft.add_time;
        x->km.state = orig->km.state;
        x->km.seq = orig->km.seq;
@@ -1215,11 +1223,12 @@ out:
        return NULL;
 }
 
-/* net->xfrm.xfrm_state_lock is held */
 struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
 {
        unsigned int h;
-       struct xfrm_state *x;
+       struct xfrm_state *x = NULL;
+
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
 
        if (m->reqid) {
                h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
@@ -1236,7 +1245,7 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
                                             m->old_family))
                                continue;
                        xfrm_state_hold(x);
-                       return x;
+                       break;
                }
        } else {
                h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
@@ -1251,11 +1260,13 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
                                             m->old_family))
                                continue;
                        xfrm_state_hold(x);
-                       return x;
+                       break;
                }
        }
 
-       return NULL;
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
+
+       return x;
 }
 EXPORT_SYMBOL(xfrm_migrate_state_find);
 
@@ -1451,7 +1462,7 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
 {
        int err = 0;
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
-       struct net *net = xs_net(*dst);
+       struct net *net = xs_net(*src);
 
        if (!afinfo)
                return -EAFNOSUPPORT;
index 1ae3ec7c18b0de977b1b781c8fee72d8357543bc..2f7ddc3a59b42db13c1df648b188a8dc312c5f8b 100644 (file)
 #include <linux/in6.h>
 #endif
 
-static inline int aead_len(struct xfrm_algo_aead *alg)
-{
-       return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
-}
-
 static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
 {
        struct nlattr *rt = attrs[type];
@@ -1226,7 +1221,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
                return 0;
 
        uctx = nla_data(rt);
-       return security_xfrm_policy_alloc(&pol->security, uctx);
+       return security_xfrm_policy_alloc(&pol->security, uctx, GFP_KERNEL);
 }
 
 static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
@@ -1631,7 +1626,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                if (rt) {
                        struct xfrm_user_sec_ctx *uctx = nla_data(rt);
 
-                       err = security_xfrm_policy_alloc(&ctx, uctx);
+                       err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL);
                        if (err)
                                return err;
                }
@@ -1933,7 +1928,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
                if (rt) {
                        struct xfrm_user_sec_ctx *uctx = nla_data(rt);
 
-                       err = security_xfrm_policy_alloc(&ctx, uctx);
+                       err = security_xfrm_policy_alloc(&ctx, uctx, GFP_KERNEL);
                        if (err)
                                return err;
                }
index 547e15daf03dc86dbfa72818122bc4c61929edb0..93a0da26582b863c64efd5ff226a8386bfb58064 100644 (file)
@@ -155,6 +155,15 @@ ld-option = $(call try-run,\
 # Important: no spaces around options
 ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
 
+# ld-version
+# Usage: $(call ld-version)
+# Note this is mainly for HJ Lu's 3 number binutil versions
+ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
+
+# ld-ifversion
+# Usage:  $(call ld-ifversion, -ge, 22252, y)
+ld-ifversion = $(shell [ $(call ld-version) $(1) $(2) ] && echo $(3))
+
 ######
 
 ###
index d5d859c8072964014971b9b1401b96f83a183e5d..9f0ee22b914f3c8e83ea58ab71278e98b8c03e89 100644 (file)
@@ -198,7 +198,7 @@ $(multi-objs-y:.o=.s)   : modname = $(modname-multi)
 $(multi-objs-y:.o=.lst) : modname = $(modname-multi)
 
 quiet_cmd_cc_s_c = CC $(quiet_modtag)  $@
-cmd_cc_s_c       = $(CC) $(c_flags) -fverbose-asm -S -o $@ $<
+cmd_cc_s_c       = $(CC) $(c_flags) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
 
 $(obj)/%.s: $(src)/%.c FORCE
        $(call if_changed_dep,cc_s_c)
index 49392ecbef17baf113bb9e3771384d06413bbb25..79c059e708600b04b63f8bc27cca94b485684cc8 100644 (file)
@@ -152,6 +152,7 @@ ld_flags       = $(LDFLAGS) $(ldflags-y)
 dtc_cpp_flags  = -Wp,-MD,$(depfile).pre.tmp -nostdinc                    \
                 -I$(srctree)/arch/$(SRCARCH)/boot/dts                   \
                 -I$(srctree)/arch/$(SRCARCH)/boot/dts/include           \
+                -I$(srctree)/drivers/of/testcase-data                   \
                 -undef -D__DTS__
 
 # Finds the multi-part object the current object will be linked into
index 0ea2a1e24ade493ed22c6b817c91a07736b11563..464dcef79b353be5426115fb3fb8ba1f746546df 100755 (executable)
@@ -471,7 +471,7 @@ sub seed_camelcase_includes {
 
        $camelcase_seeded = 1;
 
-       if (-d ".git") {
+       if (-e ".git") {
                my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
                chomp $git_last_include_commit;
                $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
@@ -499,7 +499,7 @@ sub seed_camelcase_includes {
                return;
        }
 
-       if (-d ".git") {
+       if (-e ".git") {
                $files = `git ls-files "include/*.h"`;
                @include_files = split('\n', $files);
        }
diff --git a/scripts/gcc-ld b/scripts/gcc-ld
new file mode 100644 (file)
index 0000000..cadab9a
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+# run gcc with ld options
+# used as a wrapper to execute link time optimizations
+# yes virginia, this is not pretty
+
+ARGS="-nostdlib"
+
+while [ "$1" != "" ] ; do
+       case "$1" in
+       -save-temps|-m32|-m64) N="$1" ;;
+       -r) N="$1" ;;
+       -[Wg]*) N="$1" ;;
+       -[olv]|-[Ofd]*|-nostdlib) N="$1" ;;
+       --end-group|--start-group)
+                N="-Wl,$1" ;;
+       -[RTFGhIezcbyYu]*|\
+--script|--defsym|-init|-Map|--oformat|-rpath|\
+-rpath-link|--sort-section|--section-start|-Tbss|-Tdata|-Ttext|\
+--version-script|--dynamic-list|--version-exports-symbol|--wrap|-m)
+               A="$1" ; shift ; N="-Wl,$A,$1" ;;
+       -[m]*) N="$1" ;;
+       -*) N="-Wl,$1" ;;
+       *)  N="$1" ;;
+       esac
+       ARGS="$ARGS $N"
+       shift
+done
+
+exec $CC $ARGS
index ef474098d9f1d1e2609221d3d3571c1f29d1b599..17fa901418ae6a491ba61f3814a1143e2a62bfde 100644 (file)
@@ -257,7 +257,7 @@ case "$arg" in
                 && compr="lzop -9 -f"
                echo "$output_file" | grep -q "\.lz4$" \
                 && [ -x "`which lz4 2> /dev/null`" ] \
-                && compr="lz4 -9 -f"
+                && compr="lz4 -l -9 -f"
                echo "$output_file" | grep -q "\.cpio$" && compr="cat"
                shift
                ;;
index 9c3986f4140c47c089f96bead3331a5b5d9d6cef..41987885bd31db413f484ada73556d90f59d9577 100755 (executable)
@@ -95,7 +95,7 @@ my %VCS_cmds;
 
 my %VCS_cmds_git = (
     "execute_cmd" => \&git_execute_cmd,
-    "available" => '(which("git") ne "") && (-d ".git")',
+    "available" => '(which("git") ne "") && (-e ".git")',
     "find_signers_cmd" =>
        "git log --no-color --follow --since=\$email_git_since " .
            '--numstat --no-merges ' .
diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh
new file mode 100755 (executable)
index 0000000..198580d
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/awk -f
+# extract linker version number from stdin and turn into single number
+       {
+       gsub(".*)", "");
+       split($1,a, ".");
+       print a[1]*10000000 + a[2]*100000 + a[3]*10000 + a[4]*100 + a[5];
+       exit
+       }
index 23708636b05c873f78b1ef5911eb795ba7114497..25e5cb0aaef6fd68fd77d15037a66f046e6c72e6 100644 (file)
@@ -210,8 +210,8 @@ static void do_usb_entry(void *symval,
                                range_lo < 0x9 ? "[%X-9" : "[%X",
                                range_lo);
                        sprintf(alias + strlen(alias),
-                               range_hi > 0xA ? "a-%X]" : "%X]",
-                               range_lo);
+                               range_hi > 0xA ? "A-%X]" : "%X]",
+                               range_hi);
                }
        }
        if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
index 40610984a1b54b06c579f953dabeb5ddb1304525..066355673930342a1b5e839950cbd1186ed6c24b 100644 (file)
@@ -623,7 +623,10 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
 
        switch (sym->st_shndx) {
        case SHN_COMMON:
-               warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
+               if (!strncmp(symname, "__gnu_lto_", sizeof("__gnu_lto_")-1)) {
+                       /* Should warn here, but modpost runs before the linker */
+               } else
+                       warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
                break;
        case SHN_UNDEF:
                /* undefined symbol */
@@ -849,6 +852,7 @@ static const char *section_white_list[] =
        ".xt.lit",         /* xtensa */
        ".arcextmap*",                  /* arc */
        ".gnu.linkonce.arcext*",        /* arc : modules */
+       ".gnu.lto*",
        NULL
 };
 
@@ -1455,6 +1459,10 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,
                to = find_elf_symbol(elf, r->r_addend, sym);
                tosym = sym_name(elf, to);
 
+               if (!strncmp(fromsym, "reference___initcall",
+                               sizeof("reference___initcall")-1))
+                       return;
+
                /* check whitelist - we may ignore it */
                if (secref_whitelist(mismatch,
                                        fromsec, fromsym, tosec, tosym)) {
@@ -1502,6 +1510,16 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
 #define R_ARM_JUMP24   29
 #endif
 
+#ifndef        R_ARM_THM_CALL
+#define        R_ARM_THM_CALL          10
+#endif
+#ifndef        R_ARM_THM_JUMP24
+#define        R_ARM_THM_JUMP24        30
+#endif
+#ifndef        R_ARM_THM_JUMP19
+#define        R_ARM_THM_JUMP19        51
+#endif
+
 static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
 {
        unsigned int r_typ = ELF_R_TYPE(r->r_info);
@@ -1515,6 +1533,9 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
        case R_ARM_PC24:
        case R_ARM_CALL:
        case R_ARM_JUMP24:
+       case R_ARM_THM_CALL:
+       case R_ARM_THM_JUMP24:
+       case R_ARM_THM_JUMP19:
                /* From ARM ABI: ((S + A) | T) - P */
                r->r_addend = (int)(long)(elf->hdr +
                              sechdr->sh_offset +
@@ -1680,6 +1701,19 @@ static void check_sec_ref(struct module *mod, const char *modname,
        }
 }
 
+static char *remove_dot(char *s)
+{
+       char *end;
+       int n = strcspn(s, ".");
+
+       if (n > 0 && s[n] != 0) {
+               strtoul(s + n + 1, &end, 10);
+               if  (end > s + n + 1 && (*end == '.' || *end == 0))
+                       s[n] = 0;
+       }
+       return s;
+}
+
 static void read_symbols(char *modname)
 {
        const char *symname;
@@ -1718,7 +1752,7 @@ static void read_symbols(char *modname)
        }
 
        for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
-               symname = info.strtab + sym->st_name;
+               symname = remove_dot(info.strtab + sym->st_name);
 
                handle_modversions(mod, &info, sym, symname);
                handle_moddevtable(mod, &info, sym, symname);
index 51207e4d5f8bcae0add675e31cf579f28763d1d4..168b43dc0a59b6be4edea0fc5768fb2d63cfa440 100644 (file)
@@ -127,7 +127,7 @@ struct elf_info {
        Elf_Section  export_gpl_sec;
        Elf_Section  export_unused_gpl_sec;
        Elf_Section  export_gpl_future_sec;
-       const char   *strtab;
+       char         *strtab;
        char         *modinfo;
        unsigned int modinfo_len;
 
index e9c6ac724fef153efb0c8ae3ceea6da99407ae7c..beb86b500adffd406e65b26d0cf9abeab3891703 100644 (file)
@@ -103,7 +103,7 @@ config INTEL_TXT
 config LSM_MMAP_MIN_ADDR
        int "Low address space for LSM to protect from user allocation"
        depends on SECURITY && SECURITY_SELINUX
-       default 32768 if ARM
+       default 32768 if ARM || (ARM64 && COMPAT)
        default 65536
        help
          This is the portion of low virtual memory which should be protected
index 8b4f24ae43381de05af67271edd9a8ddd57c651f..21e2b9cae685f01536ed159443707d5046c8c34c 100644 (file)
@@ -757,7 +757,8 @@ static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
-                                         struct xfrm_user_sec_ctx *sec_ctx)
+                                         struct xfrm_user_sec_ctx *sec_ctx,
+                                         gfp_t gfp)
 {
        return 0;
 }
index bbd32c729dbb4e019d1461116b84c25107e35ab8..347896548ad3159a152186a4c1a27cdf92f1f4ad 100644 (file)
@@ -65,8 +65,8 @@ no_payload:
  * taking a 32-bit syscall are zero.  If you can, you should call sys_keyctl()
  * directly.
  */
-asmlinkage long compat_sys_keyctl(u32 option,
-                                 u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
+                      u32, arg2, u32, arg3, u32, arg4, u32, arg5)
 {
        switch (option) {
        case KEYCTL_GET_KEYRING_ID:
index d46cbc5e335e9c330ccd74a08fcbf78aeafe8c96..2fb2576dc6448b3c1020dc311e0d81bfe77fb768 100644 (file)
@@ -1000,7 +1000,11 @@ static int keyring_detect_cycle_iterator(const void *object,
 
        kenter("{%d}", key->serial);
 
-       BUG_ON(key != ctx->match_data);
+       /* We might get a keyring with matching index-key that is nonetheless a
+        * different keyring. */
+       if (key != ctx->match_data)
+               return 0;
+
        ctx->result = ERR_PTR(-EDEADLK);
        return 1;
 }
index 15b6928592ef68aac565e3fc94daf4737b6adc54..919cad93ac82fa2fa7c017b5c85353ca8ac6818e 100644 (file)
@@ -1317,9 +1317,11 @@ void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 
-int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
+int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
+                              struct xfrm_user_sec_ctx *sec_ctx,
+                              gfp_t gfp)
 {
-       return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx);
+       return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx, gfp);
 }
 EXPORT_SYMBOL(security_xfrm_policy_alloc);
 
index 4b34847208cc9690284e9e7c7b6f9a960cfbead3..b332e2cc0954becf1fa365f9690fef63d52ba97c 100644 (file)
@@ -668,7 +668,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                if (flags[i] == SBLABEL_MNT)
                        continue;
                rc = security_context_to_sid(mount_options[i],
-                                            strlen(mount_options[i]), &sid);
+                                            strlen(mount_options[i]), &sid, GFP_KERNEL);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
                               "(%s) failed for (dev %s, type %s) errno=%d\n",
@@ -2489,7 +2489,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
                if (flags[i] == SBLABEL_MNT)
                        continue;
                len = strlen(mount_options[i]);
-               rc = security_context_to_sid(mount_options[i], len, &sid);
+               rc = security_context_to_sid(mount_options[i], len, &sid,
+                                            GFP_KERNEL);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
                               "(%s) failed for (dev %s, type %s) errno=%d\n",
@@ -2893,7 +2894,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
        if (rc)
                return rc;
 
-       rc = security_context_to_sid(value, size, &newsid);
+       rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
        if (rc == -EINVAL) {
                if (!capable(CAP_MAC_ADMIN)) {
                        struct audit_buffer *ab;
@@ -3050,7 +3051,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
        if (!value || !size)
                return -EACCES;
 
-       rc = security_context_to_sid((void *)value, size, &newsid);
+       rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL);
        if (rc)
                return rc;
 
@@ -5529,7 +5530,7 @@ static int selinux_setprocattr(struct task_struct *p,
                        str[size-1] = 0;
                        size--;
                }
-               error = security_context_to_sid(value, size, &sid);
+               error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
                if (error == -EINVAL && !strcmp(name, "fscreate")) {
                        if (!capable(CAP_MAC_ADMIN)) {
                                struct audit_buffer *ab;
@@ -5638,7 +5639,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 
 static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
-       return security_context_to_sid(secdata, seclen, secid);
+       return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
 }
 
 static void selinux_release_secctx(char *secdata, u32 seclen)
index 8ed8daf7f1eed9df82f963294e89e849b0da4b1d..ce7852cf526b8e564f69a20c005da00a19a941ca 100644 (file)
@@ -134,7 +134,7 @@ int security_sid_to_context(u32 sid, char **scontext,
 int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
 
 int security_context_to_sid(const char *scontext, u32 scontext_len,
-       u32 *out_sid);
+                           u32 *out_sid, gfp_t gfp);
 
 int security_context_to_sid_default(const char *scontext, u32 scontext_len,
                                    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
index 48c3cc94c1681718a78e6793c7e961e2d404f3fb..9f0584710c858a8281d51f2c287dc3b43b30d77f 100644 (file)
@@ -10,7 +10,8 @@
 #include <net/flow.h>
 
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
-                             struct xfrm_user_sec_ctx *uctx);
+                             struct xfrm_user_sec_ctx *uctx,
+                             gfp_t gfp);
 int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
                              struct xfrm_sec_ctx **new_ctxp);
 void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
index 332ac8a80cf5b62c77bff350f6a92698d76a8e0f..2df7b900e25965828ed91e3bd376340a672d9c0f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/inet_diag.h>
 #include <linux/xfrm.h>
 #include <linux/audit.h>
+#include <linux/sock_diag.h>
 
 #include "flask.h"
 #include "av_permissions.h"
@@ -78,6 +79,7 @@ static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
 {
        { TCPDIAG_GETSOCK,      NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
        { DCCPDIAG_GETSOCK,     NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
+       { SOCK_DIAG_BY_FAMILY,  NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
 };
 
 static struct nlmsg_perm nlmsg_xfrm_perms[] =
index 5122affe06a8840e193150d62bd9b2f996fe67fe..d60c0ee66387d8078055414992ad36d7a2d31fa8 100644 (file)
@@ -576,7 +576,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
        if (length)
                goto out;
 
-       length = security_context_to_sid(buf, size, &sid);
+       length = security_context_to_sid(buf, size, &sid, GFP_KERNEL);
        if (length)
                goto out;
 
@@ -731,11 +731,13 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
                goto out;
 
-       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
+       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
+       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
@@ -817,11 +819,13 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
                objname = namebuf;
        }
 
-       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
+       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
+       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
@@ -878,11 +882,13 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
                goto out;
 
-       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
+       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
+       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
@@ -934,7 +940,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s", con, user) != 2)
                goto out;
 
-       length = security_context_to_sid(con, strlen(con) + 1, &sid);
+       length = security_context_to_sid(con, strlen(con) + 1, &sid, GFP_KERNEL);
        if (length)
                goto out;
 
@@ -994,11 +1000,13 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
                goto out;
 
-       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
+       length = security_context_to_sid(scon, strlen(scon) + 1, &ssid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
+       length = security_context_to_sid(tcon, strlen(tcon) + 1, &tsid,
+                                        GFP_KERNEL);
        if (length)
                goto out;
 
index c0f4988421292f0ab6610421704ee21381b59a0f..9c5cdc2caaef7637b4bf9178a8efcbe69558c6b9 100644 (file)
@@ -3338,10 +3338,10 @@ static int filename_write_helper(void *key, void *data, void *ptr)
        if (rc)
                return rc;
 
-       buf[0] = ft->stype;
-       buf[1] = ft->ttype;
-       buf[2] = ft->tclass;
-       buf[3] = otype->otype;
+       buf[0] = cpu_to_le32(ft->stype);
+       buf[1] = cpu_to_le32(ft->ttype);
+       buf[2] = cpu_to_le32(ft->tclass);
+       buf[3] = cpu_to_le32(otype->otype);
 
        rc = put_entry(buf, sizeof(u32), 4, fp);
        if (rc)
index c93c21127f0cc5b6bc55c2930fdfe2441dc2a19c..4bca49414a40e5a40c4369415f5c5b0aecba6347 100644 (file)
@@ -1232,6 +1232,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
        struct context context;
        int rc = 0;
 
+       /* An empty security context is never valid. */
+       if (!scontext_len)
+               return -EINVAL;
+
        if (!ss_initialized) {
                int i;
 
@@ -1285,16 +1289,18 @@ out:
  * @scontext: security context
  * @scontext_len: length in bytes
  * @sid: security identifier, SID
+ * @gfp: context for the allocation
  *
  * Obtains a SID associated with the security context that
  * has the string representation specified by @scontext.
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
+int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid,
+                           gfp_t gfp)
 {
        return security_context_to_sid_core(scontext, scontext_len,
-                                           sid, SECSID_NULL, GFP_KERNEL, 0);
+                                           sid, SECSID_NULL, gfp, 0);
 }
 
 /**
index 0462cb3ff0a741a36b279dcef37ee784e8520c5c..98b042630a9eafcfa982a469461ee5fd4da362b7 100644 (file)
@@ -78,7 +78,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
  * xfrm_user_sec_ctx context.
  */
 static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
-                                  struct xfrm_user_sec_ctx *uctx)
+                                  struct xfrm_user_sec_ctx *uctx,
+                                  gfp_t gfp)
 {
        int rc;
        const struct task_security_struct *tsec = current_security();
@@ -94,7 +95,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
        if (str_len >= PAGE_SIZE)
                return -ENOMEM;
 
-       ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
+       ctx = kmalloc(sizeof(*ctx) + str_len + 1, gfp);
        if (!ctx)
                return -ENOMEM;
 
@@ -103,7 +104,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
        ctx->ctx_len = str_len;
        memcpy(ctx->ctx_str, &uctx[1], str_len);
        ctx->ctx_str[str_len] = '\0';
-       rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
+       rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid, gfp);
        if (rc)
                goto err;
 
@@ -282,9 +283,10 @@ int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
  * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
  */
 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
-                             struct xfrm_user_sec_ctx *uctx)
+                             struct xfrm_user_sec_ctx *uctx,
+                             gfp_t gfp)
 {
-       return selinux_xfrm_alloc_user(ctxp, uctx);
+       return selinux_xfrm_alloc_user(ctxp, uctx, gfp);
 }
 
 /*
@@ -332,7 +334,7 @@ int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 int selinux_xfrm_state_alloc(struct xfrm_state *x,
                             struct xfrm_user_sec_ctx *uctx)
 {
-       return selinux_xfrm_alloc_user(&x->security, uctx);
+       return selinux_xfrm_alloc_user(&x->security, uctx, GFP_KERNEL);
 }
 
 /*
index 7a20897d33dbc1147b381ca6884f87dc88eb7ff1..7403f348ed1425733ce77735c8dff37d1610ad4d 100644 (file)
@@ -133,7 +133,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
                kfree(data);
        }
        snd_card_unref(compr->card);
-       return 0;
+       return ret;
 }
 
 static int snd_compr_free(struct inode *inode, struct file *f)
index ec4536c8d8d43c0987d43fd0ef9d07fe9a417ef4..dafcf82139e2bbdcdb4bad0539ad6c616661d892 100644 (file)
@@ -932,7 +932,7 @@ int snd_hda_bus_new(struct snd_card *card,
 }
 EXPORT_SYMBOL_GPL(snd_hda_bus_new);
 
-#ifdef CONFIG_SND_HDA_GENERIC
+#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
 #define is_generic_config(codec) \
        (codec->modelname && !strcmp(codec->modelname, "generic"))
 #else
@@ -1339,23 +1339,15 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
 /*
  * Dynamic symbol binding for the codec parsers
  */
-#ifdef MODULE
-#define load_parser_sym(sym)           ((int (*)(struct hda_codec *))symbol_request(sym))
-#define unload_parser_addr(addr)       symbol_put_addr(addr)
-#else
-#define load_parser_sym(sym)           (sym)
-#define unload_parser_addr(addr)       do {} while (0)
-#endif
 
 #define load_parser(codec, sym) \
-       ((codec)->parser = load_parser_sym(sym))
+       ((codec)->parser = (int (*)(struct hda_codec *))symbol_request(sym))
 
 static void unload_parser(struct hda_codec *codec)
 {
-       if (codec->parser) {
-               unload_parser_addr(codec->parser);
-               codec->parser = NULL;
-       }
+       if (codec->parser)
+               symbol_put_addr(codec->parser);
+       codec->parser = NULL;
 }
 
 /*
@@ -1570,7 +1562,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
 EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets);
 
 
-#ifdef CONFIG_SND_HDA_CODEC_HDMI
+#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
 /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
 static bool is_likely_hdmi_codec(struct hda_codec *codec)
 {
@@ -1620,12 +1612,20 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                patch = codec->preset->patch;
        if (!patch) {
                unload_parser(codec); /* to be sure */
-               if (is_likely_hdmi_codec(codec))
+               if (is_likely_hdmi_codec(codec)) {
+#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
                        patch = load_parser(codec, snd_hda_parse_hdmi_codec);
-#ifdef CONFIG_SND_HDA_GENERIC
-               if (!patch)
+#elif IS_BUILTIN(CONFIG_SND_HDA_CODEC_HDMI)
+                       patch = snd_hda_parse_hdmi_codec;
+#endif
+               }
+               if (!patch) {
+#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
                        patch = load_parser(codec, snd_hda_parse_generic_codec);
+#elif IS_BUILTIN(CONFIG_SND_HDA_GENERIC)
+                       patch = snd_hda_parse_generic_codec;
 #endif
+               }
                if (!patch) {
                        printk(KERN_ERR "hda-codec: No codec parser is available\n");
                        return -ENODEV;
index 8321a97d5c05047ab2312f8c62603826041a1897..d9a09bdd09db656891aa51f910753b686dc79964 100644 (file)
@@ -3269,7 +3269,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
        mutex_unlock(&codec->control_mutex);
        snd_hda_codec_flush_cache(codec); /* flush the updates */
        if (err >= 0 && spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, ucontrol);
+               spec->cap_sync_hook(codec, kcontrol, ucontrol);
        return err;
 }
 
@@ -3390,7 +3390,7 @@ static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
                return ret;
 
        if (spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, ucontrol);
+               spec->cap_sync_hook(codec, kcontrol, ucontrol);
 
        return ret;
 }
@@ -3795,7 +3795,7 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
                return 0;
        snd_hda_activate_path(codec, path, true, false);
        if (spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, NULL);
+               spec->cap_sync_hook(codec, NULL, NULL);
        path_power_down_sync(codec, old_path);
        return 1;
 }
@@ -5270,7 +5270,7 @@ static void init_input_src(struct hda_codec *codec)
        }
 
        if (spec->cap_sync_hook)
-               spec->cap_sync_hook(codec, NULL);
+               spec->cap_sync_hook(codec, NULL, NULL);
 }
 
 /* set right pin controls for digital I/O */
index 07f767231c9f439bef66a950f6a5cab3ce957156..c908afbe4d94662fcaa92cf4009efc64b2114680 100644 (file)
@@ -274,6 +274,7 @@ struct hda_gen_spec {
        void (*init_hook)(struct hda_codec *codec);
        void (*automute_hook)(struct hda_codec *codec);
        void (*cap_sync_hook)(struct hda_codec *codec,
+                             struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol);
 
        /* PCM hooks */
index fa2879a21a50a51beed9fdc1bcc77ea607b00b27..e354ab1ec20f2dcd942931582761cc10b5543648 100644 (file)
@@ -198,7 +198,7 @@ MODULE_DESCRIPTION("Intel HDA driver");
 #endif
 
 #if defined(CONFIG_PM) && defined(CONFIG_VGA_SWITCHEROO)
-#ifdef CONFIG_SND_HDA_CODEC_HDMI
+#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
 #define SUPPORT_VGA_SWITCHEROO
 #endif
 #endif
index 7a426ed491f2bea356f6a2610329f5ed84e17ebf..8ed0bcc0138637e69e19ff7056b99a86fac09fa6 100644 (file)
@@ -244,6 +244,19 @@ static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
        }
 }
 
+/* Toshiba Satellite L40 implements EAPD in a standard way unlike others */
+static void ad1986a_fixup_eapd(struct hda_codec *codec,
+                              const struct hda_fixup *fix, int action)
+{
+       struct ad198x_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               codec->inv_eapd = 0;
+               spec->gen.keep_eapd_on = 1;
+               spec->eapd_nid = 0x1b;
+       }
+}
+
 enum {
        AD1986A_FIXUP_INV_JACK_DETECT,
        AD1986A_FIXUP_ULTRA,
@@ -251,6 +264,7 @@ enum {
        AD1986A_FIXUP_3STACK,
        AD1986A_FIXUP_LAPTOP,
        AD1986A_FIXUP_LAPTOP_IMIC,
+       AD1986A_FIXUP_EAPD,
 };
 
 static const struct hda_fixup ad1986a_fixups[] = {
@@ -311,6 +325,10 @@ static const struct hda_fixup ad1986a_fixups[] = {
                .chained_before = 1,
                .chain_id = AD1986A_FIXUP_LAPTOP,
        },
+       [AD1986A_FIXUP_EAPD] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = ad1986a_fixup_eapd,
+       },
 };
 
 static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
@@ -318,6 +336,7 @@ static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
        SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK),
        SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK),
        SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK),
+       SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40", AD1986A_FIXUP_EAPD),
        SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP),
        SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG),
        SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA),
@@ -472,6 +491,8 @@ static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
 static int patch_ad1983(struct hda_codec *codec)
 {
        struct ad198x_spec *spec;
+       static hda_nid_t conn_0c[] = { 0x08 };
+       static hda_nid_t conn_0d[] = { 0x09 };
        int err;
 
        err = alloc_ad_spec(codec);
@@ -479,8 +500,14 @@ static int patch_ad1983(struct hda_codec *codec)
                return err;
        spec = codec->spec;
 
+       spec->gen.mixer_nid = 0x0e;
        spec->gen.beep_nid = 0x10;
        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+
+       /* limit the loopback routes not to confuse the parser */
+       snd_hda_override_conn_list(codec, 0x0c, ARRAY_SIZE(conn_0c), conn_0c);
+       snd_hda_override_conn_list(codec, 0x0d, ARRAY_SIZE(conn_0d), conn_0d);
+
        err = ad198x_parse_auto_config(codec, false);
        if (err < 0)
                goto error;
@@ -999,6 +1026,9 @@ static void ad1884_fixup_thinkpad(struct hda_codec *codec,
                spec->gen.keep_eapd_on = 1;
                spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
                spec->eapd_nid = 0x12;
+               /* Analog PC Beeper - allow firmware/ACPI beeps */
+               spec->beep_amp = HDA_COMPOSE_AMP_VAL(0x20, 3, 3, HDA_INPUT);
+               spec->gen.beep_nid = 0; /* no digital beep */
        }
 }
 
@@ -1065,6 +1095,7 @@ static int patch_ad1884(struct hda_codec *codec)
        spec = codec->spec;
 
        spec->gen.mixer_nid = 0x20;
+       spec->gen.mixer_merge_nid = 0x21;
        spec->gen.beep_nid = 0x10;
        set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
 
index 54d14793725a7dd93623083d29f72f41a5ddc4bd..46ecdbb9053f337ee6f1b199d9babdeb043d72d5 100644 (file)
@@ -2661,60 +2661,6 @@ static bool dspload_wait_loaded(struct hda_codec *codec)
        return false;
 }
 
-/*
- * PCM stuffs
- */
-static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-                                u32 stream_tag,
-                                int channel_id, int format)
-{
-       unsigned int oldval, newval;
-
-       if (!nid)
-               return;
-
-       snd_printdd(
-                  "ca0132_setup_stream: NID=0x%x, stream=0x%x, "
-                  "channel=%d, format=0x%x\n",
-                  nid, stream_tag, channel_id, format);
-
-       /* update the format-id if changed */
-       oldval = snd_hda_codec_read(codec, nid, 0,
-                                   AC_VERB_GET_STREAM_FORMAT,
-                                   0);
-       if (oldval != format) {
-               msleep(20);
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_STREAM_FORMAT,
-                                   format);
-       }
-
-       oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
-       newval = (stream_tag << 4) | channel_id;
-       if (oldval != newval) {
-               snd_hda_codec_write(codec, nid, 0,
-                                   AC_VERB_SET_CHANNEL_STREAMID,
-                                   newval);
-       }
-}
-
-static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
-{
-       unsigned int val;
-
-       if (!nid)
-               return;
-
-       snd_printdd(KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n", nid);
-
-       val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
-       if (!val)
-               return;
-
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
-}
-
 /*
  * PCM callbacks
  */
@@ -2726,7 +2672,7 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 {
        struct ca0132_spec *spec = codec->spec;
 
-       ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
+       snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
 
        return 0;
 }
@@ -2745,7 +2691,7 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
        if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
                msleep(50);
 
-       ca0132_cleanup_stream(codec, spec->dacs[0]);
+       snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
 
        return 0;
 }
@@ -2822,10 +2768,8 @@ static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
                                        unsigned int format,
                                        struct snd_pcm_substream *substream)
 {
-       struct ca0132_spec *spec = codec->spec;
-
-       ca0132_setup_stream(codec, spec->adcs[substream->number],
-                           stream_tag, 0, format);
+       snd_hda_codec_setup_stream(codec, hinfo->nid,
+                                  stream_tag, 0, format);
 
        return 0;
 }
@@ -2839,7 +2783,7 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
        if (spec->dsp_state == DSP_DOWNLOADING)
                return 0;
 
-       ca0132_cleanup_stream(codec, hinfo->nid);
+       snd_hda_codec_cleanup_stream(codec, hinfo->nid);
        return 0;
 }
 
@@ -4742,6 +4686,8 @@ static int patch_ca0132(struct hda_codec *codec)
                return err;
 
        codec->patch_ops = ca0132_patch_ops;
+       codec->pcm_format_first = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
index 4e0ec146553dadebda31c7ea996a4583dc296764..bcf91bea33179ce50b9485fd1db59caf1349b64c 100644 (file)
@@ -3291,7 +3291,8 @@ static void cxt_update_headset_mode(struct hda_codec *codec)
 }
 
 static void cxt_update_headset_mode_hook(struct hda_codec *codec,
-                            struct snd_ctl_elem_value *ucontrol)
+                                        struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
 {
        cxt_update_headset_mode(codec);
 }
index 56a8f187660333a51149910648d00b0a944e685b..8d0a84436674bf893ec871173a53b00b89f92c68 100644 (file)
@@ -708,7 +708,8 @@ static void alc_inv_dmic_sync(struct hda_codec *codec, bool force)
 }
 
 static void alc_inv_dmic_hook(struct hda_codec *codec,
-                            struct snd_ctl_elem_value *ucontrol)
+                             struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
 {
        alc_inv_dmic_sync(codec, false);
 }
@@ -1821,6 +1822,7 @@ enum {
        ALC889_FIXUP_IMAC91_VREF,
        ALC889_FIXUP_MBA11_VREF,
        ALC889_FIXUP_MBA21_VREF,
+       ALC889_FIXUP_MP11_VREF,
        ALC882_FIXUP_INV_DMIC,
        ALC882_FIXUP_NO_PRIMARY_HP,
        ALC887_FIXUP_ASUS_BASS,
@@ -2190,6 +2192,12 @@ static const struct hda_fixup alc882_fixups[] = {
                .chained = true,
                .chain_id = ALC889_FIXUP_MBP_VREF,
        },
+       [ALC889_FIXUP_MP11_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc889_fixup_mba11_vref,
+               .chained = true,
+               .chain_id = ALC885_FIXUP_MACPRO_GPIO,
+       },
        [ALC882_FIXUP_INV_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
@@ -2253,7 +2261,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
-       SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF),
        SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
        SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
        SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
@@ -3211,7 +3219,8 @@ static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)
 
 /* turn on/off mic-mute LED per capture hook */
 static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
-                              struct snd_ctl_elem_value *ucontrol)
+                                              struct snd_kcontrol *kcontrol,
+                                              struct snd_ctl_elem_value *ucontrol)
 {
        struct alc_spec *spec = codec->spec;
        unsigned int oldval = spec->gpio_led;
@@ -3521,7 +3530,8 @@ static void alc_update_headset_mode(struct hda_codec *codec)
 }
 
 static void alc_update_headset_mode_hook(struct hda_codec *codec,
-                            struct snd_ctl_elem_value *ucontrol)
+                                        struct snd_kcontrol *kcontrol,
+                                        struct snd_ctl_elem_value *ucontrol)
 {
        alc_update_headset_mode(codec);
 }
@@ -3606,6 +3616,19 @@ static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
        }
 }
 
+static void alc_no_shutup(struct hda_codec *codec)
+{
+}
+
+static void alc_fixup_no_shutup(struct hda_codec *codec,
+                               const struct hda_fixup *fix, int action)
+{
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               struct alc_spec *spec = codec->spec;
+               spec->shutup = alc_no_shutup;
+       }
+}
+
 static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
 {
@@ -3834,6 +3857,7 @@ enum {
        ALC269_FIXUP_HP_GPIO_LED,
        ALC269_FIXUP_INV_DMIC,
        ALC269_FIXUP_LENOVO_DOCK,
+       ALC269_FIXUP_NO_SHUTUP,
        ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
        ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
        ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
@@ -4010,6 +4034,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC269_FIXUP_NO_SHUTUP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_no_shutup,
+       },
        [ALC269_FIXUP_LENOVO_DOCK] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -4243,6 +4271,7 @@ static const struct hda_fixup alc269_fixups[] = {
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
@@ -4298,7 +4327,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0651, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0652, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4307,6 +4338,54 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
+       /* ALC282 */
+       SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22a0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c1, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22cd, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       /* ALC290 */
+       SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2280, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2281, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x2289, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -4322,6 +4401,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
+       SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
        SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
@@ -4343,6 +4423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5096,12 +5177,13 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_AUTO_MUTE),
        SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_AUTO_MUTE),
        SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE),
-       SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE),
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
        SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),
index 6998cf29b9bc34016e2d2ee1574b6b3d02ce8ef2..3bc29c9b25296d6ed058eaf552bf71bdba356cab 100644 (file)
@@ -83,6 +83,7 @@ enum {
        STAC_DELL_M6_BOTH,
        STAC_DELL_EQ,
        STAC_ALIENWARE_M17X,
+       STAC_92HD89XX_HP_FRONT_JACK,
        STAC_92HD73XX_MODELS
 };
 
@@ -97,6 +98,7 @@ enum {
        STAC_92HD83XXX_HP_LED,
        STAC_92HD83XXX_HP_INV_LED,
        STAC_92HD83XXX_HP_MIC_LED,
+       STAC_HP_LED_GPIO10,
        STAC_92HD83XXX_HEADSET_JACK,
        STAC_92HD83XXX_HP,
        STAC_HP_ENVY_BASS,
@@ -194,7 +196,7 @@ struct sigmatel_spec {
        int default_polarity;
 
        unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */
-       bool mic_mute_led_on; /* current mic mute state */
+       unsigned int mic_enabled; /* current mic mute state (bitmask) */
 
        /* stream */
        unsigned int stream_delay;
@@ -324,19 +326,26 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
 
 /* hook for controlling mic-mute LED GPIO */
 static void stac_capture_led_hook(struct hda_codec *codec,
-                              struct snd_ctl_elem_value *ucontrol)
+                                 struct snd_kcontrol *kcontrol,
+                                 struct snd_ctl_elem_value *ucontrol)
 {
        struct sigmatel_spec *spec = codec->spec;
-       bool mute;
+       unsigned int mask;
+       bool cur_mute, prev_mute;
 
-       if (!ucontrol)
+       if (!kcontrol || !ucontrol)
                return;
 
-       mute = !(ucontrol->value.integer.value[0] ||
-                ucontrol->value.integer.value[1]);
-       if (spec->mic_mute_led_on != mute) {
-               spec->mic_mute_led_on = mute;
-               if (mute)
+       mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+       prev_mute = !spec->mic_enabled;
+       if (ucontrol->value.integer.value[0] ||
+           ucontrol->value.integer.value[1])
+               spec->mic_enabled |= mask;
+       else
+               spec->mic_enabled &= ~mask;
+       cur_mute = !spec->mic_enabled;
+       if (cur_mute != prev_mute) {
+               if (cur_mute)
                        spec->gpio_data |= spec->mic_mute_led_gpio;
                else
                        spec->gpio_data &= ~spec->mic_mute_led_gpio;
@@ -1788,6 +1797,12 @@ static const struct hda_pintbl intel_dg45id_pin_configs[] = {
        {}
 };
 
+static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
+       { 0x0a, 0x02214030 },
+       { 0x0b, 0x02A19010 },
+       {}
+};
+
 static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
 {
@@ -1906,6 +1921,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
        [STAC_92HD73XX_NO_JD] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = stac92hd73xx_fixup_no_jd,
+       },
+       [STAC_92HD89XX_HP_FRONT_JACK] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = stac92hd89xx_hp_front_jack_pin_configs,
        }
 };
 
@@ -1966,6 +1985,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
                      "Alienware M17x", STAC_ALIENWARE_M17X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
                      "Alienware M17x R3", STAC_DELL_EQ),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
+                               "unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
        {} /* terminator */
 };
 
@@ -2110,6 +2131,17 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
        }
 }
 
+static void stac92hd83xxx_fixup_hp_led_gpio10(struct hda_codec *codec,
+                                  const struct hda_fixup *fix, int action)
+{
+       struct sigmatel_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->gpio_led = 0x10; /* GPIO4 */
+               spec->default_polarity = 0;
+       }
+}
+
 static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
 {
@@ -2604,6 +2636,12 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = {
                .chained = true,
                .chain_id = STAC_92HD83XXX_HP,
        },
+       [STAC_HP_LED_GPIO10] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = stac92hd83xxx_fixup_hp_led_gpio10,
+               .chained = true,
+               .chain_id = STAC_92HD83XXX_HP,
+       },
        [STAC_92HD83XXX_HEADSET_JACK] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = stac92hd83xxx_fixup_headset_jack,
@@ -2682,6 +2720,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
                          "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1888,
                          "HP Envy Spectre", STAC_HP_ENVY_BASS),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1899,
+                         "HP Folio 13", STAC_HP_LED_GPIO10),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df,
                          "HP Folio", STAC_HP_BNB13_EQ),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18F8,
@@ -4462,7 +4502,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
        if (spec->mic_mute_led_gpio) {
                spec->gpio_mask |= spec->mic_mute_led_gpio;
                spec->gpio_dir |= spec->mic_mute_led_gpio;
-               spec->mic_mute_led_on = true;
+               spec->mic_enabled = 0;
                spec->gpio_data |= spec->mic_mute_led_gpio;
 
                spec->gen.cap_sync_hook = stac_capture_led_hook;
index 5799fbc24c28a20a8a19fc6b93acaca53528887a..8fe3b8c18ed4b2c25c00b4963ec766b7671829d9 100644 (file)
@@ -39,6 +39,7 @@ static void update_tpacpi_mute_led(void *private_data, int enabled)
 }
 
 static void update_tpacpi_micmute_led(struct hda_codec *codec,
+                                     struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_value *ucontrol)
 {
        if (!ucontrol || !led_set_func)
index ed6f199f8a38ac3d1412fc8efa4010ba23ecee4d..4cf3200e988b03adf40129af71cfe1c9bb51bb69 100644 (file)
@@ -238,11 +238,21 @@ void set_cs4245_adc_params(struct oxygen *chip,
        cs4245_write_spi(chip, CS4245_MCLK_FREQ);
 }
 
+static inline unsigned int shift_bits(unsigned int value,
+                                     unsigned int shift_from,
+                                     unsigned int shift_to,
+                                     unsigned int mask)
+{
+       if (shift_from < shift_to)
+               return (value << (shift_to - shift_from)) & mask;
+       else
+               return (value >> (shift_from - shift_to)) & mask;
+}
+
 unsigned int adjust_dg_dac_routing(struct oxygen *chip,
                                          unsigned int play_routing)
 {
        struct dg *data = chip->model_data;
-       unsigned int routing = 0;
 
        switch (data->output_sel) {
        case PLAYBACK_DST_HP:
@@ -252,15 +262,23 @@ unsigned int adjust_dg_dac_routing(struct oxygen *chip,
                        OXYGEN_PLAY_MUTE67, OXYGEN_PLAY_MUTE_MASK);
                break;
        case PLAYBACK_DST_MULTICH:
-               routing = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) |
-                         (2 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) |
-                         (1 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) |
-                         (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT);
                oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING,
                        OXYGEN_PLAY_MUTE01, OXYGEN_PLAY_MUTE_MASK);
                break;
        }
-       return routing;
+       return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
+              shift_bits(play_routing,
+                         OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
+                         OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
+                         OXYGEN_PLAY_DAC1_SOURCE_MASK) |
+              shift_bits(play_routing,
+                         OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
+                         OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
+                         OXYGEN_PLAY_DAC2_SOURCE_MASK) |
+              shift_bits(play_routing,
+                         OXYGEN_PLAY_DAC0_SOURCE_SHIFT,
+                         OXYGEN_PLAY_DAC3_SOURCE_SHIFT,
+                         OXYGEN_PLAY_DAC3_SOURCE_MASK);
 }
 
 void dump_cs4245_registers(struct oxygen *chip,
index 54f74f8cbb754a0e66aecc3953fff0c8ba63966c..4544d8eb1452b24638c969ed15432a6f41e98ef8 100644 (file)
@@ -11,7 +11,7 @@ config SND_BF5XX_I2S
 
 config SND_BF5XX_SOC_SSM2602
        tristate "SoC SSM2602 Audio Codec Add-On Card support"
-       depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+       depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
        select SND_BF5XX_SOC_I2S if !BF60x
        select SND_BF6XX_SOC_I2S if BF60x
        select SND_SOC_SSM2602
@@ -21,10 +21,9 @@ config SND_BF5XX_SOC_SSM2602
 
 config SND_SOC_BFIN_EVAL_ADAU1701
        tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards"
-       depends on SND_BF5XX_I2S
+       depends on SND_BF5XX_I2S && I2C
        select SND_BF5XX_SOC_I2S
        select SND_SOC_ADAU1701
-       select I2C
        help
          Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ
          board connected to one of the Blackfin evaluation boards like the
@@ -45,7 +44,7 @@ config SND_SOC_BFIN_EVAL_ADAU1373
 
 config SND_SOC_BFIN_EVAL_ADAV80X
        tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
-       depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+       depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
        select SND_BF5XX_SOC_I2S
        select SND_SOC_ADAV80X
        help
@@ -58,7 +57,7 @@ config SND_SOC_BFIN_EVAL_ADAV80X
 
 config SND_BF5XX_SOC_AD1836
        tristate "SoC AD1836 Audio support for BF5xx"
-       depends on SND_BF5XX_I2S
+       depends on SND_BF5XX_I2S && SPI_MASTER
        select SND_BF5XX_SOC_I2S
        select SND_SOC_AD1836
        help
@@ -66,7 +65,7 @@ config SND_BF5XX_SOC_AD1836
 
 config SND_BF5XX_SOC_AD193X
        tristate "SoC AD193X Audio support for Blackfin"
-       depends on SND_BF5XX_I2S
+       depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
        select SND_BF5XX_SOC_I2S
        select SND_SOC_AD193X
        help
index 75d0ad5d2dcb38107934536ba7ef93410025c2f6..647a72cda005a5cc4f8b362fefe8aa1ad3f68a76 100644 (file)
@@ -1328,6 +1328,9 @@ static int pm860x_probe(struct snd_soc_codec *codec)
        pm860x->codec = codec;
 
        codec->control_data = pm860x->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+       if (ret)
+               return ret;
 
        for (i = 0; i < 4; i++) {
                ret = request_threaded_irq(pm860x->irq[i], NULL,
index 7257a8885f426d7cf05b017fbda1aa3f01abe236..34d965a4a040c91d861a8d2f8a3ef183b95bc5e8 100644 (file)
@@ -57,8 +57,8 @@ static const u16 ad1980_reg[] = {
 static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line",
                "Stereo Mix", "Mono Mix", "Phone"};
 
-static const struct soc_enum ad1980_cap_src =
-       SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel);
+static SOC_ENUM_DOUBLE_DECL(ad1980_cap_src,
+                           AC97_REC_SEL, 8, 0, ad1980_rec_sel);
 
 static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = {
 SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
index f295b65699105897743fad1ecbc4439a71e58f0e..f4d965ebc29e8320469becd09a3ac58a2668e8de 100644 (file)
@@ -1268,11 +1268,23 @@ static struct snd_soc_dai_driver da732x_dai[] = {
        },
 };
 
+static bool da732x_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case DA732X_REG_HPL_DAC_OFF_CNTL:
+       case DA732X_REG_HPR_DAC_OFF_CNTL:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static const struct regmap_config da732x_regmap = {
        .reg_bits               = 8,
        .val_bits               = 8,
 
        .max_register           = DA732X_MAX_REG,
+       .volatile_reg           = da732x_volatile,
        .reg_defaults           = da732x_reg_cache,
        .num_reg_defaults       = ARRAY_SIZE(da732x_reg_cache),
        .cache_type             = REGCACHE_RBTREE,
index 52b79a487ac7db318dd252fe30befd6a3c56b2ec..422812613a28b1cff117b1adfee2029b69e6049b 100644 (file)
@@ -1523,8 +1523,15 @@ static int da9055_remove(struct i2c_client *client)
        return 0;
 }
 
+/*
+ * DO NOT change the device Ids. The naming is intentionally specific as both
+ * the CODEC and PMIC parts of this chip are instantiated separately as I2C
+ * devices (both have configurable I2C addresses, and are to all intents and
+ * purposes separate). As a result there are specific DA9055 Ids for CODEC
+ * and PMIC, which must be different to operate together.
+ */
 static const struct i2c_device_id da9055_i2c_id[] = {
-       { "da9055", 0 },
+       { "da9055-codec", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
@@ -1532,7 +1539,7 @@ MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
 /* I2C codec control layer */
 static struct i2c_driver da9055_i2c_driver = {
        .driver = {
-               .name = "da9055",
+               .name = "da9055-codec",
                .owner = THIS_MODULE,
        },
        .probe          = da9055_i2c_probe,
index 5839048ec4674e5d20cc5f06e206c2210977999e..cb736ddc446dc0bc5a387dc3ebc28e4bb0fee9aa 100644 (file)
@@ -140,13 +140,17 @@ static const char *isabelle_rx1_texts[] = {"VRX1", "ARX1"};
 static const char *isabelle_rx2_texts[] = {"VRX2", "ARX2"};
 
 static const struct soc_enum isabelle_rx1_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3, 1, isabelle_rx1_texts),
-       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5, 1, isabelle_rx1_texts),
+       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 3,
+                       ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 5,
+                       ARRAY_SIZE(isabelle_rx1_texts), isabelle_rx1_texts),
 };
 
 static const struct soc_enum isabelle_rx2_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2, 1, isabelle_rx2_texts),
-       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4, 1, isabelle_rx2_texts),
+       SOC_ENUM_SINGLE(ISABELLE_VOICE_HPF_CFG_REG, 2,
+                       ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AUDIO_HPF_CFG_REG, 4,
+                       ARRAY_SIZE(isabelle_rx2_texts), isabelle_rx2_texts),
 };
 
 /* Headset DAC playback switches */
@@ -161,13 +165,17 @@ static const char *isabelle_atx_texts[] = {"AMIC1", "DMIC"};
 static const char *isabelle_vtx_texts[] = {"AMIC2", "DMIC"};
 
 static const struct soc_enum isabelle_atx_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7, 1, isabelle_atx_texts),
-       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_atx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+                       ARRAY_SIZE(isabelle_atx_texts), isabelle_atx_texts),
 };
 
 static const struct soc_enum isabelle_vtx_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6, 1, isabelle_vtx_texts),
-       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0, 1, isabelle_vtx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 6,
+                       ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
+       SOC_ENUM_SINGLE(ISABELLE_DMIC_CFG_REG, 0,
+                       ARRAY_SIZE(isabelle_vtx_texts), isabelle_vtx_texts),
 };
 
 static const struct snd_kcontrol_new atx_mux_controls =
@@ -183,17 +191,13 @@ static const char *isabelle_amic1_texts[] = {
 /* Left analog microphone selection */
 static const char *isabelle_amic2_texts[] = {"Sub Mic", "Aux/FM Right"};
 
-static const struct soc_enum isabelle_amic1_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 5,
-                       ARRAY_SIZE(isabelle_amic1_texts),
-                       isabelle_amic1_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic1_enum,
+                           ISABELLE_AMIC_CFG_REG, 5,
+                           isabelle_amic1_texts);
 
-static const struct soc_enum isabelle_amic2_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_AMIC_CFG_REG, 4,
-                       ARRAY_SIZE(isabelle_amic2_texts),
-                       isabelle_amic2_texts),
-};
+static SOC_ENUM_SINGLE_DECL(isabelle_amic2_enum,
+                           ISABELLE_AMIC_CFG_REG, 4,
+                           isabelle_amic2_texts);
 
 static const struct snd_kcontrol_new amic1_control =
        SOC_DAPM_ENUM("Route", isabelle_amic1_enum);
@@ -206,16 +210,20 @@ static const char *isabelle_st_audio_texts[] = {"ATX1", "ATX2"};
 static const char *isabelle_st_voice_texts[] = {"VTX1", "VTX2"};
 
 static const struct soc_enum isabelle_st_audio_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA1_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_audio_texts),
                        isabelle_st_audio_texts),
-       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_ATX_STPGA2_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_audio_texts),
                        isabelle_st_audio_texts),
 };
 
 static const struct soc_enum isabelle_st_voice_enum[] = {
-       SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_VTX_STPGA1_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_voice_texts),
                        isabelle_st_voice_texts),
-       SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7, 1,
+       SOC_ENUM_SINGLE(ISABELLE_VTX2_STPGA2_CFG_REG, 7,
+                       ARRAY_SIZE(isabelle_st_voice_texts),
                        isabelle_st_voice_texts),
 };
 
index 51f9b3d16b41dbf4cc80dddc6d0a081ccb83fe90..9f714ea86613cc6939c62c3a420dc0c2ce07bb17 100644 (file)
@@ -336,6 +336,7 @@ static bool max98090_readable_register(struct device *dev, unsigned int reg)
        case M98090_REG_RECORD_TDM_SLOT:
        case M98090_REG_SAMPLE_RATE:
        case M98090_REG_DMIC34_BIQUAD_BASE ... M98090_REG_DMIC34_BIQUAD_BASE + 0x0E:
+       case M98090_REG_REVISION_ID:
                return true;
        default:
                return false;
@@ -1769,16 +1770,6 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = regcache_sync(max98090->regmap);
-
-                       if (ret != 0) {
-                               dev_err(codec->dev,
-                                       "Failed to sync cache: %d\n", ret);
-                               return ret;
-                       }
-               }
-
                if (max98090->jack_state == M98090_JACK_STATE_HEADSET) {
                        /*
                         * Set to normal bias level.
@@ -1792,6 +1783,16 @@ static int max98090_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regcache_sync(max98090->regmap);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to sync cache: %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
        case SND_SOC_BIAS_OFF:
                /* Set internal pull-up to lowest power mode */
                snd_soc_update_bits(codec, M98090_REG_JACK_DETECT,
index a3fb411796364a683d554b6278ba9bda6b942326..886924934aa5c7db067f352aafc4113d5ab97c06 100644 (file)
@@ -2093,6 +2093,7 @@ MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
 #ifdef CONFIG_ACPI
 static struct acpi_device_id rt5640_acpi_match[] = {
        { "INT33CA", 0 },
+       { "10EC5640", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
index 52e7cb08434bd281354c4a34f520f16c38b0446f..fa2b8e07f420dd9c14ac0dc944babfe66dfbe2b2 100644 (file)
@@ -210,7 +210,7 @@ out:
 static int si476x_codec_probe(struct snd_soc_codec *codec)
 {
        codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
-       return 0;
+       return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
 }
 
 static struct snd_soc_dai_ops si476x_dai_ops = {
index 06edb396e733f1ad2ef26698a41b4eb1fdc18ea6..2735361a4c3cfc5fbc652ee10d62ec2728626184 100644 (file)
@@ -187,42 +187,42 @@ static const unsigned int sta32x_limiter_drc_release_tlv[] = {
        13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0),
 };
 
-static const struct soc_enum sta32x_drc_ac_enum =
-       SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
-                       2, sta32x_drc_ac);
-static const struct soc_enum sta32x_auto_eq_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
-                       3, sta32x_auto_eq_mode);
-static const struct soc_enum sta32x_auto_gc_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
-                       4, sta32x_auto_gc_mode);
-static const struct soc_enum sta32x_auto_xo_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
-                       16, sta32x_auto_xo_mode);
-static const struct soc_enum sta32x_preset_eq_enum =
-       SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
-                       32, sta32x_preset_eq_mode);
-static const struct soc_enum sta32x_limiter_ch1_enum =
-       SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
-                       3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch2_enum =
-       SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
-                       3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter_ch3_enum =
-       SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
-                       3, sta32x_limiter_select);
-static const struct soc_enum sta32x_limiter1_attack_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT,
-                       16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter2_attack_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT,
-                       16, sta32x_limiter_attack_rate);
-static const struct soc_enum sta32x_limiter1_release_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT,
-                       16, sta32x_limiter_release_rate);
-static const struct soc_enum sta32x_limiter2_release_rate_enum =
-       SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT,
-                       16, sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_drc_ac_enum,
+                           STA32X_CONFD, STA32X_CONFD_DRC_SHIFT,
+                           sta32x_drc_ac);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_eq_enum,
+                           STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT,
+                           sta32x_auto_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_gc_enum,
+                           STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT,
+                           sta32x_auto_gc_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_auto_xo_enum,
+                           STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT,
+                           sta32x_auto_xo_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_preset_eq_enum,
+                           STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT,
+                           sta32x_preset_eq_mode);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch1_enum,
+                           STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT,
+                           sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch2_enum,
+                           STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT,
+                           sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter_ch3_enum,
+                           STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT,
+                           sta32x_limiter_select);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_attack_rate_enum,
+                           STA32X_L1AR, STA32X_LxA_SHIFT,
+                           sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_attack_rate_enum,
+                           STA32X_L2AR, STA32X_LxA_SHIFT,
+                           sta32x_limiter_attack_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter1_release_rate_enum,
+                           STA32X_L1AR, STA32X_LxR_SHIFT,
+                           sta32x_limiter_release_rate);
+static SOC_ENUM_SINGLE_DECL(sta32x_limiter2_release_rate_enum,
+                           STA32X_L2AR, STA32X_LxR_SHIFT,
+                           sta32x_limiter_release_rate);
 
 /* byte array controls for setting biquad, mixer, scaling coefficients;
  * for biquads all five coefficients need to be set in one go,
@@ -331,7 +331,7 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
 
 static int sta32x_cache_sync(struct snd_soc_codec *codec)
 {
-       struct sta32x_priv *sta32x = codec->control_data;
+       struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
        unsigned int mute;
        int rc;
 
@@ -434,7 +434,7 @@ SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0,
 SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum),
 SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum),
 SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
-SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum),
+SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter2_release_rate_enum),
 
 /* depending on mode, the attack/release thresholds have
  * two different enum definitions; provide both
index 48dc7d2fee36fc07c236f6e9a09ea74cdb38d824..6d684d934f4de1e2b2c43dfc18d5659ada570cf1 100644 (file)
@@ -117,19 +117,23 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
 static const char *wm8400_digital_sidetone[] =
        {"None", "Left ADC", "Right ADC", "Reserved"};
 
-static const struct soc_enum wm8400_left_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
-               WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_left_digital_sidetone_enum,
+                           WM8400_DIGITAL_SIDE_TONE,
+                           WM8400_ADC_TO_DACL_SHIFT,
+                           wm8400_digital_sidetone);
 
-static const struct soc_enum wm8400_right_digital_sidetone_enum =
-SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE,
-               WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_digital_sidetone_enum,
+                           WM8400_DIGITAL_SIDE_TONE,
+                           WM8400_ADC_TO_DACR_SHIFT,
+                           wm8400_digital_sidetone);
 
 static const char *wm8400_adcmode[] =
        {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
 
-static const struct soc_enum wm8400_right_adcmode_enum =
-SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode);
+static SOC_ENUM_SINGLE_DECL(wm8400_right_adcmode_enum,
+                           WM8400_ADC_CTRL,
+                           WM8400_ADC_HPF_CUT_SHIFT,
+                           wm8400_adcmode);
 
 static const struct snd_kcontrol_new wm8400_snd_controls[] = {
 /* INMIXL */
@@ -422,9 +426,10 @@ SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT,
 static const char *wm8400_ainlmux[] =
        {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
 
-static const struct soc_enum wm8400_ainlmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT,
-       ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainlmux_enum,
+                           WM8400_INPUT_MIXER1,
+                           WM8400_AINLMODE_SHIFT,
+                           wm8400_ainlmux);
 
 static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls =
 SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
@@ -435,9 +440,10 @@ SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum);
 static const char *wm8400_ainrmux[] =
        {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
 
-static const struct soc_enum wm8400_ainrmux_enum =
-SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT,
-       ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux);
+static SOC_ENUM_SINGLE_DECL(wm8400_ainrmux_enum,
+                           WM8400_INPUT_MIXER1,
+                           WM8400_AINRMODE_SHIFT,
+                           wm8400_ainrmux);
 
 static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls =
 SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum);
index 89a18d82f303e168f874a418840a9d33a4923910..5bce2101348514aa6508dc9dac7f895d176ae0d9 100644 (file)
@@ -196,8 +196,8 @@ static const char *ain_text[] = {
        "AIN5", "AIN6", "AIN7", "AIN8"
 };
 
-static const struct soc_enum ain_enum =
-       SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text);
+static SOC_ENUM_DOUBLE_DECL(ain_enum,
+                           WM8770_ADCMUX, 0, 4, ain_text);
 
 static const struct snd_kcontrol_new ain_mux =
        SOC_DAPM_ENUM("Capture Mux", ain_enum);
index e98bc7038a086b39231ecbb5196fb7a40fc92d1e..43c2201cb90131ebdb66e2f10326f4c904700011 100644 (file)
@@ -304,53 +304,53 @@ static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
 
 static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
 
-static const struct soc_enum mic_bias_level =
-SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
+static SOC_ENUM_SINGLE_DECL(mic_bias_level,
+                           WM8900_REG_INCTL, 8, mic_bias_level_txt);
 
 static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
 
-static const struct soc_enum dac_mute_rate =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
+static SOC_ENUM_SINGLE_DECL(dac_mute_rate,
+                           WM8900_REG_DACCTRL, 7, dac_mute_rate_txt);
 
 static const char *dac_deemphasis_txt[] = {
        "Disabled", "32kHz", "44.1kHz", "48kHz"
 };
 
-static const struct soc_enum dac_deemphasis =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
+static SOC_ENUM_SINGLE_DECL(dac_deemphasis,
+                           WM8900_REG_DACCTRL, 4, dac_deemphasis_txt);
 
 static const char *adc_hpf_cut_txt[] = {
        "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
 };
 
-static const struct soc_enum adc_hpf_cut =
-SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
+static SOC_ENUM_SINGLE_DECL(adc_hpf_cut,
+                           WM8900_REG_ADCCTRL, 5, adc_hpf_cut_txt);
 
 static const char *lr_txt[] = {
        "Left", "Right"
 };
 
-static const struct soc_enum aifl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifl_src,
+                           WM8900_REG_AUDIO1, 15, lr_txt);
 
-static const struct soc_enum aifr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(aifr_src,
+                           WM8900_REG_AUDIO1, 14, lr_txt);
 
-static const struct soc_enum dacl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_src,
+                           WM8900_REG_AUDIO2, 15, lr_txt);
 
-static const struct soc_enum dacr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_src,
+                           WM8900_REG_AUDIO2, 14, lr_txt);
 
 static const char *sidetone_txt[] = {
        "Disabled", "Left ADC", "Right ADC"
 };
 
-static const struct soc_enum dacl_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacl_sidetone,
+                           WM8900_REG_SIDETONE, 2, sidetone_txt);
 
-static const struct soc_enum dacr_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
+static SOC_ENUM_SINGLE_DECL(dacr_sidetone,
+                           WM8900_REG_SIDETONE, 0, sidetone_txt);
 
 static const struct snd_kcontrol_new wm8900_snd_controls[] = {
 SOC_ENUM("Mic Bias Level", mic_bias_level),
@@ -496,8 +496,8 @@ SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
 
 static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" };
 
-static const struct soc_enum wm8900_lineout2_lp_mux =
-SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux);
+static SOC_ENUM_SINGLE_DECL(wm8900_lineout2_lp_mux,
+                           WM8900_REG_LOUTMIXCTL1, 1, wm8900_lp_mux);
 
 static const struct snd_kcontrol_new wm8900_lineout2_lp =
 SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
index b7488f190d2bc9d5b86da537a560fc6be9f6ca0a..d4248e00160e35a0bede71fcfbd7db785d49de89 100644 (file)
@@ -153,7 +153,7 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
 
                        data32 &= 0xffffff;
 
-                       wm8994_bulk_write(codec->control_data,
+                       wm8994_bulk_write(wm8994->wm8994,
                                          data32 & 0xffffff,
                                          block_len / 2,
                                          (void *)(data + 8));
index 433d59a0f3efa025598cf5c63f42640120893f90..2ee23a39622c14f2cdbc072cdcdb496e8291e9c0 100644 (file)
@@ -1562,7 +1562,6 @@ static int wm8993_remove(struct snd_soc_codec *codec)
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 
        wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
        return 0;
 }
 
index b9be9cbc460391d4530e970e3c77a0521109c2a2..adb72063d44ef6a0a5c9da1e2a53bd0d16a67825 100644 (file)
@@ -265,21 +265,21 @@ static const char *sidetone_hpf_text[] = {
        "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz"
 };
 
-static const struct soc_enum sidetone_hpf =
-       SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text);
+static SOC_ENUM_SINGLE_DECL(sidetone_hpf,
+                           WM8994_SIDETONE, 7, sidetone_hpf_text);
 
 static const char *adc_hpf_text[] = {
        "HiFi", "Voice 1", "Voice 2", "Voice 3"
 };
 
-static const struct soc_enum aif1adc1_hpf =
-       SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc1_hpf,
+                           WM8994_AIF1_ADC1_FILTERS, 13, adc_hpf_text);
 
-static const struct soc_enum aif1adc2_hpf =
-       SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif1adc2_hpf,
+                           WM8994_AIF1_ADC2_FILTERS, 13, adc_hpf_text);
 
-static const struct soc_enum aif2adc_hpf =
-       SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_hpf,
+                           WM8994_AIF2_ADC_FILTERS, 13, adc_hpf_text);
 
 static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0);
 static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
@@ -501,39 +501,39 @@ static const char *aif_chan_src_text[] = {
        "Left", "Right"
 };
 
-static const struct soc_enum aif1adcl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcl_src,
+                           WM8994_AIF1_CONTROL_1, 15, aif_chan_src_text);
 
-static const struct soc_enum aif1adcr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1adcr_src,
+                           WM8994_AIF1_CONTROL_1, 14, aif_chan_src_text);
 
-static const struct soc_enum aif2adcl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcl_src,
+                           WM8994_AIF2_CONTROL_1, 15, aif_chan_src_text);
 
-static const struct soc_enum aif2adcr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2adcr_src,
+                           WM8994_AIF2_CONTROL_1, 14, aif_chan_src_text);
 
-static const struct soc_enum aif1dacl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacl_src,
+                           WM8994_AIF1_CONTROL_2, 15, aif_chan_src_text);
 
-static const struct soc_enum aif1dacr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif1dacr_src,
+                           WM8994_AIF1_CONTROL_2, 14, aif_chan_src_text);
 
-static const struct soc_enum aif2dacl_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src,
+                           WM8994_AIF2_CONTROL_2, 15, aif_chan_src_text);
 
-static const struct soc_enum aif2dacr_src =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src,
+                           WM8994_AIF2_CONTROL_2, 14, aif_chan_src_text);
 
 static const char *osr_text[] = {
        "Low Power", "High Performance",
 };
 
-static const struct soc_enum dac_osr =
-       SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(dac_osr,
+                           WM8994_OVERSAMPLING, 0, osr_text);
 
-static const struct soc_enum adc_osr =
-       SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text);
+static SOC_ENUM_SINGLE_DECL(adc_osr,
+                           WM8994_OVERSAMPLING, 1, osr_text);
 
 static const struct snd_kcontrol_new wm8994_snd_controls[] = {
 SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
@@ -690,17 +690,20 @@ static const char *wm8958_ng_text[] = {
        "30ms", "125ms", "250ms", "500ms",
 };
 
-static const struct soc_enum wm8958_aif1dac1_ng_hold =
-       SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
-                       WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac1_ng_hold,
+                           WM8958_AIF1_DAC1_NOISE_GATE,
+                           WM8958_AIF1DAC1_NG_THR_SHIFT,
+                           wm8958_ng_text);
 
-static const struct soc_enum wm8958_aif1dac2_ng_hold =
-       SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
-                       WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif1dac2_ng_hold,
+                           WM8958_AIF1_DAC2_NOISE_GATE,
+                           WM8958_AIF1DAC2_NG_THR_SHIFT,
+                           wm8958_ng_text);
 
-static const struct soc_enum wm8958_aif2dac_ng_hold =
-       SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
-                       WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif2dac_ng_hold,
+                           WM8958_AIF2_DAC_NOISE_GATE,
+                           WM8958_AIF2DAC_NG_THR_SHIFT,
+                           wm8958_ng_text);
 
 static const struct snd_kcontrol_new wm8958_snd_controls[] = {
 SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
@@ -1341,8 +1344,8 @@ static const char *adc_mux_text[] = {
        "DMIC",
 };
 
-static const struct soc_enum adc_enum =
-       SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text);
+static SOC_ENUM_SINGLE_DECL(adc_enum,
+                           0, 0, adc_mux_text);
 
 static const struct snd_kcontrol_new adcl_mux =
        SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum);
@@ -1478,14 +1481,14 @@ static const char *sidetone_text[] = {
        "ADC/DMIC1", "DMIC2",
 };
 
-static const struct soc_enum sidetone1_enum =
-       SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone1_enum,
+                           WM8994_SIDETONE, 0, sidetone_text);
 
 static const struct snd_kcontrol_new sidetone1_mux =
        SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum);
 
-static const struct soc_enum sidetone2_enum =
-       SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text);
+static SOC_ENUM_SINGLE_DECL(sidetone2_enum,
+                           WM8994_SIDETONE, 1, sidetone_text);
 
 static const struct snd_kcontrol_new sidetone2_mux =
        SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum);
@@ -1498,22 +1501,24 @@ static const char *loopback_text[] = {
        "None", "ADCDAT",
 };
 
-static const struct soc_enum aif1_loopback_enum =
-       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2,
-                       loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif1_loopback_enum,
+                           WM8994_AIF1_CONTROL_2,
+                           WM8994_AIF1_LOOPBACK_SHIFT,
+                           loopback_text);
 
 static const struct snd_kcontrol_new aif1_loopback =
        SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum);
 
-static const struct soc_enum aif2_loopback_enum =
-       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2,
-                       loopback_text);
+static SOC_ENUM_SINGLE_DECL(aif2_loopback_enum,
+                           WM8994_AIF2_CONTROL_2,
+                           WM8994_AIF2_LOOPBACK_SHIFT,
+                           loopback_text);
 
 static const struct snd_kcontrol_new aif2_loopback =
        SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum);
 
-static const struct soc_enum aif1dac_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text);
+static SOC_ENUM_SINGLE_DECL(aif1dac_enum,
+                           WM8994_POWER_MANAGEMENT_6, 0, aif1dac_text);
 
 static const struct snd_kcontrol_new aif1dac_mux =
        SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum);
@@ -1522,8 +1527,8 @@ static const char *aif2dac_text[] = {
        "AIF2DACDAT", "AIF3DACDAT",
 };
 
-static const struct soc_enum aif2dac_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text);
+static SOC_ENUM_SINGLE_DECL(aif2dac_enum,
+                           WM8994_POWER_MANAGEMENT_6, 1, aif2dac_text);
 
 static const struct snd_kcontrol_new aif2dac_mux =
        SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum);
@@ -1532,8 +1537,8 @@ static const char *aif2adc_text[] = {
        "AIF2ADCDAT", "AIF3DACDAT",
 };
 
-static const struct soc_enum aif2adc_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text);
+static SOC_ENUM_SINGLE_DECL(aif2adc_enum,
+                           WM8994_POWER_MANAGEMENT_6, 2, aif2adc_text);
 
 static const struct snd_kcontrol_new aif2adc_mux =
        SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum);
@@ -1542,14 +1547,14 @@ static const char *aif3adc_text[] = {
        "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM",
 };
 
-static const struct soc_enum wm8994_aif3adc_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8994_aif3adc_enum,
+                           WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
 
 static const struct snd_kcontrol_new wm8994_aif3adc_mux =
        SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum);
 
-static const struct soc_enum wm8958_aif3adc_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text);
+static SOC_ENUM_SINGLE_DECL(wm8958_aif3adc_enum,
+                           WM8994_POWER_MANAGEMENT_6, 3, aif3adc_text);
 
 static const struct snd_kcontrol_new wm8958_aif3adc_mux =
        SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum);
@@ -1558,8 +1563,8 @@ static const char *mono_pcm_out_text[] = {
        "None", "AIF2ADCL", "AIF2ADCR",
 };
 
-static const struct soc_enum mono_pcm_out_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text);
+static SOC_ENUM_SINGLE_DECL(mono_pcm_out_enum,
+                           WM8994_POWER_MANAGEMENT_6, 9, mono_pcm_out_text);
 
 static const struct snd_kcontrol_new mono_pcm_out_mux =
        SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum);
@@ -1569,14 +1574,14 @@ static const char *aif2dac_src_text[] = {
 };
 
 /* Note that these two control shouldn't be simultaneously switched to AIF3 */
-static const struct soc_enum aif2dacl_src_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacl_src_enum,
+                           WM8994_POWER_MANAGEMENT_6, 7, aif2dac_src_text);
 
 static const struct snd_kcontrol_new aif2dacl_src_mux =
        SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum);
 
-static const struct soc_enum aif2dacr_src_enum =
-       SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text);
+static SOC_ENUM_SINGLE_DECL(aif2dacr_src_enum,
+                           WM8994_POWER_MANAGEMENT_6, 8, aif2dac_src_text);
 
 static const struct snd_kcontrol_new aif2dacr_src_mux =
        SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum);
index 70ff3772079f2186cdf2967c1c050ff95f37350b..5e3bc3c6801a6bbf9512731f6cd094b2eb41511f 100644 (file)
@@ -399,6 +399,7 @@ static struct platform_driver davinci_evm_driver = {
        .driver         = {
                .name   = "davinci_evm",
                .owner  = THIS_MODULE,
+               .pm     = &snd_soc_pm_ops,
                .of_match_table = of_match_ptr(davinci_evm_dt_ids),
        },
 };
index b7858bfa0295357bc5d3ca6d1328932595167b9e..670afa29e30d0d5b97f7c60601d1e40793b5b499 100644 (file)
@@ -263,7 +263,9 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                         unsigned int fmt)
 {
        struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret = 0;
 
+       pm_runtime_get_sync(mcasp->dev);
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
        case SND_SOC_DAIFMT_AC97:
@@ -317,7 +319,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                break;
 
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -354,10 +357,12 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                break;
 
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               break;
        }
-
-       return 0;
+out:
+       pm_runtime_put_sync(mcasp->dev);
+       return ret;
 }
 
 static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
@@ -448,7 +453,7 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
        return 0;
 }
 
-static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
+static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
                                    int channels)
 {
        int i;
@@ -524,12 +529,18 @@ static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
        return 0;
 }
 
-static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
+static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
 {
        int i, active_slots;
        u32 mask = 0;
        u32 busel = 0;
 
+       if ((mcasp->tdm_slots < 2) || (mcasp->tdm_slots > 32)) {
+               dev_err(mcasp->dev, "tdm slot %d not supported\n",
+                       mcasp->tdm_slots);
+               return -EINVAL;
+       }
+
        active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots;
        for (i = 0; i < active_slots; i++)
                mask |= (1 << i);
@@ -539,35 +550,21 @@ static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
        if (!mcasp->dat_port)
                busel = TXSEL;
 
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* bit stream is MSB first  with no delay */
-               /* DSP_B mode */
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
-               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
-
-               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
-                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
-                                      FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
-               else
-                       printk(KERN_ERR "playback tdm slot %d not supported\n",
-                               mcasp->tdm_slots);
-       } else {
-               /* bit stream is MSB first with no delay */
-               /* DSP_B mode */
-               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
-
-               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
-                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
-                                      FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
-               else
-                       printk(KERN_ERR "capture tdm slot %d not supported\n",
-                               mcasp->tdm_slots);
-       }
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
+       mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
+                      FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
+       mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
+                      FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
+
+       return 0;
 }
 
 /* S/PDIF */
-static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
+static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp)
 {
        /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
           and LSB first */
@@ -589,6 +586,8 @@ static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
 
        /* Enable the DIT */
        mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+
+       return 0;
 }
 
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
@@ -605,13 +604,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
        u8 slots = mcasp->tdm_slots;
        u8 active_serializers;
        int channels;
+       int ret;
        struct snd_interval *pcm_channels = hw_param_interval(params,
                                        SNDRV_PCM_HW_PARAM_CHANNELS);
        channels = pcm_channels->min;
 
        active_serializers = (channels + slots - 1) / slots;
 
-       if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL)
+       if (mcasp_common_hw_param(mcasp, substream->stream, channels) == -EINVAL)
                return -EINVAL;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                fifo_level = mcasp->txnumevt * active_serializers;
@@ -619,9 +619,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                fifo_level = mcasp->rxnumevt * active_serializers;
 
        if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
-               davinci_hw_dit_param(mcasp);
+               ret = mcasp_dit_hw_param(mcasp);
        else
-               davinci_hw_param(mcasp, substream->stream);
+               ret = mcasp_i2s_hw_param(mcasp, substream->stream);
+
+       if (ret)
+               return ret;
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_U8:
@@ -678,19 +681,9 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ret = pm_runtime_get_sync(mcasp->dev);
-               if (IS_ERR_VALUE(ret))
-                       dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n");
                davinci_mcasp_start(mcasp, substream->stream);
                break;
-
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               davinci_mcasp_stop(mcasp, substream->stream);
-               ret = pm_runtime_put_sync(mcasp->dev);
-               if (IS_ERR_VALUE(ret))
-                       dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n");
-               break;
-
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                davinci_mcasp_stop(mcasp, substream->stream);
index d0c72ed261e74c37f9d2b7cde738b34aab303ad4..c84026c991347f99014dad7df74c57731b789e24 100644 (file)
@@ -326,7 +326,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
        regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
                           ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
        regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
-                          ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(tx_mask));
+                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
 
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
                           ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
@@ -334,7 +334,7 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
                           ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
-                          ESAI_xSMA_xS_MASK, ESAI_xSMB_xS(rx_mask));
+                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
 
        esai_priv->slot_width = slot_width;
 
index 9c9f957fcae179c2d3d5525161fdbb0a0e338204..75e14033e8d8f0a7da6b1db6387d543c5a9a1acc 100644 (file)
 #define ESAI_xSMB_xS_SHIFT     0
 #define ESAI_xSMB_xS_WIDTH     16
 #define ESAI_xSMB_xS_MASK      (((1 << ESAI_xSMB_xS_WIDTH) - 1) << ESAI_xSMB_xS_SHIFT)
-#define ESAI_xSMB_xS(v)                (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMA_xS_MASK)
+#define ESAI_xSMB_xS(v)                (((v) >> ESAI_xSMA_xS_WIDTH) & ESAI_xSMB_xS_MASK)
 
 /* Port C Direction Register -- REG_ESAI_PRRC 0xF8 */
 #define ESAI_PRRC_PDC_SHIFT    0
index 79cee782dbbf9184264e69383b6d5a5ff1ba0fd7..a2fd7321b5a9a1bbd321f756af14fd9f071a372f 100644 (file)
@@ -160,7 +160,6 @@ static struct platform_driver imx_mc13783_audio_driver = {
        .driver = {
                .name = "imx_mc13783",
                .owner = THIS_MODULE,
-               .pm = &snd_soc_pm_ops,
        },
        .probe = imx_mc13783_probe,
        .remove = imx_mc13783_remove
index f2beae78969f6dd8e03125f92e3f288a8776f411..1cb22dd034eb63e98ac7e60e6d3ce5f719227db4 100644 (file)
@@ -33,8 +33,7 @@ struct imx_sgtl5000_data {
 
 static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct imx_sgtl5000_data *data = container_of(rtd->card,
-                                       struct imx_sgtl5000_data, card);
+       struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(rtd->card);
        struct device *dev = rtd->card->dev;
        int ret;
 
@@ -159,13 +158,15 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
        data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
        data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
 
+       platform_set_drvdata(pdev, &data->card);
+       snd_soc_card_set_drvdata(&data->card, data);
+
        ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
                goto fail;
        }
 
-       platform_set_drvdata(pdev, data);
        of_node_put(ssi_np);
        of_node_put(codec_np);
 
@@ -184,7 +185,8 @@ fail:
 
 static int imx_sgtl5000_remove(struct platform_device *pdev)
 {
-       struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct imx_sgtl5000_data *data = snd_soc_card_get_drvdata(card);
 
        clk_put(data->codec_clk);
 
index 3fd76bc391de19a2431dd320d0abfbdcd9616cf5..3a3d17ce6ba40feea5dc6582693d7c1ee846ef13 100644 (file)
@@ -71,7 +71,7 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
 {
        struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
        struct imx_priv *priv = &card_priv;
-       struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
+       struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
        struct device *dev = &priv->pdev->dev;
        unsigned int pll_out;
        int ret;
@@ -137,7 +137,7 @@ static int imx_wm8962_late_probe(struct snd_soc_card *card)
 {
        struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
        struct imx_priv *priv = &card_priv;
-       struct imx_wm8962_data *data = platform_get_drvdata(priv->pdev);
+       struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
        struct device *dev = &priv->pdev->dev;
        int ret;
 
@@ -264,13 +264,15 @@ static int imx_wm8962_probe(struct platform_device *pdev)
        data->card.late_probe = imx_wm8962_late_probe;
        data->card.set_bias_level = imx_wm8962_set_bias_level;
 
+       platform_set_drvdata(pdev, &data->card);
+       snd_soc_card_set_drvdata(&data->card, data);
+
        ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
                goto clk_fail;
        }
 
-       platform_set_drvdata(pdev, data);
        of_node_put(ssi_np);
        of_node_put(codec_np);
 
@@ -289,7 +291,8 @@ fail:
 
 static int imx_wm8962_remove(struct platform_device *pdev)
 {
-       struct imx_wm8962_data *data = platform_get_drvdata(pdev);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct imx_wm8962_data *data = snd_soc_card_get_drvdata(card);
 
        if (!IS_ERR(data->codec_clk))
                clk_disable_unprepare(data->codec_clk);
index 3fde9e402710f2bb16baf80b605da42772df69a0..d163e18d85d416b58be1dc5a905975c12623cfc9 100644 (file)
@@ -305,7 +305,9 @@ static int __init n810_soc_init(void)
        int err;
        struct device *dev;
 
-       if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
+       if (!of_have_populated_dt() ||
+           (!of_machine_is_compatible("nokia,n810") &&
+            !of_machine_is_compatible("nokia,n810-wimax")))
                return -ENODEV;
 
        n810_snd_device = platform_device_alloc("soc-audio", -1);
index 454f41cfc82847e98a6297b2db5822db35d717a6..3507574003913b5023f66853a50bec809d6187bf 100644 (file)
@@ -59,7 +59,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
        select SND_SOC_WM8750
        select SND_S3C2412_SOC_I2S
        help
-         Sat Y if you want to add support for SoC audio on the Jive.
+         Say Y if you want to add support for SoC audio on the Jive.
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
        tristate "SoC I2S Audio support for WM8580 on SMDK"
@@ -145,11 +145,11 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380
 
 config SND_SOC_SAMSUNG_SMDK_WM9713
        tristate "SoC AC97 Audio support for SMDK with WM9713"
-       depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110 || MACH_SMDKV310 || MACH_SMDKC210)
+       depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
        select SND_SOC_WM9713
        select SND_SAMSUNG_AC97
        help
-         Sat Y if you want to add support for SoC audio on the SMDK.
+         Say Y if you want to add support for SoC audio on the SMDK.
 
 config SND_SOC_SMARTQ
        tristate "SoC I2S Audio support for SmartQ board"
index dc8ff13187f7ca91ef960312f48eac732c44d938..b9dc6acbba8c55661eb0cf423a02fb9b7dda1c87 100644 (file)
@@ -1218,7 +1218,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                        ret = regulator_allow_bypass(w->regulator, false);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "ASoC: Failed to bypass %s: %d\n",
+                                        "ASoC: Failed to unbypass %s: %d\n",
                                         w->name, ret);
                }
 
@@ -1228,7 +1228,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
                        ret = regulator_allow_bypass(w->regulator, true);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "ASoC: Failed to unbypass %s: %d\n",
+                                        "ASoC: Failed to bypass %s: %d\n",
                                         w->name, ret);
                }
 
@@ -3210,15 +3210,11 @@ int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        const char *pin = (const char *)kcontrol->private_value;
 
-       mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-
        if (ucontrol->value.integer.value[0])
                snd_soc_dapm_enable_pin(&card->dapm, pin);
        else
                snd_soc_dapm_disable_pin(&card->dapm, pin);
 
-       mutex_unlock(&card->dapm_mutex);
-
        snd_soc_dapm_sync(&card->dapm);
        return 0;
 }
@@ -3248,7 +3244,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                        ret = regulator_allow_bypass(w->regulator, true);
                        if (ret != 0)
                                dev_warn(w->dapm->dev,
-                                        "ASoC: Failed to unbypass %s: %d\n",
+                                        "ASoC: Failed to bypass %s: %d\n",
                                         w->name, ret);
                }
                break;
@@ -3766,6 +3762,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
        mutex_unlock(&card->dapm_mutex);
 }
 
+/**
+ * snd_soc_dapm_enable_pin_unlocked - enable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Enables input/output pin and its parents or children widgets iff there is
+ * a valid audio route and active audio stream.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                  const char *pin)
+{
+       return snd_soc_dapm_set_pin(dapm, pin, 1);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
+
 /**
  * snd_soc_dapm_enable_pin - enable pin.
  * @dapm: DAPM context
@@ -3773,17 +3789,26 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
  *
  * Enables input/output pin and its parents or children widgets iff there is
  * a valid audio route and active audio stream.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
 int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
 {
-       return snd_soc_dapm_set_pin(dapm, pin, 1);
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_set_pin(dapm, pin, 1);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
 
 /**
- * snd_soc_dapm_force_enable_pin - force a pin to be enabled
+ * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
  * @dapm: DAPM context
  * @pin: pin name
  *
@@ -3791,11 +3816,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
  * intended for use with microphone bias supplies used in microphone
  * jack detection.
  *
+ * Requires external locking.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
-int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
-                                 const char *pin)
+int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                        const char *pin)
 {
        struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
 
@@ -3811,24 +3838,102 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
+
+/**
+ * snd_soc_dapm_force_enable_pin - force a pin to be enabled
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Enables input/output pin regardless of any other state.  This is
+ * intended for use with microphone bias supplies used in microphone
+ * jack detection.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
+                                 const char *pin)
+{
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
 
+/**
+ * snd_soc_dapm_disable_pin_unlocked - disable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Disables input/output pin and its parents or children widgets.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                                   const char *pin)
+{
+       return snd_soc_dapm_set_pin(dapm, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
+
 /**
  * snd_soc_dapm_disable_pin - disable pin.
  * @dapm: DAPM context
  * @pin: pin name
  *
  * Disables input/output pin and its parents or children widgets.
+ *
  * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
  * do any widget power switching.
  */
 int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
                             const char *pin)
 {
-       return snd_soc_dapm_set_pin(dapm, pin, 0);
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_set_pin(dapm, pin, 0);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
 
+/**
+ * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
+ * @dapm: DAPM context
+ * @pin: pin name
+ *
+ * Marks the specified pin as being not connected, disabling it along
+ * any parent or child widgets.  At present this is identical to
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
+ * additional things such as disabling controls which only affect
+ * paths through the pin.
+ *
+ * Requires external locking.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
+                              const char *pin)
+{
+       return snd_soc_dapm_set_pin(dapm, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
+
 /**
  * snd_soc_dapm_nc_pin - permanently disable pin.
  * @dapm: DAPM context
@@ -3845,7 +3950,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
  */
 int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
 {
-       return snd_soc_dapm_set_pin(dapm, pin, 0);
+       int ret;
+
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
+
+       ret = snd_soc_dapm_set_pin(dapm, pin, 0);
+
+       mutex_unlock(&dapm->card->dapm_mutex);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
 
index 47e1ce771e65e0403e1ab743c677083c98452a8c..28522bd03b8e05c7b1bf5fbf4af611efe109930d 100644 (file)
@@ -1989,6 +1989,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
 
                paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
                if (paths < 0) {
+                       dpcm_path_put(&list);
                        dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
                                        fe->dai_link->name,  "playback");
                        mutex_unlock(&card->mutex);
@@ -2018,6 +2019,7 @@ capture:
 
                paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
                if (paths < 0) {
+                       dpcm_path_put(&list);
                        dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
                                        fe->dai_link->name,  "capture");
                        mutex_unlock(&card->mutex);
@@ -2082,6 +2084,7 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
        fe->dpcm[stream].runtime = fe_substream->runtime;
 
        if (dpcm_path_get(fe, stream, &list) <= 0) {
+               dpcm_path_put(&list);
                dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
                        fe->dai_link->name, stream ? "capture" : "playback");
        }
index e0305a1485680b18cbc85ba33a506bda799f47c1..9edd68db9f482e618e4e245a40dfbd0c94711e5d 100644 (file)
@@ -183,14 +183,16 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
+
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        drvdata->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(drvdata->base))
                return PTR_ERR(drvdata->base);
 
-       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
        platform_set_drvdata(pdev, drvdata);
        drvdata->physbase = r->start;
        if (sizeof(drvdata->physbase) > sizeof(r->start) &&
index de9408b83f7577b22071aac72b1ecf0390522d44..e05a86b7c0da236e5efddc4c762aecca443283fd 100644 (file)
@@ -14,6 +14,7 @@ config SND_USB_AUDIO
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
+       select BITREVERSE
        help
          Say Y here to include support for USB audio and USB MIDI
          devices.
index 44b0ba4feab3bd1b43100feb457e82e290ea26dc..1bed780e21d96945d1cf913ce23fe31409df0cc4 100644 (file)
@@ -883,6 +883,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
                }
                break;
 
+       case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */
        case USB_ID(0x046d, 0x0808):
        case USB_ID(0x046d, 0x0809):
        case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */
index 32af6b741ef5a8aff8581f90b0c5d583d151a6ee..d1d72ff50347a3118c2e90d5452457b8948ad0d6 100644 (file)
@@ -328,6 +328,11 @@ static struct usbmix_name_map gamecom780_map[] = {
        {}
 };
 
+static const struct usbmix_name_map kef_x300a_map[] = {
+       { 10, NULL }, /* firmware locks up (?) when we try to access this FU */
+       { 0 }
+};
+
 /*
  * Control map entries
  */
@@ -419,6 +424,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x200c, 0x1018),
                .map = ebox44_map,
        },
+       {
+               .id = USB_ID(0x27ac, 0x1000),
+               .map = kef_x300a_map,
+       },
        { 0 } /* terminator */
 };
 
diff --git a/tools/include/linux/hash.h b/tools/include/linux/hash.h
new file mode 100644 (file)
index 0000000..d026c65
--- /dev/null
@@ -0,0 +1,5 @@
+#include "../../../include/linux/hash.h"
+
+#ifndef _TOOLS_LINUX_HASH_H
+#define _TOOLS_LINUX_HASH_H
+#endif
index ed2f51e11b80f36d63601c7abb1ea32db13566ff..ce00f7ee6455248d92dba7016b2770c824e897f9 100644 (file)
@@ -9,8 +9,10 @@ LIB_H=
 LIB_OBJS=
 
 LIB_H += fs/debugfs.h
+LIB_H += fs/fs.h
 
 LIB_OBJS += $(OUTPUT)fs/debugfs.o
+LIB_OBJS += $(OUTPUT)fs/fs.o
 
 LIBFILE = libapikfs.a
 
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
new file mode 100644 (file)
index 0000000..5b5eb78
--- /dev/null
@@ -0,0 +1,124 @@
+/* TODO merge/factor in debugfs.c here */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/vfs.h>
+
+#include "debugfs.h"
+#include "fs.h"
+
+static const char * const sysfs__fs_known_mountpoints[] = {
+       "/sys",
+       0,
+};
+
+static const char * const procfs__known_mountpoints[] = {
+       "/proc",
+       0,
+};
+
+struct fs {
+       const char              *name;
+       const char * const      *mounts;
+       char                     path[PATH_MAX + 1];
+       bool                     found;
+       long                     magic;
+};
+
+enum {
+       FS__SYSFS  = 0,
+       FS__PROCFS = 1,
+};
+
+static struct fs fs__entries[] = {
+       [FS__SYSFS] = {
+               .name   = "sysfs",
+               .mounts = sysfs__fs_known_mountpoints,
+               .magic  = SYSFS_MAGIC,
+       },
+       [FS__PROCFS] = {
+               .name   = "proc",
+               .mounts = procfs__known_mountpoints,
+               .magic  = PROC_SUPER_MAGIC,
+       },
+};
+
+static bool fs__read_mounts(struct fs *fs)
+{
+       bool found = false;
+       char type[100];
+       FILE *fp;
+
+       fp = fopen("/proc/mounts", "r");
+       if (fp == NULL)
+               return NULL;
+
+       while (!found &&
+              fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
+                     fs->path, type) == 2) {
+
+               if (strcmp(type, fs->name) == 0)
+                       found = true;
+       }
+
+       fclose(fp);
+       return fs->found = found;
+}
+
+static int fs__valid_mount(const char *fs, long magic)
+{
+       struct statfs st_fs;
+
+       if (statfs(fs, &st_fs) < 0)
+               return -ENOENT;
+       else if (st_fs.f_type != magic)
+               return -ENOENT;
+
+       return 0;
+}
+
+static bool fs__check_mounts(struct fs *fs)
+{
+       const char * const *ptr;
+
+       ptr = fs->mounts;
+       while (*ptr) {
+               if (fs__valid_mount(*ptr, fs->magic) == 0) {
+                       fs->found = true;
+                       strcpy(fs->path, *ptr);
+                       return true;
+               }
+               ptr++;
+       }
+
+       return false;
+}
+
+static const char *fs__get_mountpoint(struct fs *fs)
+{
+       if (fs__check_mounts(fs))
+               return fs->path;
+
+       return fs__read_mounts(fs) ? fs->path : NULL;
+}
+
+static const char *fs__mountpoint(int idx)
+{
+       struct fs *fs = &fs__entries[idx];
+
+       if (fs->found)
+               return (const char *)fs->path;
+
+       return fs__get_mountpoint(fs);
+}
+
+#define FS__MOUNTPOINT(name, idx)      \
+const char *name##__mountpoint(void)   \
+{                                      \
+       return fs__mountpoint(idx);     \
+}
+
+FS__MOUNTPOINT(sysfs,  FS__SYSFS);
+FS__MOUNTPOINT(procfs, FS__PROCFS);
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
new file mode 100644 (file)
index 0000000..cb70495
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __API_FS__
+#define __API_FS__
+
+#ifndef SYSFS_MAGIC
+#define SYSFS_MAGIC            0x62656572
+#endif
+
+#ifndef PROC_SUPER_MAGIC
+#define PROC_SUPER_MAGIC       0x9fa0
+#endif
+
+const char *sysfs__mountpoint(void);
+const char *procfs__mountpoint(void);
+#endif /* __API_FS__ */
index da8b7aa3d3518d1e52532af42974fc2e3981376f..07b0b7542511e9912e830b11885e1212bbf63a76 100644 (file)
@@ -87,8 +87,8 @@ endif # BUILD_SRC
 # We process the rest of the Makefile if this is the final invocation of make
 ifeq ($(skip-makefile),)
 
-srctree                := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
-objtree                := $(CURDIR)
+srctree                := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)))
+objtree                := $(realpath $(CURDIR))
 src            := $(srctree)
 obj            := $(objtree)
 
@@ -112,7 +112,7 @@ export Q VERBOSE
 
 LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
 
-INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES)
+INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include $(CONFIG_INCLUDES)
 
 # Set compile option CFLAGS if not set elsewhere
 CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
index f8465a811aa554e6510477ac0c733b2eb02bb5f4..23bd69cb5ade7014e8630e87ad89a16e2d95be71 100644 (file)
@@ -418,7 +418,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
 
 __attribute__((constructor)) static void init_preload(void)
 {
-       if (__init_state != done)
+       if (__init_state == done)
                return;
 
 #ifndef __GLIBC__
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/tools/lib/lockdep/uinclude/asm/hash.h b/tools/lib/lockdep/uinclude/asm/hash.h
new file mode 100644 (file)
index 0000000..d82b170
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_GENERIC_HASH_H
+#define __ASM_GENERIC_HASH_H
+
+/* Stub */
+
+#endif /* __ASM_GENERIC_HASH_H */
index 4c99fcb5da2769ef48067b5e6adf05806e758396..042ee8e463c98bf03d9a92e4d18dd3c01ec32162 100644 (file)
@@ -13,4 +13,9 @@ static inline int rcu_is_cpu_idle(void)
        return 1;
 }
 
+static inline bool rcu_is_watching(void)
+{
+       return false;
+}
+
 #endif
index 004cd74734b62b941cf64db1634d2774f70f6e3c..ee577ea03ba50f05a4b14379ddcd17a3f73593c0 100644 (file)
@@ -12,7 +12,7 @@ YACC = bison
 
 all : bpf_jit_disasm bpf_dbg bpf_asm
 
-bpf_jit_disasm : CFLAGS = -Wall -O2
+bpf_jit_disasm : CFLAGS = -Wall -O2 -DPACKAGE='bpf_jit_disasm'
 bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
 bpf_jit_disasm : bpf_jit_disasm.o
 
index 888d51137fbe61e0dc04546b36a46486a9d9a555..1d78a4064da48218b90b15f8495c3626cf614b2c 100644 (file)
@@ -18,6 +18,10 @@ from it, into perf.data. Perf record options are accepted and are passed through
 "perf mem -t <TYPE> report" displays the result. It invokes perf report with the
 right set of options to display a memory access profile.
 
+Note that on Intel systems the memory latency reported is the use-latency,
+not the pure load (or store latency). Use latency includes any pipeline
+queueing delays in addition to the memory subsystem latency.
+
 OPTIONS
 -------
 <command>...::
index b715cb71592b0299d473eb7b40df77433485d28f..1513935c399b67c6e2158b9041af548edf3e610c 100644 (file)
@@ -136,6 +136,8 @@ Each probe argument follows below syntax.
 'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
 'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
 
+On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
+
 LINE SYNTAX
 -----------
 Line range is described by following syntax.
index f41572d0dd76125b9ebc4b03fd0beb832192b39d..c0c87c87b60f83d92356e43488c83e6c074cb6e8 100644 (file)
@@ -6,6 +6,7 @@ tools/lib/symbol/kallsyms.c
 tools/lib/symbol/kallsyms.h
 tools/include/asm/bug.h
 tools/include/linux/compiler.h
+tools/include/linux/hash.h
 include/linux/const.h
 include/linux/perf_event.h
 include/linux/rbtree.h
index 7257e7e9e38a5e625f2fa562836ff3793d0275c4..50d875d970c4331f82dccfa35b6ebd980b1e3ea4 100644 (file)
@@ -7,6 +7,8 @@ include config/utilities.mak
 
 # Define V to have a more verbose compile.
 #
+# Define VF to have a more verbose feature check output.
+#
 # Define O to save output files in a separate directory.
 #
 # Define ARCH as name of target architecture if you want cross-builds.
@@ -55,6 +57,9 @@ include config/utilities.mak
 # Define NO_LIBAUDIT if you do not want libaudit support
 #
 # Define NO_LIBBIONIC if you do not want bionic support
+#
+# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
+# for dwarf backtrace post unwind.
 
 ifeq ($(srctree),)
 srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -208,7 +213,7 @@ LIB_H += ../../include/uapi/linux/perf_event.h
 LIB_H += ../../include/linux/rbtree.h
 LIB_H += ../../include/linux/list.h
 LIB_H += ../../include/uapi/linux/const.h
-LIB_H += ../../include/linux/hash.h
+LIB_H += ../include/linux/hash.h
 LIB_H += ../../include/linux/stringify.h
 LIB_H += util/include/linux/bitmap.h
 LIB_H += util/include/linux/bitops.h
@@ -218,9 +223,7 @@ LIB_H += util/include/linux/ctype.h
 LIB_H += util/include/linux/kernel.h
 LIB_H += util/include/linux/list.h
 LIB_H += util/include/linux/export.h
-LIB_H += util/include/linux/magic.h
 LIB_H += util/include/linux/poison.h
-LIB_H += util/include/linux/prefetch.h
 LIB_H += util/include/linux/rbtree.h
 LIB_H += util/include/linux/rbtree_augmented.h
 LIB_H += util/include/linux/string.h
@@ -244,7 +247,6 @@ LIB_H += util/cache.h
 LIB_H += util/callchain.h
 LIB_H += util/build-id.h
 LIB_H += util/debug.h
-LIB_H += util/fs.h
 LIB_H += util/pmu.h
 LIB_H += util/event.h
 LIB_H += util/evsel.h
@@ -306,7 +308,6 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
 LIB_OBJS += $(OUTPUT)util/build-id.o
 LIB_OBJS += $(OUTPUT)util/config.o
 LIB_OBJS += $(OUTPUT)util/ctype.o
-LIB_OBJS += $(OUTPUT)util/fs.o
 LIB_OBJS += $(OUTPUT)util/pmu.o
 LIB_OBJS += $(OUTPUT)util/environment.o
 LIB_OBJS += $(OUTPUT)util/event.o
@@ -408,6 +409,11 @@ endif
 LIB_OBJS += $(OUTPUT)tests/code-reading.o
 LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
 LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
+ifndef NO_DWARF_UNWIND
+ifeq ($(ARCH),x86)
+LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
+endif
+endif
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -420,6 +426,9 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
 endif
 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
 BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
+BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
+BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
+BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
 BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
@@ -475,8 +484,13 @@ ifndef NO_DWARF
 endif # NO_DWARF
 endif # NO_LIBELF
 
+ifndef NO_LIBDW_DWARF_UNWIND
+  LIB_OBJS += $(OUTPUT)util/unwind-libdw.o
+  LIB_H += util/unwind-libdw.h
+endif
+
 ifndef NO_LIBUNWIND
-  LIB_OBJS += $(OUTPUT)util/unwind.o
+  LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o
 endif
 LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
 
@@ -533,6 +547,7 @@ ifeq ($(NO_PERF_REGS),0)
   ifeq ($(ARCH),x86)
     LIB_H += arch/x86/include/perf_regs.h
   endif
+  LIB_OBJS += $(OUTPUT)util/perf_regs.o
 endif
 
 ifndef NO_LIBNUMA
@@ -655,6 +670,9 @@ $(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
                -DPYTHON='"$(PYTHON_WORD)"' \
                $<
 
+$(OUTPUT)tests/dwarf-unwind.o: tests/dwarf-unwind.c
+       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -fno-optimize-sibling-calls $<
+
 $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
@@ -707,9 +725,15 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 # we depend the various files onto their directories.
 DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
 DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
-$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
+# no need to add flex objects, because they depend on bison ones
+DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c
+DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c
+
+OUTPUT_DIRECTORIES := $(sort $(dir $(DIRECTORY_DEPS)))
+
+$(DIRECTORY_DEPS): | $(OUTPUT_DIRECTORIES)
 # In the second step, we make a rule to actually create these directories
-$(sort $(dir $(DIRECTORY_DEPS))):
+$(OUTPUT_DIRECTORIES):
        $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
 
 $(LIB_FILE): $(LIB_OBJS)
@@ -886,7 +910,7 @@ config-clean:
 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
        $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
        $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
-       $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
+       $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
        $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
        $(python-clean)
 
index fe9b61e322a557b063ecc78eccb9a87c8de73dda..67e9b3d38e89209dec2810a9ca229127fd49f17c 100644 (file)
@@ -3,5 +3,5 @@ PERF_HAVE_DWARF_REGS := 1
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
 ifndef NO_LIBUNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
 endif
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
new file mode 100644 (file)
index 0000000..729ed69
--- /dev/null
@@ -0,0 +1,48 @@
+
+#include <errno.h>
+#include <libunwind.h>
+#include "perf_regs.h"
+#include "../../util/unwind.h"
+
+int libunwind__arch_reg_id(int regnum)
+{
+       switch (regnum) {
+       case UNW_ARM_R0:
+               return PERF_REG_ARM_R0;
+       case UNW_ARM_R1:
+               return PERF_REG_ARM_R1;
+       case UNW_ARM_R2:
+               return PERF_REG_ARM_R2;
+       case UNW_ARM_R3:
+               return PERF_REG_ARM_R3;
+       case UNW_ARM_R4:
+               return PERF_REG_ARM_R4;
+       case UNW_ARM_R5:
+               return PERF_REG_ARM_R5;
+       case UNW_ARM_R6:
+               return PERF_REG_ARM_R6;
+       case UNW_ARM_R7:
+               return PERF_REG_ARM_R7;
+       case UNW_ARM_R8:
+               return PERF_REG_ARM_R8;
+       case UNW_ARM_R9:
+               return PERF_REG_ARM_R9;
+       case UNW_ARM_R10:
+               return PERF_REG_ARM_R10;
+       case UNW_ARM_R11:
+               return PERF_REG_ARM_FP;
+       case UNW_ARM_R12:
+               return PERF_REG_ARM_IP;
+       case UNW_ARM_R13:
+               return PERF_REG_ARM_SP;
+       case UNW_ARM_R14:
+               return PERF_REG_ARM_LR;
+       case UNW_ARM_R15:
+               return PERF_REG_ARM_PC;
+       default:
+               pr_err("unwind: invalid reg id %d\n", regnum);
+               return -EINVAL;
+       }
+
+       return -EINVAL;
+}
diff --git a/tools/perf/arch/arm/util/unwind.c b/tools/perf/arch/arm/util/unwind.c
deleted file mode 100644 (file)
index da3dc95..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-
-#include <errno.h>
-#include <libunwind.h>
-#include "perf_regs.h"
-#include "../../util/unwind.h"
-
-int unwind__arch_reg_id(int regnum)
-{
-       switch (regnum) {
-       case UNW_ARM_R0:
-               return PERF_REG_ARM_R0;
-       case UNW_ARM_R1:
-               return PERF_REG_ARM_R1;
-       case UNW_ARM_R2:
-               return PERF_REG_ARM_R2;
-       case UNW_ARM_R3:
-               return PERF_REG_ARM_R3;
-       case UNW_ARM_R4:
-               return PERF_REG_ARM_R4;
-       case UNW_ARM_R5:
-               return PERF_REG_ARM_R5;
-       case UNW_ARM_R6:
-               return PERF_REG_ARM_R6;
-       case UNW_ARM_R7:
-               return PERF_REG_ARM_R7;
-       case UNW_ARM_R8:
-               return PERF_REG_ARM_R8;
-       case UNW_ARM_R9:
-               return PERF_REG_ARM_R9;
-       case UNW_ARM_R10:
-               return PERF_REG_ARM_R10;
-       case UNW_ARM_R11:
-               return PERF_REG_ARM_FP;
-       case UNW_ARM_R12:
-               return PERF_REG_ARM_IP;
-       case UNW_ARM_R13:
-               return PERF_REG_ARM_SP;
-       case UNW_ARM_R14:
-               return PERF_REG_ARM_LR;
-       case UNW_ARM_R15:
-               return PERF_REG_ARM_PC;
-       default:
-               pr_err("unwind: invalid reg id %d\n", regnum);
-               return -EINVAL;
-       }
-
-       return -EINVAL;
-}
index 8801fe02f206a93a97d7f7cc8a56094dffa1d05c..1641542e3636693abe587a9aab99d74ccb5b6bb9 100644 (file)
@@ -3,7 +3,14 @@ PERF_HAVE_DWARF_REGS := 1
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
 ifndef NO_LIBUNWIND
-LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
+endif
+ifndef NO_LIBDW_DWARF_UNWIND
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
+endif
+ifndef NO_DWARF_UNWIND
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
 endif
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
index e84ca76aae779ef484df1633b7cff3e35b327ba8..fc819ca34a7eeffd564cace9b9d0baea71ef36ed 100644 (file)
@@ -5,14 +5,20 @@
 #include "../../util/types.h"
 #include <asm/perf_regs.h>
 
+void perf_regs_load(u64 *regs);
+
 #ifndef HAVE_ARCH_X86_64_SUPPORT
 #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
+#define PERF_REGS_MAX PERF_REG_X86_32_MAX
+#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
 #else
 #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
                       (1ULL << PERF_REG_X86_ES) | \
                       (1ULL << PERF_REG_X86_FS) | \
                       (1ULL << PERF_REG_X86_GS))
 #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT)
+#define PERF_REGS_MAX PERF_REG_X86_64_MAX
+#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
 #endif
 #define PERF_REG_IP PERF_REG_X86_IP
 #define PERF_REG_SP PERF_REG_X86_SP
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
new file mode 100644 (file)
index 0000000..b602ad9
--- /dev/null
@@ -0,0 +1,59 @@
+#include <string.h>
+#include "perf_regs.h"
+#include "thread.h"
+#include "map.h"
+#include "event.h"
+#include "tests/tests.h"
+
+#define STACK_SIZE 8192
+
+static int sample_ustack(struct perf_sample *sample,
+                        struct thread *thread, u64 *regs)
+{
+       struct stack_dump *stack = &sample->user_stack;
+       struct map *map;
+       unsigned long sp;
+       u64 stack_size, *buf;
+
+       buf = malloc(STACK_SIZE);
+       if (!buf) {
+               pr_debug("failed to allocate sample uregs data\n");
+               return -1;
+       }
+
+       sp = (unsigned long) regs[PERF_REG_X86_SP];
+
+       map = map_groups__find(&thread->mg, MAP__FUNCTION, (u64) sp);
+       if (!map) {
+               pr_debug("failed to get stack map\n");
+               return -1;
+       }
+
+       stack_size = map->end - sp;
+       stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
+
+       memcpy(buf, (void *) sp, stack_size);
+       stack->data = (char *) buf;
+       stack->size = stack_size;
+       return 0;
+}
+
+int test__arch_unwind_sample(struct perf_sample *sample,
+                            struct thread *thread)
+{
+       struct regs_dump *regs = &sample->user_regs;
+       u64 *buf;
+
+       buf = malloc(sizeof(u64) * PERF_REGS_MAX);
+       if (!buf) {
+               pr_debug("failed to allocate sample uregs data\n");
+               return -1;
+       }
+
+       perf_regs_load(buf);
+       regs->abi  = PERF_SAMPLE_REGS_ABI;
+       regs->regs = buf;
+       regs->mask = PERF_REGS_MASK;
+
+       return sample_ustack(sample, thread, buf);
+}
diff --git a/tools/perf/arch/x86/tests/regs_load.S b/tools/perf/arch/x86/tests/regs_load.S
new file mode 100644 (file)
index 0000000..99167bf
--- /dev/null
@@ -0,0 +1,92 @@
+
+#include <linux/linkage.h>
+
+#define AX      0
+#define BX      1 * 8
+#define CX      2 * 8
+#define DX      3 * 8
+#define SI      4 * 8
+#define DI      5 * 8
+#define BP      6 * 8
+#define SP      7 * 8
+#define IP      8 * 8
+#define FLAGS   9 * 8
+#define CS     10 * 8
+#define SS     11 * 8
+#define DS     12 * 8
+#define ES     13 * 8
+#define FS     14 * 8
+#define GS     15 * 8
+#define R8     16 * 8
+#define R9     17 * 8
+#define R10    18 * 8
+#define R11    19 * 8
+#define R12    20 * 8
+#define R13    21 * 8
+#define R14    22 * 8
+#define R15    23 * 8
+
+.text
+#ifdef HAVE_ARCH_X86_64_SUPPORT
+ENTRY(perf_regs_load)
+       movq %rax, AX(%rdi)
+       movq %rbx, BX(%rdi)
+       movq %rcx, CX(%rdi)
+       movq %rdx, DX(%rdi)
+       movq %rsi, SI(%rdi)
+       movq %rdi, DI(%rdi)
+       movq %rbp, BP(%rdi)
+
+       leaq 8(%rsp), %rax /* exclude this call.  */
+       movq %rax, SP(%rdi)
+
+       movq 0(%rsp), %rax
+       movq %rax, IP(%rdi)
+
+       movq $0, FLAGS(%rdi)
+       movq $0, CS(%rdi)
+       movq $0, SS(%rdi)
+       movq $0, DS(%rdi)
+       movq $0, ES(%rdi)
+       movq $0, FS(%rdi)
+       movq $0, GS(%rdi)
+
+       movq %r8,  R8(%rdi)
+       movq %r9,  R9(%rdi)
+       movq %r10, R10(%rdi)
+       movq %r11, R11(%rdi)
+       movq %r12, R12(%rdi)
+       movq %r13, R13(%rdi)
+       movq %r14, R14(%rdi)
+       movq %r15, R15(%rdi)
+       ret
+ENDPROC(perf_regs_load)
+#else
+ENTRY(perf_regs_load)
+       push %edi
+       movl 8(%esp), %edi
+       movl %eax, AX(%edi)
+       movl %ebx, BX(%edi)
+       movl %ecx, CX(%edi)
+       movl %edx, DX(%edi)
+       movl %esi, SI(%edi)
+       pop %eax
+       movl %eax, DI(%edi)
+       movl %ebp, BP(%edi)
+
+       leal 4(%esp), %eax /* exclude this call.  */
+       movl %eax, SP(%edi)
+
+       movl 0(%esp), %eax
+       movl %eax, IP(%edi)
+
+       movl $0, FLAGS(%edi)
+       movl $0, CS(%edi)
+       movl $0, SS(%edi)
+       movl $0, DS(%edi)
+       movl $0, ES(%edi)
+       movl $0, FS(%edi)
+       movl $0, GS(%edi)
+       ret
+ENDPROC(perf_regs_load)
+#endif
diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c
new file mode 100644 (file)
index 0000000..c4b7217
--- /dev/null
@@ -0,0 +1,51 @@
+#include <elfutils/libdwfl.h>
+#include "../../util/unwind-libdw.h"
+#include "../../util/perf_regs.h"
+
+bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
+{
+       struct unwind_info *ui = arg;
+       struct regs_dump *user_regs = &ui->sample->user_regs;
+       Dwarf_Word dwarf_regs[17];
+       unsigned nregs;
+
+#define REG(r) ({                                              \
+       Dwarf_Word val = 0;                                     \
+       perf_reg_value(&val, user_regs, PERF_REG_X86_##r);      \
+       val;                                                    \
+})
+
+       if (user_regs->abi == PERF_SAMPLE_REGS_ABI_32) {
+               dwarf_regs[0] = REG(AX);
+               dwarf_regs[1] = REG(CX);
+               dwarf_regs[2] = REG(DX);
+               dwarf_regs[3] = REG(BX);
+               dwarf_regs[4] = REG(SP);
+               dwarf_regs[5] = REG(BP);
+               dwarf_regs[6] = REG(SI);
+               dwarf_regs[7] = REG(DI);
+               dwarf_regs[8] = REG(IP);
+               nregs = 9;
+       } else {
+               dwarf_regs[0]  = REG(AX);
+               dwarf_regs[1]  = REG(DX);
+               dwarf_regs[2]  = REG(CX);
+               dwarf_regs[3]  = REG(BX);
+               dwarf_regs[4]  = REG(SI);
+               dwarf_regs[5]  = REG(DI);
+               dwarf_regs[6]  = REG(BP);
+               dwarf_regs[7]  = REG(SP);
+               dwarf_regs[8]  = REG(R8);
+               dwarf_regs[9]  = REG(R9);
+               dwarf_regs[10] = REG(R10);
+               dwarf_regs[11] = REG(R11);
+               dwarf_regs[12] = REG(R12);
+               dwarf_regs[13] = REG(R13);
+               dwarf_regs[14] = REG(R14);
+               dwarf_regs[15] = REG(R15);
+               dwarf_regs[16] = REG(IP);
+               nregs = 17;
+       }
+
+       return dwfl_thread_state_registers(thread, 0, nregs, dwarf_regs);
+}
diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c
new file mode 100644 (file)
index 0000000..3261f68
--- /dev/null
@@ -0,0 +1,111 @@
+
+#include <errno.h>
+#include <libunwind.h>
+#include "perf_regs.h"
+#include "../../util/unwind.h"
+
+#ifdef HAVE_ARCH_X86_64_SUPPORT
+int libunwind__arch_reg_id(int regnum)
+{
+       int id;
+
+       switch (regnum) {
+       case UNW_X86_64_RAX:
+               id = PERF_REG_X86_AX;
+               break;
+       case UNW_X86_64_RDX:
+               id = PERF_REG_X86_DX;
+               break;
+       case UNW_X86_64_RCX:
+               id = PERF_REG_X86_CX;
+               break;
+       case UNW_X86_64_RBX:
+               id = PERF_REG_X86_BX;
+               break;
+       case UNW_X86_64_RSI:
+               id = PERF_REG_X86_SI;
+               break;
+       case UNW_X86_64_RDI:
+               id = PERF_REG_X86_DI;
+               break;
+       case UNW_X86_64_RBP:
+               id = PERF_REG_X86_BP;
+               break;
+       case UNW_X86_64_RSP:
+               id = PERF_REG_X86_SP;
+               break;
+       case UNW_X86_64_R8:
+               id = PERF_REG_X86_R8;
+               break;
+       case UNW_X86_64_R9:
+               id = PERF_REG_X86_R9;
+               break;
+       case UNW_X86_64_R10:
+               id = PERF_REG_X86_R10;
+               break;
+       case UNW_X86_64_R11:
+               id = PERF_REG_X86_R11;
+               break;
+       case UNW_X86_64_R12:
+               id = PERF_REG_X86_R12;
+               break;
+       case UNW_X86_64_R13:
+               id = PERF_REG_X86_R13;
+               break;
+       case UNW_X86_64_R14:
+               id = PERF_REG_X86_R14;
+               break;
+       case UNW_X86_64_R15:
+               id = PERF_REG_X86_R15;
+               break;
+       case UNW_X86_64_RIP:
+               id = PERF_REG_X86_IP;
+               break;
+       default:
+               pr_err("unwind: invalid reg id %d\n", regnum);
+               return -EINVAL;
+       }
+
+       return id;
+}
+#else
+int libunwind__arch_reg_id(int regnum)
+{
+       int id;
+
+       switch (regnum) {
+       case UNW_X86_EAX:
+               id = PERF_REG_X86_AX;
+               break;
+       case UNW_X86_EDX:
+               id = PERF_REG_X86_DX;
+               break;
+       case UNW_X86_ECX:
+               id = PERF_REG_X86_CX;
+               break;
+       case UNW_X86_EBX:
+               id = PERF_REG_X86_BX;
+               break;
+       case UNW_X86_ESI:
+               id = PERF_REG_X86_SI;
+               break;
+       case UNW_X86_EDI:
+               id = PERF_REG_X86_DI;
+               break;
+       case UNW_X86_EBP:
+               id = PERF_REG_X86_BP;
+               break;
+       case UNW_X86_ESP:
+               id = PERF_REG_X86_SP;
+               break;
+       case UNW_X86_EIP:
+               id = PERF_REG_X86_IP;
+               break;
+       default:
+               pr_err("unwind: invalid reg id %d\n", regnum);
+               return -EINVAL;
+       }
+
+       return id;
+}
+#endif /* HAVE_ARCH_X86_64_SUPPORT */
diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c
deleted file mode 100644 (file)
index 456a88c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-
-#include <errno.h>
-#include <libunwind.h>
-#include "perf_regs.h"
-#include "../../util/unwind.h"
-
-#ifdef HAVE_ARCH_X86_64_SUPPORT
-int unwind__arch_reg_id(int regnum)
-{
-       int id;
-
-       switch (regnum) {
-       case UNW_X86_64_RAX:
-               id = PERF_REG_X86_AX;
-               break;
-       case UNW_X86_64_RDX:
-               id = PERF_REG_X86_DX;
-               break;
-       case UNW_X86_64_RCX:
-               id = PERF_REG_X86_CX;
-               break;
-       case UNW_X86_64_RBX:
-               id = PERF_REG_X86_BX;
-               break;
-       case UNW_X86_64_RSI:
-               id = PERF_REG_X86_SI;
-               break;
-       case UNW_X86_64_RDI:
-               id = PERF_REG_X86_DI;
-               break;
-       case UNW_X86_64_RBP:
-               id = PERF_REG_X86_BP;
-               break;
-       case UNW_X86_64_RSP:
-               id = PERF_REG_X86_SP;
-               break;
-       case UNW_X86_64_R8:
-               id = PERF_REG_X86_R8;
-               break;
-       case UNW_X86_64_R9:
-               id = PERF_REG_X86_R9;
-               break;
-       case UNW_X86_64_R10:
-               id = PERF_REG_X86_R10;
-               break;
-       case UNW_X86_64_R11:
-               id = PERF_REG_X86_R11;
-               break;
-       case UNW_X86_64_R12:
-               id = PERF_REG_X86_R12;
-               break;
-       case UNW_X86_64_R13:
-               id = PERF_REG_X86_R13;
-               break;
-       case UNW_X86_64_R14:
-               id = PERF_REG_X86_R14;
-               break;
-       case UNW_X86_64_R15:
-               id = PERF_REG_X86_R15;
-               break;
-       case UNW_X86_64_RIP:
-               id = PERF_REG_X86_IP;
-               break;
-       default:
-               pr_err("unwind: invalid reg id %d\n", regnum);
-               return -EINVAL;
-       }
-
-       return id;
-}
-#else
-int unwind__arch_reg_id(int regnum)
-{
-       int id;
-
-       switch (regnum) {
-       case UNW_X86_EAX:
-               id = PERF_REG_X86_AX;
-               break;
-       case UNW_X86_EDX:
-               id = PERF_REG_X86_DX;
-               break;
-       case UNW_X86_ECX:
-               id = PERF_REG_X86_CX;
-               break;
-       case UNW_X86_EBX:
-               id = PERF_REG_X86_BX;
-               break;
-       case UNW_X86_ESI:
-               id = PERF_REG_X86_SI;
-               break;
-       case UNW_X86_EDI:
-               id = PERF_REG_X86_DI;
-               break;
-       case UNW_X86_EBP:
-               id = PERF_REG_X86_BP;
-               break;
-       case UNW_X86_ESP:
-               id = PERF_REG_X86_SP;
-               break;
-       case UNW_X86_EIP:
-               id = PERF_REG_X86_IP;
-               break;
-       default:
-               pr_err("unwind: invalid reg id %d\n", regnum);
-               return -EINVAL;
-       }
-
-       return id;
-}
-#endif /* HAVE_ARCH_X86_64_SUPPORT */
index 0fdc85269c4dc4c2bd72220526879a07e76679be..eba46709b279d42244f1ed85265c390e2778b500 100644 (file)
@@ -31,6 +31,9 @@ extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
 extern int bench_mem_memcpy(int argc, const char **argv,
                            const char *prefix __maybe_unused);
 extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
+extern int bench_futex_hash(int argc, const char **argv, const char *prefix);
+extern int bench_futex_wake(int argc, const char **argv, const char *prefix);
+extern int bench_futex_requeue(int argc, const char **argv, const char *prefix);
 
 #define BENCH_FORMAT_DEFAULT_STR       "default"
 #define BENCH_FORMAT_DEFAULT           0
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
new file mode 100644 (file)
index 0000000..a84206e
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013  Davidlohr Bueso <davidlohr@hp.com>
+ *
+ * futex-hash: Stress the hell out of the Linux kernel futex uaddr hashing.
+ *
+ * This program is particularly useful for measuring the kernel's futex hash
+ * table/function implementation. In order for it to make sense, use with as
+ * many threads and futexes as possible.
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/stat.h"
+#include "../util/parse-options.h"
+#include "../util/header.h"
+#include "bench.h"
+#include "futex.h"
+
+#include <err.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+static unsigned int nthreads = 0;
+static unsigned int nsecs    = 10;
+/* amount of futexes per thread */
+static unsigned int nfutexes = 1024;
+static bool fshared = false, done = false, silent = false;
+
+struct timeval start, end, runtime;
+static pthread_mutex_t thread_lock;
+static unsigned int threads_starting;
+static struct stats throughput_stats;
+static pthread_cond_t thread_parent, thread_worker;
+
+struct worker {
+       int tid;
+       u_int32_t *futex;
+       pthread_t thread;
+       unsigned long ops;
+};
+
+static const struct option options[] = {
+       OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
+       OPT_UINTEGER('r', "runtime", &nsecs,    "Specify runtime (in seconds)"),
+       OPT_UINTEGER('f', "futexes", &nfutexes, "Specify amount of futexes per threads"),
+       OPT_BOOLEAN( 's', "silent",  &silent,   "Silent mode: do not display data/details"),
+       OPT_BOOLEAN( 'S', "shared",  &fshared,  "Use shared futexes instead of private ones"),
+       OPT_END()
+};
+
+static const char * const bench_futex_hash_usage[] = {
+       "perf bench futex hash <options>",
+       NULL
+};
+
+static void *workerfn(void *arg)
+{
+       int ret;
+       unsigned int i;
+       struct worker *w = (struct worker *) arg;
+
+       pthread_mutex_lock(&thread_lock);
+       threads_starting--;
+       if (!threads_starting)
+               pthread_cond_signal(&thread_parent);
+       pthread_cond_wait(&thread_worker, &thread_lock);
+       pthread_mutex_unlock(&thread_lock);
+
+       do {
+               for (i = 0; i < nfutexes; i++, w->ops++) {
+                       /*
+                        * We want the futex calls to fail in order to stress
+                        * the hashing of uaddr and not measure other steps,
+                        * such as internal waitqueue handling, thus enlarging
+                        * the critical region protected by hb->lock.
+                        */
+                       ret = futex_wait(&w->futex[i], 1234, NULL,
+                                        fshared ? 0 : FUTEX_PRIVATE_FLAG);
+                       if (!silent &&
+                           (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
+                               warn("Non-expected futex return call");
+               }
+       }  while (!done);
+
+       return NULL;
+}
+
+static void toggle_done(int sig __maybe_unused,
+                       siginfo_t *info __maybe_unused,
+                       void *uc __maybe_unused)
+{
+       /* inform all threads that we're done for the day */
+       done = true;
+       gettimeofday(&end, NULL);
+       timersub(&end, &start, &runtime);
+}
+
+static void print_summary(void)
+{
+       unsigned long avg = avg_stats(&throughput_stats);
+       double stddev = stddev_stats(&throughput_stats);
+
+       printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
+              !silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
+              (int) runtime.tv_sec);
+}
+
+int bench_futex_hash(int argc, const char **argv,
+                    const char *prefix __maybe_unused)
+{
+       int ret = 0;
+       cpu_set_t cpu;
+       struct sigaction act;
+       unsigned int i, ncpus;
+       pthread_attr_t thread_attr;
+       struct worker *worker = NULL;
+
+       argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0);
+       if (argc) {
+               usage_with_options(bench_futex_hash_usage, options);
+               exit(EXIT_FAILURE);
+       }
+
+       ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+       sigfillset(&act.sa_mask);
+       act.sa_sigaction = toggle_done;
+       sigaction(SIGINT, &act, NULL);
+
+       if (!nthreads) /* default to the number of CPUs */
+               nthreads = ncpus;
+
+       worker = calloc(nthreads, sizeof(*worker));
+       if (!worker)
+               goto errmem;
+
+       printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
+              getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
+
+       init_stats(&throughput_stats);
+       pthread_mutex_init(&thread_lock, NULL);
+       pthread_cond_init(&thread_parent, NULL);
+       pthread_cond_init(&thread_worker, NULL);
+
+       threads_starting = nthreads;
+       pthread_attr_init(&thread_attr);
+       gettimeofday(&start, NULL);
+       for (i = 0; i < nthreads; i++) {
+               worker[i].tid = i;
+               worker[i].futex = calloc(nfutexes, sizeof(*worker[i].futex));
+               if (!worker[i].futex)
+                       goto errmem;
+
+               CPU_ZERO(&cpu);
+               CPU_SET(i % ncpus, &cpu);
+
+               ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu);
+               if (ret)
+                       err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
+
+               ret = pthread_create(&worker[i].thread, &thread_attr, workerfn,
+                                    (void *)(struct worker *) &worker[i]);
+               if (ret)
+                       err(EXIT_FAILURE, "pthread_create");
+
+       }
+       pthread_attr_destroy(&thread_attr);
+
+       pthread_mutex_lock(&thread_lock);
+       while (threads_starting)
+               pthread_cond_wait(&thread_parent, &thread_lock);
+       pthread_cond_broadcast(&thread_worker);
+       pthread_mutex_unlock(&thread_lock);
+
+       sleep(nsecs);
+       toggle_done(0, NULL, NULL);
+
+       for (i = 0; i < nthreads; i++) {
+               ret = pthread_join(worker[i].thread, NULL);
+               if (ret)
+                       err(EXIT_FAILURE, "pthread_join");
+       }
+
+       /* cleanup & report results */
+       pthread_cond_destroy(&thread_parent);
+       pthread_cond_destroy(&thread_worker);
+       pthread_mutex_destroy(&thread_lock);
+
+       for (i = 0; i < nthreads; i++) {
+               unsigned long t = worker[i].ops/runtime.tv_sec;
+               update_stats(&throughput_stats, t);
+               if (!silent) {
+                       if (nfutexes == 1)
+                               printf("[thread %2d] futex: %p [ %ld ops/sec ]\n",
+                                      worker[i].tid, &worker[i].futex[0], t);
+                       else
+                               printf("[thread %2d] futexes: %p ... %p [ %ld ops/sec ]\n",
+                                      worker[i].tid, &worker[i].futex[0],
+                                      &worker[i].futex[nfutexes-1], t);
+               }
+
+               free(worker[i].futex);
+       }
+
+       print_summary();
+
+       free(worker);
+       return ret;
+errmem:
+       err(EXIT_FAILURE, "calloc");
+}
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
new file mode 100644 (file)
index 0000000..a162558
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2013  Davidlohr Bueso <davidlohr@hp.com>
+ *
+ * futex-requeue: Block a bunch of threads on futex1 and requeue them
+ *                on futex2, N at a time.
+ *
+ * This program is particularly useful to measure the latency of nthread
+ * requeues without waking up any tasks -- thus mimicking a regular futex_wait.
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/stat.h"
+#include "../util/parse-options.h"
+#include "../util/header.h"
+#include "bench.h"
+#include "futex.h"
+
+#include <err.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+static u_int32_t futex1 = 0, futex2 = 0;
+
+/*
+ * How many tasks to requeue at a time.
+ * Default to 1 in order to make the kernel work more.
+ */
+static unsigned int nrequeue = 1;
+
+/*
+ * There can be significant variance from run to run,
+ * the more repeats, the more exact the overall avg and
+ * the better idea of the futex latency.
+ */
+static unsigned int repeat = 10;
+
+static pthread_t *worker;
+static bool done = 0, silent = 0;
+static pthread_mutex_t thread_lock;
+static pthread_cond_t thread_parent, thread_worker;
+static struct stats requeuetime_stats, requeued_stats;
+static unsigned int ncpus, threads_starting, nthreads = 0;
+
+static const struct option options[] = {
+       OPT_UINTEGER('t', "threads",  &nthreads, "Specify amount of threads"),
+       OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
+       OPT_UINTEGER('r', "repeat",   &repeat,   "Specify amount of times to repeat the run"),
+       OPT_BOOLEAN( 's', "silent",   &silent,   "Silent mode: do not display data/details"),
+       OPT_END()
+};
+
+static const char * const bench_futex_requeue_usage[] = {
+       "perf bench futex requeue <options>",
+       NULL
+};
+
+static void print_summary(void)
+{
+       double requeuetime_avg = avg_stats(&requeuetime_stats);
+       double requeuetime_stddev = stddev_stats(&requeuetime_stats);
+       unsigned int requeued_avg = avg_stats(&requeued_stats);
+
+       printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n",
+              requeued_avg,
+              nthreads,
+              requeuetime_avg/1e3,
+              rel_stddev_stats(requeuetime_stddev, requeuetime_avg));
+}
+
+static void *workerfn(void *arg __maybe_unused)
+{
+       pthread_mutex_lock(&thread_lock);
+       threads_starting--;
+       if (!threads_starting)
+               pthread_cond_signal(&thread_parent);
+       pthread_cond_wait(&thread_worker, &thread_lock);
+       pthread_mutex_unlock(&thread_lock);
+
+       futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG);
+       return NULL;
+}
+
+static void block_threads(pthread_t *w,
+                         pthread_attr_t thread_attr)
+{
+       cpu_set_t cpu;
+       unsigned int i;
+
+       threads_starting = nthreads;
+
+       /* create and block all threads */
+       for (i = 0; i < nthreads; i++) {
+               CPU_ZERO(&cpu);
+               CPU_SET(i % ncpus, &cpu);
+
+               if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu))
+                       err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
+
+               if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
+                       err(EXIT_FAILURE, "pthread_create");
+       }
+}
+
+static void toggle_done(int sig __maybe_unused,
+                       siginfo_t *info __maybe_unused,
+                       void *uc __maybe_unused)
+{
+       done = true;
+}
+
+int bench_futex_requeue(int argc, const char **argv,
+                       const char *prefix __maybe_unused)
+{
+       int ret = 0;
+       unsigned int i, j;
+       struct sigaction act;
+       pthread_attr_t thread_attr;
+
+       argc = parse_options(argc, argv, options, bench_futex_requeue_usage, 0);
+       if (argc)
+               goto err;
+
+       ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+       sigfillset(&act.sa_mask);
+       act.sa_sigaction = toggle_done;
+       sigaction(SIGINT, &act, NULL);
+
+       if (!nthreads)
+               nthreads = ncpus;
+
+       worker = calloc(nthreads, sizeof(*worker));
+       if (!worker)
+               err(EXIT_FAILURE, "calloc");
+
+       printf("Run summary [PID %d]: Requeuing %d threads (from %p to %p), "
+              "%d at a time.\n\n",
+              getpid(), nthreads, &futex1, &futex2, nrequeue);
+
+       init_stats(&requeued_stats);
+       init_stats(&requeuetime_stats);
+       pthread_attr_init(&thread_attr);
+       pthread_mutex_init(&thread_lock, NULL);
+       pthread_cond_init(&thread_parent, NULL);
+       pthread_cond_init(&thread_worker, NULL);
+
+       for (j = 0; j < repeat && !done; j++) {
+               unsigned int nrequeued = 0;
+               struct timeval start, end, runtime;
+
+               /* create, launch & block all threads */
+               block_threads(worker, thread_attr);
+
+               /* make sure all threads are already blocked */
+               pthread_mutex_lock(&thread_lock);
+               while (threads_starting)
+                       pthread_cond_wait(&thread_parent, &thread_lock);
+               pthread_cond_broadcast(&thread_worker);
+               pthread_mutex_unlock(&thread_lock);
+
+               usleep(100000);
+
+               /* Ok, all threads are patiently blocked, start requeueing */
+               gettimeofday(&start, NULL);
+               for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue)
+                       /*
+                        * Do not wakeup any tasks blocked on futex1, allowing
+                        * us to really measure futex_wait functionality.
+                        */
+                       futex_cmp_requeue(&futex1, 0, &futex2, 0, nrequeue,
+                                         FUTEX_PRIVATE_FLAG);
+               gettimeofday(&end, NULL);
+               timersub(&end, &start, &runtime);
+
+               update_stats(&requeued_stats, nrequeued);
+               update_stats(&requeuetime_stats, runtime.tv_usec);
+
+               if (!silent) {
+                       printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n",
+                              j + 1, nrequeued, nthreads, runtime.tv_usec/1e3);
+               }
+
+               /* everybody should be blocked on futex2, wake'em up */
+               nrequeued = futex_wake(&futex2, nthreads, FUTEX_PRIVATE_FLAG);
+               if (nthreads != nrequeued)
+                       warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
+
+               for (i = 0; i < nthreads; i++) {
+                       ret = pthread_join(worker[i], NULL);
+                       if (ret)
+                               err(EXIT_FAILURE, "pthread_join");
+               }
+
+       }
+
+       /* cleanup & report results */
+       pthread_cond_destroy(&thread_parent);
+       pthread_cond_destroy(&thread_worker);
+       pthread_mutex_destroy(&thread_lock);
+       pthread_attr_destroy(&thread_attr);
+
+       print_summary();
+
+       free(worker);
+       return ret;
+err:
+       usage_with_options(bench_futex_requeue_usage, options);
+       exit(EXIT_FAILURE);
+}
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
new file mode 100644 (file)
index 0000000..d096169
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2013  Davidlohr Bueso <davidlohr@hp.com>
+ *
+ * futex-wake: Block a bunch of threads on a futex and wake'em up, N at a time.
+ *
+ * This program is particularly useful to measure the latency of nthread wakeups
+ * in non-error situations:  all waiters are queued and all wake calls wakeup
+ * one or more tasks, and thus the waitqueue is never empty.
+ */
+
+#include "../perf.h"
+#include "../util/util.h"
+#include "../util/stat.h"
+#include "../util/parse-options.h"
+#include "../util/header.h"
+#include "bench.h"
+#include "futex.h"
+
+#include <err.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+/* all threads will block on the same futex */
+static u_int32_t futex1 = 0;
+
+/*
+ * How many wakeups to do at a time.
+ * Default to 1 in order to make the kernel work more.
+ */
+static unsigned int nwakes = 1;
+
+/*
+ * There can be significant variance from run to run,
+ * the more repeats, the more exact the overall avg and
+ * the better idea of the futex latency.
+ */
+static unsigned int repeat = 10;
+
+pthread_t *worker;
+static bool done = 0, silent = 0;
+static pthread_mutex_t thread_lock;
+static pthread_cond_t thread_parent, thread_worker;
+static struct stats waketime_stats, wakeup_stats;
+static unsigned int ncpus, threads_starting, nthreads = 0;
+
+static const struct option options[] = {
+       OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
+       OPT_UINTEGER('w', "nwakes",  &nwakes,   "Specify amount of threads to wake at once"),
+       OPT_UINTEGER('r', "repeat",  &repeat,   "Specify amount of times to repeat the run"),
+       OPT_BOOLEAN( 's', "silent",  &silent,   "Silent mode: do not display data/details"),
+       OPT_END()
+};
+
+static const char * const bench_futex_wake_usage[] = {
+       "perf bench futex wake <options>",
+       NULL
+};
+
+static void *workerfn(void *arg __maybe_unused)
+{
+       pthread_mutex_lock(&thread_lock);
+       threads_starting--;
+       if (!threads_starting)
+               pthread_cond_signal(&thread_parent);
+       pthread_cond_wait(&thread_worker, &thread_lock);
+       pthread_mutex_unlock(&thread_lock);
+
+       futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG);
+       return NULL;
+}
+
+static void print_summary(void)
+{
+       double waketime_avg = avg_stats(&waketime_stats);
+       double waketime_stddev = stddev_stats(&waketime_stats);
+       unsigned int wakeup_avg = avg_stats(&wakeup_stats);
+
+       printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n",
+              wakeup_avg,
+              nthreads,
+              waketime_avg/1e3,
+              rel_stddev_stats(waketime_stddev, waketime_avg));
+}
+
+static void block_threads(pthread_t *w,
+                         pthread_attr_t thread_attr)
+{
+       cpu_set_t cpu;
+       unsigned int i;
+
+       threads_starting = nthreads;
+
+       /* create and block all threads */
+       for (i = 0; i < nthreads; i++) {
+               CPU_ZERO(&cpu);
+               CPU_SET(i % ncpus, &cpu);
+
+               if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpu))
+                       err(EXIT_FAILURE, "pthread_attr_setaffinity_np");
+
+               if (pthread_create(&w[i], &thread_attr, workerfn, NULL))
+                       err(EXIT_FAILURE, "pthread_create");
+       }
+}
+
+static void toggle_done(int sig __maybe_unused,
+                       siginfo_t *info __maybe_unused,
+                       void *uc __maybe_unused)
+{
+       done = true;
+}
+
+int bench_futex_wake(int argc, const char **argv,
+                    const char *prefix __maybe_unused)
+{
+       int ret = 0;
+       unsigned int i, j;
+       struct sigaction act;
+       pthread_attr_t thread_attr;
+
+       argc = parse_options(argc, argv, options, bench_futex_wake_usage, 0);
+       if (argc) {
+               usage_with_options(bench_futex_wake_usage, options);
+               exit(EXIT_FAILURE);
+       }
+
+       ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+       sigfillset(&act.sa_mask);
+       act.sa_sigaction = toggle_done;
+       sigaction(SIGINT, &act, NULL);
+
+       if (!nthreads)
+               nthreads = ncpus;
+
+       worker = calloc(nthreads, sizeof(*worker));
+       if (!worker)
+               err(EXIT_FAILURE, "calloc");
+
+       printf("Run summary [PID %d]: blocking on %d threads (at futex %p), "
+              "waking up %d at a time.\n\n",
+              getpid(), nthreads, &futex1, nwakes);
+
+       init_stats(&wakeup_stats);
+       init_stats(&waketime_stats);
+       pthread_attr_init(&thread_attr);
+       pthread_mutex_init(&thread_lock, NULL);
+       pthread_cond_init(&thread_parent, NULL);
+       pthread_cond_init(&thread_worker, NULL);
+
+       for (j = 0; j < repeat && !done; j++) {
+               unsigned int nwoken = 0;
+               struct timeval start, end, runtime;
+
+               /* create, launch & block all threads */
+               block_threads(worker, thread_attr);
+
+               /* make sure all threads are already blocked */
+               pthread_mutex_lock(&thread_lock);
+               while (threads_starting)
+                       pthread_cond_wait(&thread_parent, &thread_lock);
+               pthread_cond_broadcast(&thread_worker);
+               pthread_mutex_unlock(&thread_lock);
+
+               usleep(100000);
+
+               /* Ok, all threads are patiently blocked, start waking folks up */
+               gettimeofday(&start, NULL);
+               while (nwoken != nthreads)
+                       nwoken += futex_wake(&futex1, nwakes, FUTEX_PRIVATE_FLAG);
+               gettimeofday(&end, NULL);
+               timersub(&end, &start, &runtime);
+
+               update_stats(&wakeup_stats, nwoken);
+               update_stats(&waketime_stats, runtime.tv_usec);
+
+               if (!silent) {
+                       printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
+                              j + 1, nwoken, nthreads, runtime.tv_usec/1e3);
+               }
+
+               for (i = 0; i < nthreads; i++) {
+                       ret = pthread_join(worker[i], NULL);
+                       if (ret)
+                               err(EXIT_FAILURE, "pthread_join");
+               }
+
+       }
+
+       /* cleanup & report results */
+       pthread_cond_destroy(&thread_parent);
+       pthread_cond_destroy(&thread_worker);
+       pthread_mutex_destroy(&thread_lock);
+       pthread_attr_destroy(&thread_attr);
+
+       print_summary();
+
+       free(worker);
+       return ret;
+}
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
new file mode 100644 (file)
index 0000000..71f2844
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Glibc independent futex library for testing kernel functionality.
+ * Shamelessly stolen from Darren Hart <dvhltc@us.ibm.com>
+ *    http://git.kernel.org/cgit/linux/kernel/git/dvhart/futextest.git/
+ */
+
+#ifndef _FUTEX_H
+#define _FUTEX_H
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <linux/futex.h>
+
+/**
+ * futex() - SYS_futex syscall wrapper
+ * @uaddr:     address of first futex
+ * @op:                futex op code
+ * @val:       typically expected value of uaddr, but varies by op
+ * @timeout:   typically an absolute struct timespec (except where noted
+ *             otherwise). Overloaded by some ops
+ * @uaddr2:    address of second futex for some ops\
+ * @val3:      varies by op
+ * @opflags:   flags to be bitwise OR'd with op, such as FUTEX_PRIVATE_FLAG
+ *
+ * futex() is used by all the following futex op wrappers. It can also be
+ * used for misuse and abuse testing. Generally, the specific op wrappers
+ * should be used instead. It is a macro instead of an static inline function as
+ * some of the types over overloaded (timeout is used for nr_requeue for
+ * example).
+ *
+ * These argument descriptions are the defaults for all
+ * like-named arguments in the following wrappers except where noted below.
+ */
+#define futex(uaddr, op, val, timeout, uaddr2, val3, opflags) \
+       syscall(SYS_futex, uaddr, op | opflags, val, timeout, uaddr2, val3)
+
+/**
+ * futex_wait() - block on uaddr with optional timeout
+ * @timeout:   relative timeout
+ */
+static inline int
+futex_wait(u_int32_t *uaddr, u_int32_t val, struct timespec *timeout, int opflags)
+{
+       return futex(uaddr, FUTEX_WAIT, val, timeout, NULL, 0, opflags);
+}
+
+/**
+ * futex_wake() - wake one or more tasks blocked on uaddr
+ * @nr_wake:   wake up to this many tasks
+ */
+static inline int
+futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
+{
+       return futex(uaddr, FUTEX_WAKE, nr_wake, NULL, NULL, 0, opflags);
+}
+
+/**
+* futex_cmp_requeue() - requeue tasks from uaddr to uaddr2
+* @nr_wake:        wake up to this many tasks
+* @nr_requeue:        requeue up to this many tasks
+*/
+static inline int
+futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wake,
+                int nr_requeue, int opflags)
+{
+       return futex(uaddr, FUTEX_CMP_REQUEUE, nr_wake, nr_requeue, uaddr2,
+                val, opflags);
+}
+
+#endif /* _FUTEX_H */
index d4c83c60b9b29fa7d6249de70e5f0673d2066287..97d86d828190950af7f133c1b8be72550070d3d1 100644 (file)
@@ -1593,6 +1593,7 @@ static void init_params(struct params *p, const char *name, int argc, const char
        p->data_rand_walk               = true;
        p->nr_loops                     = -1;
        p->init_random                  = true;
+       p->run_all                      = argc == 1;
 }
 
 static int run_bench_numa(const char *name, const char **argv)
index e47f90cc7b98cdde57079975bbd5637f3249ce44..1e6e77710545afc472eae5c0f5e5a63f5ec432d1 100644 (file)
@@ -12,6 +12,7 @@
  *  sched ... scheduler and IPC performance
  *  mem   ... memory access performance
  *  numa  ... NUMA scheduling and MM performance
+ *  futex ... Futex performance
  */
 #include "perf.h"
 #include "util/util.h"
@@ -54,6 +55,14 @@ static struct bench mem_benchmarks[] = {
        { NULL,         NULL,                                           NULL                    }
 };
 
+static struct bench futex_benchmarks[] = {
+       { "hash",       "Benchmark for futex hash table",               bench_futex_hash        },
+       { "wake",       "Benchmark for futex wake calls",               bench_futex_wake        },
+       { "requeue",    "Benchmark for futex requeue calls",            bench_futex_requeue     },
+       { "all",        "Test all futex benchmarks",                    NULL                    },
+       { NULL,         NULL,                                           NULL                    }
+};
+
 struct collection {
        const char      *name;
        const char      *summary;
@@ -61,11 +70,12 @@ struct collection {
 };
 
 static struct collection collections[] = {
-       { "sched",      "Scheduler and IPC benchmarks",         sched_benchmarks        },
+       { "sched",      "Scheduler and IPC benchmarks",                 sched_benchmarks        },
        { "mem",        "Memory access benchmarks",                     mem_benchmarks          },
 #ifdef HAVE_LIBNUMA_SUPPORT
        { "numa",       "NUMA scheduling and MM benchmarks",            numa_benchmarks         },
 #endif
+       {"futex",       "Futex stressing benchmarks",                   futex_benchmarks        },
        { "all",        "All benchmarks",                               NULL                    },
        { NULL,         NULL,                                           NULL                    }
 };
@@ -76,7 +86,7 @@ static struct collection collections[] = {
 
 /* Iterate over all benchmarks within a collection: */
 #define for_each_bench(coll, bench) \
-       for (bench = coll->benchmarks; bench->name; bench++)
+       for (bench = coll->benchmarks; bench && bench->name; bench++)
 
 static void dump_benchmarks(struct collection *coll)
 {
index cfede86161d8ae9410c123745bb60def09785331..b22dbb16f8776112f335e9185740a85645f2cf86 100644 (file)
@@ -63,11 +63,35 @@ static int build_id_cache__kcore_dir(char *dir, size_t sz)
        return 0;
 }
 
+static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
+{
+       char from[PATH_MAX];
+       char to[PATH_MAX];
+       const char *name;
+       u64 addr1 = 0, addr2 = 0;
+       int i;
+
+       scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
+       scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);
+
+       for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
+               addr1 = kallsyms__get_function_start(from, name);
+               if (addr1)
+                       break;
+       }
+
+       if (name)
+               addr2 = kallsyms__get_function_start(to, name);
+
+       return addr1 == addr2;
+}
+
 static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
                                          size_t to_dir_sz)
 {
        char from[PATH_MAX];
        char to[PATH_MAX];
+       char to_subdir[PATH_MAX];
        struct dirent *dent;
        int ret = -1;
        DIR *d;
@@ -86,10 +110,11 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
                        continue;
                scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
                          dent->d_name);
-               if (!compare_proc_modules(from, to)) {
-                       scnprintf(to, sizeof(to), "%s/%s", to_dir,
-                                 dent->d_name);
-                       strlcpy(to_dir, to, to_dir_sz);
+               scnprintf(to_subdir, sizeof(to_subdir), "%s/%s",
+                         to_dir, dent->d_name);
+               if (!compare_proc_modules(from, to) &&
+                   same_kallsyms_reloc(from_dir, to_subdir)) {
+                       strlcpy(to_dir, to_subdir, to_dir_sz);
                        ret = 0;
                        break;
                }
index a77e31246c00ba1841a0b8447d97a04302f2ea3b..204fffe225320f3aa710d9e50da63de25c9d56a2 100644 (file)
@@ -952,8 +952,8 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
                                 dfmt->header_width, buf);
 }
 
-static int hpp__header(struct perf_hpp_fmt *fmt,
-                      struct perf_hpp *hpp)
+static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+                      struct perf_evsel *evsel __maybe_unused)
 {
        struct diff_hpp_fmt *dfmt =
                container_of(fmt, struct diff_hpp_fmt, fmt);
@@ -963,7 +963,8 @@ static int hpp__header(struct perf_hpp_fmt *fmt,
 }
 
 static int hpp__width(struct perf_hpp_fmt *fmt,
-                     struct perf_hpp *hpp __maybe_unused)
+                     struct perf_hpp *hpp __maybe_unused,
+                     struct perf_evsel *evsel __maybe_unused)
 {
        struct diff_hpp_fmt *dfmt =
                container_of(fmt, struct diff_hpp_fmt, fmt);
index b3466018bbd7b514811dd6a5e2bad10ed275eb5b..3a7387551369c97ab38b249ced193cc386c2cabe 100644 (file)
@@ -312,7 +312,6 @@ found:
        sample_sw.period = sample->period;
        sample_sw.time   = sample->time;
        perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
-                                     evsel->attr.sample_regs_user,
                                      evsel->attr.read_format, &sample_sw,
                                      false);
        build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
index a7350519c63f528cfb627d736867742b57b1a2e8..21c164b8f9db2a70a9467e1341fbb6a49a3536a1 100644 (file)
@@ -1691,17 +1691,15 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
                OPT_END()
        };
 
-
-       const char * const kvm_usage[] = {
-               "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
-               NULL
-       };
+       const char *const kvm_subcommands[] = { "top", "record", "report", "diff",
+                                               "buildid-list", "stat", NULL };
+       const char *kvm_usage[] = { NULL, NULL };
 
        perf_host  = 0;
        perf_guest = 1;
 
-       argc = parse_options(argc, argv, kvm_options, kvm_usage,
-                       PARSE_OPT_STOP_AT_NON_OPTION);
+       argc = parse_options_subcommand(argc, argv, kvm_options, kvm_subcommands, kvm_usage,
+                                       PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc)
                usage_with_options(kvm_usage, kvm_options);
 
index 78948882e3de72c9a521f1d3c6d3bff29f2e493d..cdcd4eb3a57df5e48a77a3ba914251c896e0bfc1 100644 (file)
@@ -268,9 +268,9 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
        return 0;
 }
 
-static void init_params(void)
+static int init_params(void)
 {
-       line_range__init(&params.line_range);
+       return line_range__init(&params.line_range);
 }
 
 static void cleanup_params(void)
@@ -515,9 +515,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix)
 {
        int ret;
 
-       init_params();
-       ret = __cmd_probe(argc, argv, prefix);
-       cleanup_params();
+       ret = init_params();
+       if (!ret) {
+               ret = __cmd_probe(argc, argv, prefix);
+               cleanup_params();
+       }
 
        return ret;
 }
index 3c394bf16fa8cd86ce01d3d5852bab8a078f5ae4..eb524f91bffe5d9098d582e07050734a1c3e5343 100644 (file)
@@ -287,10 +287,7 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
         * have no _text sometimes.
         */
        err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
-                                                machine, "_text");
-       if (err < 0)
-               err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
-                                                        machine, "_stext");
+                                                machine);
        if (err < 0)
                pr_err("Couldn't record guest kernel [%d]'s reference"
                       " relocation symbol.\n", machine->pid);
@@ -457,10 +454,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
        }
 
        err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
-                                                machine, "_text");
-       if (err < 0)
-               err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
-                                                        machine, "_stext");
+                                                machine);
        if (err < 0)
                pr_err("Couldn't record kernel reference relocation symbol\n"
                       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
@@ -655,7 +649,7 @@ error:
        return ret;
 }
 
-#ifdef HAVE_LIBUNWIND_SUPPORT
+#ifdef HAVE_DWARF_UNWIND_SUPPORT
 static int get_stack_size(char *str, unsigned long *_size)
 {
        char *endptr;
@@ -681,7 +675,7 @@ static int get_stack_size(char *str, unsigned long *_size)
               max_size, str);
        return -1;
 }
-#endif /* HAVE_LIBUNWIND_SUPPORT */
+#endif /* HAVE_DWARF_UNWIND_SUPPORT */
 
 int record_parse_callchain(const char *arg, struct record_opts *opts)
 {
@@ -710,7 +704,7 @@ int record_parse_callchain(const char *arg, struct record_opts *opts)
                                       "needed for -g fp\n");
                        break;
 
-#ifdef HAVE_LIBUNWIND_SUPPORT
+#ifdef HAVE_DWARF_UNWIND_SUPPORT
                /* Dwarf style */
                } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
                        const unsigned long default_stack_dump_size = 8192;
@@ -726,7 +720,7 @@ int record_parse_callchain(const char *arg, struct record_opts *opts)
                                ret = get_stack_size(tok, &size);
                                opts->stack_dump_size = size;
                        }
-#endif /* HAVE_LIBUNWIND_SUPPORT */
+#endif /* HAVE_DWARF_UNWIND_SUPPORT */
                } else {
                        pr_err("callchain: Unknown --call-graph option "
                               "value: %s\n", arg);
@@ -741,7 +735,9 @@ int record_parse_callchain(const char *arg, struct record_opts *opts)
 
 static void callchain_debug(struct record_opts *opts)
 {
-       pr_debug("callchain: type %d\n", opts->call_graph);
+       static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
+
+       pr_debug("callchain: type %s\n", str[opts->call_graph]);
 
        if (opts->call_graph == CALLCHAIN_DWARF)
                pr_debug("callchain: stack dump size %d\n",
@@ -755,6 +751,8 @@ int record_parse_callchain_opt(const struct option *opt,
        struct record_opts *opts = opt->value;
        int ret;
 
+       opts->call_graph_enabled = !unset;
+
        /* --no-call-graph */
        if (unset) {
                opts->call_graph = CALLCHAIN_NONE;
@@ -775,6 +773,8 @@ int record_callchain_opt(const struct option *opt,
 {
        struct record_opts *opts = opt->value;
 
+       opts->call_graph_enabled = !unset;
+
        if (opts->call_graph == CALLCHAIN_NONE)
                opts->call_graph = CALLCHAIN_FP;
 
@@ -782,6 +782,16 @@ int record_callchain_opt(const struct option *opt,
        return 0;
 }
 
+static int perf_record_config(const char *var, const char *value, void *cb)
+{
+       struct record *rec = cb;
+
+       if (!strcmp(var, "record.call-graph"))
+               return record_parse_callchain(value, &rec->opts);
+
+       return perf_default_config(var, value, cb);
+}
+
 static const char * const record_usage[] = {
        "perf record [<options>] [<command>]",
        "perf record [<options>] -- <command> [<options>]",
@@ -813,7 +823,7 @@ static struct record record = {
 
 #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
 
-#ifdef HAVE_LIBUNWIND_SUPPORT
+#ifdef HAVE_DWARF_UNWIND_SUPPORT
 const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
 #else
 const char record_callchain_help[] = CALLCHAIN_HELP "fp";
@@ -913,6 +923,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
        if (rec->evlist == NULL)
                return -ENOMEM;
 
+       perf_config(perf_record_config, rec);
+
        argc = parse_options(argc, argv, record_options, record_usage,
                            PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc && target__none(&rec->opts.target))
index 3c53ec268fbc52a5298f390a83e3802eecd156a6..c8f21137dfd8ad7f80472acf020eab9e3f492bb6 100644 (file)
@@ -75,13 +75,10 @@ static int report__config(const char *var, const char *value, void *cb)
        return perf_default_config(var, value, cb);
 }
 
-static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al,
-                                     struct perf_sample *sample, struct perf_evsel *evsel,
-                                     union perf_event *event)
+static int report__add_mem_hist_entry(struct report *rep, struct addr_location *al,
+                                     struct perf_sample *sample, struct perf_evsel *evsel)
 {
-       struct report *rep = container_of(tool, struct report, tool);
        struct symbol *parent = NULL;
-       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
        struct hist_entry *he;
        struct mem_info *mi, *mx;
        uint64_t cost;
@@ -90,7 +87,7 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati
        if (err)
                return err;
 
-       mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode);
+       mi = sample__resolve_mem(sample, al);
        if (!mi)
                return -ENOMEM;
 
@@ -113,14 +110,16 @@ static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_locati
        if (!he)
                return -ENOMEM;
 
-       err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
-       if (err)
-               goto out;
+       if (ui__has_annotation()) {
+               err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+               if (err)
+                       goto out;
 
-       mx = he->mem_info;
-       err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
-       if (err)
-               goto out;
+               mx = he->mem_info;
+               err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
+               if (err)
+                       goto out;
+       }
 
        evsel->hists.stats.total_period += cost;
        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
@@ -129,10 +128,9 @@ out:
        return err;
 }
 
-static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al,
+static int report__add_branch_hist_entry(struct report *rep, struct addr_location *al,
                                         struct perf_sample *sample, struct perf_evsel *evsel)
 {
-       struct report *rep = container_of(tool, struct report, tool);
        struct symbol *parent = NULL;
        unsigned i;
        struct hist_entry *he;
@@ -142,8 +140,7 @@ static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_loc
        if (err)
                return err;
 
-       bi = machine__resolve_bstack(al->machine, al->thread,
-                                    sample->branch_stack);
+       bi = sample__resolve_bstack(sample, al);
        if (!bi)
                return -ENOMEM;
 
@@ -164,14 +161,18 @@ static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_loc
                he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
                                        1, 1, 0);
                if (he) {
-                       bx = he->branch_info;
-                       err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
-                       if (err)
-                               goto out;
-
-                       err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
-                       if (err)
-                               goto out;
+                       if (ui__has_annotation()) {
+                               bx = he->branch_info;
+                               err = addr_map_symbol__inc_samples(&bx->from,
+                                                                  evsel->idx);
+                               if (err)
+                                       goto out;
+
+                               err = addr_map_symbol__inc_samples(&bx->to,
+                                                                  evsel->idx);
+                               if (err)
+                                       goto out;
+                       }
 
                        evsel->hists.stats.total_period += 1;
                        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
@@ -184,10 +185,9 @@ out:
        return err;
 }
 
-static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
+static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
                                  struct addr_location *al, struct perf_sample *sample)
 {
-       struct report *rep = container_of(tool, struct report, tool);
        struct symbol *parent = NULL;
        struct hist_entry *he;
        int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
@@ -205,7 +205,9 @@ static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evs
        if (err)
                goto out;
 
-       err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+       if (ui__has_annotation())
+               err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+
        evsel->hists.stats.total_period += sample->period;
        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
 out:
@@ -229,25 +231,25 @@ static int process_sample_event(struct perf_tool *tool,
                return -1;
        }
 
-       if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
+       if (rep->hide_unresolved && al.sym == NULL)
                return 0;
 
        if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
                return 0;
 
        if (sort__mode == SORT_MODE__BRANCH) {
-               ret = report__add_branch_hist_entry(tool, &al, sample, evsel);
+               ret = report__add_branch_hist_entry(rep, &al, sample, evsel);
                if (ret < 0)
                        pr_debug("problem adding lbr entry, skipping event\n");
        } else if (rep->mem_mode == 1) {
-               ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event);
+               ret = report__add_mem_hist_entry(rep, &al, sample, evsel);
                if (ret < 0)
                        pr_debug("problem adding mem entry, skipping event\n");
        } else {
                if (al.map != NULL)
                        al.map->dso->hit = 1;
 
-               ret = report__add_hist_entry(tool, evsel, &al, sample);
+               ret = report__add_hist_entry(rep, evsel, &al, sample);
                if (ret < 0)
                        pr_debug("problem incrementing symbol period, skipping event\n");
        }
@@ -926,7 +928,7 @@ repeat:
         * so don't allocate extra space that won't be used in the stdio
         * implementation.
         */
-       if (use_browser == 1 && sort__has_sym) {
+       if (ui__has_annotation()) {
                symbol_conf.priv_size = sizeof(struct annotation);
                machines__set_symbol_filter(&session->machines,
                                            symbol__annotate_init);
index 6a76a07b67890c253fbb1e227e9aaa980b499779..9ac0a495c954e5793ddfe9e0e42ef4ee995bec56 100644 (file)
@@ -1124,7 +1124,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
 
        avg = work_list->total_lat / work_list->nb_atoms;
 
-       printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n",
+       printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n",
              (double)work_list->total_runtime / 1e6,
                 work_list->nb_atoms, (double)avg / 1e6,
                 (double)work_list->max_lat / 1e6,
@@ -1527,9 +1527,9 @@ static int perf_sched__lat(struct perf_sched *sched)
 
        perf_sched__sort_lat(sched);
 
-       printf("\n ---------------------------------------------------------------------------------------------------------------\n");
-       printf("  Task                  |   Runtime ms  | Switches | Average delay ms | Maximum delay ms | Maximum delay at     |\n");
-       printf(" ---------------------------------------------------------------------------------------------------------------\n");
+       printf("\n -----------------------------------------------------------------------------------------------------------------\n");
+       printf("  Task                  |   Runtime ms  | Switches | Average delay ms | Maximum delay ms | Maximum delay at       |\n");
+       printf(" -----------------------------------------------------------------------------------------------------------------\n");
 
        next = rb_first(&sched->sorted_atom_root);
 
@@ -1541,7 +1541,7 @@ static int perf_sched__lat(struct perf_sched *sched)
                next = rb_next(next);
        }
 
-       printf(" -----------------------------------------------------------------------------------------\n");
+       printf(" -----------------------------------------------------------------------------------------------------------------\n");
        printf("  TOTAL:                |%11.3f ms |%9" PRIu64 " |\n",
                (double)sched->all_runtime / 1e6, sched->all_count);
 
index 25526d6eae59f65a4a0405c9186d93b9cd5d3d59..74db2568b867b7996726674edd20539a7820dcc9 100644 (file)
@@ -494,7 +494,7 @@ static const char *cat_backtrace(union perf_event *event,
                        continue;
                }
 
-               tal.filtered = false;
+               tal.filtered = 0;
                thread__find_addr_location(al.thread, machine, cpumode,
                                           MAP__FUNCTION, ip, &tal);
 
@@ -1238,7 +1238,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar
        for (i = 0; i < old_power_args_nr; i++)
                *p++ = strdup(old_power_args[i]);
 
-       for (j = 1; j < (unsigned int)argc; j++)
+       for (j = 0; j < (unsigned int)argc; j++)
                *p++ = argv[j];
 
        return cmd_record(rec_argc, rec_argv, NULL);
index 76cd510d34d023bf3c580ec2b3e2e217d8831cba..65aaa5bbf7ec75830b9b58afae6c6d66d352a9f7 100644 (file)
@@ -176,7 +176,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
 {
        struct annotation *notes;
        struct symbol *sym;
-       int err;
+       int err = 0;
 
        if (he == NULL || he->ms.sym == NULL ||
            ((top->sym_filter_entry == NULL ||
@@ -190,7 +190,9 @@ static void perf_top__record_precise_ip(struct perf_top *top,
                return;
 
        ip = he->ms.map->map_ip(he->ms.map, ip);
-       err = hist_entry__inc_addr_samples(he, counter, ip);
+
+       if (ui__has_annotation())
+               err = hist_entry__inc_addr_samples(he, counter, ip);
 
        pthread_mutex_unlock(&notes->lock);
 
@@ -991,6 +993,16 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
        return record_parse_callchain_opt(opt, arg, unset);
 }
 
+static int perf_top_config(const char *var, const char *value, void *cb)
+{
+       struct perf_top *top = cb;
+
+       if (!strcmp(var, "top.call-graph"))
+               return record_parse_callchain(value, &top->record_opts);
+
+       return perf_default_config(var, value, cb);
+}
+
 static int
 parse_percent_limit(const struct option *opt, const char *arg,
                    int unset __maybe_unused)
@@ -1115,6 +1127,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        if (top.evlist == NULL)
                return -ENOMEM;
 
+       perf_config(perf_top_config, &top);
+
        argc = parse_options(argc, argv, options, top_usage, 0);
        if (argc)
                usage_with_options(top_usage, options);
index 896f27047ed6178fd6aed5566863fb4f4c251e84..f954c26de231d2860cf1b70a5ccb6597629137b8 100644 (file)
 # define MADV_UNMERGEABLE      13
 #endif
 
+#ifndef EFD_SEMAPHORE
+# define EFD_SEMAPHORE         1
+#endif
+
 struct tp_field {
        int offset;
        union {
@@ -279,6 +283,11 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
 
 #define SCA_STRARRAY syscall_arg__scnprintf_strarray
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches as soon as the ioctl beautifier
+ *       gets rewritten to support all arches.
+ */
 static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
                                                 struct syscall_arg *arg)
 {
@@ -286,6 +295,7 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
 }
 
 #define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
                                        struct syscall_arg *arg);
@@ -815,7 +825,6 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
        P_SIGNUM(PIPE);
        P_SIGNUM(ALRM);
        P_SIGNUM(TERM);
-       P_SIGNUM(STKFLT);
        P_SIGNUM(CHLD);
        P_SIGNUM(CONT);
        P_SIGNUM(STOP);
@@ -831,6 +840,15 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
        P_SIGNUM(IO);
        P_SIGNUM(PWR);
        P_SIGNUM(SYS);
+#ifdef SIGEMT
+       P_SIGNUM(EMT);
+#endif
+#ifdef SIGSTKFLT
+       P_SIGNUM(STKFLT);
+#endif
+#ifdef SIGSWI
+       P_SIGNUM(SWI);
+#endif
        default: break;
        }
 
@@ -839,6 +857,10 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
 
 #define SCA_SIGNUM syscall_arg__scnprintf_signum
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches.
+ */
 #define TCGETS         0x5401
 
 static const char *tioctls[] = {
@@ -860,6 +882,7 @@ static const char *tioctls[] = {
 };
 
 static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
+#endif /* defined(__i386__) || defined(__x86_64__) */
 
 #define STRARRAY(arg, name, array) \
          .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
@@ -941,9 +964,16 @@ static struct syscall_fmt {
        { .name     = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
        { .name     = "ioctl",      .errmsg = true,
          .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * FIXME: Make this available to all arches.
+ */
                             [1] = SCA_STRHEXARRAY, /* cmd */
                             [2] = SCA_HEX, /* arg */ },
          .arg_parm      = { [1] = &strarray__tioctls, /* cmd */ }, },
+#else
+                            [2] = SCA_HEX, /* arg */ }, },
+#endif
        { .name     = "kill",       .errmsg = true,
          .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
        { .name     = "linkat",     .errmsg = true,
index c48d44958172b7dd8f75634ece4d909ae2d5b15b..c23418225c2c806086012b982faf7769f64efd98 100644 (file)
@@ -59,6 +59,18 @@ ifeq ($(NO_PERF_REGS),0)
   CFLAGS += -DHAVE_PERF_REGS_SUPPORT
 endif
 
+ifndef NO_LIBELF
+  # for linking with debug library, run like:
+  # make DEBUG=1 LIBDW_DIR=/opt/libdw/
+  ifdef LIBDW_DIR
+    LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
+    LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
+
+    FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
+    FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
+  endif
+endif
+
 # include ARCH specific config
 -include $(src-perf)/arch/$(ARCH)/Makefile
 
@@ -147,7 +159,35 @@ CORE_FEATURE_TESTS =                       \
        libunwind                       \
        on-exit                         \
        stackprotector-all              \
-       timerfd
+       timerfd                         \
+       libdw-dwarf-unwind
+
+LIB_FEATURE_TESTS =                    \
+       dwarf                           \
+       glibc                           \
+       gtk2                            \
+       libaudit                        \
+       libbfd                          \
+       libelf                          \
+       libnuma                         \
+       libperl                         \
+       libpython                       \
+       libslang                        \
+       libunwind                       \
+       libdw-dwarf-unwind
+
+VF_FEATURE_TESTS =                     \
+       backtrace                       \
+       fortify-source                  \
+       gtk2-infobar                    \
+       libelf-getphdrnum               \
+       libelf-mmap                     \
+       libpython-version               \
+       on-exit                         \
+       stackprotector-all              \
+       timerfd                         \
+       libunwind-debug-frame           \
+       bionic
 
 # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
 # If in the future we need per-feature checks/flags for features not
@@ -160,17 +200,6 @@ endef
 
 $(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
 
-#
-# So here we detect whether test-all was rebuilt, to be able
-# to skip the print-out of the long features list if the file
-# existed before and after it was built:
-#
-ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),)
-  test-all-failed := 1
-else
-  test-all-failed := 0
-endif
-
 #
 # Special fast-path for the 'all features are available' case:
 #
@@ -180,15 +209,6 @@ $(call feature_check,all,$(MSG))
 # Just in case the build freshly failed, make sure we print the
 # feature matrix:
 #
-ifeq ($(feature-all), 0)
-  test-all-failed := 1
-endif
-
-ifeq ($(test-all-failed),1)
-  $(info )
-  $(info Auto-detecting system features:)
-endif
-
 ifeq ($(feature-all), 1)
   #
   # test-all.c passed - just set all the core feature flags to 1:
@@ -199,27 +219,6 @@ else
   $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
 endif
 
-#
-# Print the result of the feature test:
-#
-feature_print = $(eval $(feature_print_code)) $(info $(MSG))
-
-define feature_print_code
-  ifeq ($(feature-$(1)), 1)
-    MSG = $(shell printf '...%30s: [ \033[32mon\033[m  ]' $(1))
-  else
-    MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
-  endif
-endef
-
-#
-# Only print out our features if we rebuilt the testcases or if a test failed:
-#
-ifeq ($(test-all-failed), 1)
-  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
-  $(info )
-endif
-
 ifeq ($(feature-stackprotector-all), 1)
   CFLAGS += -fstack-protector-all
 endif
@@ -264,6 +263,7 @@ ifdef NO_LIBELF
   NO_DWARF := 1
   NO_DEMANGLE := 1
   NO_LIBUNWIND := 1
+  NO_LIBDW_DWARF_UNWIND := 1
 else
   ifeq ($(feature-libelf), 0)
     ifeq ($(feature-glibc), 1)
@@ -282,13 +282,12 @@ else
       msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
     endif
   else
-    # for linking with debug library, run like:
-    # make DEBUG=1 LIBDW_DIR=/opt/libdw/
-    ifdef LIBDW_DIR
-      LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
-      LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
+    ifndef NO_LIBDW_DWARF_UNWIND
+      ifneq ($(feature-libdw-dwarf-unwind),1)
+        NO_LIBDW_DWARF_UNWIND := 1
+        msg := $(warning No libdw DWARF unwind found, Please install elfutils-devel/libdw-dev >= 0.158 and/or set LIBDW_DIR);
+      endif
     endif
-
     ifneq ($(feature-dwarf), 1)
       msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
       NO_DWARF := 1
@@ -324,25 +323,51 @@ endif # NO_LIBELF
 
 ifndef NO_LIBUNWIND
   ifneq ($(feature-libunwind), 1)
-    msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
+    msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
     NO_LIBUNWIND := 1
+  endif
+endif
+
+dwarf-post-unwind := 1
+dwarf-post-unwind-text := BUG
+
+# setup DWARF post unwinder
+ifdef NO_LIBUNWIND
+  ifdef NO_LIBDW_DWARF_UNWIND
+    msg := $(warning Disabling post unwind, no support found.);
+    dwarf-post-unwind := 0
   else
-    ifeq ($(ARCH),arm)
-      $(call feature_check,libunwind-debug-frame)
-      ifneq ($(feature-libunwind-debug-frame), 1)
-        msg := $(warning No debug_frame support found in libunwind);
-        CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
-      endif
-    else
-      # non-ARM has no dwarf_find_debug_frame() function:
+    dwarf-post-unwind-text := libdw
+  endif
+else
+  dwarf-post-unwind-text := libunwind
+  # Enable libunwind support by default.
+  ifndef NO_LIBDW_DWARF_UNWIND
+    NO_LIBDW_DWARF_UNWIND := 1
+  endif
+endif
+
+ifeq ($(dwarf-post-unwind),1)
+  CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
+else
+  NO_DWARF_UNWIND := 1
+endif
+
+ifndef NO_LIBUNWIND
+  ifeq ($(ARCH),arm)
+    $(call feature_check,libunwind-debug-frame)
+    ifneq ($(feature-libunwind-debug-frame), 1)
+      msg := $(warning No debug_frame support found in libunwind);
       CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
     endif
-
-    CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
-    EXTLIBS += $(LIBUNWIND_LIBS)
-    CFLAGS += $(LIBUNWIND_CFLAGS)
-    LDFLAGS += $(LIBUNWIND_LDFLAGS)
-  endif # ifneq ($(feature-libunwind), 1)
+  else
+    # non-ARM has no dwarf_find_debug_frame() function:
+    CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
+  endif
+  CFLAGS  += -DHAVE_LIBUNWIND_SUPPORT
+  EXTLIBS += $(LIBUNWIND_LIBS)
+  CFLAGS  += $(LIBUNWIND_CFLAGS)
+  LDFLAGS += $(LIBUNWIND_LDFLAGS)
 endif
 
 ifndef NO_LIBAUDIT
@@ -478,7 +503,7 @@ else
 endif
 
 ifeq ($(feature-libbfd), 1)
-  EXTLIBS += -lbfd
+  EXTLIBS += -lbfd -lz -liberty
 endif
 
 ifdef NO_DEMANGLE
@@ -602,3 +627,84 @@ ifdef DESTDIR
 plugindir=$(libdir)/traceevent/plugins
 plugindir_SQ= $(subst ','\'',$(plugindir))
 endif
+
+#
+# Print the result of the feature test:
+#
+feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
+
+define feature_print_status_code
+  ifeq ($(feature-$(1)), 1)
+    MSG = $(shell printf '...%30s: [ \033[32mon\033[m  ]' $(1))
+  else
+    MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
+  endif
+endef
+
+feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
+define feature_print_var_code
+    MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
+endef
+
+feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
+define feature_print_text_code
+    MSG = $(shell printf '...%30s: %s' $(1) $(2))
+endef
+
+PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
+PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
+
+ifeq ($(dwarf-post-unwind),1)
+  PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
+endif
+
+# The $(display_lib) controls the default detection message
+# output. It's set if:
+# - detected features differes from stored features from
+#   last build (in PERF-FEATURES file)
+# - one of the $(LIB_FEATURE_TESTS) is not detected
+# - VF is enabled
+
+ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
+  $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
+  display_lib := 1
+endif
+
+feature_check = $(eval $(feature_check_code))
+define feature_check_code
+  ifneq ($(feature-$(1)), 1)
+    display_lib := 1
+  endif
+endef
+
+$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
+
+ifeq ($(VF),1)
+  display_lib := 1
+  display_vf := 1
+endif
+
+ifeq ($(display_lib),1)
+  $(info )
+  $(info Auto-detecting system features:)
+  $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
+
+  ifeq ($(dwarf-post-unwind),1)
+    $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
+  endif
+endif
+
+ifeq ($(display_vf),1)
+  $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
+  $(info )
+  $(call feature_print_var,prefix)
+  $(call feature_print_var,bindir)
+  $(call feature_print_var,libdir)
+  $(call feature_print_var,sysconfdir)
+  $(call feature_print_var,LIBUNWIND_DIR)
+  $(call feature_print_var,LIBDW_DIR)
+endif
+
+ifeq ($(display_lib),1)
+  $(info )
+endif
index 12e551346fa6414d7b85c69fcee0b224283fdc0c..2da103c53f892762b0ad634e1d60669a7c4b5b8a 100644 (file)
@@ -26,7 +26,8 @@ FILES=                                        \
        test-libunwind-debug-frame.bin  \
        test-on-exit.bin                \
        test-stackprotector-all.bin     \
-       test-timerfd.bin
+       test-timerfd.bin                \
+       test-libdw-dwarf-unwind.bin
 
 CC := $(CROSS_COMPILE)gcc -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -121,7 +122,7 @@ test-libpython-version.bin:
        $(BUILD) $(FLAGS_PYTHON_EMBED)
 
 test-libbfd.bin:
-       $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
+       $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
 
 test-liberty.bin:
        $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
@@ -141,6 +142,9 @@ test-backtrace.bin:
 test-timerfd.bin:
        $(BUILD)
 
+test-libdw-dwarf-unwind.bin:
+       $(BUILD)
+
 -include *.d
 
 ###############################
index 9b8a544155bbdf2a628f21f400dda8e65f9d51a7..fc37eb3ca17b9121c60ae47133b540896700756c 100644 (file)
 # include "test-stackprotector-all.c"
 #undef main
 
+#define main main_test_libdw_dwarf_unwind
+# include "test-libdw-dwarf-unwind.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -111,6 +115,7 @@ int main(int argc, char *argv[])
        main_test_libnuma();
        main_test_timerfd();
        main_test_stackprotector_all();
+       main_test_libdw_dwarf_unwind();
 
        return 0;
 }
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
new file mode 100644 (file)
index 0000000..f676a3f
--- /dev/null
@@ -0,0 +1,13 @@
+
+#include <elfutils/libdwfl.h>
+
+int main(void)
+{
+       /*
+        * This function is guarded via: __nonnull_attribute__ (1, 2).
+        * Passing '1' as arguments value. This code is never executed,
+        * only compiled.
+        */
+       dwfl_thread_getframes((void *) 1, (void *) 1, NULL);
+       return 0;
+}
index 67e5d0cace85aad7c70c7ba3ac8bbcf95c4d6e10..a28dca2582aa63f38fb2997235ab1818a9a45e42 100644 (file)
@@ -18,7 +18,7 @@ underlying hardware counters.
 Performance counters are accessed via special file descriptors.
 There's one file descriptor per virtual counter used.
 
-The special file descriptor is opened via the perf_event_open()
+The special file descriptor is opened via the sys_perf_event_open()
 system call:
 
    int sys_perf_event_open(struct perf_event_attr *hw_event_uptr,
@@ -82,7 +82,7 @@ machine-specific.
 If 'raw_type' is 0, then the 'type' field says what kind of counter
 this is, with the following encoding:
 
-enum perf_event_types {
+enum perf_type_id {
        PERF_TYPE_HARDWARE              = 0,
        PERF_TYPE_SOFTWARE              = 1,
        PERF_TYPE_TRACEPOINT            = 2,
@@ -95,7 +95,7 @@ specified by 'event_id':
  * Generalized performance counter event types, used by the hw_event.event_id
  * parameter of the sys_perf_event_open() syscall:
  */
-enum hw_event_ids {
+enum perf_hw_id {
        /*
         * Common hardware events, generalized by the kernel:
         */
@@ -129,7 +129,7 @@ software events, selected by 'event_id':
  * physical and sw events of the kernel (and allow the profiling of them as
  * well):
  */
-enum sw_event_ids {
+enum perf_sw_ids {
        PERF_COUNT_SW_CPU_CLOCK         = 0,
        PERF_COUNT_SW_TASK_CLOCK        = 1,
        PERF_COUNT_SW_PAGE_FAULTS       = 2,
@@ -230,7 +230,7 @@ these events are recorded in the ring-buffer (see below).
 The 'comm' bit allows tracking of process comm data on process creation.
 This too is recorded in the ring-buffer (see below).
 
-The 'pid' parameter to the perf_event_open() system call allows the
+The 'pid' parameter to the sys_perf_event_open() system call allows the
 counter to be specific to a task:
 
  pid == 0: if the pid parameter is zero, the counter is attached to the
@@ -260,7 +260,7 @@ The 'flags' parameter is currently unused and must be zero.
 
 The 'group_fd' parameter allows counter "groups" to be set up.  A
 counter group has one counter which is the group "leader".  The leader
-is created first, with group_fd = -1 in the perf_event_open call
+is created first, with group_fd = -1 in the sys_perf_event_open call
 that creates it.  The rest of the group members are created
 subsequently, with group_fd giving the fd of the group leader.
 (A single counter on its own is created with group_fd = -1 and is
@@ -454,7 +454,6 @@ So to start with, in order to add HAVE_PERF_EVENTS to your Kconfig, you
 will need at least this:
        - asm/perf_event.h - a basic stub will suffice at first
        - support for atomic64 types (and associated helper functions)
-       - set_perf_event_pending() implemented
 
 If your architecture does have hardware capabilities, you can override the
 weak stub hw_perf_event_init() to register hardware counters.
index 496e2abb54824e3fbcc937e3cfc267ea3bfa82b0..ae3a57694b6bda9937146c25e291ab9a80929ce7 100644 (file)
@@ -123,7 +123,7 @@ __perf_main ()
                __perfcomp_colon "$evts" "$cur"
        # List subcommands for 'perf kvm'
        elif [[ $prev == "kvm" ]]; then
-               subcmds="top record report diff buildid-list stat"
+               subcmds=$($cmd $prev --list-cmds)
                __perfcomp_colon "$subcmds" "$cur"
        # List long option names
        elif [[ $cur == --* ]];  then
index 7daa806d9050246c336a9121ca8cf7d00c828020..e18a8b5e69531cca4e1fbf889098d779ff14cf4d 100644 (file)
@@ -12,6 +12,9 @@
 #ifndef __NR_perf_event_open
 # define __NR_perf_event_open 336
 #endif
+#ifndef __NR_futex
+# define __NR_futex 240
+#endif
 #endif
 
 #if defined(__x86_64__)
@@ -23,6 +26,9 @@
 #ifndef __NR_perf_event_open
 # define __NR_perf_event_open 298
 #endif
+#ifndef __NR_futex
+# define __NR_futex 202
+#endif
 #endif
 
 #ifdef __powerpc__
 
 #ifdef __aarch64__
 #define mb()           asm volatile("dmb ish" ::: "memory")
-#define wmb()          asm volatile("dmb ishld" ::: "memory")
-#define rmb()          asm volatile("dmb ishst" ::: "memory")
+#define wmb()          asm volatile("dmb ishst" ::: "memory")
+#define rmb()          asm volatile("dmb ishld" ::: "memory")
 #define cpu_relax()    asm volatile("yield" ::: "memory")
 #endif
 
@@ -251,12 +257,14 @@ void pthread__unblock_sigwinch(void);
 enum perf_call_graph_mode {
        CALLCHAIN_NONE,
        CALLCHAIN_FP,
-       CALLCHAIN_DWARF
+       CALLCHAIN_DWARF,
+       CALLCHAIN_MAX
 };
 
 struct record_opts {
        struct target target;
        int          call_graph;
+       bool         call_graph_enabled;
        bool         group;
        bool         inherit_stat;
        bool         no_buffering;
index 1e67437fb4cae5c770087432d248591b05baa033..b11bf8a08430b1c37ea4ac0f70ba2f418986508d 100644 (file)
@@ -115,6 +115,14 @@ static struct test {
                .desc = "Test parsing with no sample_id_all bit set",
                .func = test__parse_no_sample_id_all,
        },
+#if defined(__x86_64__) || defined(__i386__)
+#ifdef HAVE_DWARF_UNWIND_SUPPORT
+       {
+               .desc = "Test dwarf unwind",
+               .func = test__dwarf_unwind,
+       },
+#endif
+#endif
        {
                .func = NULL,
        },
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
new file mode 100644 (file)
index 0000000..c059ee8
--- /dev/null
@@ -0,0 +1,144 @@
+#include <linux/compiler.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "tests.h"
+#include "debug.h"
+#include "machine.h"
+#include "event.h"
+#include "unwind.h"
+#include "perf_regs.h"
+#include "map.h"
+#include "thread.h"
+
+static int mmap_handler(struct perf_tool *tool __maybe_unused,
+                       union perf_event *event,
+                       struct perf_sample *sample __maybe_unused,
+                       struct machine *machine)
+{
+       return machine__process_mmap_event(machine, event, NULL);
+}
+
+static int init_live_machine(struct machine *machine)
+{
+       union perf_event event;
+       pid_t pid = getpid();
+
+       return perf_event__synthesize_mmap_events(NULL, &event, pid, pid,
+                                                 mmap_handler, machine, true);
+}
+
+#define MAX_STACK 6
+
+static int unwind_entry(struct unwind_entry *entry, void *arg)
+{
+       unsigned long *cnt = (unsigned long *) arg;
+       char *symbol = entry->sym ? entry->sym->name : NULL;
+       static const char *funcs[MAX_STACK] = {
+               "test__arch_unwind_sample",
+               "unwind_thread",
+               "krava_3",
+               "krava_2",
+               "krava_1",
+               "test__dwarf_unwind"
+       };
+
+       if (*cnt >= MAX_STACK) {
+               pr_debug("failed: crossed the max stack value %d\n", MAX_STACK);
+               return -1;
+       }
+
+       if (!symbol) {
+               pr_debug("failed: got unresolved address 0x%" PRIx64 "\n",
+                        entry->ip);
+               return -1;
+       }
+
+       pr_debug("got: %s 0x%" PRIx64 "\n", symbol, entry->ip);
+       return strcmp((const char *) symbol, funcs[(*cnt)++]);
+}
+
+__attribute__ ((noinline))
+static int unwind_thread(struct thread *thread, struct machine *machine)
+{
+       struct perf_sample sample;
+       unsigned long cnt = 0;
+       int err = -1;
+
+       memset(&sample, 0, sizeof(sample));
+
+       if (test__arch_unwind_sample(&sample, thread)) {
+               pr_debug("failed to get unwind sample\n");
+               goto out;
+       }
+
+       err = unwind__get_entries(unwind_entry, &cnt, machine, thread,
+                                 &sample, MAX_STACK);
+       if (err)
+               pr_debug("unwind failed\n");
+       else if (cnt != MAX_STACK) {
+               pr_debug("got wrong number of stack entries %lu != %d\n",
+                        cnt, MAX_STACK);
+               err = -1;
+       }
+
+ out:
+       free(sample.user_stack.data);
+       free(sample.user_regs.regs);
+       return err;
+}
+
+__attribute__ ((noinline))
+static int krava_3(struct thread *thread, struct machine *machine)
+{
+       return unwind_thread(thread, machine);
+}
+
+__attribute__ ((noinline))
+static int krava_2(struct thread *thread, struct machine *machine)
+{
+       return krava_3(thread, machine);
+}
+
+__attribute__ ((noinline))
+static int krava_1(struct thread *thread, struct machine *machine)
+{
+       return krava_2(thread, machine);
+}
+
+int test__dwarf_unwind(void)
+{
+       struct machines machines;
+       struct machine *machine;
+       struct thread *thread;
+       int err = -1;
+
+       machines__init(&machines);
+
+       machine = machines__find(&machines, HOST_KERNEL_ID);
+       if (!machine) {
+               pr_err("Could not get machine\n");
+               return -1;
+       }
+
+       if (init_live_machine(machine)) {
+               pr_err("Could not init machine\n");
+               goto out;
+       }
+
+       if (verbose > 1)
+               machine__fprintf(machine, stderr);
+
+       thread = machine__find_thread(machine, getpid(), getpid());
+       if (!thread) {
+               pr_err("Could not get thread\n");
+               goto out;
+       }
+
+       err = krava_1(thread, machine);
+
+ out:
+       machine__delete_threads(machine);
+       machine__exit(machine);
+       machines__exit(&machines);
+       return err;
+}
index 2b6519e0e36f09bdbdeac4865fed851f82a3a1ac..7ccbc7b6ae775e0c2793e77706a0acfaf86f5a27 100644 (file)
@@ -101,6 +101,7 @@ static struct machine *setup_fake_machine(struct machines *machines)
                        .mmap = {
                                .header = { .misc = PERF_RECORD_MISC_USER, },
                                .pid = fake_mmap_info[i].pid,
+                               .tid = fake_mmap_info[i].pid,
                                .start = fake_mmap_info[i].start,
                                .len = 0x1000ULL,
                                .pgoff = 0ULL,
index 00544b8b644b3bf28c97e392955bfcdb36a509fb..5daeae1cb4c01b3a87f4c54ee4018199c12aeeb6 100644 (file)
@@ -27,6 +27,7 @@ make_no_ui          := NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
 make_no_demangle    := NO_DEMANGLE=1
 make_no_libelf      := NO_LIBELF=1
 make_no_libunwind   := NO_LIBUNWIND=1
+make_no_libdw_dwarf_unwind := NO_LIBDW_DWARF_UNWIND=1
 make_no_backtrace   := NO_BACKTRACE=1
 make_no_libnuma     := NO_LIBNUMA=1
 make_no_libaudit    := NO_LIBAUDIT=1
@@ -35,8 +36,9 @@ make_tags           := tags
 make_cscope         := cscope
 make_help           := help
 make_doc            := doc
-make_perf_o         := perf.o
-make_util_map_o     := util/map.o
+make_perf_o           := perf.o
+make_util_map_o       := util/map.o
+make_util_pmu_bison_o := util/pmu-bison.o
 make_install        := install
 make_install_bin    := install-bin
 make_install_doc    := install-doc
@@ -49,6 +51,7 @@ make_install_pdf    := install-pdf
 make_minimal        := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
 make_minimal        += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
 make_minimal        += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
+make_minimal        += NO_LIBDW_DWARF_UNWIND=1
 
 # $(run) contains all available tests
 run := make_pure
@@ -65,6 +68,7 @@ run += make_no_ui
 run += make_no_demangle
 run += make_no_libelf
 run += make_no_libunwind
+run += make_no_libdw_dwarf_unwind
 run += make_no_backtrace
 run += make_no_libnuma
 run += make_no_libaudit
@@ -73,6 +77,7 @@ run += make_help
 run += make_doc
 run += make_perf_o
 run += make_util_map_o
+run += make_util_pmu_bison_o
 run += make_install
 run += make_install_bin
 # FIXME 'install-*' commented out till they're fixed
@@ -113,8 +118,9 @@ test_make_doc_O  := $(test_ok)
 
 test_make_python_perf_so := test -f $(PERF)/python/perf.so
 
-test_make_perf_o     := test -f $(PERF)/perf.o
-test_make_util_map_o := test -f $(PERF)/util/map.o
+test_make_perf_o           := test -f $(PERF)/perf.o
+test_make_util_map_o       := test -f $(PERF)/util/map.o
+test_make_util_pmu_bison_o := test -f $(PERF)/util/pmu-bison.o
 
 define test_dest_files
   for file in $(1); do                         \
@@ -167,13 +173,10 @@ test_make_install_info_O := $(test_ok)
 test_make_install_pdf    := $(test_ok)
 test_make_install_pdf_O  := $(test_ok)
 
-# Kbuild tests only
-#test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so
-#test_make_perf_o_O         := test -f $$TMP/tools/perf/perf.o
-#test_make_util_map_o_O     := test -f $$TMP/tools/perf/util/map.o
-
-test_make_perf_o_O     := true
-test_make_util_map_o_O := true
+test_make_python_perf_so_O    := test -f $$TMP_O/python/perf.so
+test_make_perf_o_O            := test -f $$TMP_O/perf.o
+test_make_util_map_o_O        := test -f $$TMP_O/util/map.o
+test_make_util_pmu_bison_o_O := test -f $$TMP_O/util/pmu-bison.o
 
 test_default = test -x $(PERF)/perf
 test = $(if $(test_$1),$(test_$1),$(test_default))
index 4db0ae617d7080cd7c97467a15fbe36d9bcedf30..8605ff5572aeeb402ae8b9c118e5f87439bc70f7 100644 (file)
@@ -2,7 +2,7 @@
 #include "parse-events.h"
 #include "evsel.h"
 #include "evlist.h"
-#include "fs.h"
+#include <api/fs/fs.h>
 #include <api/fs/debugfs.h>
 #include "tests.h"
 #include <linux/hw_breakpoint.h>
index 1b677202638d087b94903f3f395d9fab8ae15bc7..0014d3c8c21cd47d2868cac66bc65253913e888e 100644 (file)
@@ -22,8 +22,8 @@
 } while (0)
 
 static bool samples_same(const struct perf_sample *s1,
-                        const struct perf_sample *s2, u64 type, u64 regs_user,
-                        u64 read_format)
+                        const struct perf_sample *s2,
+                        u64 type, u64 read_format)
 {
        size_t i;
 
@@ -95,8 +95,9 @@ static bool samples_same(const struct perf_sample *s1,
        }
 
        if (type & PERF_SAMPLE_REGS_USER) {
-               size_t sz = hweight_long(regs_user) * sizeof(u64);
+               size_t sz = hweight_long(s1->user_regs.mask) * sizeof(u64);
 
+               COMP(user_regs.mask);
                COMP(user_regs.abi);
                if (s1->user_regs.abi &&
                    (!s1->user_regs.regs || !s2->user_regs.regs ||
@@ -174,6 +175,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
                .branch_stack   = &branch_stack.branch_stack,
                .user_regs      = {
                        .abi    = PERF_SAMPLE_REGS_ABI_64,
+                       .mask   = sample_regs_user,
                        .regs   = user_regs,
                },
                .user_stack     = {
@@ -201,8 +203,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
                sample.read.one.id    = 99;
        }
 
-       sz = perf_event__sample_event_size(&sample, sample_type,
-                                          sample_regs_user, read_format);
+       sz = perf_event__sample_event_size(&sample, sample_type, read_format);
        bufsz = sz + 4096; /* Add a bit for overrun checking */
        event = malloc(bufsz);
        if (!event) {
@@ -215,8 +216,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
        event->header.misc = 0;
        event->header.size = sz;
 
-       err = perf_event__synthesize_sample(event, sample_type,
-                                           sample_regs_user, read_format,
+       err = perf_event__synthesize_sample(event, sample_type, read_format,
                                            &sample, false);
        if (err) {
                pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
@@ -244,8 +244,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
                goto out_free;
        }
 
-       if (!samples_same(&sample, &sample_out, sample_type,
-                         sample_regs_user, read_format)) {
+       if (!samples_same(&sample, &sample_out, sample_type, read_format)) {
                pr_debug("parsing failed for sample_type %#"PRIx64"\n",
                         sample_type);
                goto out_free;
index e0ac713857ba5708fee69a8b1000cd81d9ae0a76..a24795ca002db3a25742ee324fca6bc6d74e8e14 100644 (file)
@@ -40,5 +40,14 @@ int test__code_reading(void);
 int test__sample_parsing(void);
 int test__keep_tracking(void);
 int test__parse_no_sample_id_all(void);
+int test__dwarf_unwind(void);
 
+#if defined(__x86_64__) || defined(__i386__)
+#ifdef HAVE_DWARF_UNWIND_SUPPORT
+struct thread;
+struct perf_sample;
+int test__arch_unwind_sample(struct perf_sample *sample,
+                            struct thread *thread);
+#endif
+#endif
 #endif /* TESTS_H */
index 2bd13edcbc1760b9d1428ece9f708ad5957e617e..3d9088003a5b6d16da0038d0abbfa1fc427ed65b 100644 (file)
@@ -26,7 +26,6 @@ int test__vmlinux_matches_kallsyms(void)
        struct map *kallsyms_map, *vmlinux_map;
        struct machine kallsyms, vmlinux;
        enum map_type type = MAP__FUNCTION;
-       struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
        u64 mem_start, mem_end;
 
        /*
@@ -70,14 +69,6 @@ int test__vmlinux_matches_kallsyms(void)
         */
        kallsyms_map = machine__kernel_map(&kallsyms, type);
 
-       sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
-       if (sym == NULL) {
-               pr_debug("dso__find_symbol_by_name ");
-               goto out;
-       }
-
-       ref_reloc_sym.addr = UM(sym->start);
-
        /*
         * Step 5:
         *
@@ -89,7 +80,6 @@ int test__vmlinux_matches_kallsyms(void)
        }
 
        vmlinux_map = machine__kernel_map(&vmlinux, type);
-       map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
 
        /*
         * Step 6:
index b720b92eba6eb95cc7dd9bd4a57693f0a79d91b9..7ec871af3f6f8c5cc4796f40c14c801aa3ba3943 100644 (file)
@@ -587,95 +587,52 @@ struct hpp_arg {
        bool current_entry;
 };
 
-static int __hpp__color_callchain(struct hpp_arg *arg)
+static int __hpp__overhead_callback(struct perf_hpp *hpp, bool front)
 {
-       if (!symbol_conf.use_callchain)
-               return 0;
-
-       slsmg_printf("%c ", arg->folded_sign);
-       return 2;
-}
-
-static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
-                           u64 (*get_field)(struct hist_entry *),
-                           int (*callchain_cb)(struct hpp_arg *))
-{
-       int ret = 0;
-       double percent = 0.0;
-       struct hists *hists = he->hists;
        struct hpp_arg *arg = hpp->ptr;
 
-       if (hists->stats.total_period)
-               percent = 100.0 * get_field(he) / hists->stats.total_period;
-
-       ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
-
-       if (callchain_cb)
-               ret += callchain_cb(arg);
-
-       ret += scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
-       slsmg_printf("%s", hpp->buf);
-
-       if (symbol_conf.event_group) {
-               int prev_idx, idx_delta;
-               struct perf_evsel *evsel = hists_to_evsel(hists);
-               struct hist_entry *pair;
-               int nr_members = evsel->nr_members;
-
-               if (nr_members <= 1)
-                       goto out;
+       if (arg->current_entry && arg->b->navkeypressed)
+               ui_browser__set_color(arg->b, HE_COLORSET_SELECTED);
+       else
+               ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
 
-               prev_idx = perf_evsel__group_idx(evsel);
+       if (front) {
+               if (!symbol_conf.use_callchain)
+                       return 0;
 
-               list_for_each_entry(pair, &he->pairs.head, pairs.node) {
-                       u64 period = get_field(pair);
-                       u64 total = pair->hists->stats.total_period;
+               slsmg_printf("%c ", arg->folded_sign);
+               return 2;
+       }
 
-                       if (!total)
-                               continue;
+       return 0;
+}
 
-                       evsel = hists_to_evsel(pair->hists);
-                       idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
+static int __hpp__color_callback(struct perf_hpp *hpp, bool front __maybe_unused)
+{
+       struct hpp_arg *arg = hpp->ptr;
 
-                       while (idx_delta--) {
-                               /*
-                                * zero-fill group members in the middle which
-                                * have no sample
-                                */
-                               ui_browser__set_percent_color(arg->b, 0.0,
-                                                       arg->current_entry);
-                               ret += scnprintf(hpp->buf, hpp->size,
-                                                " %6.2f%%", 0.0);
-                               slsmg_printf("%s", hpp->buf);
-                       }
+       if (!arg->current_entry || !arg->b->navkeypressed)
+               ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
+       return 0;
+}
 
-                       percent = 100.0 * period / total;
-                       ui_browser__set_percent_color(arg->b, percent,
-                                                     arg->current_entry);
-                       ret += scnprintf(hpp->buf, hpp->size,
-                                        " %6.2f%%", percent);
-                       slsmg_printf("%s", hpp->buf);
+static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
+{
+       struct hpp_arg *arg = hpp->ptr;
+       int ret;
+       va_list args;
+       double percent;
 
-                       prev_idx = perf_evsel__group_idx(evsel);
-               }
+       va_start(args, fmt);
+       percent = va_arg(args, double);
+       va_end(args);
 
-               idx_delta = nr_members - prev_idx - 1;
+       ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
 
-               while (idx_delta--) {
-                       /*
-                        * zero-fill group members at last which have no sample
-                        */
-                       ui_browser__set_percent_color(arg->b, 0.0,
-                                                     arg->current_entry);
-                       ret += scnprintf(hpp->buf, hpp->size,
-                                        " %6.2f%%", 0.0);
-                       slsmg_printf("%s", hpp->buf);
-               }
-       }
-out:
-       if (!arg->current_entry || !arg->b->navkeypressed)
-               ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
+       ret = scnprintf(hpp->buf, hpp->size, fmt, percent);
+       slsmg_printf("%s", hpp->buf);
 
+       advance_hpp(hpp, ret);
        return ret;
 }
 
@@ -690,14 +647,15 @@ hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\
                                struct perf_hpp *hpp,                   \
                                struct hist_entry *he)                  \
 {                                                                      \
-       return __hpp__color_fmt(hpp, he, __hpp_get_##_field, _cb);      \
+       return __hpp__fmt(hpp, he, __hpp_get_##_field, _cb, " %6.2f%%", \
+                         __hpp__slsmg_color_printf, true);             \
 }
 
-__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__color_callchain)
-__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, NULL)
-__HPP_COLOR_PERCENT_FN(overhead_us, period_us, NULL)
-__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, NULL)
-__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, NULL)
+__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__overhead_callback)
+__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, __hpp__color_callback)
+__HPP_COLOR_PERCENT_FN(overhead_us, period_us, __hpp__color_callback)
+__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, __hpp__color_callback)
+__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, __hpp__color_callback)
 
 #undef __HPP_COLOR_PERCENT_FN
 
index 5b95c44f34354215ba597c19d736d3e63c559d1e..e395ef9b0ae00494187c089fde8c6b6a7a5259c4 100644 (file)
@@ -8,16 +8,24 @@
 
 #define MAX_COLUMNS                    32
 
-static int __percent_color_snprintf(char *buf, size_t size, double percent)
+static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
 {
        int ret = 0;
+       va_list args;
+       double percent;
        const char *markup;
+       char *buf = hpp->buf;
+       size_t size = hpp->size;
+
+       va_start(args, fmt);
+       percent = va_arg(args, double);
+       va_end(args);
 
        markup = perf_gtk__get_percent_color(percent);
        if (markup)
                ret += scnprintf(buf, size, markup);
 
-       ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent);
+       ret += scnprintf(buf + ret, size - ret, fmt, percent);
 
        if (markup)
                ret += scnprintf(buf + ret, size - ret, "</span>");
@@ -25,66 +33,6 @@ static int __percent_color_snprintf(char *buf, size_t size, double percent)
        return ret;
 }
 
-
-static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
-                           u64 (*get_field)(struct hist_entry *))
-{
-       int ret;
-       double percent = 0.0;
-       struct hists *hists = he->hists;
-       struct perf_evsel *evsel = hists_to_evsel(hists);
-
-       if (hists->stats.total_period)
-               percent = 100.0 * get_field(he) / hists->stats.total_period;
-
-       ret = __percent_color_snprintf(hpp->buf, hpp->size, percent);
-
-       if (perf_evsel__is_group_event(evsel)) {
-               int prev_idx, idx_delta;
-               struct hist_entry *pair;
-               int nr_members = evsel->nr_members;
-
-               prev_idx = perf_evsel__group_idx(evsel);
-
-               list_for_each_entry(pair, &he->pairs.head, pairs.node) {
-                       u64 period = get_field(pair);
-                       u64 total = pair->hists->stats.total_period;
-
-                       evsel = hists_to_evsel(pair->hists);
-                       idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
-
-                       while (idx_delta--) {
-                               /*
-                                * zero-fill group members in the middle which
-                                * have no sample
-                                */
-                               ret += __percent_color_snprintf(hpp->buf + ret,
-                                                               hpp->size - ret,
-                                                               0.0);
-                       }
-
-                       percent = 100.0 * period / total;
-                       ret += __percent_color_snprintf(hpp->buf + ret,
-                                                       hpp->size - ret,
-                                                       percent);
-
-                       prev_idx = perf_evsel__group_idx(evsel);
-               }
-
-               idx_delta = nr_members - prev_idx - 1;
-
-               while (idx_delta--) {
-                       /*
-                        * zero-fill group members at last which have no sample
-                        */
-                       ret += __percent_color_snprintf(hpp->buf + ret,
-                                                       hpp->size - ret,
-                                                       0.0);
-               }
-       }
-       return ret;
-}
-
 #define __HPP_COLOR_PERCENT_FN(_type, _field)                                  \
 static u64 he_get_##_field(struct hist_entry *he)                              \
 {                                                                              \
@@ -95,7 +43,8 @@ static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,
                                       struct perf_hpp *hpp,                    \
                                       struct hist_entry *he)                   \
 {                                                                              \
-       return __hpp__color_fmt(hpp, he, he_get_##_field);                      \
+       return __hpp__fmt(hpp, he, he_get_##_field, NULL, " %6.2f%%",           \
+                         __percent_color_snprintf, true);                      \
 }
 
 __HPP_COLOR_PERCENT_FN(overhead, period)
@@ -216,7 +165,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
        struct perf_hpp hpp = {
                .buf            = s,
                .size           = sizeof(s),
-               .ptr            = hists_to_evsel(hists),
        };
 
        nr_cols = 0;
@@ -243,7 +191,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
        col_idx = 0;
 
        perf_hpp__for_each_format(fmt) {
-               fmt->header(fmt, &hpp);
+               fmt->header(fmt, &hpp, hists_to_evsel(hists));
 
                gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
                                                            -1, ltrim(s),
index 78f4c92e9b73c1c55e5699bce4b628f551348beb..0f403b83e9d1c1da19b7be850c7c49ffba0b074d 100644 (file)
@@ -8,16 +8,27 @@
 
 /* hist period print (hpp) functions */
 
-typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...);
-
-static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
-                     u64 (*get_field)(struct hist_entry *),
-                     const char *fmt, hpp_snprint_fn print_fn,
-                     bool fmt_percent)
+#define hpp__call_print_fn(hpp, fn, fmt, ...)                  \
+({                                                             \
+       int __ret = fn(hpp, fmt, ##__VA_ARGS__);                \
+       advance_hpp(hpp, __ret);                                \
+       __ret;                                                  \
+})
+
+int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
+              hpp_field_fn get_field, hpp_callback_fn callback,
+              const char *fmt, hpp_snprint_fn print_fn, bool fmt_percent)
 {
-       int ret;
+       int ret = 0;
        struct hists *hists = he->hists;
        struct perf_evsel *evsel = hists_to_evsel(hists);
+       char *buf = hpp->buf;
+       size_t size = hpp->size;
+
+       if (callback) {
+               ret = callback(hpp, true);
+               advance_hpp(hpp, ret);
+       }
 
        if (fmt_percent) {
                double percent = 0.0;
@@ -26,9 +37,9 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
                        percent = 100.0 * get_field(he) /
                                  hists->stats.total_period;
 
-               ret = print_fn(hpp->buf, hpp->size, fmt, percent);
+               ret += hpp__call_print_fn(hpp, print_fn, fmt, percent);
        } else
-               ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he));
+               ret += hpp__call_print_fn(hpp, print_fn, fmt, get_field(he));
 
        if (perf_evsel__is_group_event(evsel)) {
                int prev_idx, idx_delta;
@@ -52,16 +63,22 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
                                 * zero-fill group members in the middle which
                                 * have no sample
                                 */
-                               ret += print_fn(hpp->buf + ret, hpp->size - ret,
-                                               fmt, 0);
+                               if (fmt_percent) {
+                                       ret += hpp__call_print_fn(hpp, print_fn,
+                                                                 fmt, 0.0);
+                               } else {
+                                       ret += hpp__call_print_fn(hpp, print_fn,
+                                                                 fmt, 0ULL);
+                               }
                        }
 
-                       if (fmt_percent)
-                               ret += print_fn(hpp->buf + ret, hpp->size - ret,
-                                               fmt, 100.0 * period / total);
-                       else
-                               ret += print_fn(hpp->buf + ret, hpp->size - ret,
-                                               fmt, period);
+                       if (fmt_percent) {
+                               ret += hpp__call_print_fn(hpp, print_fn, fmt,
+                                                         100.0 * period / total);
+                       } else {
+                               ret += hpp__call_print_fn(hpp, print_fn, fmt,
+                                                         period);
+                       }
 
                        prev_idx = perf_evsel__group_idx(evsel);
                }
@@ -72,41 +89,87 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
                        /*
                         * zero-fill group members at last which have no sample
                         */
-                       ret += print_fn(hpp->buf + ret, hpp->size - ret,
-                                       fmt, 0);
+                       if (fmt_percent) {
+                               ret += hpp__call_print_fn(hpp, print_fn,
+                                                         fmt, 0.0);
+                       } else {
+                               ret += hpp__call_print_fn(hpp, print_fn,
+                                                         fmt, 0ULL);
+                       }
                }
        }
+
+       if (callback) {
+               int __ret = callback(hpp, false);
+
+               advance_hpp(hpp, __ret);
+               ret += __ret;
+       }
+
+       /*
+        * Restore original buf and size as it's where caller expects
+        * the result will be saved.
+        */
+       hpp->buf = buf;
+       hpp->size = size;
+
        return ret;
 }
 
 #define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width)          \
 static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused,        \
-                              struct perf_hpp *hpp)                    \
+                              struct perf_hpp *hpp,                    \
+                              struct perf_evsel *evsel)                \
 {                                                                      \
        int len = _min_width;                                           \
                                                                        \
-       if (symbol_conf.event_group) {                                  \
-               struct perf_evsel *evsel = hpp->ptr;                    \
-                                                                       \
+       if (symbol_conf.event_group)                                    \
                len = max(len, evsel->nr_members * _unit_width);        \
-       }                                                               \
+                                                                       \
        return scnprintf(hpp->buf, hpp->size, "%*s", len, _str);        \
 }
 
 #define __HPP_WIDTH_FN(_type, _min_width, _unit_width)                         \
 static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
-                             struct perf_hpp *hpp __maybe_unused)      \
+                             struct perf_hpp *hpp __maybe_unused,      \
+                             struct perf_evsel *evsel)                 \
 {                                                                      \
        int len = _min_width;                                           \
                                                                        \
-       if (symbol_conf.event_group) {                                  \
-               struct perf_evsel *evsel = hpp->ptr;                    \
-                                                                       \
+       if (symbol_conf.event_group)                                    \
                len = max(len, evsel->nr_members * _unit_width);        \
-       }                                                               \
+                                                                       \
        return len;                                                     \
 }
 
+static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
+{
+       va_list args;
+       ssize_t ssize = hpp->size;
+       double percent;
+       int ret;
+
+       va_start(args, fmt);
+       percent = va_arg(args, double);
+       ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent);
+       va_end(args);
+
+       return (ret >= ssize) ? (ssize - 1) : ret;
+}
+
+static int hpp_entry_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
+{
+       va_list args;
+       ssize_t ssize = hpp->size;
+       int ret;
+
+       va_start(args, fmt);
+       ret = vsnprintf(hpp->buf, hpp->size, fmt, args);
+       va_end(args);
+
+       return (ret >= ssize) ? (ssize - 1) : ret;
+}
+
 #define __HPP_COLOR_PERCENT_FN(_type, _field)                                  \
 static u64 he_get_##_field(struct hist_entry *he)                              \
 {                                                                              \
@@ -116,8 +179,8 @@ static u64 he_get_##_field(struct hist_entry *he)                           \
 static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,         \
                              struct perf_hpp *hpp, struct hist_entry *he)      \
 {                                                                              \
-       return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%",                 \
-                         percent_color_snprintf, true);                        \
+       return __hpp__fmt(hpp, he, he_get_##_field, NULL, " %6.2f%%",           \
+                         hpp_color_scnprintf, true);                           \
 }
 
 #define __HPP_ENTRY_PERCENT_FN(_type, _field)                                  \
@@ -125,8 +188,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused,             \
                              struct perf_hpp *hpp, struct hist_entry *he)      \
 {                                                                              \
        const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%";         \
-       return __hpp__fmt(hpp, he, he_get_##_field, fmt,                        \
-                         scnprintf, true);                                     \
+       return __hpp__fmt(hpp, he, he_get_##_field, NULL, fmt,                  \
+                         hpp_entry_scnprintf, true);                           \
 }
 
 #define __HPP_ENTRY_RAW_FN(_type, _field)                                      \
@@ -139,7 +202,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused,             \
                              struct perf_hpp *hpp, struct hist_entry *he)      \
 {                                                                              \
        const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64;    \
-       return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \
+       return __hpp__fmt(hpp, he, he_get_raw_##_field, NULL, fmt,              \
+                         hpp_entry_scnprintf, false);                          \
 }
 
 #define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width)  \
@@ -263,15 +327,13 @@ unsigned int hists__sort_list_width(struct hists *hists)
        struct perf_hpp_fmt *fmt;
        struct sort_entry *se;
        int i = 0, ret = 0;
-       struct perf_hpp dummy_hpp = {
-               .ptr    = hists_to_evsel(hists),
-       };
+       struct perf_hpp dummy_hpp;
 
        perf_hpp__for_each_format(fmt) {
                if (i)
                        ret += 2;
 
-               ret += fmt->width(fmt, &dummy_hpp);
+               ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
        }
 
        list_for_each_entry(se, &hist_entry__sort_list, list)
index 831fbb77d1ff010ab786ff12ee747aaf8873bcbe..d59893edf03130549079a748ffe17440ab8231a9 100644 (file)
@@ -306,12 +306,6 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
        return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
 }
 
-static inline void advance_hpp(struct perf_hpp *hpp, int inc)
-{
-       hpp->buf  += inc;
-       hpp->size -= inc;
-}
-
 static int hist_entry__period_snprintf(struct perf_hpp *hpp,
                                       struct hist_entry *he)
 {
@@ -385,7 +379,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
        struct perf_hpp dummy_hpp = {
                .buf    = bf,
                .size   = sizeof(bf),
-               .ptr    = hists_to_evsel(hists),
        };
        bool first = true;
        size_t linesz;
@@ -404,7 +397,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                else
                        first = false;
 
-               fmt->header(fmt, &dummy_hpp);
+               fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
                fprintf(fp, "%s", bf);
        }
 
@@ -449,7 +442,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                else
                        first = false;
 
-               width = fmt->width(fmt, &dummy_hpp);
+               width = fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
                for (i = 0; i < width; i++)
                        fprintf(fp, ".");
        }
index 469eb679fb9d09d9e96e8687cc2051fa44f86565..809b4c50beaed3e3a57845919b3a034fe7ab8c9e 100644 (file)
@@ -8,6 +8,8 @@
  */
 
 #include "util.h"
+#include "ui/ui.h"
+#include "sort.h"
 #include "build-id.h"
 #include "color.h"
 #include "cache.h"
@@ -489,7 +491,7 @@ static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 {
        struct annotation *notes;
 
-       if (sym == NULL || use_browser != 1 || !sort__has_sym)
+       if (sym == NULL)
                return 0;
 
        notes = symbol__annotation(sym);
@@ -1234,6 +1236,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
        struct dso *dso = map->dso;
        char *filename;
        const char *d_filename;
+       const char *evsel_name = perf_evsel__name(evsel);
        struct annotation *notes = symbol__annotation(sym);
        struct disasm_line *pos, *queue = NULL;
        u64 start = map__rip_2objdump(map, sym->start);
@@ -1241,7 +1244,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
        int more = 0;
        u64 len;
        int width = 8;
-       int namelen;
+       int namelen, evsel_name_len, graph_dotted_len;
 
        filename = strdup(dso->long_name);
        if (!filename)
@@ -1254,14 +1257,17 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
 
        len = symbol__size(sym);
        namelen = strlen(d_filename);
+       evsel_name_len = strlen(evsel_name);
 
        if (perf_evsel__is_group_event(evsel))
                width *= evsel->nr_members;
 
-       printf(" %-*.*s|        Source code & Disassembly of %s\n",
-              width, width, "Percent", d_filename);
-       printf("-%-*.*s-------------------------------------\n",
-              width+namelen, width+namelen, graph_dotted_line);
+       printf(" %-*.*s|        Source code & Disassembly of %s for %s\n",
+              width, width, "Percent", d_filename, evsel_name);
+
+       graph_dotted_len = width + namelen + evsel_name_len;
+       printf("-%-*.*s-----------------------------------------\n",
+              graph_dotted_len, graph_dotted_len, graph_dotted_line);
 
        if (verbose)
                symbol__annotate_hits(sym, evsel);
@@ -1399,3 +1405,8 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize)
 {
        return symbol__annotate(he->ms.sym, he->ms.map, privsize);
 }
+
+bool ui__has_annotation(void)
+{
+       return use_browser == 1 && sort__has_sym;
+}
index b2aef59d6bb29741dff0dbee40fa0c1d04f1cf65..56ad4f5287dec04bf8e94fe15c814b6abc8b42ee 100644 (file)
@@ -151,6 +151,8 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
 void disasm__purge(struct list_head *head);
 
+bool ui__has_annotation(void);
+
 int symbol__tty_annotate(struct symbol *sym, struct map *map,
                         struct perf_evsel *evsel, bool print_lines,
                         bool full_paths, int min_pcnt, int max_lines);
index a9b48c42e81eb36e34cce24e091be66437270d44..7fe4994eeb638a63f7b52105ad326afa448915ab 100644 (file)
@@ -1,5 +1,5 @@
 #include "util.h"
-#include "fs.h"
+#include <api/fs/fs.h>
 #include "../perf.h"
 #include "cpumap.h"
 #include <assert.h>
index 4045d086d9d957823af08d79db4d8407fb9a460f..64453d63b971212ea3c626eb0d57fbefb62ea236 100644 (file)
@@ -45,8 +45,8 @@ int dso__read_binary_type_filename(const struct dso *dso,
                        debuglink--;
                if (*debuglink == '/')
                        debuglink++;
-               filename__read_debuglink(dso->long_name, debuglink,
-                                        size - (debuglink - filename));
+               ret = filename__read_debuglink(dso->long_name, debuglink,
+                                              size - (debuglink - filename));
                }
                break;
        case DSO_BINARY_TYPE__BUILD_ID_CACHE:
index cd7d6f078cddf618e40e709eab6c1d93750e155a..ab06f1c0365542cc35c000ba90d6879b34070ed6 100644 (file)
@@ -102,6 +102,16 @@ struct dso {
        char             name[0];
 };
 
+/* dso__for_each_symbol - iterate over the symbols of given type
+ *
+ * @dso: the 'struct dso *' in which symbols itereated
+ * @pos: the 'struct symbol *' to use as a loop cursor
+ * @n: the 'struct rb_node *' to use as a temporary storage
+ * @type: the 'enum map_type' type of symbols
+ */
+#define dso__for_each_symbol(dso, pos, n, type)        \
+       symbols__for_each_entry(&(dso)->symbols[(type)], pos, n)
+
 static inline void dso__set_loaded(struct dso *dso, enum map_type type)
 {
        dso->loaded |= (1 << type);
index 1fc1c2f04772fa06b9f7624c9f378e0e2f748d0f..9d12aa6dd485336104068aef0f3c40f8436d10b2 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include "event.h"
 #include "debug.h"
+#include "hist.h"
 #include "machine.h"
 #include "sort.h"
 #include "string.h"
@@ -94,14 +95,10 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
 
 static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
                                         union perf_event *event, pid_t pid,
-                                        int full,
                                         perf_event__handler_t process,
                                         struct machine *machine)
 {
-       char filename[PATH_MAX];
        size_t size;
-       DIR *tasks;
-       struct dirent dirent, *next;
        pid_t tgid;
 
        memset(&event->comm, 0, sizeof(event->comm));
@@ -124,55 +121,35 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
        event->comm.header.size = (sizeof(event->comm) -
                                (sizeof(event->comm.comm) - size) +
                                machine->id_hdr_size);
-       if (!full) {
-               event->comm.tid = pid;
-
-               if (process(tool, event, &synth_sample, machine) != 0)
-                       return -1;
-
-               goto out;
-       }
+       event->comm.tid = pid;
 
-       if (machine__is_default_guest(machine))
-               return 0;
-
-       snprintf(filename, sizeof(filename), "%s/proc/%d/task",
-                machine->root_dir, pid);
-
-       tasks = opendir(filename);
-       if (tasks == NULL) {
-               pr_debug("couldn't open %s\n", filename);
-               return 0;
-       }
+       if (process(tool, event, &synth_sample, machine) != 0)
+               return -1;
 
-       while (!readdir_r(tasks, &dirent, &next) && next) {
-               char *end;
-               pid = strtol(dirent.d_name, &end, 10);
-               if (*end)
-                       continue;
+out:
+       return tgid;
+}
 
-               /* already have tgid; jut want to update the comm */
-               (void) perf_event__get_comm_tgid(pid, event->comm.comm,
-                                        sizeof(event->comm.comm));
+static int perf_event__synthesize_fork(struct perf_tool *tool,
+                                      union perf_event *event, pid_t pid,
+                                      pid_t tgid, perf_event__handler_t process,
+                                      struct machine *machine)
+{
+       memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
 
-               size = strlen(event->comm.comm) + 1;
-               size = PERF_ALIGN(size, sizeof(u64));
-               memset(event->comm.comm + size, 0, machine->id_hdr_size);
-               event->comm.header.size = (sizeof(event->comm) -
-                                         (sizeof(event->comm.comm) - size) +
-                                         machine->id_hdr_size);
+       /* this is really a clone event but we use fork to synthesize it */
+       event->fork.ppid = tgid;
+       event->fork.ptid = tgid;
+       event->fork.pid  = tgid;
+       event->fork.tid  = pid;
+       event->fork.header.type = PERF_RECORD_FORK;
 
-               event->comm.tid = pid;
+       event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
 
-               if (process(tool, event, &synth_sample, machine) != 0) {
-                       tgid = -1;
-                       break;
-               }
-       }
+       if (process(tool, event, &synth_sample, machine) != 0)
+               return -1;
 
-       closedir(tasks);
-out:
-       return tgid;
+       return 0;
 }
 
 int perf_event__synthesize_mmap_events(struct perf_tool *tool,
@@ -324,17 +301,71 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
 
 static int __event__synthesize_thread(union perf_event *comm_event,
                                      union perf_event *mmap_event,
+                                     union perf_event *fork_event,
                                      pid_t pid, int full,
                                          perf_event__handler_t process,
                                      struct perf_tool *tool,
                                      struct machine *machine, bool mmap_data)
 {
-       pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
+       char filename[PATH_MAX];
+       DIR *tasks;
+       struct dirent dirent, *next;
+       pid_t tgid;
+
+       /* special case: only send one comm event using passed in pid */
+       if (!full) {
+               tgid = perf_event__synthesize_comm(tool, comm_event, pid,
+                                                  process, machine);
+
+               if (tgid == -1)
+                       return -1;
+
+               return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
+                                                         process, machine, mmap_data);
+       }
+
+       if (machine__is_default_guest(machine))
+               return 0;
+
+       snprintf(filename, sizeof(filename), "%s/proc/%d/task",
+                machine->root_dir, pid);
+
+       tasks = opendir(filename);
+       if (tasks == NULL) {
+               pr_debug("couldn't open %s\n", filename);
+               return 0;
+       }
+
+       while (!readdir_r(tasks, &dirent, &next) && next) {
+               char *end;
+               int rc = 0;
+               pid_t _pid;
+
+               _pid = strtol(dirent.d_name, &end, 10);
+               if (*end)
+                       continue;
+
+               tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
+                                                  process, machine);
+               if (tgid == -1)
+                       return -1;
+
+               if (_pid == pid) {
+                       /* process the parent's maps too */
+                       rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
+                                               process, machine, mmap_data);
+               } else {
+                       /* only fork the tid's map, to save time */
+                       rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
                                                 process, machine);
-       if (tgid == -1)
-               return -1;
-       return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
-                                                 process, machine, mmap_data);
+               }
+
+               if (rc)
+                       return rc;
+       }
+
+       closedir(tasks);
+       return 0;
 }
 
 int perf_event__synthesize_thread_map(struct perf_tool *tool,
@@ -343,7 +374,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
                                      struct machine *machine,
                                      bool mmap_data)
 {
-       union perf_event *comm_event, *mmap_event;
+       union perf_event *comm_event, *mmap_event, *fork_event;
        int err = -1, thread, j;
 
        comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -354,9 +385,14 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
        if (mmap_event == NULL)
                goto out_free_comm;
 
+       fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
+       if (fork_event == NULL)
+               goto out_free_mmap;
+
        err = 0;
        for (thread = 0; thread < threads->nr; ++thread) {
                if (__event__synthesize_thread(comm_event, mmap_event,
+                                              fork_event,
                                               threads->map[thread], 0,
                                               process, tool, machine,
                                               mmap_data)) {
@@ -382,6 +418,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
                        /* if not, generate events for it */
                        if (need_leader &&
                            __event__synthesize_thread(comm_event, mmap_event,
+                                                      fork_event,
                                                       comm_event->comm.pid, 0,
                                                       process, tool, machine,
                                                       mmap_data)) {
@@ -390,6 +427,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
                        }
                }
        }
+       free(fork_event);
+out_free_mmap:
        free(mmap_event);
 out_free_comm:
        free(comm_event);
@@ -404,9 +443,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
        DIR *proc;
        char proc_path[PATH_MAX];
        struct dirent dirent, *next;
-       union perf_event *comm_event, *mmap_event;
+       union perf_event *comm_event, *mmap_event, *fork_event;
        int err = -1;
 
+       if (machine__is_default_guest(machine))
+               return 0;
+
        comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
        if (comm_event == NULL)
                goto out;
@@ -415,14 +457,15 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
        if (mmap_event == NULL)
                goto out_free_comm;
 
-       if (machine__is_default_guest(machine))
-               return 0;
+       fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
+       if (fork_event == NULL)
+               goto out_free_mmap;
 
        snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
        proc = opendir(proc_path);
 
        if (proc == NULL)
-               goto out_free_mmap;
+               goto out_free_fork;
 
        while (!readdir_r(proc, &dirent, &next) && next) {
                char *end;
@@ -434,12 +477,14 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                 * We may race with exiting thread, so don't stop just because
                 * one thread couldn't be synthesized.
                 */
-               __event__synthesize_thread(comm_event, mmap_event, pid, 1,
-                                          process, tool, machine, mmap_data);
+               __event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
+                                          1, process, tool, machine, mmap_data);
        }
 
        err = 0;
        closedir(proc);
+out_free_fork:
+       free(fork_event);
 out_free_mmap:
        free(mmap_event);
 out_free_comm:
@@ -470,23 +515,32 @@ static int find_symbol_cb(void *arg, const char *name, char type,
        return 1;
 }
 
+u64 kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name)
+{
+       struct process_symbol_args args = { .name = symbol_name, };
+
+       if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
+               return 0;
+
+       return args.start;
+}
+
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
                                       perf_event__handler_t process,
-                                      struct machine *machine,
-                                      const char *symbol_name)
+                                      struct machine *machine)
 {
        size_t size;
-       const char *filename, *mmap_name;
-       char path[PATH_MAX];
+       const char *mmap_name;
        char name_buff[PATH_MAX];
        struct map *map;
+       struct kmap *kmap;
        int err;
        /*
         * We should get this from /sys/kernel/sections/.text, but till that is
         * available use this, and after it is use this as a fallback for older
         * kernels.
         */
-       struct process_symbol_args args = { .name = symbol_name, };
        union perf_event *event = zalloc((sizeof(event->mmap) +
                                          machine->id_hdr_size));
        if (event == NULL) {
@@ -502,30 +556,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
                 * see kernel/perf_event.c __perf_event_mmap
                 */
                event->header.misc = PERF_RECORD_MISC_KERNEL;
-               filename = "/proc/kallsyms";
        } else {
                event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
-               if (machine__is_default_guest(machine))
-                       filename = (char *) symbol_conf.default_guest_kallsyms;
-               else {
-                       sprintf(path, "%s/proc/kallsyms", machine->root_dir);
-                       filename = path;
-               }
-       }
-
-       if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) {
-               free(event);
-               return -ENOENT;
        }
 
        map = machine->vmlinux_maps[MAP__FUNCTION];
+       kmap = map__kmap(map);
        size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
-                       "%s%s", mmap_name, symbol_name) + 1;
+                       "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
        size = PERF_ALIGN(size, sizeof(u64));
        event->mmap.header.type = PERF_RECORD_MMAP;
        event->mmap.header.size = (sizeof(event->mmap) -
                        (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
-       event->mmap.pgoff = args.start;
+       event->mmap.pgoff = kmap->ref_reloc_sym->addr;
        event->mmap.start = map->start;
        event->mmap.len   = map->end - event->mmap.start;
        event->mmap.pid   = machine->pid;
@@ -663,7 +706,7 @@ void thread__find_addr_map(struct thread *thread,
        al->thread = thread;
        al->addr = addr;
        al->cpumode = cpumode;
-       al->filtered = false;
+       al->filtered = 0;
 
        if (machine == NULL) {
                al->map = NULL;
@@ -689,11 +732,11 @@ void thread__find_addr_map(struct thread *thread,
                if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
                        cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
                        !perf_guest)
-                       al->filtered = true;
+                       al->filtered |= (1 << HIST_FILTER__GUEST);
                if ((cpumode == PERF_RECORD_MISC_USER ||
                        cpumode == PERF_RECORD_MISC_KERNEL) &&
                        !perf_host)
-                       al->filtered = true;
+                       al->filtered |= (1 << HIST_FILTER__HOST);
 
                return;
        }
@@ -750,9 +793,6 @@ int perf_event__preprocess_sample(const union perf_event *event,
        if (thread == NULL)
                return -1;
 
-       if (thread__is_filtered(thread))
-               goto out_filtered;
-
        dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
        /*
         * Have we already created the kernel maps for this machine?
@@ -770,6 +810,10 @@ int perf_event__preprocess_sample(const union perf_event *event,
        dump_printf(" ...... dso: %s\n",
                    al->map ? al->map->dso->long_name :
                        al->level == 'H' ? "[hypervisor]" : "<not found>");
+
+       if (thread__is_filtered(thread))
+               al->filtered |= (1 << HIST_FILTER__THREAD);
+
        al->sym = NULL;
        al->cpu = sample->cpu;
 
@@ -781,8 +825,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
                                                  dso->short_name) ||
                               (dso->short_name != dso->long_name &&
                                strlist__has_entry(symbol_conf.dso_list,
-                                                  dso->long_name)))))
-                       goto out_filtered;
+                                                  dso->long_name))))) {
+                       al->filtered |= (1 << HIST_FILTER__DSO);
+               }
 
                al->sym = map__find_symbol(al->map, al->addr,
                                           machine->symbol_filter);
@@ -790,12 +835,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
 
        if (symbol_conf.sym_list &&
                (!al->sym || !strlist__has_entry(symbol_conf.sym_list,
-                                               al->sym->name)))
-               goto out_filtered;
-
-       return 0;
+                                               al->sym->name))) {
+               al->filtered |= (1 << HIST_FILTER__SYMBOL);
+       }
 
-out_filtered:
-       al->filtered = true;
        return 0;
 }
index faf6e219be21f5ec73d85b568592279fb47e1fa1..38457d447a13106360fb60d7b93dd3eab5217f50 100644 (file)
@@ -85,6 +85,7 @@ struct sample_event {
 
 struct regs_dump {
        u64 abi;
+       u64 mask;
        u64 *regs;
 };
 
@@ -214,8 +215,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                                   struct machine *machine, bool mmap_data);
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
                                       perf_event__handler_t process,
-                                      struct machine *machine,
-                                      const char *symbol_name);
+                                      struct machine *machine);
 
 int perf_event__synthesize_modules(struct perf_tool *tool,
                                   perf_event__handler_t process,
@@ -260,9 +260,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
 const char *perf_event__name(unsigned int id);
 
 size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
-                                    u64 sample_regs_user, u64 read_format);
+                                    u64 read_format);
 int perf_event__synthesize_sample(union perf_event *event, u64 type,
-                                 u64 sample_regs_user, u64 read_format,
+                                 u64 read_format,
                                  const struct perf_sample *sample,
                                  bool swapped);
 
@@ -279,4 +279,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
+u64 kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name);
+
 #endif /* __PERF_RECORD_H */
index 55407c594b87f1657e8ff06f8e64ee27ba2662c2..5c28d82b76c472d2107e097656a5d45e4f151536 100644 (file)
@@ -500,6 +500,34 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
        return ret;
 }
 
+static void
+perf_evsel__config_callgraph(struct perf_evsel *evsel,
+                            struct record_opts *opts)
+{
+       bool function = perf_evsel__is_function_event(evsel);
+       struct perf_event_attr *attr = &evsel->attr;
+
+       perf_evsel__set_sample_bit(evsel, CALLCHAIN);
+
+       if (opts->call_graph == CALLCHAIN_DWARF) {
+               if (!function) {
+                       perf_evsel__set_sample_bit(evsel, REGS_USER);
+                       perf_evsel__set_sample_bit(evsel, STACK_USER);
+                       attr->sample_regs_user = PERF_REGS_MASK;
+                       attr->sample_stack_user = opts->stack_dump_size;
+                       attr->exclude_callchain_user = 1;
+               } else {
+                       pr_info("Cannot use DWARF unwind for function trace event,"
+                               " falling back to framepointers.\n");
+               }
+       }
+
+       if (function) {
+               pr_info("Disabling user space callchains for function trace event.\n");
+               attr->exclude_callchain_user = 1;
+       }
+}
+
 /*
  * The enable_on_exec/disabled value strategy:
  *
@@ -595,17 +623,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
                attr->mmap_data = track;
        }
 
-       if (opts->call_graph) {
-               perf_evsel__set_sample_bit(evsel, CALLCHAIN);
-
-               if (opts->call_graph == CALLCHAIN_DWARF) {
-                       perf_evsel__set_sample_bit(evsel, REGS_USER);
-                       perf_evsel__set_sample_bit(evsel, STACK_USER);
-                       attr->sample_regs_user = PERF_REGS_MASK;
-                       attr->sample_stack_user = opts->stack_dump_size;
-                       attr->exclude_callchain_user = 1;
-               }
-       }
+       if (opts->call_graph_enabled)
+               perf_evsel__config_callgraph(evsel, opts);
 
        if (target__has_cpu(&opts->target))
                perf_evsel__set_sample_bit(evsel, CPU);
@@ -1004,7 +1023,7 @@ retry_sample_id:
 
                        group_fd = get_group_fd(evsel, cpu, thread);
 retry_open:
-                       pr_debug2("perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx\n",
+                       pr_debug2("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx\n",
                                  pid, cpus->map[cpu], group_fd, flags);
 
                        FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
@@ -1013,7 +1032,7 @@ retry_open:
                                                                     group_fd, flags);
                        if (FD(evsel, cpu, thread) < 0) {
                                err = -errno;
-                               pr_debug2("perf_event_open failed, error %d\n",
+                               pr_debug2("sys_perf_event_open failed, error %d\n",
                                          err);
                                goto try_fallback;
                        }
@@ -1220,7 +1239,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
        memset(data, 0, sizeof(*data));
        data->cpu = data->pid = data->tid = -1;
        data->stream_id = data->id = data->time = -1ULL;
-       data->period = 1;
+       data->period = evsel->attr.sample_period;
        data->weight = 0;
 
        if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -1396,10 +1415,11 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
                array++;
 
                if (data->user_regs.abi) {
-                       u64 regs_user = evsel->attr.sample_regs_user;
+                       u64 mask = evsel->attr.sample_regs_user;
 
-                       sz = hweight_long(regs_user) * sizeof(u64);
+                       sz = hweight_long(mask) * sizeof(u64);
                        OVERFLOW_CHECK(array, sz, max_size);
+                       data->user_regs.mask = mask;
                        data->user_regs.regs = (u64 *)array;
                        array = (void *)array + sz;
                }
@@ -1451,7 +1471,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
 }
 
 size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
-                                    u64 sample_regs_user, u64 read_format)
+                                    u64 read_format)
 {
        size_t sz, result = sizeof(struct sample_event);
 
@@ -1517,7 +1537,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
        if (type & PERF_SAMPLE_REGS_USER) {
                if (sample->user_regs.abi) {
                        result += sizeof(u64);
-                       sz = hweight_long(sample_regs_user) * sizeof(u64);
+                       sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
                        result += sz;
                } else {
                        result += sizeof(u64);
@@ -1546,7 +1566,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
 }
 
 int perf_event__synthesize_sample(union perf_event *event, u64 type,
-                                 u64 sample_regs_user, u64 read_format,
+                                 u64 read_format,
                                  const struct perf_sample *sample,
                                  bool swapped)
 {
@@ -1687,7 +1707,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
        if (type & PERF_SAMPLE_REGS_USER) {
                if (sample->user_regs.abi) {
                        *array++ = sample->user_regs.abi;
-                       sz = hweight_long(sample_regs_user) * sizeof(u64);
+                       sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
                        memcpy(array, sample->user_regs.regs, sz);
                        array = (void *)array + sz;
                } else {
index f1b325665aae8201b9696b2c3c5a6a64e009ffb7..0c9926cfb292ba2667de9f270fc8103182d857ab 100644 (file)
@@ -315,6 +315,24 @@ static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel)
        return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1;
 }
 
+/**
+ * perf_evsel__is_function_event - Return whether given evsel is a function
+ * trace event
+ *
+ * @evsel - evsel selector to be tested
+ *
+ * Return %true if event is function trace event
+ */
+static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel)
+{
+#define FUNCTION_EVENT "ftrace:function"
+
+       return evsel->name &&
+              !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT));
+
+#undef FUNCTION_EVENT
+}
+
 struct perf_attr_details {
        bool freq;
        bool verbose;
diff --git a/tools/perf/util/fs.c b/tools/perf/util/fs.c
deleted file mode 100644 (file)
index f5be1f2..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-
-/* TODO merge/factor into tools/lib/lk/debugfs.c */
-
-#include "util.h"
-#include "util/fs.h"
-
-static const char * const sysfs__fs_known_mountpoints[] = {
-       "/sys",
-       0,
-};
-
-static const char * const procfs__known_mountpoints[] = {
-       "/proc",
-       0,
-};
-
-struct fs {
-       const char              *name;
-       const char * const      *mounts;
-       char                     path[PATH_MAX + 1];
-       bool                     found;
-       long                     magic;
-};
-
-enum {
-       FS__SYSFS  = 0,
-       FS__PROCFS = 1,
-};
-
-static struct fs fs__entries[] = {
-       [FS__SYSFS] = {
-               .name   = "sysfs",
-               .mounts = sysfs__fs_known_mountpoints,
-               .magic  = SYSFS_MAGIC,
-       },
-       [FS__PROCFS] = {
-               .name   = "proc",
-               .mounts = procfs__known_mountpoints,
-               .magic  = PROC_SUPER_MAGIC,
-       },
-};
-
-static bool fs__read_mounts(struct fs *fs)
-{
-       bool found = false;
-       char type[100];
-       FILE *fp;
-
-       fp = fopen("/proc/mounts", "r");
-       if (fp == NULL)
-               return NULL;
-
-       while (!found &&
-              fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
-                     fs->path, type) == 2) {
-
-               if (strcmp(type, fs->name) == 0)
-                       found = true;
-       }
-
-       fclose(fp);
-       return fs->found = found;
-}
-
-static int fs__valid_mount(const char *fs, long magic)
-{
-       struct statfs st_fs;
-
-       if (statfs(fs, &st_fs) < 0)
-               return -ENOENT;
-       else if (st_fs.f_type != magic)
-               return -ENOENT;
-
-       return 0;
-}
-
-static bool fs__check_mounts(struct fs *fs)
-{
-       const char * const *ptr;
-
-       ptr = fs->mounts;
-       while (*ptr) {
-               if (fs__valid_mount(*ptr, fs->magic) == 0) {
-                       fs->found = true;
-                       strcpy(fs->path, *ptr);
-                       return true;
-               }
-               ptr++;
-       }
-
-       return false;
-}
-
-static const char *fs__get_mountpoint(struct fs *fs)
-{
-       if (fs__check_mounts(fs))
-               return fs->path;
-
-       return fs__read_mounts(fs) ? fs->path : NULL;
-}
-
-static const char *fs__mountpoint(int idx)
-{
-       struct fs *fs = &fs__entries[idx];
-
-       if (fs->found)
-               return (const char *)fs->path;
-
-       return fs__get_mountpoint(fs);
-}
-
-#define FS__MOUNTPOINT(name, idx)      \
-const char *name##__mountpoint(void)   \
-{                                      \
-       return fs__mountpoint(idx);     \
-}
-
-FS__MOUNTPOINT(sysfs,  FS__SYSFS);
-FS__MOUNTPOINT(procfs, FS__PROCFS);
diff --git a/tools/perf/util/fs.h b/tools/perf/util/fs.h
deleted file mode 100644 (file)
index 5e09ce1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __PERF_FS
-#define __PERF_FS
-
-const char *sysfs__mountpoint(void);
-const char *procfs__mountpoint(void);
-
-#endif /* __PERF_FS */
index e4e6249b87d4eef1cd89d3df1aa3da022b550f84..f38590d7561b99733c5c32154eb1dee8c9777572 100644 (file)
@@ -13,13 +13,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
 static bool hists__filter_entry_by_symbol(struct hists *hists,
                                          struct hist_entry *he);
 
-enum hist_filter {
-       HIST_FILTER__DSO,
-       HIST_FILTER__THREAD,
-       HIST_FILTER__PARENT,
-       HIST_FILTER__SYMBOL,
-};
-
 struct callchain_param callchain_param = {
        .mode   = CHAIN_GRAPH_REL,
        .min_percent = 0.5,
@@ -290,7 +283,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
                if (he->branch_info) {
                        /*
                         * This branch info is (a part of) allocated from
-                        * machine__resolve_bstack() and will be freed after
+                        * sample__resolve_bstack() and will be freed after
                         * adding new entries.  So we need to save a copy.
                         */
                        he->branch_info = malloc(sizeof(*he->branch_info));
@@ -369,7 +362,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
                        he_stat__add_period(&he->stat, period, weight);
 
                        /*
-                        * This mem info was allocated from machine__resolve_mem
+                        * This mem info was allocated from sample__resolve_mem
                         * and will not be used anymore.
                         */
                        zfree(&entry->mem_info);
@@ -429,7 +422,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
                        .weight = weight,
                },
                .parent = sym_parent,
-               .filtered = symbol__parent_filter(sym_parent),
+               .filtered = symbol__parent_filter(sym_parent) | al->filtered,
                .hists  = hists,
                .branch_info = bi,
                .mem_info = mi,
index a59743fa3ef73d3aeb8c5c832a32aa2e04773a4c..1f1f513dfe7fb05f9cf0e77caeab43a327182fa1 100644 (file)
@@ -14,6 +14,15 @@ struct hist_entry;
 struct addr_location;
 struct symbol;
 
+enum hist_filter {
+       HIST_FILTER__DSO,
+       HIST_FILTER__THREAD,
+       HIST_FILTER__PARENT,
+       HIST_FILTER__SYMBOL,
+       HIST_FILTER__GUEST,
+       HIST_FILTER__HOST,
+};
+
 /*
  * The kernel collects the number of events it couldn't send in a stretch and
  * when possible sends this number in a PERF_RECORD_LOST event. The number of
@@ -132,8 +141,10 @@ struct perf_hpp {
 };
 
 struct perf_hpp_fmt {
-       int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp);
-       int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp);
+       int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+                     struct perf_evsel *evsel);
+       int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+                    struct perf_evsel *evsel);
        int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
                     struct hist_entry *he);
        int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -166,6 +177,20 @@ void perf_hpp__init(void);
 void perf_hpp__column_register(struct perf_hpp_fmt *format);
 void perf_hpp__column_enable(unsigned col);
 
+typedef u64 (*hpp_field_fn)(struct hist_entry *he);
+typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
+typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
+
+int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
+              hpp_field_fn get_field, hpp_callback_fn callback,
+              const char *fmt, hpp_snprint_fn print_fn, bool fmt_percent);
+
+static inline void advance_hpp(struct perf_hpp *hpp, int inc)
+{
+       hpp->buf  += inc;
+       hpp->size -= inc;
+}
+
 static inline size_t perf_hpp__use_color(void)
 {
        return !symbol_conf.field_sep;
diff --git a/tools/perf/util/include/asm/hash.h b/tools/perf/util/include/asm/hash.h
new file mode 100644 (file)
index 0000000..d82b170
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_GENERIC_HASH_H
+#define __ASM_GENERIC_HASH_H
+
+/* Stub */
+
+#endif /* __ASM_GENERIC_HASH_H */
index 45cf10a562bd7958c9edd160ab20a0725ecb0385..dadfa7e54287b9aaa46da7227d4b0f275717ddb2 100644 (file)
@@ -87,13 +87,15 @@ static __always_inline unsigned long __ffs(unsigned long word)
        return num;
 }
 
+typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
+
 /*
  * Find the first set bit in a memory region.
  */
 static inline unsigned long
 find_first_bit(const unsigned long *addr, unsigned long size)
 {
-       const unsigned long *p = addr;
+       long_alias_t *p = (long_alias_t *) addr;
        unsigned long result = 0;
        unsigned long tmp;
 
diff --git a/tools/perf/util/include/linux/hash.h b/tools/perf/util/include/linux/hash.h
deleted file mode 100644 (file)
index 201f573..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "../../../../include/linux/hash.h"
-
-#ifndef PERF_HASH_H
-#define PERF_HASH_H
-#endif
index d8c927c868eee79e9dc82d6c24a66f689f75288d..9844c31b7c2bb26c25a71e5a0203800e3a2daa26 100644 (file)
@@ -94,12 +94,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
        return (i >= ssize) ? (ssize - 1) : i;
 }
 
-static inline unsigned long
-simple_strtoul(const char *nptr, char **endptr, int base)
-{
-       return strtoul(nptr, endptr, base);
-}
-
 int eprintf(int level,
            const char *fmt, ...) __attribute__((format(printf, 2, 3)));
 
index 1d928a0ce9972014f435d93646c576bad56ad84b..bfe0a2afd0d28bc736b8ab8ae9c063ca0248a158 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/prefetch.h>
 
 #include "../../../../include/linux/list.h"
 
diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h
deleted file mode 100644 (file)
index 07d63cf..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _PERF_LINUX_MAGIC_H_
-#define _PERF_LINUX_MAGIC_H_
-
-#ifndef DEBUGFS_MAGIC
-#define DEBUGFS_MAGIC          0x64626720
-#endif
-
-#ifndef SYSFS_MAGIC
-#define SYSFS_MAGIC            0x62656572
-#endif
-
-#ifndef PROC_SUPER_MAGIC
-#define PROC_SUPER_MAGIC       0x9fa0
-#endif
-
-#endif
diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h
deleted file mode 100644 (file)
index 7841e48..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef PERF_LINUX_PREFETCH_H
-#define PERF_LINUX_PREFETCH_H
-
-static inline void prefetch(void *a __attribute__((unused))) { }
-
-#endif
index ded74590b92feaabd36f50b89baa77494514fd54..a53cd0b8c151cdb898d3711c36e5081846813a15 100644 (file)
@@ -327,9 +327,10 @@ struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
        return __machine__findnew_thread(machine, pid, tid, true);
 }
 
-struct thread *machine__find_thread(struct machine *machine, pid_t tid)
+struct thread *machine__find_thread(struct machine *machine, pid_t pid,
+                                   pid_t tid)
 {
-       return __machine__findnew_thread(machine, 0, tid, false);
+       return __machine__findnew_thread(machine, pid, tid, false);
 }
 
 int machine__process_comm_event(struct machine *machine, union perf_event *event,
@@ -496,19 +497,22 @@ static int symbol__in_kernel(void *arg, const char *name,
        return 1;
 }
 
+static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
+                                          size_t bufsz)
+{
+       if (machine__is_default_guest(machine))
+               scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
+       else
+               scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
+}
+
 /* Figure out the start address of kernel map from /proc/kallsyms */
 static u64 machine__get_kernel_start_addr(struct machine *machine)
 {
-       const char *filename;
-       char path[PATH_MAX];
+       char filename[PATH_MAX];
        struct process_args args;
 
-       if (machine__is_default_guest(machine))
-               filename = (char *)symbol_conf.default_guest_kallsyms;
-       else {
-               sprintf(path, "%s/proc/kallsyms", machine->root_dir);
-               filename = path;
-       }
+       machine__get_kallsyms_filename(machine, filename, PATH_MAX);
 
        if (symbol__restricted_filename(filename, "/proc/kallsyms"))
                return 0;
@@ -829,9 +833,25 @@ static int machine__create_modules(struct machine *machine)
        return 0;
 }
 
+const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
+
 int machine__create_kernel_maps(struct machine *machine)
 {
        struct dso *kernel = machine__get_kernel(machine);
+       char filename[PATH_MAX];
+       const char *name;
+       u64 addr = 0;
+       int i;
+
+       machine__get_kallsyms_filename(machine, filename, PATH_MAX);
+
+       for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
+               addr = kallsyms__get_function_start(filename, name);
+               if (addr)
+                       break;
+       }
+       if (!addr)
+               return -1;
 
        if (kernel == NULL ||
            __machine__create_kernel_maps(machine, kernel) < 0)
@@ -850,6 +870,13 @@ int machine__create_kernel_maps(struct machine *machine)
         * Now that we have all the maps created, just set the ->end of them:
         */
        map_groups__fixup_end(&machine->kmaps);
+
+       if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name,
+                                            addr)) {
+               machine__destroy_kernel_maps(machine);
+               return -1;
+       }
+
        return 0;
 }
 
@@ -1000,7 +1027,7 @@ int machine__process_mmap2_event(struct machine *machine,
        }
 
        thread = machine__findnew_thread(machine, event->mmap2.pid,
-                                       event->mmap2.pid);
+                                       event->mmap2.tid);
        if (thread == NULL)
                goto out_problem;
 
@@ -1048,7 +1075,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
        }
 
        thread = machine__findnew_thread(machine, event->mmap.pid,
-                                        event->mmap.pid);
+                                        event->mmap.tid);
        if (thread == NULL)
                goto out_problem;
 
@@ -1088,7 +1115,9 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)
 int machine__process_fork_event(struct machine *machine, union perf_event *event,
                                struct perf_sample *sample)
 {
-       struct thread *thread = machine__find_thread(machine, event->fork.tid);
+       struct thread *thread = machine__find_thread(machine,
+                                                    event->fork.pid,
+                                                    event->fork.tid);
        struct thread *parent = machine__findnew_thread(machine,
                                                        event->fork.ppid,
                                                        event->fork.ptid);
@@ -1114,7 +1143,9 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
 int machine__process_exit_event(struct machine *machine, union perf_event *event,
                                struct perf_sample *sample __maybe_unused)
 {
-       struct thread *thread = machine__find_thread(machine, event->fork.tid);
+       struct thread *thread = machine__find_thread(machine,
+                                                    event->fork.pid,
+                                                    event->fork.tid);
 
        if (dump_trace)
                perf_event__fprintf_task(event, stdout);
@@ -1158,39 +1189,22 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
        return 0;
 }
 
-static const u8 cpumodes[] = {
-       PERF_RECORD_MISC_USER,
-       PERF_RECORD_MISC_KERNEL,
-       PERF_RECORD_MISC_GUEST_USER,
-       PERF_RECORD_MISC_GUEST_KERNEL
-};
-#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
-
 static void ip__resolve_ams(struct machine *machine, struct thread *thread,
                            struct addr_map_symbol *ams,
                            u64 ip)
 {
        struct addr_location al;
-       size_t i;
-       u8 m;
 
        memset(&al, 0, sizeof(al));
+       /*
+        * We cannot use the header.misc hint to determine whether a
+        * branch stack address is user, kernel, guest, hypervisor.
+        * Branches may straddle the kernel/user/hypervisor boundaries.
+        * Thus, we have to try consecutively until we find a match
+        * or else, the symbol is unknown
+        */
+       thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al);
 
-       for (i = 0; i < NCPUMODES; i++) {
-               m = cpumodes[i];
-               /*
-                * We cannot use the header.misc hint to determine whether a
-                * branch stack address is user, kernel, guest, hypervisor.
-                * Branches may straddle the kernel/user/hypervisor boundaries.
-                * Thus, we have to try consecutively until we find a match
-                * or else, the symbol is unknown
-                */
-               thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
-                               ip, &al);
-               if (al.sym)
-                       goto found;
-       }
-found:
        ams->addr = ip;
        ams->al_addr = al.addr;
        ams->sym = al.sym;
@@ -1212,37 +1226,35 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
        ams->map = al.map;
 }
 
-struct mem_info *machine__resolve_mem(struct machine *machine,
-                                     struct thread *thr,
-                                     struct perf_sample *sample,
-                                     u8 cpumode)
+struct mem_info *sample__resolve_mem(struct perf_sample *sample,
+                                    struct addr_location *al)
 {
        struct mem_info *mi = zalloc(sizeof(*mi));
 
        if (!mi)
                return NULL;
 
-       ip__resolve_ams(machine, thr, &mi->iaddr, sample->ip);
-       ip__resolve_data(machine, thr, cpumode, &mi->daddr, sample->addr);
+       ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip);
+       ip__resolve_data(al->machine, al->thread, al->cpumode,
+                        &mi->daddr, sample->addr);
        mi->data_src.val = sample->data_src;
 
        return mi;
 }
 
-struct branch_info *machine__resolve_bstack(struct machine *machine,
-                                           struct thread *thr,
-                                           struct branch_stack *bs)
+struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
+                                          struct addr_location *al)
 {
-       struct branch_info *bi;
        unsigned int i;
+       const struct branch_stack *bs = sample->branch_stack;
+       struct branch_info *bi = calloc(bs->nr, sizeof(struct branch_info));
 
-       bi = calloc(bs->nr, sizeof(struct branch_info));
        if (!bi)
                return NULL;
 
        for (i = 0; i < bs->nr; i++) {
-               ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to);
-               ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from);
+               ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to);
+               ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from);
                bi[i].flags = bs->entries[i].flags;
        }
        return bi;
@@ -1300,7 +1312,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
                        continue;
                }
 
-               al.filtered = false;
+               al.filtered = 0;
                thread__find_addr_location(thread, machine, cpumode,
                                           MAP__FUNCTION, ip, &al);
                if (al.sym != NULL) {
@@ -1359,8 +1371,7 @@ int machine__resolve_callchain(struct machine *machine,
                return 0;
 
        return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
-                                  thread, evsel->attr.sample_regs_user,
-                                  sample, max_stack);
+                                  thread, sample, max_stack);
 
 }
 
index 477133015440483f16ee6c2aca4758f7dfba85e6..c8c74a1193983ab6dbc66db56dacdb157a0ba315 100644 (file)
@@ -18,6 +18,8 @@ union perf_event;
 #define        HOST_KERNEL_ID                  (-1)
 #define        DEFAULT_GUEST_KERNEL_ID         (0)
 
+extern const char *ref_reloc_sym_names[];
+
 struct machine {
        struct rb_node    rb_node;
        pid_t             pid;
@@ -39,7 +41,8 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
        return machine->vmlinux_maps[type];
 }
 
-struct thread *machine__find_thread(struct machine *machine, pid_t tid);
+struct thread *machine__find_thread(struct machine *machine, pid_t pid,
+                                   pid_t tid);
 
 int machine__process_comm_event(struct machine *machine, union perf_event *event,
                                struct perf_sample *sample);
@@ -89,12 +92,10 @@ void machine__delete_dead_threads(struct machine *machine);
 void machine__delete_threads(struct machine *machine);
 void machine__delete(struct machine *machine);
 
-struct branch_info *machine__resolve_bstack(struct machine *machine,
-                                           struct thread *thread,
-                                           struct branch_stack *bs);
-struct mem_info *machine__resolve_mem(struct machine *machine,
-                                     struct thread *thread,
-                                     struct perf_sample *sample, u8 cpumode);
+struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
+                                          struct addr_location *al);
+struct mem_info *sample__resolve_mem(struct perf_sample *sample,
+                                    struct addr_location *al);
 int machine__resolve_callchain(struct machine *machine,
                               struct perf_evsel *evsel,
                               struct thread *thread,
index 3b97513f0e7714738e63479049e59f138b22871c..39cd2d0faff65667b32738a8788817b6c670cedb 100644 (file)
@@ -39,6 +39,7 @@ void map__init(struct map *map, enum map_type type,
        map->start    = start;
        map->end      = end;
        map->pgoff    = pgoff;
+       map->reloc    = 0;
        map->dso      = dso;
        map->map_ip   = map__map_ip;
        map->unmap_ip = map__unmap_ip;
@@ -288,7 +289,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
        if (map->dso->rel)
                return rip - map->pgoff;
 
-       return map->unmap_ip(map, rip);
+       return map->unmap_ip(map, rip) - map->reloc;
 }
 
 /**
@@ -311,7 +312,7 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
        if (map->dso->rel)
                return map->unmap_ip(map, ip + map->pgoff);
 
-       return ip;
+       return ip + map->reloc;
 }
 
 void map_groups__init(struct map_groups *mg)
index 18068c6b71c19df77b0d61a60aeb47ef508a0492..f00f058afb3b6b510da22c7c04d2f2c4aee3b0e9 100644 (file)
@@ -36,6 +36,7 @@ struct map {
        bool                    erange_warned;
        u32                     priv;
        u64                     pgoff;
+       u64                     reloc;
        u32                     maj, min; /* only valid for MMAP2 record */
        u64                     ino;      /* only valid for MMAP2 record */
        u64                     ino_generation;/* only valid for MMAP2 record */
@@ -89,6 +90,16 @@ u64 map__objdump_2mem(struct map *map, u64 ip);
 
 struct symbol;
 
+/* map__for_each_symbol - iterate over the symbols in the given map
+ *
+ * @map: the 'struct map *' in which symbols itereated
+ * @pos: the 'struct symbol *' to use as a loop cursor
+ * @n: the 'struct rb_node *' to use as a temporary storage
+ * Note: caller must ensure map->dso is not NULL (map is loaded).
+ */
+#define map__for_each_symbol(map, pos, n)      \
+       dso__for_each_symbol(map->dso, pos, n, map->type)
+
 typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
 
 void map__init(struct map *map, enum map_type type,
index d248fca6d7ed7302c77d5500a79c853d3073ea07..1e15df10a88c2c1ff7b62dbfbcc05f39ffbe4cd1 100644 (file)
@@ -1091,12 +1091,12 @@ int is_valid_tracepoint(const char *event_string)
 static bool is_event_supported(u8 type, unsigned config)
 {
        bool ret = true;
+       int open_return;
        struct perf_evsel *evsel;
        struct perf_event_attr attr = {
                .type = type,
                .config = config,
                .disabled = 1,
-               .exclude_kernel = 1,
        };
        struct {
                struct thread_map map;
@@ -1108,7 +1108,20 @@ static bool is_event_supported(u8 type, unsigned config)
 
        evsel = perf_evsel__new(&attr);
        if (evsel) {
-               ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
+               open_return = perf_evsel__open(evsel, NULL, &tmap.map);
+               ret = open_return >= 0;
+
+               if (open_return == -EACCES) {
+                       /*
+                        * This happens if the paranoid value
+                        * /proc/sys/kernel/perf_event_paranoid is set to 2
+                        * Re-run with exclude_kernel set; we don't do that
+                        * by default as some ARM machines do not support it.
+                        *
+                        */
+                       evsel->attr.exclude_kernel = 1;
+                       ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
+               }
                perf_evsel__delete(evsel);
        }
 
index d22e3f8017dc429a67458bc18457a6de7cd9f778..bf48092983c65fe8cec8bb3ff4662e1b1803b18e 100644 (file)
@@ -407,7 +407,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                if (internal_help && !strcmp(arg + 2, "help"))
                        return usage_with_options_internal(usagestr, options, 0);
                if (!strcmp(arg + 2, "list-opts"))
-                       return PARSE_OPT_LIST;
+                       return PARSE_OPT_LIST_OPTS;
+               if (!strcmp(arg + 2, "list-cmds"))
+                       return PARSE_OPT_LIST_SUBCMDS;
                switch (parse_long_opt(ctx, arg + 2, options)) {
                case -1:
                        return parse_options_usage(usagestr, options, arg + 2, 0);
@@ -433,25 +435,45 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
        return ctx->cpidx + ctx->argc;
 }
 
-int parse_options(int argc, const char **argv, const struct option *options,
-                 const char * const usagestr[], int flags)
+int parse_options_subcommand(int argc, const char **argv, const struct option *options,
+                       const char *const subcommands[], const char *usagestr[], int flags)
 {
        struct parse_opt_ctx_t ctx;
 
        perf_header__set_cmdline(argc, argv);
 
+       /* build usage string if it's not provided */
+       if (subcommands && !usagestr[0]) {
+               struct strbuf buf = STRBUF_INIT;
+
+               strbuf_addf(&buf, "perf %s [<options>] {", argv[0]);
+               for (int i = 0; subcommands[i]; i++) {
+                       if (i)
+                               strbuf_addstr(&buf, "|");
+                       strbuf_addstr(&buf, subcommands[i]);
+               }
+               strbuf_addstr(&buf, "}");
+
+               usagestr[0] = strdup(buf.buf);
+               strbuf_release(&buf);
+       }
+
        parse_options_start(&ctx, argc, argv, flags);
        switch (parse_options_step(&ctx, options, usagestr)) {
        case PARSE_OPT_HELP:
                exit(129);
        case PARSE_OPT_DONE:
                break;
-       case PARSE_OPT_LIST:
+       case PARSE_OPT_LIST_OPTS:
                while (options->type != OPTION_END) {
                        printf("--%s ", options->long_name);
                        options++;
                }
                exit(130);
+       case PARSE_OPT_LIST_SUBCMDS:
+               for (int i = 0; subcommands[i]; i++)
+                       printf("%s ", subcommands[i]);
+               exit(130);
        default: /* PARSE_OPT_UNKNOWN */
                if (ctx.argv[0][1] == '-') {
                        error("unknown option `%s'", ctx.argv[0] + 2);
@@ -464,6 +486,13 @@ int parse_options(int argc, const char **argv, const struct option *options,
        return parse_options_end(&ctx);
 }
 
+int parse_options(int argc, const char **argv, const struct option *options,
+                 const char * const usagestr[], int flags)
+{
+       return parse_options_subcommand(argc, argv, options, NULL,
+                                       (const char **) usagestr, flags);
+}
+
 #define USAGE_OPTS_WIDTH 24
 #define USAGE_GAP         2
 
index cbf0149cf221783aea2aeafd8643900b80e6765d..d8dac8ac5f371403cf23f0ea0953d5db767540d4 100644 (file)
@@ -140,6 +140,11 @@ extern int parse_options(int argc, const char **argv,
                          const struct option *options,
                          const char * const usagestr[], int flags);
 
+extern int parse_options_subcommand(int argc, const char **argv,
+                               const struct option *options,
+                               const char *const subcommands[],
+                               const char *usagestr[], int flags);
+
 extern NORETURN void usage_with_options(const char * const *usagestr,
                                         const struct option *options);
 
@@ -148,7 +153,8 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
 enum {
        PARSE_OPT_HELP = -1,
        PARSE_OPT_DONE,
-       PARSE_OPT_LIST,
+       PARSE_OPT_LIST_OPTS,
+       PARSE_OPT_LIST_SUBCMDS,
        PARSE_OPT_UNKNOWN,
 };
 
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
new file mode 100644 (file)
index 0000000..a3539ef
--- /dev/null
@@ -0,0 +1,19 @@
+#include <errno.h>
+#include "perf_regs.h"
+
+int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
+{
+       int i, idx = 0;
+       u64 mask = regs->mask;
+
+       if (!(mask & (1 << id)))
+               return -EINVAL;
+
+       for (i = 0; i < id; i++) {
+               if (mask & (1 << i))
+                       idx++;
+       }
+
+       *valp = regs->regs[idx];
+       return 0;
+}
index a3d42cd749196b83c4c8226bfd069a68cd3a6917..d6e8b6a8d7f38f03632921789281569433826816 100644 (file)
@@ -1,8 +1,14 @@
 #ifndef __PERF_REGS_H
 #define __PERF_REGS_H
 
+#include "types.h"
+#include "event.h"
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
+
+int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
+
 #else
 #define PERF_REGS_MASK 0
 
@@ -10,5 +16,12 @@ static inline const char *perf_reg_name(int id __maybe_unused)
 {
        return NULL;
 }
+
+static inline int perf_reg_value(u64 *valp __maybe_unused,
+                                struct regs_dump *regs __maybe_unused,
+                                int id __maybe_unused)
+{
+       return 0;
+}
 #endif /* HAVE_PERF_REGS_SUPPORT */
 #endif /* __PERF_REGS_H */
index b752ecb40d86af6245b7f8646bb3607992bcd9f6..00a7dcb2f55cb0d7734e7eb331384d00aa42809c 100644 (file)
@@ -3,7 +3,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <dirent.h>
-#include "fs.h"
+#include <api/fs/fs.h>
 #include <locale.h>
 #include "util.h"
 #include "pmu.h"
index a8a9b6cd93a8f080a968f1cd05e7f80bb0df0ca6..0d1542f33d879a6f761fe6f1fbd61b6299635237 100644 (file)
@@ -70,34 +70,32 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
 }
 
 static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
-static int convert_name_to_addr(struct perf_probe_event *pev,
-                               const char *exec);
 static void clear_probe_trace_event(struct probe_trace_event *tev);
-static struct machine machine;
+static struct machine *host_machine;
 
 /* Initialize symbol maps and path of vmlinux/modules */
-static int init_vmlinux(void)
+static int init_symbol_maps(bool user_only)
 {
        int ret;
 
        symbol_conf.sort_by_name = true;
-       if (symbol_conf.vmlinux_name == NULL)
-               symbol_conf.try_vmlinux_path = true;
-       else
-               pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
        ret = symbol__init();
        if (ret < 0) {
                pr_debug("Failed to init symbol map.\n");
                goto out;
        }
 
-       ret = machine__init(&machine, "", HOST_KERNEL_ID);
-       if (ret < 0)
-               goto out;
+       if (host_machine || user_only)  /* already initialized */
+               return 0;
 
-       if (machine__create_kernel_maps(&machine) < 0) {
-               pr_debug("machine__create_kernel_maps() failed.\n");
-               goto out;
+       if (symbol_conf.vmlinux_name)
+               pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
+
+       host_machine = machine__new_host();
+       if (!host_machine) {
+               pr_debug("machine__new_host() failed.\n");
+               symbol__exit();
+               ret = -1;
        }
 out:
        if (ret < 0)
@@ -105,21 +103,66 @@ out:
        return ret;
 }
 
+static void exit_symbol_maps(void)
+{
+       if (host_machine) {
+               machine__delete(host_machine);
+               host_machine = NULL;
+       }
+       symbol__exit();
+}
+
 static struct symbol *__find_kernel_function_by_name(const char *name,
                                                     struct map **mapp)
 {
-       return machine__find_kernel_function_by_name(&machine, name, mapp,
+       return machine__find_kernel_function_by_name(host_machine, name, mapp,
                                                     NULL);
 }
 
+static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
+{
+       return machine__find_kernel_function(host_machine, addr, mapp, NULL);
+}
+
+static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
+{
+       /* kmap->ref_reloc_sym should be set if host_machine is initialized */
+       struct kmap *kmap;
+
+       if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0)
+               return NULL;
+
+       kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
+       return kmap->ref_reloc_sym;
+}
+
+static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
+{
+       struct ref_reloc_sym *reloc_sym;
+       struct symbol *sym;
+       struct map *map;
+
+       /* ref_reloc_sym is just a label. Need a special fix*/
+       reloc_sym = kernel_get_ref_reloc_sym();
+       if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
+               return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
+       else {
+               sym = __find_kernel_function_by_name(name, &map);
+               if (sym)
+                       return map->unmap_ip(map, sym->start) -
+                               (reloc) ? 0 : map->reloc;
+       }
+       return 0;
+}
+
 static struct map *kernel_get_module_map(const char *module)
 {
        struct rb_node *nd;
-       struct map_groups *grp = &machine.kmaps;
+       struct map_groups *grp = &host_machine->kmaps;
 
        /* A file path -- this is an offline module */
        if (module && strchr(module, '/'))
-               return machine__new_module(&machine, 0, module);
+               return machine__new_module(host_machine, 0, module);
 
        if (!module)
                module = "kernel";
@@ -141,7 +184,7 @@ static struct dso *kernel_get_module_dso(const char *module)
        const char *vmlinux_name;
 
        if (module) {
-               list_for_each_entry(dso, &machine.kernel_dsos, node) {
+               list_for_each_entry(dso, &host_machine->kernel_dsos, node) {
                        if (strncmp(dso->short_name + 1, module,
                                    dso->short_name_len - 2) == 0)
                                goto found;
@@ -150,7 +193,7 @@ static struct dso *kernel_get_module_dso(const char *module)
                return NULL;
        }
 
-       map = machine.vmlinux_maps[MAP__FUNCTION];
+       map = host_machine->vmlinux_maps[MAP__FUNCTION];
        dso = map->dso;
 
        vmlinux_name = symbol_conf.vmlinux_name;
@@ -173,20 +216,6 @@ const char *kernel_get_module_path(const char *module)
        return (dso) ? dso->long_name : NULL;
 }
 
-static int init_user_exec(void)
-{
-       int ret = 0;
-
-       symbol_conf.try_vmlinux_path = false;
-       symbol_conf.sort_by_name = true;
-       ret = symbol__init();
-
-       if (ret < 0)
-               pr_debug("Failed to init symbol map.\n");
-
-       return ret;
-}
-
 static int convert_exec_to_group(const char *exec, char **result)
 {
        char *ptr1, *ptr2, *exec_copy;
@@ -218,32 +247,23 @@ out:
        return ret;
 }
 
-static int convert_to_perf_probe_point(struct probe_trace_point *tp,
-                                       struct perf_probe_point *pp)
+static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
 {
-       pp->function = strdup(tp->symbol);
-
-       if (pp->function == NULL)
-               return -ENOMEM;
-
-       pp->offset = tp->offset;
-       pp->retprobe = tp->retprobe;
+       int i;
 
-       return 0;
+       for (i = 0; i < ntevs; i++)
+               clear_probe_trace_event(tevs + i);
 }
 
 #ifdef HAVE_DWARF_SUPPORT
+
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module)
 {
-       const char *path;
+       const char *path = module;
 
-       /* A file path -- this is an offline module */
-       if (module && strchr(module, '/'))
-               path = module;
-       else {
+       if (!module || !strchr(module, '/')) {
                path = kernel_get_module_path(module);
-
                if (!path) {
                        pr_err("Failed to find path of %s module.\n",
                               module ?: "kernel");
@@ -253,46 +273,6 @@ static struct debuginfo *open_debuginfo(const char *module)
        return debuginfo__new(path);
 }
 
-/*
- * Convert trace point to probe point with debuginfo
- * Currently only handles kprobes.
- */
-static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
-                                       struct perf_probe_point *pp)
-{
-       struct symbol *sym;
-       struct map *map;
-       u64 addr;
-       int ret = -ENOENT;
-       struct debuginfo *dinfo;
-
-       sym = __find_kernel_function_by_name(tp->symbol, &map);
-       if (sym) {
-               addr = map->unmap_ip(map, sym->start + tp->offset);
-               pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
-                        tp->offset, addr);
-
-               dinfo = debuginfo__new_online_kernel(addr);
-               if (dinfo) {
-                       ret = debuginfo__find_probe_point(dinfo,
-                                                (unsigned long)addr, pp);
-                       debuginfo__delete(dinfo);
-               } else {
-                       pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
-                                addr);
-                       ret = -ENOENT;
-               }
-       }
-       if (ret <= 0) {
-               pr_debug("Failed to find corresponding probes from "
-                        "debuginfo. Use kprobe event information.\n");
-               return convert_to_perf_probe_point(tp, pp);
-       }
-       pp->retprobe = tp->retprobe;
-
-       return 0;
-}
-
 static int get_text_start_address(const char *exec, unsigned long *address)
 {
        Elf *elf;
@@ -321,12 +301,62 @@ out:
        return ret;
 }
 
+/*
+ * Convert trace point to probe point with debuginfo
+ */
+static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
+                                           struct perf_probe_point *pp,
+                                           bool is_kprobe)
+{
+       struct debuginfo *dinfo = NULL;
+       unsigned long stext = 0;
+       u64 addr = tp->address;
+       int ret = -ENOENT;
+
+       /* convert the address to dwarf address */
+       if (!is_kprobe) {
+               if (!addr) {
+                       ret = -EINVAL;
+                       goto error;
+               }
+               ret = get_text_start_address(tp->module, &stext);
+               if (ret < 0)
+                       goto error;
+               addr += stext;
+       } else {
+               addr = kernel_get_symbol_address_by_name(tp->symbol, false);
+               if (addr == 0)
+                       goto error;
+               addr += tp->offset;
+       }
+
+       pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
+                tp->module ? : "kernel");
+
+       dinfo = open_debuginfo(tp->module);
+       if (dinfo) {
+               ret = debuginfo__find_probe_point(dinfo,
+                                                (unsigned long)addr, pp);
+               debuginfo__delete(dinfo);
+       } else {
+               pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
+               ret = -ENOENT;
+       }
+
+       if (ret > 0) {
+               pp->retprobe = tp->retprobe;
+               return 0;
+       }
+error:
+       pr_debug("Failed to find corresponding probes from debuginfo.\n");
+       return ret ? : -ENOENT;
+}
+
 static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
                                          int ntevs, const char *exec)
 {
        int i, ret = 0;
-       unsigned long offset, stext = 0;
-       char buf[32];
+       unsigned long stext = 0;
 
        if (!exec)
                return 0;
@@ -336,16 +366,10 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
                return ret;
 
        for (i = 0; i < ntevs && ret >= 0; i++) {
-               offset = tevs[i].point.address - stext;
-               offset += tevs[i].point.offset;
-               tevs[i].point.offset = 0;
-               zfree(&tevs[i].point.symbol);
-               ret = e_snprintf(buf, 32, "0x%lx", offset);
-               if (ret < 0)
-                       break;
+               /* point.address is the addres of point.symbol + point.offset */
+               tevs[i].point.address -= stext;
                tevs[i].point.module = strdup(exec);
-               tevs[i].point.symbol = strdup(buf);
-               if (!tevs[i].point.symbol || !tevs[i].point.module) {
+               if (!tevs[i].point.module) {
                        ret = -ENOMEM;
                        break;
                }
@@ -388,12 +412,40 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
        return ret;
 }
 
-static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
+/* Post processing the probe events */
+static int post_process_probe_trace_events(struct probe_trace_event *tevs,
+                                          int ntevs, const char *module,
+                                          bool uprobe)
 {
+       struct ref_reloc_sym *reloc_sym;
+       char *tmp;
        int i;
 
-       for (i = 0; i < ntevs; i++)
-               clear_probe_trace_event(tevs + i);
+       if (uprobe)
+               return add_exec_to_probe_trace_events(tevs, ntevs, module);
+
+       /* Note that currently ref_reloc_sym based probe is not for drivers */
+       if (module)
+               return add_module_to_probe_trace_events(tevs, ntevs, module);
+
+       reloc_sym = kernel_get_ref_reloc_sym();
+       if (!reloc_sym) {
+               pr_warning("Relocated base symbol is not found!\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ntevs; i++) {
+               if (tevs[i].point.address) {
+                       tmp = strdup(reloc_sym->name);
+                       if (!tmp)
+                               return -ENOMEM;
+                       free(tevs[i].point.symbol);
+                       tevs[i].point.symbol = tmp;
+                       tevs[i].point.offset = tevs[i].point.address -
+                                              reloc_sym->unrelocated_addr;
+               }
+       }
+       return 0;
 }
 
 /* Try to find perf_probe_event with debuginfo */
@@ -416,21 +468,16 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
                return 0;
        }
 
+       pr_debug("Try to find probe point from debuginfo.\n");
        /* Searching trace events corresponding to a probe event */
        ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
 
        debuginfo__delete(dinfo);
 
        if (ntevs > 0) {        /* Succeeded to find trace events */
-               pr_debug("find %d probe_trace_events.\n", ntevs);
-               if (target) {
-                       if (pev->uprobes)
-                               ret = add_exec_to_probe_trace_events(*tevs,
-                                                ntevs, target);
-                       else
-                               ret = add_module_to_probe_trace_events(*tevs,
-                                                ntevs, target);
-               }
+               pr_debug("Found %d probe_trace_events.\n", ntevs);
+               ret = post_process_probe_trace_events(*tevs, ntevs,
+                                                       target, pev->uprobes);
                if (ret < 0) {
                        clear_probe_trace_events(*tevs, ntevs);
                        zfree(tevs);
@@ -563,20 +610,16 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
  * Show line-range always requires debuginfo to find source file and
  * line number.
  */
-int show_line_range(struct line_range *lr, const char *module)
+static int __show_line_range(struct line_range *lr, const char *module)
 {
        int l = 1;
-       struct line_node *ln;
+       struct int_node *ln;
        struct debuginfo *dinfo;
        FILE *fp;
        int ret;
        char *tmp;
 
        /* Search a line range */
-       ret = init_vmlinux();
-       if (ret < 0)
-               return ret;
-
        dinfo = open_debuginfo(module);
        if (!dinfo) {
                pr_warning("Failed to open debuginfo file.\n");
@@ -623,8 +666,8 @@ int show_line_range(struct line_range *lr, const char *module)
                        goto end;
        }
 
-       list_for_each_entry(ln, &lr->line_list, list) {
-               for (; ln->line > l; l++) {
+       intlist__for_each(ln, lr->line_list) {
+               for (; ln->i > l; l++) {
                        ret = show_one_line(fp, l - lr->offset);
                        if (ret < 0)
                                goto end;
@@ -646,6 +689,19 @@ end:
        return ret;
 }
 
+int show_line_range(struct line_range *lr, const char *module)
+{
+       int ret;
+
+       ret = init_symbol_maps(false);
+       if (ret < 0)
+               return ret;
+       ret = __show_line_range(lr, module);
+       exit_symbol_maps();
+
+       return ret;
+}
+
 static int show_available_vars_at(struct debuginfo *dinfo,
                                  struct perf_probe_event *pev,
                                  int max_vls, struct strfilter *_filter,
@@ -707,14 +763,15 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
        int i, ret = 0;
        struct debuginfo *dinfo;
 
-       ret = init_vmlinux();
+       ret = init_symbol_maps(false);
        if (ret < 0)
                return ret;
 
        dinfo = open_debuginfo(module);
        if (!dinfo) {
                pr_warning("Failed to open debuginfo file.\n");
-               return -ENOENT;
+               ret = -ENOENT;
+               goto out;
        }
 
        setup_pager();
@@ -724,23 +781,19 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
                                             externs);
 
        debuginfo__delete(dinfo);
+out:
+       exit_symbol_maps();
        return ret;
 }
 
 #else  /* !HAVE_DWARF_SUPPORT */
 
-static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
-                                       struct perf_probe_point *pp)
+static int
+find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
+                                struct perf_probe_point *pp __maybe_unused,
+                                bool is_kprobe __maybe_unused)
 {
-       struct symbol *sym;
-
-       sym = __find_kernel_function_by_name(tp->symbol, NULL);
-       if (!sym) {
-               pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
-               return -ENOENT;
-       }
-
-       return convert_to_perf_probe_point(tp, pp);
+       return -ENOSYS;
 }
 
 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
@@ -776,24 +829,22 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
 
 void line_range__clear(struct line_range *lr)
 {
-       struct line_node *ln;
-
        free(lr->function);
        free(lr->file);
        free(lr->path);
        free(lr->comp_dir);
-       while (!list_empty(&lr->line_list)) {
-               ln = list_first_entry(&lr->line_list, struct line_node, list);
-               list_del(&ln->list);
-               free(ln);
-       }
+       intlist__delete(lr->line_list);
        memset(lr, 0, sizeof(*lr));
 }
 
-void line_range__init(struct line_range *lr)
+int line_range__init(struct line_range *lr)
 {
        memset(lr, 0, sizeof(*lr));
-       INIT_LIST_HEAD(&lr->line_list);
+       lr->line_list = intlist__new(NULL);
+       if (!lr->line_list)
+               return -ENOMEM;
+       else
+               return 0;
 }
 
 static int parse_line_num(char **ptr, int *val, const char *what)
@@ -1267,16 +1318,21 @@ static int parse_probe_trace_command(const char *cmd,
        } else
                p = argv[1];
        fmt1_str = strtok_r(p, "+", &fmt);
-       tp->symbol = strdup(fmt1_str);
-       if (tp->symbol == NULL) {
-               ret = -ENOMEM;
-               goto out;
+       if (fmt1_str[0] == '0') /* only the address started with 0x */
+               tp->address = strtoul(fmt1_str, NULL, 0);
+       else {
+               /* Only the symbol-based probe has offset */
+               tp->symbol = strdup(fmt1_str);
+               if (tp->symbol == NULL) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               fmt2_str = strtok_r(NULL, "", &fmt);
+               if (fmt2_str == NULL)
+                       tp->offset = 0;
+               else
+                       tp->offset = strtoul(fmt2_str, NULL, 10);
        }
-       fmt2_str = strtok_r(NULL, "", &fmt);
-       if (fmt2_str == NULL)
-               tp->offset = 0;
-       else
-               tp->offset = strtoul(fmt2_str, NULL, 10);
 
        tev->nargs = argc - 2;
        tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
@@ -1518,20 +1574,27 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
        if (buf == NULL)
                return NULL;
 
+       len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
+                        tev->group, tev->event);
+       if (len <= 0)
+               goto error;
+
+       /* Uprobes must have tp->address and tp->module */
+       if (tev->uprobes && (!tp->address || !tp->module))
+               goto error;
+
+       /* Use the tp->address for uprobes */
        if (tev->uprobes)
-               len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s",
-                                tp->retprobe ? 'r' : 'p',
-                                tev->group, tev->event,
-                                tp->module, tp->symbol);
+               ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
+                                tp->module, tp->address);
        else
-               len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
-                                tp->retprobe ? 'r' : 'p',
-                                tev->group, tev->event,
+               ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
                                 tp->module ?: "", tp->module ? ":" : "",
                                 tp->symbol, tp->offset);
 
-       if (len <= 0)
+       if (ret <= 0)
                goto error;
+       len += ret;
 
        for (i = 0; i < tev->nargs; i++) {
                ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
@@ -1547,6 +1610,79 @@ error:
        return NULL;
 }
 
+static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
+                                         struct perf_probe_point *pp,
+                                         bool is_kprobe)
+{
+       struct symbol *sym = NULL;
+       struct map *map;
+       u64 addr;
+       int ret = -ENOENT;
+
+       if (!is_kprobe) {
+               map = dso__new_map(tp->module);
+               if (!map)
+                       goto out;
+               addr = tp->address;
+               sym = map__find_symbol(map, addr, NULL);
+       } else {
+               addr = kernel_get_symbol_address_by_name(tp->symbol, true);
+               if (addr) {
+                       addr += tp->offset;
+                       sym = __find_kernel_function(addr, &map);
+               }
+       }
+       if (!sym)
+               goto out;
+
+       pp->retprobe = tp->retprobe;
+       pp->offset = addr - map->unmap_ip(map, sym->start);
+       pp->function = strdup(sym->name);
+       ret = pp->function ? 0 : -ENOMEM;
+
+out:
+       if (map && !is_kprobe) {
+               dso__delete(map->dso);
+               map__delete(map);
+       }
+
+       return ret;
+}
+
+static int convert_to_perf_probe_point(struct probe_trace_point *tp,
+                                       struct perf_probe_point *pp,
+                                       bool is_kprobe)
+{
+       char buf[128];
+       int ret;
+
+       ret = find_perf_probe_point_from_dwarf(tp, pp, is_kprobe);
+       if (!ret)
+               return 0;
+       ret = find_perf_probe_point_from_map(tp, pp, is_kprobe);
+       if (!ret)
+               return 0;
+
+       pr_debug("Failed to find probe point from both of dwarf and map.\n");
+
+       if (tp->symbol) {
+               pp->function = strdup(tp->symbol);
+               pp->offset = tp->offset;
+       } else if (!tp->module && !is_kprobe) {
+               ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
+               if (ret < 0)
+                       return ret;
+               pp->function = strdup(buf);
+               pp->offset = 0;
+       }
+       if (pp->function == NULL)
+               return -ENOMEM;
+
+       pp->retprobe = tp->retprobe;
+
+       return 0;
+}
+
 static int convert_to_perf_probe_event(struct probe_trace_event *tev,
                               struct perf_probe_event *pev, bool is_kprobe)
 {
@@ -1560,11 +1696,7 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
                return -ENOMEM;
 
        /* Convert trace_point to probe_point */
-       if (is_kprobe)
-               ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
-       else
-               ret = convert_to_perf_probe_point(&tev->point, &pev->point);
-
+       ret = convert_to_perf_probe_point(&tev->point, &pev->point, is_kprobe);
        if (ret < 0)
                return ret;
 
@@ -1731,7 +1863,8 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
 }
 
 /* Show an event */
-static int show_perf_probe_event(struct perf_probe_event *pev)
+static int show_perf_probe_event(struct perf_probe_event *pev,
+                                const char *module)
 {
        int i, ret;
        char buf[128];
@@ -1747,6 +1880,8 @@ static int show_perf_probe_event(struct perf_probe_event *pev)
                return ret;
 
        printf("  %-20s (on %s", buf, place);
+       if (module)
+               printf(" in %s", module);
 
        if (pev->nargs > 0) {
                printf(" with");
@@ -1784,7 +1919,8 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
                        ret = convert_to_perf_probe_event(&tev, &pev,
                                                                is_kprobe);
                        if (ret >= 0)
-                               ret = show_perf_probe_event(&pev);
+                               ret = show_perf_probe_event(&pev,
+                                                           tev.point.module);
                }
                clear_perf_probe_event(&pev);
                clear_probe_trace_event(&tev);
@@ -1807,7 +1943,7 @@ int show_perf_probe_events(void)
        if (fd < 0)
                return fd;
 
-       ret = init_vmlinux();
+       ret = init_symbol_maps(false);
        if (ret < 0)
                return ret;
 
@@ -1820,6 +1956,7 @@ int show_perf_probe_events(void)
                close(fd);
        }
 
+       exit_symbol_maps();
        return ret;
 }
 
@@ -1982,7 +2119,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
                group = pev->group;
                pev->event = tev->event;
                pev->group = tev->group;
-               show_perf_probe_event(pev);
+               show_perf_probe_event(pev, tev->point.module);
                /* Trick here - restore current event/group */
                pev->event = (char *)event;
                pev->group = (char *)group;
@@ -2008,113 +2145,175 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
        return ret;
 }
 
-static int convert_to_probe_trace_events(struct perf_probe_event *pev,
-                                         struct probe_trace_event **tevs,
-                                         int max_tevs, const char *target)
+static char *looking_function_name;
+static int num_matched_functions;
+
+static int probe_function_filter(struct map *map __maybe_unused,
+                                     struct symbol *sym)
 {
+       if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
+           strcmp(looking_function_name, sym->name) == 0) {
+               num_matched_functions++;
+               return 0;
+       }
+       return 1;
+}
+
+#define strdup_or_goto(str, label)     \
+       ({ char *__p = strdup(str); if (!__p) goto label; __p; })
+
+/*
+ * Find probe function addresses from map.
+ * Return an error or the number of found probe_trace_event
+ */
+static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
+                                           struct probe_trace_event **tevs,
+                                           int max_tevs, const char *target)
+{
+       struct map *map = NULL;
+       struct kmap *kmap = NULL;
+       struct ref_reloc_sym *reloc_sym = NULL;
        struct symbol *sym;
-       int ret, i;
+       struct rb_node *nd;
        struct probe_trace_event *tev;
+       struct perf_probe_point *pp = &pev->point;
+       struct probe_trace_point *tp;
+       int ret, i;
 
-       if (pev->uprobes && !pev->group) {
-               /* Replace group name if not given */
-               ret = convert_exec_to_group(target, &pev->group);
-               if (ret != 0) {
-                       pr_warning("Failed to make a group name.\n");
-                       return ret;
-               }
+       /* Init maps of given executable or kernel */
+       if (pev->uprobes)
+               map = dso__new_map(target);
+       else
+               map = kernel_get_module_map(target);
+       if (!map) {
+               ret = -EINVAL;
+               goto out;
        }
 
-       /* Convert perf_probe_event with debuginfo */
-       ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
-       if (ret != 0)
-               return ret;     /* Found in debuginfo or got an error */
-
-       if (pev->uprobes) {
-               ret = convert_name_to_addr(pev, target);
-               if (ret < 0)
-                       return ret;
+       /*
+        * Load matched symbols: Since the different local symbols may have
+        * same name but different addresses, this lists all the symbols.
+        */
+       num_matched_functions = 0;
+       looking_function_name = pp->function;
+       ret = map__load(map, probe_function_filter);
+       if (ret || num_matched_functions == 0) {
+               pr_err("Failed to find symbol %s in %s\n", pp->function,
+                       target ? : "kernel");
+               ret = -ENOENT;
+               goto out;
+       } else if (num_matched_functions > max_tevs) {
+               pr_err("Too many functions matched in %s\n",
+                       target ? : "kernel");
+               ret = -E2BIG;
+               goto out;
        }
 
-       /* Allocate trace event buffer */
-       tev = *tevs = zalloc(sizeof(struct probe_trace_event));
-       if (tev == NULL)
-               return -ENOMEM;
+       if (!pev->uprobes) {
+               kmap = map__kmap(map);
+               reloc_sym = kmap->ref_reloc_sym;
+               if (!reloc_sym) {
+                       pr_warning("Relocated base symbol is not found!\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
 
-       /* Copy parameters */
-       tev->point.symbol = strdup(pev->point.function);
-       if (tev->point.symbol == NULL) {
+       /* Setup result trace-probe-events */
+       *tevs = zalloc(sizeof(*tev) * num_matched_functions);
+       if (!*tevs) {
                ret = -ENOMEM;
-               goto error;
+               goto out;
        }
 
-       if (target) {
-               tev->point.module = strdup(target);
-               if (tev->point.module == NULL) {
-                       ret = -ENOMEM;
-                       goto error;
+       ret = 0;
+       map__for_each_symbol(map, sym, nd) {
+               tev = (*tevs) + ret;
+               tp = &tev->point;
+               if (ret == num_matched_functions) {
+                       pr_warning("Too many symbols are listed. Skip it.\n");
+                       break;
                }
-       }
-
-       tev->point.offset = pev->point.offset;
-       tev->point.retprobe = pev->point.retprobe;
-       tev->nargs = pev->nargs;
-       tev->uprobes = pev->uprobes;
+               ret++;
 
-       if (tev->nargs) {
-               tev->args = zalloc(sizeof(struct probe_trace_arg)
-                                  * tev->nargs);
-               if (tev->args == NULL) {
-                       ret = -ENOMEM;
-                       goto error;
+               if (pp->offset > sym->end - sym->start) {
+                       pr_warning("Offset %ld is bigger than the size of %s\n",
+                                  pp->offset, sym->name);
+                       ret = -ENOENT;
+                       goto err_out;
+               }
+               /* Add one probe point */
+               tp->address = map->unmap_ip(map, sym->start) + pp->offset;
+               if (reloc_sym) {
+                       tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out);
+                       tp->offset = tp->address - reloc_sym->addr;
+               } else {
+                       tp->symbol = strdup_or_goto(sym->name, nomem_out);
+                       tp->offset = pp->offset;
+               }
+               tp->retprobe = pp->retprobe;
+               if (target)
+                       tev->point.module = strdup_or_goto(target, nomem_out);
+               tev->uprobes = pev->uprobes;
+               tev->nargs = pev->nargs;
+               if (tev->nargs) {
+                       tev->args = zalloc(sizeof(struct probe_trace_arg) *
+                                          tev->nargs);
+                       if (tev->args == NULL)
+                               goto nomem_out;
                }
                for (i = 0; i < tev->nargs; i++) {
-                       if (pev->args[i].name) {
-                               tev->args[i].name = strdup(pev->args[i].name);
-                               if (tev->args[i].name == NULL) {
-                                       ret = -ENOMEM;
-                                       goto error;
-                               }
-                       }
-                       tev->args[i].value = strdup(pev->args[i].var);
-                       if (tev->args[i].value == NULL) {
-                               ret = -ENOMEM;
-                               goto error;
-                       }
-                       if (pev->args[i].type) {
-                               tev->args[i].type = strdup(pev->args[i].type);
-                               if (tev->args[i].type == NULL) {
-                                       ret = -ENOMEM;
-                                       goto error;
-                               }
-                       }
+                       if (pev->args[i].name)
+                               tev->args[i].name =
+                                       strdup_or_goto(pev->args[i].name,
+                                                       nomem_out);
+
+                       tev->args[i].value = strdup_or_goto(pev->args[i].var,
+                                                           nomem_out);
+                       if (pev->args[i].type)
+                               tev->args[i].type =
+                                       strdup_or_goto(pev->args[i].type,
+                                                       nomem_out);
                }
        }
 
-       if (pev->uprobes)
-               return 1;
+out:
+       if (map && pev->uprobes) {
+               /* Only when using uprobe(exec) map needs to be released */
+               dso__delete(map->dso);
+               map__delete(map);
+       }
+       return ret;
 
-       /* Currently just checking function name from symbol map */
-       sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
-       if (!sym) {
-               pr_warning("Kernel symbol \'%s\' not found.\n",
-                          tev->point.symbol);
-               ret = -ENOENT;
-               goto error;
-       } else if (tev->point.offset > sym->end - sym->start) {
-               pr_warning("Offset specified is greater than size of %s\n",
-                          tev->point.symbol);
-               ret = -ENOENT;
-               goto error;
+nomem_out:
+       ret = -ENOMEM;
+err_out:
+       clear_probe_trace_events(*tevs, num_matched_functions);
+       zfree(tevs);
+       goto out;
+}
+
+static int convert_to_probe_trace_events(struct perf_probe_event *pev,
+                                         struct probe_trace_event **tevs,
+                                         int max_tevs, const char *target)
+{
+       int ret;
 
+       if (pev->uprobes && !pev->group) {
+               /* Replace group name if not given */
+               ret = convert_exec_to_group(target, &pev->group);
+               if (ret != 0) {
+                       pr_warning("Failed to make a group name.\n");
+                       return ret;
+               }
        }
 
-       return 1;
-error:
-       clear_probe_trace_event(tev);
-       free(tev);
-       *tevs = NULL;
-       return ret;
+       /* Convert perf_probe_event with debuginfo */
+       ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
+       if (ret != 0)
+               return ret;     /* Found in debuginfo or got an error */
+
+       return find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
 }
 
 struct __event_package {
@@ -2135,12 +2334,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
        if (pkgs == NULL)
                return -ENOMEM;
 
-       if (!pevs->uprobes)
-               /* Init vmlinux path */
-               ret = init_vmlinux();
-       else
-               ret = init_user_exec();
-
+       ret = init_symbol_maps(pevs->uprobes);
        if (ret < 0) {
                free(pkgs);
                return ret;
@@ -2174,6 +2368,7 @@ end:
                zfree(&pkgs[i].tevs);
        }
        free(pkgs);
+       exit_symbol_maps();
 
        return ret;
 }
@@ -2323,159 +2518,51 @@ static struct strfilter *available_func_filter;
 static int filter_available_functions(struct map *map __maybe_unused,
                                      struct symbol *sym)
 {
-       if (sym->binding == STB_GLOBAL &&
+       if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) &&
            strfilter__compare(available_func_filter, sym->name))
                return 0;
        return 1;
 }
 
-static int __show_available_funcs(struct map *map)
-{
-       if (map__load(map, filter_available_functions)) {
-               pr_err("Failed to load map.\n");
-               return -EINVAL;
-       }
-       if (!dso__sorted_by_name(map->dso, map->type))
-               dso__sort_by_name(map->dso, map->type);
-
-       dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
-       return 0;
-}
-
-static int available_kernel_funcs(const char *module)
+int show_available_funcs(const char *target, struct strfilter *_filter,
+                                       bool user)
 {
        struct map *map;
        int ret;
 
-       ret = init_vmlinux();
+       ret = init_symbol_maps(user);
        if (ret < 0)
                return ret;
 
-       map = kernel_get_module_map(module);
+       /* Get a symbol map */
+       if (user)
+               map = dso__new_map(target);
+       else
+               map = kernel_get_module_map(target);
        if (!map) {
-               pr_err("Failed to find %s map.\n", (module) ? : "kernel");
+               pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
                return -EINVAL;
        }
-       return __show_available_funcs(map);
-}
-
-static int available_user_funcs(const char *target)
-{
-       struct map *map;
-       int ret;
-
-       ret = init_user_exec();
-       if (ret < 0)
-               return ret;
-
-       map = dso__new_map(target);
-       ret = __show_available_funcs(map);
-       dso__delete(map->dso);
-       map__delete(map);
-       return ret;
-}
 
-int show_available_funcs(const char *target, struct strfilter *_filter,
-                                       bool user)
-{
-       setup_pager();
+       /* Load symbols with given filter */
        available_func_filter = _filter;
-
-       if (!user)
-               return available_kernel_funcs(target);
-
-       return available_user_funcs(target);
-}
-
-/*
- * uprobe_events only accepts address:
- * Convert function and any offset to address
- */
-static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
-{
-       struct perf_probe_point *pp = &pev->point;
-       struct symbol *sym;
-       struct map *map = NULL;
-       char *function = NULL;
-       int ret = -EINVAL;
-       unsigned long long vaddr = 0;
-
-       if (!pp->function) {
-               pr_warning("No function specified for uprobes");
-               goto out;
-       }
-
-       function = strdup(pp->function);
-       if (!function) {
-               pr_warning("Failed to allocate memory by strdup.\n");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       map = dso__new_map(exec);
-       if (!map) {
-               pr_warning("Cannot find appropriate DSO for %s.\n", exec);
-               goto out;
-       }
-       available_func_filter = strfilter__new(function, NULL);
        if (map__load(map, filter_available_functions)) {
-               pr_err("Failed to load map.\n");
-               goto out;
-       }
-
-       sym = map__find_symbol_by_name(map, function, NULL);
-       if (!sym) {
-               pr_warning("Cannot find %s in DSO %s\n", function, exec);
-               goto out;
-       }
-
-       if (map->start > sym->start)
-               vaddr = map->start;
-       vaddr += sym->start + pp->offset + map->pgoff;
-       pp->offset = 0;
-
-       if (!pev->event) {
-               pev->event = function;
-               function = NULL;
-       }
-       if (!pev->group) {
-               char *ptr1, *ptr2, *exec_copy;
-
-               pev->group = zalloc(sizeof(char *) * 64);
-               exec_copy = strdup(exec);
-               if (!exec_copy) {
-                       ret = -ENOMEM;
-                       pr_warning("Failed to copy exec string.\n");
-                       goto out;
-               }
-
-               ptr1 = strdup(basename(exec_copy));
-               if (ptr1) {
-                       ptr2 = strpbrk(ptr1, "-._");
-                       if (ptr2)
-                               *ptr2 = '\0';
-                       e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP,
-                                       ptr1);
-                       free(ptr1);
-               }
-               free(exec_copy);
-       }
-       free(pp->function);
-       pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS);
-       if (!pp->function) {
-               ret = -ENOMEM;
-               pr_warning("Failed to allocate memory by zalloc.\n");
-               goto out;
+               pr_err("Failed to load symbols in %s\n", (target) ? : "kernel");
+               goto end;
        }
-       e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr);
-       ret = 0;
+       if (!dso__sorted_by_name(map->dso, map->type))
+               dso__sort_by_name(map->dso, map->type);
 
-out:
-       if (map) {
+       /* Show all (filtered) symbols */
+       setup_pager();
+       dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
+end:
+       if (user) {
                dso__delete(map->dso);
                map__delete(map);
        }
-       if (function)
-               free(function);
+       exit_symbol_maps();
+
        return ret;
 }
+
index fcaf7273e85a35f41ac465c2f343ec07cbd0f1a4..776c9347a3b64252e2f4c9b30b4710b580923b72 100644 (file)
@@ -2,6 +2,7 @@
 #define _PROBE_EVENT_H
 
 #include <stdbool.h>
+#include "intlist.h"
 #include "strlist.h"
 #include "strfilter.h"
 
@@ -76,13 +77,6 @@ struct perf_probe_event {
        struct perf_probe_arg   *args;  /* Arguments */
 };
 
-
-/* Line number container */
-struct line_node {
-       struct list_head        list;
-       int                     line;
-};
-
 /* Line range */
 struct line_range {
        char                    *file;          /* File name */
@@ -92,7 +86,7 @@ struct line_range {
        int                     offset;         /* Start line offset */
        char                    *path;          /* Real path name */
        char                    *comp_dir;      /* Compile directory */
-       struct list_head        line_list;      /* Visible lines */
+       struct intlist          *line_list;     /* Visible lines */
 };
 
 /* List of variables */
@@ -124,7 +118,7 @@ extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
 extern void line_range__clear(struct line_range *lr);
 
 /* Initialize line range */
-extern void line_range__init(struct line_range *lr);
+extern int line_range__init(struct line_range *lr);
 
 /* Internal use: Return kernel/module path */
 extern const char *kernel_get_module_path(const char *module);
index 061edb162b5ba03f9b4f883543faa5c0f27e371d..df0238654698d8967120f538a68b6aec5da18426 100644 (file)
@@ -34,7 +34,9 @@
 
 #include <linux/bitops.h>
 #include "event.h"
+#include "dso.h"
 #include "debug.h"
+#include "intlist.h"
 #include "util.h"
 #include "symbol.h"
 #include "probe-finder.h"
 /* Kprobe tracer basic type is up to u64 */
 #define MAX_BASIC_TYPE_BITS    64
 
-/* Line number list operations */
-
-/* Add a line to line number list */
-static int line_list__add_line(struct list_head *head, int line)
-{
-       struct line_node *ln;
-       struct list_head *p;
-
-       /* Reverse search, because new line will be the last one */
-       list_for_each_entry_reverse(ln, head, list) {
-               if (ln->line < line) {
-                       p = &ln->list;
-                       goto found;
-               } else if (ln->line == line)    /* Already exist */
-                       return 1;
-       }
-       /* List is empty, or the smallest entry */
-       p = head;
-found:
-       pr_debug("line list: add a line %u\n", line);
-       ln = zalloc(sizeof(struct line_node));
-       if (ln == NULL)
-               return -ENOMEM;
-       ln->line = line;
-       INIT_LIST_HEAD(&ln->list);
-       list_add(&ln->list, p);
-       return 0;
-}
-
-/* Check if the line in line number list */
-static int line_list__has_line(struct list_head *head, int line)
-{
-       struct line_node *ln;
-
-       /* Reverse search, because new line will be the last one */
-       list_for_each_entry(ln, head, list)
-               if (ln->line == line)
-                       return 1;
-
-       return 0;
-}
-
-/* Init line number list */
-static void line_list__init(struct list_head *head)
-{
-       INIT_LIST_HEAD(head);
-}
-
-/* Free line number list */
-static void line_list__free(struct list_head *head)
-{
-       struct line_node *ln;
-       while (!list_empty(head)) {
-               ln = list_first_entry(head, struct line_node, list);
-               list_del(&ln->list);
-               free(ln);
-       }
-}
-
 /* Dwarf FL wrappers */
 static char *debuginfo_path;   /* Currently dummy */
 
@@ -147,80 +90,7 @@ error:
        return -ENOENT;
 }
 
-#if _ELFUTILS_PREREQ(0, 148)
-/* This method is buggy if elfutils is older than 0.148 */
-static int __linux_kernel_find_elf(Dwfl_Module *mod,
-                                  void **userdata,
-                                  const char *module_name,
-                                  Dwarf_Addr base,
-                                  char **file_name, Elf **elfp)
-{
-       int fd;
-       const char *path = kernel_get_module_path(module_name);
-
-       pr_debug2("Use file %s for %s\n", path, module_name);
-       if (path) {
-               fd = open(path, O_RDONLY);
-               if (fd >= 0) {
-                       *file_name = strdup(path);
-                       return fd;
-               }
-       }
-       /* If failed, try to call standard method */
-       return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
-                                         file_name, elfp);
-}
-
-static const Dwfl_Callbacks kernel_callbacks = {
-       .find_debuginfo = dwfl_standard_find_debuginfo,
-       .debuginfo_path = &debuginfo_path,
-
-       .find_elf = __linux_kernel_find_elf,
-       .section_address = dwfl_linux_kernel_module_section_address,
-};
-
-/* Get a Dwarf from live kernel image */
-static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
-                                              Dwarf_Addr addr)
-{
-       dbg->dwfl = dwfl_begin(&kernel_callbacks);
-       if (!dbg->dwfl)
-               return -EINVAL;
-
-       /* Load the kernel dwarves: Don't care the result here */
-       dwfl_linux_kernel_report_kernel(dbg->dwfl);
-       dwfl_linux_kernel_report_modules(dbg->dwfl);
-
-       dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
-       /* Here, check whether we could get a real dwarf */
-       if (!dbg->dbg) {
-               pr_debug("Failed to find kernel dwarf at %lx\n",
-                        (unsigned long)addr);
-               dwfl_end(dbg->dwfl);
-               memset(dbg, 0, sizeof(*dbg));
-               return -ENOENT;
-       }
-
-       return 0;
-}
-#else
-/* With older elfutils, this just support kernel module... */
-static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
-                                              Dwarf_Addr addr __maybe_unused)
-{
-       const char *path = kernel_get_module_path("kernel");
-
-       if (!path) {
-               pr_err("Failed to find vmlinux path\n");
-               return -ENOENT;
-       }
-
-       pr_debug2("Use file %s for debuginfo\n", path);
-       return debuginfo__init_offline_dwarf(dbg, path);
-}
-#endif
-
-struct debuginfo *debuginfo__new(const char *path)
+static struct debuginfo *__debuginfo__new(const char *path)
 {
        struct debuginfo *dbg = zalloc(sizeof(*dbg));
        if (!dbg)
@@ -228,21 +98,44 @@ struct debuginfo *debuginfo__new(const char *path)
 
        if (debuginfo__init_offline_dwarf(dbg, path) < 0)
                zfree(&dbg);
-
+       if (dbg)
+               pr_debug("Open Debuginfo file: %s\n", path);
        return dbg;
 }
 
-struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
-{
-       struct debuginfo *dbg = zalloc(sizeof(*dbg));
+enum dso_binary_type distro_dwarf_types[] = {
+       DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
+       DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
+       DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+       DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
+       DSO_BINARY_TYPE__NOT_FOUND,
+};
 
-       if (!dbg)
-               return NULL;
+struct debuginfo *debuginfo__new(const char *path)
+{
+       enum dso_binary_type *type;
+       char buf[PATH_MAX], nil = '\0';
+       struct dso *dso;
+       struct debuginfo *dinfo = NULL;
+
+       /* Try to open distro debuginfo files */
+       dso = dso__new(path);
+       if (!dso)
+               goto out;
 
-       if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0)
-               zfree(&dbg);
+       for (type = distro_dwarf_types;
+            !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
+            type++) {
+               if (dso__read_binary_type_filename(dso, *type, &nil,
+                                                  buf, PATH_MAX) < 0)
+                       continue;
+               dinfo = __debuginfo__new(buf);
+       }
+       dso__delete(dso);
 
-       return dbg;
+out:
+       /* if failed to open all distro debuginfo, open given binary */
+       return dinfo ? : __debuginfo__new(path);
 }
 
 void debuginfo__delete(struct debuginfo *dbg)
@@ -880,7 +773,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
 }
 
 /* Find lines which match lazy pattern */
-static int find_lazy_match_lines(struct list_head *head,
+static int find_lazy_match_lines(struct intlist *list,
                                 const char *fname, const char *pat)
 {
        FILE *fp;
@@ -901,7 +794,7 @@ static int find_lazy_match_lines(struct list_head *head,
                        line[len - 1] = '\0';
 
                if (strlazymatch(line, pat)) {
-                       line_list__add_line(head, linenum);
+                       intlist__add(list, linenum);
                        count++;
                }
                linenum++;
@@ -924,7 +817,7 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
        Dwarf_Die *sc_die, die_mem;
        int ret;
 
-       if (!line_list__has_line(&pf->lcache, lineno) ||
+       if (!intlist__has_entry(pf->lcache, lineno) ||
            strtailcmp(fname, pf->fname) != 0)
                return 0;
 
@@ -952,9 +845,9 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
        int ret = 0;
 
-       if (list_empty(&pf->lcache)) {
+       if (intlist__empty(pf->lcache)) {
                /* Matching lazy line pattern */
-               ret = find_lazy_match_lines(&pf->lcache, pf->fname,
+               ret = find_lazy_match_lines(pf->lcache, pf->fname,
                                            pf->pev->point.lazy_line);
                if (ret <= 0)
                        return ret;
@@ -1096,7 +989,9 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
 #endif
 
        off = 0;
-       line_list__init(&pf->lcache);
+       pf->lcache = intlist__new(NULL);
+       if (!pf->lcache)
+               return -ENOMEM;
 
        /* Fastpath: lookup by function name from .debug_pubnames section */
        if (pp->function) {
@@ -1149,7 +1044,8 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
        }
 
 found:
-       line_list__free(&pf->lcache);
+       intlist__delete(pf->lcache);
+       pf->lcache = NULL;
 
        return ret;
 }
@@ -1537,7 +1433,7 @@ static int line_range_add_line(const char *src, unsigned int lineno,
                if (lr->path == NULL)
                        return -ENOMEM;
        }
-       return line_list__add_line(&lr->line_list, lineno);
+       return intlist__add(lr->line_list, lineno);
 }
 
 static int line_range_walk_cb(const char *fname, int lineno,
@@ -1565,7 +1461,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
 
        /* Update status */
        if (ret >= 0)
-               if (!list_empty(&lf->lr->line_list))
+               if (!intlist__empty(lf->lr->line_list))
                        ret = lf->found = 1;
                else
                        ret = 0;        /* Lines are not found */
index ffc33cdd25cc343816fd9e05586832bf48b82205..92590b2c7e1ce650080652839e5506bf98d9093c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 #include "util.h"
+#include "intlist.h"
 #include "probe-event.h"
 
 #define MAX_PROBE_BUFFER       1024
@@ -29,8 +30,8 @@ struct debuginfo {
        Dwarf_Addr      bias;
 };
 
+/* This also tries to open distro debuginfo */
 extern struct debuginfo *debuginfo__new(const char *path);
-extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
 extern void debuginfo__delete(struct debuginfo *dbg);
 
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
@@ -66,7 +67,7 @@ struct probe_finder {
        const char              *fname;         /* Real file name */
        Dwarf_Die               cu_die;         /* Current CU */
        Dwarf_Die               sp_die;
-       struct list_head        lcache;         /* Line cache for lazy match */
+       struct intlist          *lcache;        /* Line cache for lazy match */
 
        /* For variable searching */
 #if _ELFUTILS_PREREQ(0, 142)
index 595bfc73d2ed28cf14feee7daf73c76d92527223..16a475a7d492177623062143434488116cdf2a38 100644 (file)
@@ -17,6 +17,6 @@ util/xyarray.c
 util/cgroup.c
 util/rblist.c
 util/strlist.c
-util/fs.c
+../lib/api/fs/fs.c
 util/trace-event.c
 ../../lib/rbtree.c
index 373762501dadced6c476235ad8170a5241e72801..049e0a09ccd362b6f79192fe769f75648f3730b1 100644 (file)
@@ -2,7 +2,7 @@
 #include "evsel.h"
 #include "cpumap.h"
 #include "parse-events.h"
-#include "fs.h"
+#include <api/fs/fs.h>
 #include "util.h"
 
 typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
index 0b39a48e5110a00dde5fa0408c725730ba5fe8ff..55960f22233c4c994feff352d2e458113a4f1db4 100644 (file)
@@ -702,11 +702,12 @@ static void regs_dump__printf(u64 mask, u64 *regs)
        }
 }
 
-static void regs_user__printf(struct perf_sample *sample, u64 mask)
+static void regs_user__printf(struct perf_sample *sample)
 {
        struct regs_dump *user_regs = &sample->user_regs;
 
        if (user_regs->regs) {
+               u64 mask = user_regs->mask;
                printf("... user regs: mask 0x%" PRIx64 "\n", mask);
                regs_dump__printf(mask, user_regs->regs);
        }
@@ -793,7 +794,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
        if (!dump_trace)
                return;
 
-       printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
+       printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
               event->header.misc, sample->pid, sample->tid, sample->ip,
               sample->period, sample->addr);
 
@@ -806,7 +807,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
                branch_stack__printf(sample);
 
        if (sample_type & PERF_SAMPLE_REGS_USER)
-               regs_user__printf(sample, evsel->attr.sample_regs_user);
+               regs_user__printf(sample);
 
        if (sample_type & PERF_SAMPLE_STACK_USER)
                stack_user__printf(&sample->user_stack);
@@ -1008,6 +1009,12 @@ static int perf_session__process_user_event(struct perf_session *session, union
                if (err == 0)
                        perf_session__set_id_hdr_size(session);
                return err;
+       case PERF_RECORD_HEADER_EVENT_TYPE:
+               /*
+                * Depreceated, but we need to handle it for sake
+                * of old data files create in pipe mode.
+                */
+               return 0;
        case PERF_RECORD_HEADER_TRACING_DATA:
                /* setup for reading amidst mmap */
                lseek(fd, file_offset, SEEK_SET);
index 759456728703bf1471fcfb1ad600e687d8947033..3b7dbf51d4a93bd425fc41363d98a47acd7288ff 100644 (file)
@@ -151,15 +151,15 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
 
                gelf_getshdr(sec, shp);
                str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
-               if (!strcmp(name, str)) {
+               if (str && !strcmp(name, str)) {
                        if (idx)
                                *idx = cnt;
-                       break;
+                       return sec;
                }
                ++cnt;
        }
 
-       return sec;
+       return NULL;
 }
 
 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
@@ -506,6 +506,8 @@ int filename__read_debuglink(const char *filename, char *debuglink,
        /* the start of this section is a zero-terminated string */
        strncpy(debuglink, data->d_buf, size);
 
+       err = 0;
+
 out_elf_end:
        elf_end(elf);
 out_close:
@@ -751,6 +753,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
                        if (strcmp(elf_name, kmap->ref_reloc_sym->name))
                                continue;
                        kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
+                       map->reloc = kmap->ref_reloc_sym->addr -
+                                    kmap->ref_reloc_sym->unrelocated_addr;
                        break;
                }
        }
@@ -922,6 +926,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
                                  (u64)shdr.sh_offset);
                        sym.st_value -= shdr.sh_addr - shdr.sh_offset;
                }
+new_symbol:
                /*
                 * We need to figure out if the object was created from C++ sources
                 * DWARF DW_compile_unit has this, but we don't always have access
@@ -933,7 +938,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
                        if (demangled != NULL)
                                elf_name = demangled;
                }
-new_symbol:
                f = symbol__new(sym.st_value, sym.st_size,
                                GELF_ST_BIND(sym.st_info), elf_name);
                free(demangled);
index 39ce9adbaaf0bef120e0903e72ad1e98f8114527..95e249779931216f5cbeb5b09c26ea0655a0fcf7 100644 (file)
@@ -410,7 +410,7 @@ struct symbol *dso__find_symbol(struct dso *dso,
        return symbols__find(&dso->symbols[type], addr);
 }
 
-struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
+static struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
 {
        return symbols__first(&dso->symbols[type]);
 }
@@ -627,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
  * kernel range is broken in several maps, named [kernel].N, as we don't have
  * the original ELF section names vmlinux have.
  */
-static int dso__split_kallsyms(struct dso *dso, struct map *map,
+static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
                               symbol_filter_t filter)
 {
        struct map_groups *kmaps = map__kmap(map)->kmaps;
@@ -692,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
                        char dso_name[PATH_MAX];
                        struct dso *ndso;
 
+                       if (delta) {
+                               /* Kernel was relocated at boot time */
+                               pos->start -= delta;
+                               pos->end -= delta;
+                       }
+
                        if (count == 0) {
                                curr_map = map;
                                goto filter_symbol;
@@ -721,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
                        curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
                        map_groups__insert(kmaps, curr_map);
                        ++kernel_range;
+               } else if (delta) {
+                       /* Kernel was relocated at boot time */
+                       pos->start -= delta;
+                       pos->end -= delta;
                }
 filter_symbol:
                if (filter && filter(curr_map, pos)) {
@@ -976,6 +986,23 @@ static int validate_kcore_modules(const char *kallsyms_filename,
        return 0;
 }
 
+static int validate_kcore_addresses(const char *kallsyms_filename,
+                                   struct map *map)
+{
+       struct kmap *kmap = map__kmap(map);
+
+       if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
+               u64 start;
+
+               start = kallsyms__get_function_start(kallsyms_filename,
+                                                    kmap->ref_reloc_sym->name);
+               if (start != kmap->ref_reloc_sym->addr)
+                       return -EINVAL;
+       }
+
+       return validate_kcore_modules(kallsyms_filename, map);
+}
+
 struct kcore_mapfn_data {
        struct dso *dso;
        enum map_type type;
@@ -1019,8 +1046,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
                                             kallsyms_filename))
                return -EINVAL;
 
-       /* All modules must be present at their original addresses */
-       if (validate_kcore_modules(kallsyms_filename, map))
+       /* Modules and kernel must be present at their original addresses */
+       if (validate_kcore_addresses(kallsyms_filename, map))
                return -EINVAL;
 
        md.dso = dso;
@@ -1113,15 +1140,41 @@ out_err:
        return -EINVAL;
 }
 
+/*
+ * If the kernel is relocated at boot time, kallsyms won't match.  Compute the
+ * delta based on the relocation reference symbol.
+ */
+static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
+{
+       struct kmap *kmap = map__kmap(map);
+       u64 addr;
+
+       if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
+               return 0;
+
+       addr = kallsyms__get_function_start(filename,
+                                           kmap->ref_reloc_sym->name);
+       if (!addr)
+               return -1;
+
+       *delta = addr - kmap->ref_reloc_sym->addr;
+       return 0;
+}
+
 int dso__load_kallsyms(struct dso *dso, const char *filename,
                       struct map *map, symbol_filter_t filter)
 {
+       u64 delta = 0;
+
        if (symbol__restricted_filename(filename, "/proc/kallsyms"))
                return -1;
 
        if (dso__load_all_kallsyms(dso, filename, map) < 0)
                return -1;
 
+       if (kallsyms__delta(map, filename, &delta))
+               return -1;
+
        symbols__fixup_duplicate(&dso->symbols[map->type]);
        symbols__fixup_end(&dso->symbols[map->type]);
 
@@ -1133,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
        if (!dso__load_kcore(dso, map, filename))
                return dso__split_kallsyms_for_kcore(dso, map, filter);
        else
-               return dso__split_kallsyms(dso, map, filter);
+               return dso__split_kallsyms(dso, map, delta, filter);
 }
 
 static int dso__load_perf_map(struct dso *dso, struct map *map,
@@ -1198,6 +1251,46 @@ out_failure:
        return -1;
 }
 
+static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
+                                          enum dso_binary_type type)
+{
+       switch (type) {
+       case DSO_BINARY_TYPE__JAVA_JIT:
+       case DSO_BINARY_TYPE__DEBUGLINK:
+       case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
+       case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
+       case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
+       case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
+       case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
+               return !kmod && dso->kernel == DSO_TYPE_USER;
+
+       case DSO_BINARY_TYPE__KALLSYMS:
+       case DSO_BINARY_TYPE__VMLINUX:
+       case DSO_BINARY_TYPE__KCORE:
+               return dso->kernel == DSO_TYPE_KERNEL;
+
+       case DSO_BINARY_TYPE__GUEST_KALLSYMS:
+       case DSO_BINARY_TYPE__GUEST_VMLINUX:
+       case DSO_BINARY_TYPE__GUEST_KCORE:
+               return dso->kernel == DSO_TYPE_GUEST_KERNEL;
+
+       case DSO_BINARY_TYPE__GUEST_KMODULE:
+       case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+               /*
+                * kernel modules know their symtab type - it's set when
+                * creating a module dso in machine__new_module().
+                */
+               return kmod && dso->symtab_type == type;
+
+       case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+               return true;
+
+       case DSO_BINARY_TYPE__NOT_FOUND:
+       default:
+               return false;
+       }
+}
+
 int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
 {
        char *name;
@@ -1208,6 +1301,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        int ss_pos = 0;
        struct symsrc ss_[2];
        struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
+       bool kmod;
 
        dso__set_loaded(dso, map->type);
 
@@ -1248,7 +1342,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        if (!name)
                return -1;
 
-       /* Iterate over candidate debug images.
+       kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
+               dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
+
+       /*
+        * Iterate over candidate debug images.
         * Keep track of "interesting" ones (those which have a symtab, dynsym,
         * and/or opd section) for processing.
         */
@@ -1258,6 +1356,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
 
                enum dso_binary_type symtab_type = binary_type_symtab[i];
 
+               if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
+                       continue;
+
                if (dso__read_binary_type_filename(dso, symtab_type,
                                                   root_dir, name, PATH_MAX))
                        continue;
@@ -1283,6 +1384,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
 
                        if (syms_ss && runtime_ss)
                                break;
+               } else {
+                       symsrc__destroy(ss);
                }
 
        }
@@ -1298,15 +1401,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        if (!runtime_ss && syms_ss)
                runtime_ss = syms_ss;
 
-       if (syms_ss) {
-               int km;
-
-               km = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
-                    dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
-               ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, km);
-       } else {
+       if (syms_ss)
+               ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod);
+       else
                ret = -1;
-       }
 
        if (ret > 0) {
                int nr_plt;
@@ -1424,7 +1522,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
                        continue;
                scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
                          "%s/%s/kallsyms", dir, dent->d_name);
-               if (!validate_kcore_modules(kallsyms_filename, map)) {
+               if (!validate_kcore_addresses(kallsyms_filename, map)) {
                        strlcpy(dir, kallsyms_filename, dir_sz);
                        ret = 0;
                        break;
@@ -1479,7 +1577,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
                if (fd != -1) {
                        close(fd);
                        /* If module maps match go with /proc/kallsyms */
-                       if (!validate_kcore_modules("/proc/kallsyms", map))
+                       if (!validate_kcore_addresses("/proc/kallsyms", map))
                                goto proc_kallsyms;
                }
 
index fffe2888a1c7c123d6e7de3f11eb74dfd4f4ebf8..501e4e722e8e853258e3e06b8448cc5792005971 100644 (file)
@@ -79,6 +79,17 @@ struct symbol {
 void symbol__delete(struct symbol *sym);
 void symbols__delete(struct rb_root *symbols);
 
+/* symbols__for_each_entry - iterate over symbols (rb_root)
+ *
+ * @symbols: the rb_root of symbols
+ * @pos: the 'struct symbol *' to use as a loop cursor
+ * @nd: the 'struct rb_node *' to use as a temporary storage
+ */
+#define symbols__for_each_entry(symbols, pos, nd)                      \
+       for (nd = rb_first(symbols);                                    \
+            nd && (pos = rb_entry(nd, struct symbol, rb_node));        \
+            nd = rb_next(nd))
+
 static inline size_t symbol__size(const struct symbol *sym)
 {
        return sym->end - sym->start + 1;
@@ -175,7 +186,7 @@ struct addr_location {
        struct symbol *sym;
        u64           addr;
        char          level;
-       bool          filtered;
+       u8            filtered;
        u8            cpumode;
        s32           cpu;
 };
@@ -223,7 +234,6 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
                                u64 addr);
 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
                                        const char *name);
-struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
 
 int filename__read_build_id(const char *filename, void *bf, size_t size);
 int sysfs__read_build_id(const char *filename, void *bf, size_t size);
index 0358882c89108723616c4eca0431fed0aa6be200..3ce0498bdae60bb24fe558006e1e02b4ed9ba2b9 100644 (file)
@@ -142,3 +142,24 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
 
        return 0;
 }
+
+void thread__find_cpumode_addr_location(struct thread *thread,
+                                       struct machine *machine,
+                                       enum map_type type, u64 addr,
+                                       struct addr_location *al)
+{
+       size_t i;
+       const u8 const cpumodes[] = {
+               PERF_RECORD_MISC_USER,
+               PERF_RECORD_MISC_KERNEL,
+               PERF_RECORD_MISC_GUEST_USER,
+               PERF_RECORD_MISC_GUEST_KERNEL
+       };
+
+       for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
+               thread__find_addr_location(thread, machine, cpumodes[i], type,
+                                          addr, al);
+               if (al->map)
+                       break;
+       }
+}
index 5b856bf942e11fa9691c28551a88b53b4ac3d5f2..9b29f085aedeaa637da7bb25e571c07a19697cd0 100644 (file)
@@ -44,12 +44,6 @@ void thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
 
-static inline struct map *thread__find_map(struct thread *thread,
-                                          enum map_type type, u64 addr)
-{
-       return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
-}
-
 void thread__find_addr_map(struct thread *thread, struct machine *machine,
                           u8 cpumode, enum map_type type, u64 addr,
                           struct addr_location *al);
@@ -58,6 +52,11 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
                                u8 cpumode, enum map_type type, u64 addr,
                                struct addr_location *al);
 
+void thread__find_cpumode_addr_location(struct thread *thread,
+                                       struct machine *machine,
+                                       enum map_type type, u64 addr,
+                                       struct addr_location *al);
+
 static inline void *thread__priv(struct thread *thread)
 {
        return thread->priv;
index e0d6d07f68485167f2b05260fd932a288b42eec9..c36636fd825b46481dfcadbc745014ed94f38650 100644 (file)
@@ -126,6 +126,7 @@ void event_format__print(struct event_format *event,
        trace_seq_init(&s);
        pevent_event_info(&s, event, &record);
        trace_seq_do_printf(&s);
+       trace_seq_destroy(&s);
 }
 
 void parse_proc_kallsyms(struct pevent *pevent,
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
new file mode 100644 (file)
index 0000000..67db73e
--- /dev/null
@@ -0,0 +1,210 @@
+#include <linux/compiler.h>
+#include <elfutils/libdw.h>
+#include <elfutils/libdwfl.h>
+#include <inttypes.h>
+#include <errno.h>
+#include "unwind.h"
+#include "unwind-libdw.h"
+#include "machine.h"
+#include "thread.h"
+#include "types.h"
+#include "event.h"
+#include "perf_regs.h"
+
+static char *debuginfo_path;
+
+static const Dwfl_Callbacks offline_callbacks = {
+       .find_debuginfo         = dwfl_standard_find_debuginfo,
+       .debuginfo_path         = &debuginfo_path,
+       .section_address        = dwfl_offline_section_address,
+};
+
+static int __report_module(struct addr_location *al, u64 ip,
+                           struct unwind_info *ui)
+{
+       Dwfl_Module *mod;
+       struct dso *dso = NULL;
+
+       thread__find_addr_location(ui->thread, ui->machine,
+                                  PERF_RECORD_MISC_USER,
+                                  MAP__FUNCTION, ip, al);
+
+       if (al->map)
+               dso = al->map->dso;
+
+       if (!dso)
+               return 0;
+
+       mod = dwfl_addrmodule(ui->dwfl, ip);
+       if (!mod)
+               mod = dwfl_report_elf(ui->dwfl, dso->short_name,
+                                     dso->long_name, -1, al->map->start,
+                                     false);
+
+       return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
+}
+
+static int report_module(u64 ip, struct unwind_info *ui)
+{
+       struct addr_location al;
+
+       return __report_module(&al, ip, ui);
+}
+
+static int entry(u64 ip, struct unwind_info *ui)
+
+{
+       struct unwind_entry e;
+       struct addr_location al;
+
+       if (__report_module(&al, ip, ui))
+               return -1;
+
+       e.ip  = ip;
+       e.map = al.map;
+       e.sym = al.sym;
+
+       pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
+                al.sym ? al.sym->name : "''",
+                ip,
+                al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
+
+       return ui->cb(&e, ui->arg);
+}
+
+static pid_t next_thread(Dwfl *dwfl, void *arg, void **thread_argp)
+{
+       /* We want only single thread to be processed. */
+       if (*thread_argp != NULL)
+               return 0;
+
+       *thread_argp = arg;
+       return dwfl_pid(dwfl);
+}
+
+static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
+                         Dwarf_Word *data)
+{
+       struct addr_location al;
+       ssize_t size;
+
+       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
+                             MAP__FUNCTION, addr, &al);
+       if (!al.map) {
+               pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
+               return -1;
+       }
+
+       if (!al.map->dso)
+               return -1;
+
+       size = dso__data_read_addr(al.map->dso, al.map, ui->machine,
+                                  addr, (u8 *) data, sizeof(*data));
+
+       return !(size == sizeof(*data));
+}
+
+static bool memory_read(Dwfl *dwfl __maybe_unused, Dwarf_Addr addr, Dwarf_Word *result,
+                       void *arg)
+{
+       struct unwind_info *ui = arg;
+       struct stack_dump *stack = &ui->sample->user_stack;
+       u64 start, end;
+       int offset;
+       int ret;
+
+       ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
+       if (ret)
+               return false;
+
+       end = start + stack->size;
+
+       /* Check overflow. */
+       if (addr + sizeof(Dwarf_Word) < addr)
+               return false;
+
+       if (addr < start || addr + sizeof(Dwarf_Word) > end) {
+               ret = access_dso_mem(ui, addr, result);
+               if (ret) {
+                       pr_debug("unwind: access_mem 0x%" PRIx64 " not inside range"
+                                " 0x%" PRIx64 "-0x%" PRIx64 "\n",
+                               addr, start, end);
+                       return false;
+               }
+               return true;
+       }
+
+       offset  = addr - start;
+       *result = *(Dwarf_Word *)&stack->data[offset];
+       pr_debug("unwind: access_mem addr 0x%" PRIx64 ", val %lx, offset %d\n",
+                addr, (unsigned long)*result, offset);
+       return true;
+}
+
+static const Dwfl_Thread_Callbacks callbacks = {
+       .next_thread            = next_thread,
+       .memory_read            = memory_read,
+       .set_initial_registers  = libdw__arch_set_initial_registers,
+};
+
+static int
+frame_callback(Dwfl_Frame *state, void *arg)
+{
+       struct unwind_info *ui = arg;
+       Dwarf_Addr pc;
+
+       if (!dwfl_frame_pc(state, &pc, NULL)) {
+               pr_err("%s", dwfl_errmsg(-1));
+               return DWARF_CB_ABORT;
+       }
+
+       return entry(pc, ui) || !(--ui->max_stack) ?
+              DWARF_CB_ABORT : DWARF_CB_OK;
+}
+
+int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
+                       struct machine *machine, struct thread *thread,
+                       struct perf_sample *data,
+                       int max_stack)
+{
+       struct unwind_info ui = {
+               .sample         = data,
+               .thread         = thread,
+               .machine        = machine,
+               .cb             = cb,
+               .arg            = arg,
+               .max_stack      = max_stack,
+       };
+       Dwarf_Word ip;
+       int err = -EINVAL;
+
+       if (!data->user_regs.regs)
+               return -EINVAL;
+
+       ui.dwfl = dwfl_begin(&offline_callbacks);
+       if (!ui.dwfl)
+               goto out;
+
+       err = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
+       if (err)
+               goto out;
+
+       err = report_module(ip, &ui);
+       if (err)
+               goto out;
+
+       if (!dwfl_attach_state(ui.dwfl, EM_NONE, thread->tid, &callbacks, &ui))
+               goto out;
+
+       err = dwfl_getthread_frames(ui.dwfl, thread->tid, frame_callback, &ui);
+
+       if (err && !ui.max_stack)
+               err = 0;
+
+ out:
+       if (err)
+               pr_debug("unwind: failed with '%s'\n", dwfl_errmsg(-1));
+
+       dwfl_end(ui.dwfl);
+       return 0;
+}
diff --git a/tools/perf/util/unwind-libdw.h b/tools/perf/util/unwind-libdw.h
new file mode 100644 (file)
index 0000000..417a142
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __PERF_UNWIND_LIBDW_H
+#define __PERF_UNWIND_LIBDW_H
+
+#include <elfutils/libdwfl.h>
+#include "event.h"
+#include "thread.h"
+#include "unwind.h"
+
+bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg);
+
+struct unwind_info {
+       Dwfl                    *dwfl;
+       struct perf_sample      *sample;
+       struct machine          *machine;
+       struct thread           *thread;
+       unwind_entry_cb_t       cb;
+       void                    *arg;
+       int                     max_stack;
+};
+
+#endif /* __PERF_UNWIND_LIBDW_H */
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
new file mode 100644 (file)
index 0000000..bd5768d
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
+ *
+ * Lots of this code have been borrowed or heavily inspired from parts of
+ * the libunwind 0.99 code which are (amongst other contributors I may have
+ * forgotten):
+ *
+ * Copyright (C) 2002-2007 Hewlett-Packard Co
+ *     Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * And the bugs have been added by:
+ *
+ * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
+ * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
+ *
+ */
+
+#include <elf.h>
+#include <gelf.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <linux/list.h>
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+#include "thread.h"
+#include "session.h"
+#include "perf_regs.h"
+#include "unwind.h"
+#include "symbol.h"
+#include "util.h"
+
+extern int
+UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
+                                   unw_word_t ip,
+                                   unw_dyn_info_t *di,
+                                   unw_proc_info_t *pi,
+                                   int need_unwind_info, void *arg);
+
+#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
+
+extern int
+UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
+                                unw_word_t ip,
+                                unw_word_t segbase,
+                                const char *obj_name, unw_word_t start,
+                                unw_word_t end);
+
+#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
+
+#define DW_EH_PE_FORMAT_MASK   0x0f    /* format of the encoded value */
+#define DW_EH_PE_APPL_MASK     0x70    /* how the value is to be applied */
+
+/* Pointer-encoding formats: */
+#define DW_EH_PE_omit          0xff
+#define DW_EH_PE_ptr           0x00    /* pointer-sized unsigned value */
+#define DW_EH_PE_udata4                0x03    /* unsigned 32-bit value */
+#define DW_EH_PE_udata8                0x04    /* unsigned 64-bit value */
+#define DW_EH_PE_sdata4                0x0b    /* signed 32-bit value */
+#define DW_EH_PE_sdata8                0x0c    /* signed 64-bit value */
+
+/* Pointer-encoding application: */
+#define DW_EH_PE_absptr                0x00    /* absolute value */
+#define DW_EH_PE_pcrel         0x10    /* rel. to addr. of encoded value */
+
+/*
+ * The following are not documented by LSB v1.3, yet they are used by
+ * GCC, presumably they aren't documented by LSB since they aren't
+ * used on Linux:
+ */
+#define DW_EH_PE_funcrel       0x40    /* start-of-procedure-relative */
+#define DW_EH_PE_aligned       0x50    /* aligned pointer */
+
+/* Flags intentionaly not handled, since they're not needed:
+ * #define DW_EH_PE_indirect      0x80
+ * #define DW_EH_PE_uleb128       0x01
+ * #define DW_EH_PE_udata2        0x02
+ * #define DW_EH_PE_sleb128       0x09
+ * #define DW_EH_PE_sdata2        0x0a
+ * #define DW_EH_PE_textrel       0x20
+ * #define DW_EH_PE_datarel       0x30
+ */
+
+struct unwind_info {
+       struct perf_sample      *sample;
+       struct machine          *machine;
+       struct thread           *thread;
+};
+
+#define dw_read(ptr, type, end) ({     \
+       type *__p = (type *) ptr;       \
+       type  __v;                      \
+       if ((__p + 1) > (type *) end)   \
+               return -EINVAL;         \
+       __v = *__p++;                   \
+       ptr = (typeof(ptr)) __p;        \
+       __v;                            \
+       })
+
+static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
+                                  u8 encoding)
+{
+       u8 *cur = *p;
+       *val = 0;
+
+       switch (encoding) {
+       case DW_EH_PE_omit:
+               *val = 0;
+               goto out;
+       case DW_EH_PE_ptr:
+               *val = dw_read(cur, unsigned long, end);
+               goto out;
+       default:
+               break;
+       }
+
+       switch (encoding & DW_EH_PE_APPL_MASK) {
+       case DW_EH_PE_absptr:
+               break;
+       case DW_EH_PE_pcrel:
+               *val = (unsigned long) cur;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if ((encoding & 0x07) == 0x00)
+               encoding |= DW_EH_PE_udata4;
+
+       switch (encoding & DW_EH_PE_FORMAT_MASK) {
+       case DW_EH_PE_sdata4:
+               *val += dw_read(cur, s32, end);
+               break;
+       case DW_EH_PE_udata4:
+               *val += dw_read(cur, u32, end);
+               break;
+       case DW_EH_PE_sdata8:
+               *val += dw_read(cur, s64, end);
+               break;
+       case DW_EH_PE_udata8:
+               *val += dw_read(cur, u64, end);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+ out:
+       *p = cur;
+       return 0;
+}
+
+#define dw_read_encoded_value(ptr, end, enc) ({                        \
+       u64 __v;                                                \
+       if (__dw_read_encoded_value(&ptr, end, &__v, enc)) {    \
+               return -EINVAL;                                 \
+       }                                                       \
+       __v;                                                    \
+       })
+
+static u64 elf_section_offset(int fd, const char *name)
+{
+       Elf *elf;
+       GElf_Ehdr ehdr;
+       GElf_Shdr shdr;
+       u64 offset = 0;
+
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+       if (elf == NULL)
+               return 0;
+
+       do {
+               if (gelf_getehdr(elf, &ehdr) == NULL)
+                       break;
+
+               if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
+                       break;
+
+               offset = shdr.sh_offset;
+       } while (0);
+
+       elf_end(elf);
+       return offset;
+}
+
+struct table_entry {
+       u32 start_ip_offset;
+       u32 fde_offset;
+};
+
+struct eh_frame_hdr {
+       unsigned char version;
+       unsigned char eh_frame_ptr_enc;
+       unsigned char fde_count_enc;
+       unsigned char table_enc;
+
+       /*
+        * The rest of the header is variable-length and consists of the
+        * following members:
+        *
+        *      encoded_t eh_frame_ptr;
+        *      encoded_t fde_count;
+        */
+
+       /* A single encoded pointer should not be more than 8 bytes. */
+       u64 enc[2];
+
+       /*
+        * struct {
+        *    encoded_t start_ip;
+        *    encoded_t fde_addr;
+        * } binary_search_table[fde_count];
+        */
+       char data[0];
+} __packed;
+
+static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
+                              u64 offset, u64 *table_data, u64 *segbase,
+                              u64 *fde_count)
+{
+       struct eh_frame_hdr hdr;
+       u8 *enc = (u8 *) &hdr.enc;
+       u8 *end = (u8 *) &hdr.data;
+       ssize_t r;
+
+       r = dso__data_read_offset(dso, machine, offset,
+                                 (u8 *) &hdr, sizeof(hdr));
+       if (r != sizeof(hdr))
+               return -EINVAL;
+
+       /* We dont need eh_frame_ptr, just skip it. */
+       dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
+
+       *fde_count  = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
+       *segbase    = offset;
+       *table_data = (enc - (u8 *) &hdr) + offset;
+       return 0;
+}
+
+static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
+                                    u64 *table_data, u64 *segbase,
+                                    u64 *fde_count)
+{
+       int ret = -EINVAL, fd;
+       u64 offset;
+
+       fd = dso__data_fd(dso, machine);
+       if (fd < 0)
+               return -EINVAL;
+
+       /* Check the .eh_frame section for unwinding info */
+       offset = elf_section_offset(fd, ".eh_frame_hdr");
+       close(fd);
+
+       if (offset)
+               ret = unwind_spec_ehframe(dso, machine, offset,
+                                         table_data, segbase,
+                                         fde_count);
+
+       return ret;
+}
+
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+static int read_unwind_spec_debug_frame(struct dso *dso,
+                                       struct machine *machine, u64 *offset)
+{
+       int fd = dso__data_fd(dso, machine);
+
+       if (fd < 0)
+               return -EINVAL;
+
+       /* Check the .debug_frame section for unwinding info */
+       *offset = elf_section_offset(fd, ".debug_frame");
+       close(fd);
+
+       if (*offset)
+               return 0;
+
+       return -EINVAL;
+}
+#endif
+
+static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
+{
+       struct addr_location al;
+
+       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
+                             MAP__FUNCTION, ip, &al);
+       return al.map;
+}
+
+static int
+find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
+              int need_unwind_info, void *arg)
+{
+       struct unwind_info *ui = arg;
+       struct map *map;
+       unw_dyn_info_t di;
+       u64 table_data, segbase, fde_count;
+
+       map = find_map(ip, ui);
+       if (!map || !map->dso)
+               return -EINVAL;
+
+       pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
+
+       /* Check the .eh_frame section for unwinding info */
+       if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
+                                      &table_data, &segbase, &fde_count)) {
+               memset(&di, 0, sizeof(di));
+               di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;
+               di.start_ip = map->start;
+               di.end_ip   = map->end;
+               di.u.rti.segbase    = map->start + segbase;
+               di.u.rti.table_data = map->start + table_data;
+               di.u.rti.table_len  = fde_count * sizeof(struct table_entry)
+                                     / sizeof(unw_word_t);
+               return dwarf_search_unwind_table(as, ip, &di, pi,
+                                                need_unwind_info, arg);
+       }
+
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+       /* Check the .debug_frame section for unwinding info */
+       if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
+               memset(&di, 0, sizeof(di));
+               if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name,
+                                          map->start, map->end))
+                       return dwarf_search_unwind_table(as, ip, &di, pi,
+                                                        need_unwind_info, arg);
+       }
+#endif
+
+       return -EINVAL;
+}
+
+static int access_fpreg(unw_addr_space_t __maybe_unused as,
+                       unw_regnum_t __maybe_unused num,
+                       unw_fpreg_t __maybe_unused *val,
+                       int __maybe_unused __write,
+                       void __maybe_unused *arg)
+{
+       pr_err("unwind: access_fpreg unsupported\n");
+       return -UNW_EINVAL;
+}
+
+static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
+                                 unw_word_t __maybe_unused *dil_addr,
+                                 void __maybe_unused *arg)
+{
+       return -UNW_ENOINFO;
+}
+
+static int resume(unw_addr_space_t __maybe_unused as,
+                 unw_cursor_t __maybe_unused *cu,
+                 void __maybe_unused *arg)
+{
+       pr_err("unwind: resume unsupported\n");
+       return -UNW_EINVAL;
+}
+
+static int
+get_proc_name(unw_addr_space_t __maybe_unused as,
+             unw_word_t __maybe_unused addr,
+               char __maybe_unused *bufp, size_t __maybe_unused buf_len,
+               unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
+{
+       pr_err("unwind: get_proc_name unsupported\n");
+       return -UNW_EINVAL;
+}
+
+static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
+                         unw_word_t *data)
+{
+       struct addr_location al;
+       ssize_t size;
+
+       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
+                             MAP__FUNCTION, addr, &al);
+       if (!al.map) {
+               pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
+               return -1;
+       }
+
+       if (!al.map->dso)
+               return -1;
+
+       size = dso__data_read_addr(al.map->dso, al.map, ui->machine,
+                                  addr, (u8 *) data, sizeof(*data));
+
+       return !(size == sizeof(*data));
+}
+
+static int access_mem(unw_addr_space_t __maybe_unused as,
+                     unw_word_t addr, unw_word_t *valp,
+                     int __write, void *arg)
+{
+       struct unwind_info *ui = arg;
+       struct stack_dump *stack = &ui->sample->user_stack;
+       u64 start, end;
+       int offset;
+       int ret;
+
+       /* Don't support write, probably not needed. */
+       if (__write || !stack || !ui->sample->user_regs.regs) {
+               *valp = 0;
+               return 0;
+       }
+
+       ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
+       if (ret)
+               return ret;
+
+       end = start + stack->size;
+
+       /* Check overflow. */
+       if (addr + sizeof(unw_word_t) < addr)
+               return -EINVAL;
+
+       if (addr < start || addr + sizeof(unw_word_t) >= end) {
+               ret = access_dso_mem(ui, addr, valp);
+               if (ret) {
+                       pr_debug("unwind: access_mem %p not inside range"
+                                " 0x%" PRIx64 "-0x%" PRIx64 "\n",
+                                (void *) addr, start, end);
+                       *valp = 0;
+                       return ret;
+               }
+               return 0;
+       }
+
+       offset = addr - start;
+       *valp  = *(unw_word_t *)&stack->data[offset];
+       pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
+                (void *) addr, (unsigned long)*valp, offset);
+       return 0;
+}
+
+static int access_reg(unw_addr_space_t __maybe_unused as,
+                     unw_regnum_t regnum, unw_word_t *valp,
+                     int __write, void *arg)
+{
+       struct unwind_info *ui = arg;
+       int id, ret;
+       u64 val;
+
+       /* Don't support write, I suspect we don't need it. */
+       if (__write) {
+               pr_err("unwind: access_reg w %d\n", regnum);
+               return 0;
+       }
+
+       if (!ui->sample->user_regs.regs) {
+               *valp = 0;
+               return 0;
+       }
+
+       id = libunwind__arch_reg_id(regnum);
+       if (id < 0)
+               return -EINVAL;
+
+       ret = perf_reg_value(&val, &ui->sample->user_regs, id);
+       if (ret) {
+               pr_err("unwind: can't read reg %d\n", regnum);
+               return ret;
+       }
+
+       *valp = (unw_word_t) val;
+       pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
+       return 0;
+}
+
+static void put_unwind_info(unw_addr_space_t __maybe_unused as,
+                           unw_proc_info_t *pi __maybe_unused,
+                           void *arg __maybe_unused)
+{
+       pr_debug("unwind: put_unwind_info called\n");
+}
+
+static int entry(u64 ip, struct thread *thread, struct machine *machine,
+                unwind_entry_cb_t cb, void *arg)
+{
+       struct unwind_entry e;
+       struct addr_location al;
+
+       thread__find_addr_location(thread, machine,
+                                  PERF_RECORD_MISC_USER,
+                                  MAP__FUNCTION, ip, &al);
+
+       e.ip = ip;
+       e.map = al.map;
+       e.sym = al.sym;
+
+       pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
+                al.sym ? al.sym->name : "''",
+                ip,
+                al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
+
+       return cb(&e, arg);
+}
+
+static void display_error(int err)
+{
+       switch (err) {
+       case UNW_EINVAL:
+               pr_err("unwind: Only supports local.\n");
+               break;
+       case UNW_EUNSPEC:
+               pr_err("unwind: Unspecified error.\n");
+               break;
+       case UNW_EBADREG:
+               pr_err("unwind: Register unavailable.\n");
+               break;
+       default:
+               break;
+       }
+}
+
+static unw_accessors_t accessors = {
+       .find_proc_info         = find_proc_info,
+       .put_unwind_info        = put_unwind_info,
+       .get_dyn_info_list_addr = get_dyn_info_list_addr,
+       .access_mem             = access_mem,
+       .access_reg             = access_reg,
+       .access_fpreg           = access_fpreg,
+       .resume                 = resume,
+       .get_proc_name          = get_proc_name,
+};
+
+static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
+                      void *arg, int max_stack)
+{
+       unw_addr_space_t addr_space;
+       unw_cursor_t c;
+       int ret;
+
+       addr_space = unw_create_addr_space(&accessors, 0);
+       if (!addr_space) {
+               pr_err("unwind: Can't create unwind address space.\n");
+               return -ENOMEM;
+       }
+
+       ret = unw_init_remote(&c, addr_space, ui);
+       if (ret)
+               display_error(ret);
+
+       while (!ret && (unw_step(&c) > 0) && max_stack--) {
+               unw_word_t ip;
+
+               unw_get_reg(&c, UNW_REG_IP, &ip);
+               ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
+       }
+
+       unw_destroy_addr_space(addr_space);
+       return ret;
+}
+
+int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
+                       struct machine *machine, struct thread *thread,
+                       struct perf_sample *data, int max_stack)
+{
+       u64 ip;
+       struct unwind_info ui = {
+               .sample       = data,
+               .thread       = thread,
+               .machine      = machine,
+       };
+       int ret;
+
+       if (!data->user_regs.regs)
+               return -EINVAL;
+
+       ret = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP);
+       if (ret)
+               return ret;
+
+       ret = entry(ip, thread, machine, cb, arg);
+       if (ret)
+               return -ENOMEM;
+
+       return --max_stack > 0 ? get_entries(&ui, cb, arg, max_stack) : 0;
+}
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
deleted file mode 100644 (file)
index 742f23b..0000000
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
- *
- * Lots of this code have been borrowed or heavily inspired from parts of
- * the libunwind 0.99 code which are (amongst other contributors I may have
- * forgotten):
- *
- * Copyright (C) 2002-2007 Hewlett-Packard Co
- *     Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * And the bugs have been added by:
- *
- * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
- * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
- *
- */
-
-#include <elf.h>
-#include <gelf.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <linux/list.h>
-#include <libunwind.h>
-#include <libunwind-ptrace.h>
-#include "thread.h"
-#include "session.h"
-#include "perf_regs.h"
-#include "unwind.h"
-#include "symbol.h"
-#include "util.h"
-
-extern int
-UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
-                                   unw_word_t ip,
-                                   unw_dyn_info_t *di,
-                                   unw_proc_info_t *pi,
-                                   int need_unwind_info, void *arg);
-
-#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
-
-extern int
-UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
-                                unw_word_t ip,
-                                unw_word_t segbase,
-                                const char *obj_name, unw_word_t start,
-                                unw_word_t end);
-
-#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
-
-#define DW_EH_PE_FORMAT_MASK   0x0f    /* format of the encoded value */
-#define DW_EH_PE_APPL_MASK     0x70    /* how the value is to be applied */
-
-/* Pointer-encoding formats: */
-#define DW_EH_PE_omit          0xff
-#define DW_EH_PE_ptr           0x00    /* pointer-sized unsigned value */
-#define DW_EH_PE_udata4                0x03    /* unsigned 32-bit value */
-#define DW_EH_PE_udata8                0x04    /* unsigned 64-bit value */
-#define DW_EH_PE_sdata4                0x0b    /* signed 32-bit value */
-#define DW_EH_PE_sdata8                0x0c    /* signed 64-bit value */
-
-/* Pointer-encoding application: */
-#define DW_EH_PE_absptr                0x00    /* absolute value */
-#define DW_EH_PE_pcrel         0x10    /* rel. to addr. of encoded value */
-
-/*
- * The following are not documented by LSB v1.3, yet they are used by
- * GCC, presumably they aren't documented by LSB since they aren't
- * used on Linux:
- */
-#define DW_EH_PE_funcrel       0x40    /* start-of-procedure-relative */
-#define DW_EH_PE_aligned       0x50    /* aligned pointer */
-
-/* Flags intentionaly not handled, since they're not needed:
- * #define DW_EH_PE_indirect      0x80
- * #define DW_EH_PE_uleb128       0x01
- * #define DW_EH_PE_udata2        0x02
- * #define DW_EH_PE_sleb128       0x09
- * #define DW_EH_PE_sdata2        0x0a
- * #define DW_EH_PE_textrel       0x20
- * #define DW_EH_PE_datarel       0x30
- */
-
-struct unwind_info {
-       struct perf_sample      *sample;
-       struct machine          *machine;
-       struct thread           *thread;
-       u64                     sample_uregs;
-};
-
-#define dw_read(ptr, type, end) ({     \
-       type *__p = (type *) ptr;       \
-       type  __v;                      \
-       if ((__p + 1) > (type *) end)   \
-               return -EINVAL;         \
-       __v = *__p++;                   \
-       ptr = (typeof(ptr)) __p;        \
-       __v;                            \
-       })
-
-static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
-                                  u8 encoding)
-{
-       u8 *cur = *p;
-       *val = 0;
-
-       switch (encoding) {
-       case DW_EH_PE_omit:
-               *val = 0;
-               goto out;
-       case DW_EH_PE_ptr:
-               *val = dw_read(cur, unsigned long, end);
-               goto out;
-       default:
-               break;
-       }
-
-       switch (encoding & DW_EH_PE_APPL_MASK) {
-       case DW_EH_PE_absptr:
-               break;
-       case DW_EH_PE_pcrel:
-               *val = (unsigned long) cur;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if ((encoding & 0x07) == 0x00)
-               encoding |= DW_EH_PE_udata4;
-
-       switch (encoding & DW_EH_PE_FORMAT_MASK) {
-       case DW_EH_PE_sdata4:
-               *val += dw_read(cur, s32, end);
-               break;
-       case DW_EH_PE_udata4:
-               *val += dw_read(cur, u32, end);
-               break;
-       case DW_EH_PE_sdata8:
-               *val += dw_read(cur, s64, end);
-               break;
-       case DW_EH_PE_udata8:
-               *val += dw_read(cur, u64, end);
-               break;
-       default:
-               return -EINVAL;
-       }
-
- out:
-       *p = cur;
-       return 0;
-}
-
-#define dw_read_encoded_value(ptr, end, enc) ({                        \
-       u64 __v;                                                \
-       if (__dw_read_encoded_value(&ptr, end, &__v, enc)) {    \
-               return -EINVAL;                                 \
-       }                                                       \
-       __v;                                                    \
-       })
-
-static u64 elf_section_offset(int fd, const char *name)
-{
-       Elf *elf;
-       GElf_Ehdr ehdr;
-       GElf_Shdr shdr;
-       u64 offset = 0;
-
-       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
-       if (elf == NULL)
-               return 0;
-
-       do {
-               if (gelf_getehdr(elf, &ehdr) == NULL)
-                       break;
-
-               if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
-                       break;
-
-               offset = shdr.sh_offset;
-       } while (0);
-
-       elf_end(elf);
-       return offset;
-}
-
-struct table_entry {
-       u32 start_ip_offset;
-       u32 fde_offset;
-};
-
-struct eh_frame_hdr {
-       unsigned char version;
-       unsigned char eh_frame_ptr_enc;
-       unsigned char fde_count_enc;
-       unsigned char table_enc;
-
-       /*
-        * The rest of the header is variable-length and consists of the
-        * following members:
-        *
-        *      encoded_t eh_frame_ptr;
-        *      encoded_t fde_count;
-        */
-
-       /* A single encoded pointer should not be more than 8 bytes. */
-       u64 enc[2];
-
-       /*
-        * struct {
-        *    encoded_t start_ip;
-        *    encoded_t fde_addr;
-        * } binary_search_table[fde_count];
-        */
-       char data[0];
-} __packed;
-
-static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
-                              u64 offset, u64 *table_data, u64 *segbase,
-                              u64 *fde_count)
-{
-       struct eh_frame_hdr hdr;
-       u8 *enc = (u8 *) &hdr.enc;
-       u8 *end = (u8 *) &hdr.data;
-       ssize_t r;
-
-       r = dso__data_read_offset(dso, machine, offset,
-                                 (u8 *) &hdr, sizeof(hdr));
-       if (r != sizeof(hdr))
-               return -EINVAL;
-
-       /* We dont need eh_frame_ptr, just skip it. */
-       dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
-
-       *fde_count  = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
-       *segbase    = offset;
-       *table_data = (enc - (u8 *) &hdr) + offset;
-       return 0;
-}
-
-static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
-                                    u64 *table_data, u64 *segbase,
-                                    u64 *fde_count)
-{
-       int ret = -EINVAL, fd;
-       u64 offset;
-
-       fd = dso__data_fd(dso, machine);
-       if (fd < 0)
-               return -EINVAL;
-
-       /* Check the .eh_frame section for unwinding info */
-       offset = elf_section_offset(fd, ".eh_frame_hdr");
-       close(fd);
-
-       if (offset)
-               ret = unwind_spec_ehframe(dso, machine, offset,
-                                         table_data, segbase,
-                                         fde_count);
-
-       return ret;
-}
-
-#ifndef NO_LIBUNWIND_DEBUG_FRAME
-static int read_unwind_spec_debug_frame(struct dso *dso,
-                                       struct machine *machine, u64 *offset)
-{
-       int fd = dso__data_fd(dso, machine);
-
-       if (fd < 0)
-               return -EINVAL;
-
-       /* Check the .debug_frame section for unwinding info */
-       *offset = elf_section_offset(fd, ".debug_frame");
-       close(fd);
-
-       if (*offset)
-               return 0;
-
-       return -EINVAL;
-}
-#endif
-
-static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
-{
-       struct addr_location al;
-
-       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
-                             MAP__FUNCTION, ip, &al);
-       return al.map;
-}
-
-static int
-find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
-              int need_unwind_info, void *arg)
-{
-       struct unwind_info *ui = arg;
-       struct map *map;
-       unw_dyn_info_t di;
-       u64 table_data, segbase, fde_count;
-
-       map = find_map(ip, ui);
-       if (!map || !map->dso)
-               return -EINVAL;
-
-       pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
-
-       /* Check the .eh_frame section for unwinding info */
-       if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
-                                      &table_data, &segbase, &fde_count)) {
-               memset(&di, 0, sizeof(di));
-               di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;
-               di.start_ip = map->start;
-               di.end_ip   = map->end;
-               di.u.rti.segbase    = map->start + segbase;
-               di.u.rti.table_data = map->start + table_data;
-               di.u.rti.table_len  = fde_count * sizeof(struct table_entry)
-                                     / sizeof(unw_word_t);
-               return dwarf_search_unwind_table(as, ip, &di, pi,
-                                                need_unwind_info, arg);
-       }
-
-#ifndef NO_LIBUNWIND_DEBUG_FRAME
-       /* Check the .debug_frame section for unwinding info */
-       if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
-               memset(&di, 0, sizeof(di));
-               if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name,
-                                          map->start, map->end))
-                       return dwarf_search_unwind_table(as, ip, &di, pi,
-                                                        need_unwind_info, arg);
-       }
-#endif
-
-       return -EINVAL;
-}
-
-static int access_fpreg(unw_addr_space_t __maybe_unused as,
-                       unw_regnum_t __maybe_unused num,
-                       unw_fpreg_t __maybe_unused *val,
-                       int __maybe_unused __write,
-                       void __maybe_unused *arg)
-{
-       pr_err("unwind: access_fpreg unsupported\n");
-       return -UNW_EINVAL;
-}
-
-static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
-                                 unw_word_t __maybe_unused *dil_addr,
-                                 void __maybe_unused *arg)
-{
-       return -UNW_ENOINFO;
-}
-
-static int resume(unw_addr_space_t __maybe_unused as,
-                 unw_cursor_t __maybe_unused *cu,
-                 void __maybe_unused *arg)
-{
-       pr_err("unwind: resume unsupported\n");
-       return -UNW_EINVAL;
-}
-
-static int
-get_proc_name(unw_addr_space_t __maybe_unused as,
-             unw_word_t __maybe_unused addr,
-               char __maybe_unused *bufp, size_t __maybe_unused buf_len,
-               unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
-{
-       pr_err("unwind: get_proc_name unsupported\n");
-       return -UNW_EINVAL;
-}
-
-static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
-                         unw_word_t *data)
-{
-       struct addr_location al;
-       ssize_t size;
-
-       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
-                             MAP__FUNCTION, addr, &al);
-       if (!al.map) {
-               pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
-               return -1;
-       }
-
-       if (!al.map->dso)
-               return -1;
-
-       size = dso__data_read_addr(al.map->dso, al.map, ui->machine,
-                                  addr, (u8 *) data, sizeof(*data));
-
-       return !(size == sizeof(*data));
-}
-
-static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id,
-                    u64 sample_regs)
-{
-       int i, idx = 0;
-
-       if (!(sample_regs & (1 << id)))
-               return -EINVAL;
-
-       for (i = 0; i < id; i++) {
-               if (sample_regs & (1 << i))
-                       idx++;
-       }
-
-       *valp = regs->regs[idx];
-       return 0;
-}
-
-static int access_mem(unw_addr_space_t __maybe_unused as,
-                     unw_word_t addr, unw_word_t *valp,
-                     int __write, void *arg)
-{
-       struct unwind_info *ui = arg;
-       struct stack_dump *stack = &ui->sample->user_stack;
-       unw_word_t start, end;
-       int offset;
-       int ret;
-
-       /* Don't support write, probably not needed. */
-       if (__write || !stack || !ui->sample->user_regs.regs) {
-               *valp = 0;
-               return 0;
-       }
-
-       ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP,
-                       ui->sample_uregs);
-       if (ret)
-               return ret;
-
-       end = start + stack->size;
-
-       /* Check overflow. */
-       if (addr + sizeof(unw_word_t) < addr)
-               return -EINVAL;
-
-       if (addr < start || addr + sizeof(unw_word_t) >= end) {
-               ret = access_dso_mem(ui, addr, valp);
-               if (ret) {
-                       pr_debug("unwind: access_mem %p not inside range %p-%p\n",
-                               (void *)addr, (void *)start, (void *)end);
-                       *valp = 0;
-                       return ret;
-               }
-               return 0;
-       }
-
-       offset = addr - start;
-       *valp  = *(unw_word_t *)&stack->data[offset];
-       pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n",
-                (void *)addr, (unsigned long)*valp, offset);
-       return 0;
-}
-
-static int access_reg(unw_addr_space_t __maybe_unused as,
-                     unw_regnum_t regnum, unw_word_t *valp,
-                     int __write, void *arg)
-{
-       struct unwind_info *ui = arg;
-       int id, ret;
-
-       /* Don't support write, I suspect we don't need it. */
-       if (__write) {
-               pr_err("unwind: access_reg w %d\n", regnum);
-               return 0;
-       }
-
-       if (!ui->sample->user_regs.regs) {
-               *valp = 0;
-               return 0;
-       }
-
-       id = unwind__arch_reg_id(regnum);
-       if (id < 0)
-               return -EINVAL;
-
-       ret = reg_value(valp, &ui->sample->user_regs, id, ui->sample_uregs);
-       if (ret) {
-               pr_err("unwind: can't read reg %d\n", regnum);
-               return ret;
-       }
-
-       pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
-       return 0;
-}
-
-static void put_unwind_info(unw_addr_space_t __maybe_unused as,
-                           unw_proc_info_t *pi __maybe_unused,
-                           void *arg __maybe_unused)
-{
-       pr_debug("unwind: put_unwind_info called\n");
-}
-
-static int entry(u64 ip, struct thread *thread, struct machine *machine,
-                unwind_entry_cb_t cb, void *arg)
-{
-       struct unwind_entry e;
-       struct addr_location al;
-
-       thread__find_addr_location(thread, machine,
-                                  PERF_RECORD_MISC_USER,
-                                  MAP__FUNCTION, ip, &al);
-
-       e.ip = ip;
-       e.map = al.map;
-       e.sym = al.sym;
-
-       pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
-                al.sym ? al.sym->name : "''",
-                ip,
-                al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
-
-       return cb(&e, arg);
-}
-
-static void display_error(int err)
-{
-       switch (err) {
-       case UNW_EINVAL:
-               pr_err("unwind: Only supports local.\n");
-               break;
-       case UNW_EUNSPEC:
-               pr_err("unwind: Unspecified error.\n");
-               break;
-       case UNW_EBADREG:
-               pr_err("unwind: Register unavailable.\n");
-               break;
-       default:
-               break;
-       }
-}
-
-static unw_accessors_t accessors = {
-       .find_proc_info         = find_proc_info,
-       .put_unwind_info        = put_unwind_info,
-       .get_dyn_info_list_addr = get_dyn_info_list_addr,
-       .access_mem             = access_mem,
-       .access_reg             = access_reg,
-       .access_fpreg           = access_fpreg,
-       .resume                 = resume,
-       .get_proc_name          = get_proc_name,
-};
-
-static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
-                      void *arg, int max_stack)
-{
-       unw_addr_space_t addr_space;
-       unw_cursor_t c;
-       int ret;
-
-       addr_space = unw_create_addr_space(&accessors, 0);
-       if (!addr_space) {
-               pr_err("unwind: Can't create unwind address space.\n");
-               return -ENOMEM;
-       }
-
-       ret = unw_init_remote(&c, addr_space, ui);
-       if (ret)
-               display_error(ret);
-
-       while (!ret && (unw_step(&c) > 0) && max_stack--) {
-               unw_word_t ip;
-
-               unw_get_reg(&c, UNW_REG_IP, &ip);
-               ret = entry(ip, ui->thread, ui->machine, cb, arg);
-       }
-
-       unw_destroy_addr_space(addr_space);
-       return ret;
-}
-
-int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
-                       struct machine *machine, struct thread *thread,
-                       u64 sample_uregs, struct perf_sample *data,
-                       int max_stack)
-{
-       unw_word_t ip;
-       struct unwind_info ui = {
-               .sample       = data,
-               .sample_uregs = sample_uregs,
-               .thread       = thread,
-               .machine      = machine,
-       };
-       int ret;
-
-       if (!data->user_regs.regs)
-               return -EINVAL;
-
-       ret = reg_value(&ip, &data->user_regs, PERF_REG_IP, sample_uregs);
-       if (ret)
-               return ret;
-
-       ret = entry(ip, thread, machine, cb, arg);
-       if (ret)
-               return -ENOMEM;
-
-       return get_entries(&ui, cb, arg, max_stack);
-}
index d5966f49e22cc24fb91e8f53307504cfed7e290d..b031316f221a7de76c1930d8289ba03300748672 100644 (file)
@@ -13,24 +13,25 @@ struct unwind_entry {
 
 typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
 
-#ifdef HAVE_LIBUNWIND_SUPPORT
+#ifdef HAVE_DWARF_UNWIND_SUPPORT
 int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
                        struct machine *machine,
                        struct thread *thread,
-                       u64 sample_uregs,
                        struct perf_sample *data, int max_stack);
-int unwind__arch_reg_id(int regnum);
+/* libunwind specific */
+#ifdef HAVE_LIBUNWIND_SUPPORT
+int libunwind__arch_reg_id(int regnum);
+#endif
 #else
 static inline int
 unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
                    void *arg __maybe_unused,
                    struct machine *machine __maybe_unused,
                    struct thread *thread __maybe_unused,
-                   u64 sample_uregs __maybe_unused,
                    struct perf_sample *data __maybe_unused,
                    int max_stack __maybe_unused)
 {
        return 0;
 }
-#endif /* HAVE_LIBUNWIND_SUPPORT */
+#endif /* HAVE_DWARF_UNWIND_SUPPORT */
 #endif /* __UNWIND_H */
index 42ad667bb317570e6f22216598181d1e2a8c9798..9f66549562bd6959907323573edcb91badd97380 100644 (file)
@@ -1,6 +1,6 @@
 #include "../perf.h"
 #include "util.h"
-#include "fs.h"
+#include <api/fs/fs.h>
 #include <sys/mman.h>
 #ifdef HAVE_BACKTRACE_SUPPORT
 #include <execinfo.h>
index d66418237d21522df42e33a316b808c1e5962ffd..aa290c0de6f56d9e3f142d46124ee5d0688dd68d 100644 (file)
@@ -201,6 +201,7 @@ int main(int argc, char **argv)
 
        msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
        if (msgque.msq_id == -1) {
+               err = -errno;
                printf("Can't create queue\n");
                goto err_out;
        }
index 587561d7c035a053f590fe8d33a591f8ee78c477..9b17e810ddc39c96f4b7f7e2fead951455bb9c8e 100644 (file)
@@ -96,6 +96,7 @@ identify_qemu () {
                echo qemu-system-ppc64
        else
                echo Cannot figure out what qemu command to use! 1>&2
+               echo file $1 output: $u
                # Usually this will be one of /usr/bin/qemu-system-*
                # Use RCU_QEMU_CMD environment variable or appropriate
                # argument to top-level script.
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
new file mode 100755 (executable)
index 0000000..829186e
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Analyze a given results directory for locktorture progress.
+#
+# Usage: sh kvm-recheck-lock.sh resdir
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2014
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+i="$1"
+if test -d $i
+then
+       :
+else
+       echo Unreadable results directory: $i
+       exit 1
+fi
+
+configfile=`echo $i | sed -e 's/^.*\///'`
+ncs=`grep "Writes:  Total:" $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* Total: //' -e 's/ .*$//'`
+if test -z "$ncs"
+then
+       echo $configfile
+else
+       title="$configfile ------- $ncs acquisitions/releases"
+       dur=`sed -e 's/^.* locktorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
+       if test -z "$dur"
+       then
+               :
+       else
+               ncsps=`awk -v ncs=$ncs -v dur=$dur '
+                       BEGIN { print ncs / dur }' < /dev/null`
+               title="$title ($ncsps per second)"
+       fi
+       echo $title
+fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
new file mode 100755 (executable)
index 0000000..d75b1dc
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Analyze a given results directory for rcutorture progress.
+#
+# Usage: sh kvm-recheck-rcu.sh resdir
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2014
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+i="$1"
+if test -d $i
+then
+       :
+else
+       echo Unreadable results directory: $i
+       exit 1
+fi
+
+configfile=`echo $i | sed -e 's/^.*\///'`
+ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'`
+if test -z "$ngps"
+then
+       echo $configfile
+else
+       title="$configfile ------- $ngps grace periods"
+       dur=`sed -e 's/^.* rcutorture.shutdown_secs=//' -e 's/ .*$//' < $i/qemu-cmd 2> /dev/null`
+       if test -z "$dur"
+       then
+               :
+       else
+               ngpsps=`awk -v ngps=$ngps -v dur=$dur '
+                       BEGIN { print ngps / dur }' < /dev/null`
+               title="$title ($ngpsps per second)"
+       fi
+       echo $title
+fi
index baef09f3469b1dbb914ad0459076adbd027a1cd0..a44daaa259a912e91837e102e6d35c290a17d21d 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Given the results directories for previous KVM runs of rcutorture,
+# Given the results directories for previous KVM-based torture runs,
 # check the build and console output for errors.  Given a directory
 # containing results directories, this recursively checks them all.
 #
 PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
 for rd in "$@"
 do
+       firsttime=1
        dirs=`find $rd -name Make.defconfig.out -print | sort | sed -e 's,/[^/]*$,,' | sort -u`
        for i in $dirs
        do
-               configfile=`echo $i | sed -e 's/^.*\///'`
-               echo $configfile
+               if test -n "$firsttime"
+               then
+                       firsttime=""
+                       resdir=`echo $i | sed -e 's,/$,,' -e 's,/[^/]*$,,'`
+                       head -1 $resdir/log
+               fi
+               TORTURE_SUITE="`cat $i/../TORTURE_SUITE`"
+               kvm-recheck-${TORTURE_SUITE}.sh $i
                configcheck.sh $i/.config $i/ConfigFragment
                parse-build.sh $i/Make.out $configfile
                parse-rcutorture.sh $i/console.log $configfile
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh
deleted file mode 100755 (executable)
index 151b237..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/bin/bash
-#
-# Run a kvm-based test of the specified tree on the specified configs.
-# Fully automated run and error checking, no graphics console.
-#
-# Execute this in the source tree.  Do not run it as a background task
-# because qemu does not seem to like that much.
-#
-# Usage: sh kvm-test-1-rcu.sh config builddir resdir minutes qemu-args bootargs
-#
-# qemu-args defaults to "" -- you will want "-nographic" if running headless.
-# bootargs defaults to "root=/dev/sda noapic selinux=0 console=ttyS0"
-#                      "initcall_debug debug rcutorture.stat_interval=15"
-#                      "rcutorture.shutdown_secs=$((minutes * 60))"
-#                      "rcutorture.rcutorture_runnable=1"
-#
-# Anything you specify for either qemu-args or bootargs is appended to
-# the default values.  The "-smp" value is deduced from the contents of
-# the config fragment.
-#
-# More sophisticated argument parsing is clearly needed.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2011
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-grace=120
-
-T=/tmp/kvm-test-1-rcu.sh.$$
-trap 'rm -rf $T' 0
-
-. $KVM/bin/functions.sh
-. $KVPATH/ver_functions.sh
-
-config_template=${1}
-title=`echo $config_template | sed -e 's/^.*\///'`
-builddir=${2}
-if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
-then
-       echo "kvm-test-1-rcu.sh :$builddir: Not a writable directory, cannot build into it"
-       exit 1
-fi
-resdir=${3}
-if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir"
-then
-       echo "kvm-test-1-rcu.sh :$resdir: Not a writable directory, cannot build into it"
-       exit 1
-fi
-cp $config_template $resdir/ConfigFragment
-echo ' ---' `date`: Starting build
-echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
-cat << '___EOF___' >> $T
-CONFIG_RCU_TORTURE_TEST=y
-___EOF___
-# Optimizations below this point
-# CONFIG_USB=n
-# CONFIG_SECURITY=n
-# CONFIG_NFS_FS=n
-# CONFIG_SOUND=n
-# CONFIG_INPUT_JOYSTICK=n
-# CONFIG_INPUT_TABLET=n
-# CONFIG_INPUT_TOUCHSCREEN=n
-# CONFIG_INPUT_MISC=n
-# CONFIG_INPUT_MOUSE=n
-# # CONFIG_NET=n # disables console access, so accept the slower build.
-# CONFIG_SCSI=n
-# CONFIG_ATA=n
-# CONFIG_FAT_FS=n
-# CONFIG_MSDOS_FS=n
-# CONFIG_VFAT_FS=n
-# CONFIG_ISO9660_FS=n
-# CONFIG_QUOTA=n
-# CONFIG_HID=n
-# CONFIG_CRYPTO=n
-# CONFIG_PCCARD=n
-# CONFIG_PCMCIA=n
-# CONFIG_CARDBUS=n
-# CONFIG_YENTA=n
-if kvm-build.sh $config_template $builddir $T
-then
-       cp $builddir/Make*.out $resdir
-       cp $builddir/.config $resdir
-       cp $builddir/arch/x86/boot/bzImage $resdir
-       parse-build.sh $resdir/Make.out $title
-else
-       cp $builddir/Make*.out $resdir
-       echo Build failed, not running KVM, see $resdir.
-       exit 1
-fi
-minutes=$4
-seconds=$(($minutes * 60))
-qemu_args=$5
-boot_args=$6
-
-cd $KVM
-kstarttime=`awk 'BEGIN { print systime() }' < /dev/null`
-echo ' ---' `date`: Starting kernel
-
-# Determine the appropriate flavor of qemu command.
-QEMU="`identify_qemu $builddir/vmlinux.o`"
-
-# Generate -smp qemu argument.
-cpu_count=`configNR_CPUS.sh $config_template`
-vcpus=`identify_qemu_vcpus`
-if test $cpu_count -gt $vcpus
-then
-       echo CPU count limited from $cpu_count to $vcpus
-       touch $resdir/Warnings
-       echo CPU count limited from $cpu_count to $vcpus >> $resdir/Warnings
-       cpu_count=$vcpus
-fi
-qemu_args="`specify_qemu_cpus "$QEMU" "$qemu_args" "$cpu_count"`"
-
-# Generate architecture-specific and interaction-specific qemu arguments
-qemu_args="$qemu_args `identify_qemu_args "$QEMU" "$builddir/console.log"`"
-
-# Generate qemu -append arguments
-qemu_append="`identify_qemu_append "$QEMU"`"
-
-# Pull in Kconfig-fragment boot parameters
-boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
-# Generate CPU-hotplug boot parameters
-boot_args="`rcutorture_param_onoff "$boot_args" $builddir/.config`"
-# Generate rcu_barrier() boot parameter
-boot_args="`rcutorture_param_n_barrier_cbs "$boot_args"`"
-# Pull in standard rcutorture boot arguments
-boot_args="$boot_args rcutorture.stat_interval=15 rcutorture.shutdown_secs=$seconds rcutorture.rcutorture_runnable=1"
-
-echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
-if test -n "$RCU_BUILDONLY"
-then
-       echo Build-only run specified, boot/test omitted.
-       exit 0
-fi
-$QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append "$qemu_append $boot_args" &
-qemu_pid=$!
-commandcompleted=0
-echo Monitoring qemu job at pid $qemu_pid
-for ((i=0;i<$seconds;i++))
-do
-       if kill -0 $qemu_pid > /dev/null 2>&1
-       then
-               sleep 1
-       else
-               commandcompleted=1
-               kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null`
-               if test $kruntime -lt $seconds
-               then
-                       echo Completed in $kruntime vs. $seconds >> $resdir/Warnings 2>&1
-               else
-                       echo ' ---' `date`: Kernel done
-               fi
-               break
-       fi
-done
-if test $commandcompleted -eq 0
-then
-       echo Grace period for qemu job at pid $qemu_pid
-       for ((i=0;i<=$grace;i++))
-       do
-               if kill -0 $qemu_pid > /dev/null 2>&1
-               then
-                       sleep 1
-               else
-                       break
-               fi
-               if test $i -eq $grace
-               then
-                       kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }'`
-                       echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1
-                       kill -KILL $qemu_pid
-               fi
-       done
-fi
-
-cp $builddir/console.log $resdir
-parse-rcutorture.sh $resdir/console.log $title
-parse-console.sh $resdir/console.log $title
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
new file mode 100755 (executable)
index 0000000..94b28bb
--- /dev/null
@@ -0,0 +1,203 @@
+#!/bin/bash
+#
+# Run a kvm-based test of the specified tree on the specified configs.
+# Fully automated run and error checking, no graphics console.
+#
+# Execute this in the source tree.  Do not run it as a background task
+# because qemu does not seem to like that much.
+#
+# Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
+#
+# qemu-args defaults to "-nographic", along with arguments specifying the
+#                      number of CPUs and other options generated from
+#                      the underlying CPU architecture.
+# boot_args defaults to value returned by the per_version_boot_params
+#                      shell function.
+#
+# Anything you specify for either qemu-args or boot_args is appended to
+# the default values.  The "-smp" value is deduced from the contents of
+# the config fragment.
+#
+# More sophisticated argument parsing is clearly needed.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2011
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+grace=120
+
+T=/tmp/kvm-test-1-run.sh.$$
+trap 'rm -rf $T' 0
+
+. $KVM/bin/functions.sh
+. $KVPATH/ver_functions.sh
+
+config_template=${1}
+config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'`
+title=`echo $config_template | sed -e 's/^.*\///'`
+builddir=${2}
+if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
+then
+       echo "kvm-test-1-run.sh :$builddir: Not a writable directory, cannot build into it"
+       exit 1
+fi
+resdir=${3}
+if test -z "$resdir" -o ! -d "$resdir" -o ! -w "$resdir"
+then
+       echo "kvm-test-1-run.sh :$resdir: Not a writable directory, cannot store results into it"
+       exit 1
+fi
+cp $config_template $resdir/ConfigFragment
+echo ' ---' `date`: Starting build
+echo ' ---' Kconfig fragment at: $config_template >> $resdir/log
+if test -r "$config_dir/CFcommon"
+then
+       cat < $config_dir/CFcommon >> $T
+fi
+# Optimizations below this point
+# CONFIG_USB=n
+# CONFIG_SECURITY=n
+# CONFIG_NFS_FS=n
+# CONFIG_SOUND=n
+# CONFIG_INPUT_JOYSTICK=n
+# CONFIG_INPUT_TABLET=n
+# CONFIG_INPUT_TOUCHSCREEN=n
+# CONFIG_INPUT_MISC=n
+# CONFIG_INPUT_MOUSE=n
+# # CONFIG_NET=n # disables console access, so accept the slower build.
+# CONFIG_SCSI=n
+# CONFIG_ATA=n
+# CONFIG_FAT_FS=n
+# CONFIG_MSDOS_FS=n
+# CONFIG_VFAT_FS=n
+# CONFIG_ISO9660_FS=n
+# CONFIG_QUOTA=n
+# CONFIG_HID=n
+# CONFIG_CRYPTO=n
+# CONFIG_PCCARD=n
+# CONFIG_PCMCIA=n
+# CONFIG_CARDBUS=n
+# CONFIG_YENTA=n
+if kvm-build.sh $config_template $builddir $T
+then
+       cp $builddir/Make*.out $resdir
+       cp $builddir/.config $resdir
+       cp $builddir/arch/x86/boot/bzImage $resdir
+       parse-build.sh $resdir/Make.out $title
+       if test -f $builddir.wait
+       then
+               mv $builddir.wait $builddir.ready
+       fi
+else
+       cp $builddir/Make*.out $resdir
+       echo Build failed, not running KVM, see $resdir.
+       if test -f $builddir.wait
+       then
+               mv $builddir.wait $builddir.ready
+       fi
+       exit 1
+fi
+while test -f $builddir.ready
+do
+       sleep 1
+done
+minutes=$4
+seconds=$(($minutes * 60))
+qemu_args=$5
+boot_args=$6
+
+cd $KVM
+kstarttime=`awk 'BEGIN { print systime() }' < /dev/null`
+echo ' ---' `date`: Starting kernel
+
+# Determine the appropriate flavor of qemu command.
+QEMU="`identify_qemu $builddir/vmlinux`"
+
+# Generate -smp qemu argument.
+qemu_args="-nographic $qemu_args"
+cpu_count=`configNR_CPUS.sh $config_template`
+vcpus=`identify_qemu_vcpus`
+if test $cpu_count -gt $vcpus
+then
+       echo CPU count limited from $cpu_count to $vcpus
+       touch $resdir/Warnings
+       echo CPU count limited from $cpu_count to $vcpus >> $resdir/Warnings
+       cpu_count=$vcpus
+fi
+qemu_args="`specify_qemu_cpus "$QEMU" "$qemu_args" "$cpu_count"`"
+
+# Generate architecture-specific and interaction-specific qemu arguments
+qemu_args="$qemu_args `identify_qemu_args "$QEMU" "$builddir/console.log"`"
+
+# Generate qemu -append arguments
+qemu_append="`identify_qemu_append "$QEMU"`"
+
+# Pull in Kconfig-fragment boot parameters
+boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
+# Generate kernel-version-specific boot parameters
+boot_args="`per_version_boot_params "$boot_args" $builddir/.config $seconds`"
+
+echo $QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
+if test -n "$RCU_BUILDONLY"
+then
+       echo Build-only run specified, boot/test omitted.
+       exit 0
+fi
+$QEMU $qemu_args -m 512 -kernel $builddir/arch/x86/boot/bzImage -append "$qemu_append $boot_args" &
+qemu_pid=$!
+commandcompleted=0
+echo Monitoring qemu job at pid $qemu_pid
+for ((i=0;i<$seconds;i++))
+do
+       if kill -0 $qemu_pid > /dev/null 2>&1
+       then
+               sleep 1
+       else
+               commandcompleted=1
+               kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null`
+               if test $kruntime -lt $seconds
+               then
+                       echo Completed in $kruntime vs. $seconds >> $resdir/Warnings 2>&1
+               else
+                       echo ' ---' `date`: Kernel done
+               fi
+               break
+       fi
+done
+if test $commandcompleted -eq 0
+then
+       echo Grace period for qemu job at pid $qemu_pid
+       for ((i=0;i<=$grace;i++))
+       do
+               if kill -0 $qemu_pid > /dev/null 2>&1
+               then
+                       sleep 1
+               else
+                       break
+               fi
+               if test $i -eq $grace
+               then
+                       kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }'`
+                       echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1
+                       kill -KILL $qemu_pid
+               fi
+       done
+fi
+
+cp $builddir/console.log $resdir
+parse-${TORTURE_SUITE}torture.sh $resdir/console.log $title
+parse-console.sh $resdir/console.log $title
index 1b7923bf6a702a921040c86970cbe8d9dc47a2a6..5a78cbf55f066dd3a657e9bfd210d4129e002f83 100644 (file)
 scriptname=$0
 args="$*"
 
+T=/tmp/kvm.sh.$$
+trap 'rm -rf $T' 0
+mkdir $T
+
 dur=30
+dryrun=""
 KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
 PATH=${KVM}/bin:$PATH; export PATH
 builddir="${KVM}/b1"
 RCU_INITRD="$KVM/initrd"; export RCU_INITRD
 RCU_KMAKE_ARG=""; export RCU_KMAKE_ARG
+TORTURE_SUITE=rcu
 resdir=""
 configs=""
+cpus=0
 ds=`date +%Y.%m.%d-%H:%M:%S`
 kversion=""
 
@@ -49,7 +56,9 @@ usage () {
        echo "       --builddir absolute-pathname"
        echo "       --buildonly"
        echo "       --configs \"config-file list\""
+       echo "       --cpus N"
        echo "       --datestamp string"
+       echo "       --dryrun sched|script"
        echo "       --duration minutes"
        echo "       --interactive"
        echo "       --kmake-arg kernel-make-arguments"
@@ -58,8 +67,9 @@ usage () {
        echo "       --no-initrd"
        echo "       --qemu-args qemu-system-..."
        echo "       --qemu-cmd qemu-system-..."
-       echo "       --results absolute-pathname"
        echo "       --relbuilddir relative-pathname"
+       echo "       --results absolute-pathname"
+       echo "       --torture rcu"
        exit 1
 }
 
@@ -85,11 +95,21 @@ do
                configs="$2"
                shift
                ;;
+       --cpus)
+               checkarg --cpus "(number)" "$#" "$2" '^[0-9]*$' '^--'
+               cpus=$2
+               shift
+               ;;
        --datestamp)
                checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
                ds=$2
                shift
                ;;
+       --dryrun)
+               checkarg --dryrun "sched|script" $# "$2" 'sched\|script' '^--'
+               dryrun=$2
+               shift
+               ;;
        --duration)
                checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
                dur=$2
@@ -138,6 +158,11 @@ do
                resdir=$2
                shift
                ;;
+       --torture)
+               checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--'
+               TORTURE_SUITE=$2
+               shift
+               ;;
        *)
                echo Unknown argument $1
                usage
@@ -146,7 +171,7 @@ do
        shift
 done
 
-CONFIGFRAG=${KVM}/configs; export CONFIGFRAG
+CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
 KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
 
 if test -z "$configs"
@@ -157,54 +182,231 @@ fi
 if test -z "$resdir"
 then
        resdir=$KVM/res
-       if ! test -e $resdir
-       then
-               mkdir $resdir || :
-       fi
-else
+fi
+
+if test "$dryrun" = ""
+then
        if ! test -e $resdir
        then
                mkdir -p "$resdir" || :
        fi
-fi
-mkdir $resdir/$ds
-touch $resdir/$ds/log
-echo $scriptname $args >> $resdir/$ds/log
+       mkdir $resdir/$ds
 
-pwd > $resdir/$ds/testid.txt
-if test -d .git
-then
-       git status >> $resdir/$ds/testid.txt
-       git rev-parse HEAD >> $resdir/$ds/testid.txt
-fi
-builddir=$KVM/b1
-if ! test -e $builddir
-then
-       mkdir $builddir || :
+       # Be noisy only if running the script.
+       echo Results directory: $resdir/$ds
+       echo $scriptname $args
+
+       touch $resdir/$ds/log
+       echo $scriptname $args >> $resdir/$ds/log
+       echo ${TORTURE_SUITE} > $resdir/$ds/TORTURE_SUITE
+
+       pwd > $resdir/$ds/testid.txt
+       if test -d .git
+       then
+               git status >> $resdir/$ds/testid.txt
+               git rev-parse HEAD >> $resdir/$ds/testid.txt
+       fi
 fi
 
+# Create a file of test-name/#cpus pairs, sorted by decreasing #cpus.
+touch $T/cfgcpu
 for CF in $configs
 do
-       # Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ...
-       rd=$resdir/$ds/$CF
-       if test -d "${rd}"
+       if test -f "$CONFIGFRAG/$kversion/$CF"
        then
-               n="`ls -d "${rd}"* | grep '\.[0-9]\+$' |
-                       sed -e 's/^.*\.\([0-9]\+\)/\1/' |
-                       sort -k1n | tail -1`"
-               if test -z "$n"
-               then
-                       rd="${rd}.2"
-               else
-                       n="`expr $n + 1`"
-                       rd="${rd}.${n}"
-               fi
+               echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu
+       else
+               echo "The --configs file $CF does not exist, terminating."
+               exit 1
        fi
-       mkdir "${rd}"
-       echo Results directory: $rd
-       kvm-test-1-rcu.sh $CONFIGFRAG/$kversion/$CF $builddir $rd $dur "-nographic $RCU_QEMU_ARG" "rcutorture.test_no_idle_hz=1 rcutorture.verbose=1 $RCU_BOOTARGS"
 done
+sort -k2nr $T/cfgcpu > $T/cfgcpu.sort
+
+# Use a greedy bin-packing algorithm, sorting the list accordingly.
+awk < $T/cfgcpu.sort > $T/cfgcpu.pack -v ncpus=$cpus '
+BEGIN {
+       njobs = 0;
+}
+
+{
+       # Read file of tests and corresponding required numbers of CPUs.
+       cf[njobs] = $1;
+       cpus[njobs] = $2;
+       njobs++;
+}
+
+END {
+       alldone = 0;
+       batch = 0;
+       nc = -1;
+
+       # Each pass through the following loop creates on test batch
+       # that can be executed concurrently given ncpus.  Note that a
+       # given test that requires more than the available CPUs will run in
+       # their own batch.  Such tests just have to make do with what
+       # is available.
+       while (nc != ncpus) {
+               batch++;
+               nc = ncpus;
+
+               # Each pass through the following loop considers one
+               # test for inclusion in the current batch.
+               for (i = 0; i < njobs; i++) {
+                       if (done[i])
+                               continue; # Already part of a batch.
+                       if (nc >= cpus[i] || nc == ncpus) {
+
+                               # This test fits into the current batch.
+                               done[i] = batch;
+                               nc -= cpus[i];
+                               if (nc <= 0)
+                                       break; # Too-big test in its own batch.
+                       }
+               }
+       }
+
+       # Dump out the tests in batch order.
+       for (b = 1; b <= batch; b++)
+               for (i = 0; i < njobs; i++)
+                       if (done[i] == b)
+                               print cf[i], cpus[i];
+}'
+
+# Generate a script to execute the tests in appropriate batches.
+cat << ___EOF___ > $T/script
+TORTURE_SUITE="$TORTURE_SUITE"; export TORTURE_SUITE
+___EOF___
+awk < $T/cfgcpu.pack \
+       -v CONFIGDIR="$CONFIGFRAG/$kversion/" \
+       -v KVM="$KVM" \
+       -v ncpus=$cpus \
+       -v rd=$resdir/$ds/ \
+       -v dur=$dur \
+       -v RCU_QEMU_ARG=$RCU_QEMU_ARG \
+       -v RCU_BOOTARGS=$RCU_BOOTARGS \
+'BEGIN {
+       i = 0;
+}
+
+{
+       cf[i] = $1;
+       cpus[i] = $2;
+       i++;
+}
+
+# Dump out the scripting required to run one test batch.
+function dump(first, pastlast)
+{
+       print "echo ----Start batch: `date`";
+       print "echo ----Start batch: `date` >> " rd "/log";
+       jn=1
+       for (j = first; j < pastlast; j++) {
+               builddir=KVM "/b" jn
+               cpusr[jn] = cpus[j];
+               if (cfrep[cf[j]] == "") {
+                       cfr[jn] = cf[j];
+                       cfrep[cf[j]] = 1;
+               } else {
+                       cfrep[cf[j]]++;
+                       cfr[jn] = cf[j] "." cfrep[cf[j]];
+               }
+               if (cpusr[jn] > ncpus && ncpus != 0)
+                       ovf = "(!)";
+               else
+                       ovf = "";
+               print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`";
+               print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date` >> " rd "/log";
+               print "rm -f " builddir ".*";
+               print "touch " builddir ".wait";
+               print "mkdir " builddir " > /dev/null 2>&1 || :";
+               print "mkdir " rd cfr[jn] " || :";
+               print "kvm-test-1-run.sh " CONFIGDIR cf[j], builddir, rd cfr[jn], dur " \"" RCU_QEMU_ARG "\" \"" RCU_BOOTARGS "\" > " rd cfr[jn]  "/kvm-test-1-run.sh.out 2>&1 &"
+               print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date`";
+               print "echo ", cfr[jn], cpusr[jn] ovf ": Waiting for build to complete. `date` >> " rd "/log";
+               print "while test -f " builddir ".wait"
+               print "do"
+               print "\tsleep 1"
+               print "done"
+               print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date`";
+               print "echo ", cfr[jn], cpusr[jn] ovf ": Build complete. `date` >> " rd "/log";
+               jn++;
+       }
+       for (j = 1; j < jn; j++) {
+               builddir=KVM "/b" j
+               print "rm -f " builddir ".ready"
+               print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date`";
+               print "echo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log";
+       }
+       print "wait"
+       print "echo ---- All kernel runs complete. `date`";
+       print "echo ---- All kernel runs complete. `date` >> " rd "/log";
+       for (j = 1; j < jn; j++) {
+               builddir=KVM "/b" j
+               print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results:";
+               print "echo ----", cfr[j], cpusr[j] ovf ": Build/run results: >> " rd "/log";
+               print "cat " rd cfr[j]  "/kvm-test-1-run.sh.out";
+               print "cat " rd cfr[j]  "/kvm-test-1-run.sh.out >> " rd "/log";
+       }
+}
+
+END {
+       njobs = i;
+       nc = ncpus;
+       first = 0;
+
+       # Each pass through the following loop considers one test.
+       for (i = 0; i < njobs; i++) {
+               if (ncpus == 0) {
+                       # Sequential test specified, each test its own batch.
+                       dump(i, i + 1);
+                       first = i;
+               } else if (nc < cpus[i] && i != 0) {
+                       # Out of CPUs, dump out a batch.
+                       dump(first, i);
+                       first = i;
+                       nc = ncpus;
+               }
+               # Account for the CPUs needed by the current test.
+               nc -= cpus[i];
+       }
+       # Dump the last batch.
+       if (ncpus != 0)
+               dump(first, i);
+}' >> $T/script
+
+if test "$dryrun" = script
+then
+       # Dump out the script, but define the environment variables that
+       # it needs to run standalone.
+       echo CONFIGFRAG="$CONFIGFRAG; export CONFIGFRAG"
+       echo KVM="$KVM; export KVM"
+       echo KVPATH="$KVPATH; export KVPATH"
+       echo PATH="$PATH; export PATH"
+       echo RCU_BUILDONLY="$RCU_BUILDONLY; export RCU_BUILDONLY"
+       echo RCU_INITRD="$RCU_INITRD; export RCU_INITRD"
+       echo RCU_KMAKE_ARG="$RCU_KMAKE_ARG; export RCU_KMAKE_ARG"
+       echo RCU_QEMU_CMD="$RCU_QEMU_CMD; export RCU_QEMU_CMD"
+       echo RCU_QEMU_INTERACTIVE="$RCU_QEMU_INTERACTIVE; export RCU_QEMU_INTERACTIVE"
+       echo RCU_QEMU_MAC="$RCU_QEMU_MAC; export RCU_QEMU_MAC"
+       echo "mkdir -p "$resdir" || :"
+       echo "mkdir $resdir/$ds"
+       cat $T/script
+       exit 0
+elif test "$dryrun" = sched
+then
+       # Extract the test run schedule from the script.
+       egrep 'start batch|Starting build\.' $T/script |
+               sed -e 's/:.*$//' -e 's/^echo //'
+       exit 0
+else
+       # Not a dryru, so run the script.
+       sh $T/script
+fi
+
 # Tracing: trace_event=rcu:rcu_grace_period,rcu:rcu_future_grace_period,rcu:rcu_grace_period_init,rcu:rcu_nocb_wake,rcu:rcu_preempt_task,rcu:rcu_unlock_preempted_task,rcu:rcu_quiescent_state_report,rcu:rcu_fqs,rcu:rcu_callback,rcu:rcu_kfree_callback,rcu:rcu_batch_start,rcu:rcu_invoke_callback,rcu:rcu_invoke_kfree_callback,rcu:rcu_batch_end,rcu:rcu_torture_read,rcu:rcu_barrier
 
+echo
+echo
 echo " --- `date` Test summary:"
+echo Results directory: $resdir/$ds
 kvm-recheck.sh $resdir/$ds
diff --git a/tools/testing/selftests/rcutorture/configs/CFLIST b/tools/testing/selftests/rcutorture/configs/CFLIST
deleted file mode 100644 (file)
index cd3d29c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-TREE01
-TREE02
-TREE03
-TREE04
-TREE05
-TREE06
-TREE07
-TREE08
-TREE09
-SRCU-N
-SRCU-P
-TINY01
-TINY02
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N b/tools/testing/selftests/rcutorture/configs/SRCU-N
deleted file mode 100644 (file)
index 10a0e27..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-N.boot b/tools/testing/selftests/rcutorture/configs/SRCU-N.boot
deleted file mode 100644 (file)
index 238bfe3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-rcutorture.torture_type=srcu
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P b/tools/testing/selftests/rcutorture/configs/SRCU-P
deleted file mode 100644 (file)
index 6650e00..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/SRCU-P.boot b/tools/testing/selftests/rcutorture/configs/SRCU-P.boot
deleted file mode 100644 (file)
index 238bfe3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-rcutorture.torture_type=srcu
diff --git a/tools/testing/selftests/rcutorture/configs/TINY01 b/tools/testing/selftests/rcutorture/configs/TINY01
deleted file mode 100644 (file)
index 0c2823f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG_SMP=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_TRACE=n
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PREEMPT_COUNT=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TINY02 b/tools/testing/selftests/rcutorture/configs/TINY02
deleted file mode 100644 (file)
index e5072d7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG_SMP=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_HZ_PERIODIC=y
-CONFIG_NO_HZ_IDLE=n
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PREEMPT_COUNT=y
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01 b/tools/testing/selftests/rcutorture/configs/TREE01
deleted file mode 100644 (file)
index 141119a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_RCU_TRACE=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_FANOUT=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_ZERO=y
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_RCU_BOOST=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE01.boot b/tools/testing/selftests/rcutorture/configs/TREE01.boot
deleted file mode 100644 (file)
index 0fc8a34..0000000
+++ /dev/null
@@ -1 +0,0 @@
-rcutorture.torture_type=rcu_bh
diff --git a/tools/testing/selftests/rcutorture/configs/TREE02 b/tools/testing/selftests/rcutorture/configs/TREE02
deleted file mode 100644 (file)
index 2d4d096..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_FAST_NO_HZ=n 
-CONFIG_RCU_TRACE=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_RCU_FANOUT=3
-CONFIG_RCU_FANOUT_LEAF=3
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_RCU_NOCB_CPU=n
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_PROVE_LOCKING=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=y
-CONFIG_RCU_BOOST=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE03 b/tools/testing/selftests/rcutorture/configs/TREE03
deleted file mode 100644 (file)
index a47de5b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_HZ_PERIODIC=y
-CONFIG_NO_HZ_IDLE=n
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_TRACE=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_FANOUT=4
-CONFIG_RCU_FANOUT_LEAF=4
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_RCU_NOCB_CPU=n
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04 b/tools/testing/selftests/rcutorture/configs/TREE04
deleted file mode 100644 (file)
index 8d839b8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=n
-CONFIG_NO_HZ_FULL=y
-CONFIG_NO_HZ_FULL_ALL=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_RCU_TRACE=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_RCU_FANOUT=2
-CONFIG_RCU_FANOUT_LEAF=2
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_RCU_NOCB_CPU=n
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_RCU_CPU_STALL_VERBOSE=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE04.boot b/tools/testing/selftests/rcutorture/configs/TREE04.boot
deleted file mode 100644 (file)
index 0fc8a34..0000000
+++ /dev/null
@@ -1 +0,0 @@
-rcutorture.torture_type=rcu_bh
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05 b/tools/testing/selftests/rcutorture/configs/TREE05
deleted file mode 100644 (file)
index b5ba72e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_FAST_NO_HZ=n
-CONFIG_RCU_TRACE=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_FANOUT=6
-CONFIG_RCU_FANOUT_LEAF=6
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_PROVE_RCU_DELAY=y
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE05.boot b/tools/testing/selftests/rcutorture/configs/TREE05.boot
deleted file mode 100644 (file)
index 3b42b8b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-rcutorture.torture_type=sched
diff --git a/tools/testing/selftests/rcutorture/configs/TREE06 b/tools/testing/selftests/rcutorture/configs/TREE06
deleted file mode 100644 (file)
index 7c95ab4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_FAST_NO_HZ=n
-CONFIG_RCU_TRACE=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_RCU_FANOUT=6
-CONFIG_RCU_FANOUT_LEAF=6
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_RCU_NOCB_CPU=n
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE07 b/tools/testing/selftests/rcutorture/configs/TREE07
deleted file mode 100644 (file)
index 1467404..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=n
-CONFIG_NO_HZ_FULL=y
-CONFIG_NO_HZ_FULL_ALL=y
-CONFIG_NO_HZ_FULL_SYSIDLE=y
-CONFIG_RCU_FAST_NO_HZ=n
-CONFIG_RCU_TRACE=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_FANOUT=2
-CONFIG_RCU_FANOUT_LEAF=2
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_RCU_NOCB_CPU=n
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08 b/tools/testing/selftests/rcutorture/configs/TREE08
deleted file mode 100644 (file)
index 7d097a6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_FAST_NO_HZ=n
-CONFIG_RCU_TRACE=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_RCU_FANOUT=3
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_RCU_FANOUT_LEAF=2
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_ALL=y
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_RCU_BOOST=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE08-T b/tools/testing/selftests/rcutorture/configs/TREE08-T
deleted file mode 100644 (file)
index 442c4e4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_FAST_NO_HZ=n
-CONFIG_RCU_TRACE=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_RCU_FANOUT=3
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_RCU_FANOUT_LEAF=2
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_ALL=y
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_RCU_BOOST=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/TREE09 b/tools/testing/selftests/rcutorture/configs/TREE09
deleted file mode 100644 (file)
index 0d1ec0d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-CONFIG_SMP=n
-CONFIG_NR_CPUS=1
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_HZ_PERIODIC=n
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NO_HZ_FULL=n
-CONFIG_RCU_TRACE=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_RCU_NOCB_CPU=n
-CONFIG_DEBUG_LOCK_ALLOC=n
-CONFIG_PROVE_RCU_DELAY=n
-CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
-CONFIG_RCU_BOOST=n
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
-CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED b/tools/testing/selftests/rcutorture/configs/lock/BUSTED
new file mode 100644 (file)
index 0000000..1d1da14
--- /dev/null
@@ -0,0 +1,6 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/lock/BUSTED.boot
new file mode 100644 (file)
index 0000000..6386c15
--- /dev/null
@@ -0,0 +1 @@
+locktorture.torture_type=lock_busted
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
new file mode 100644 (file)
index 0000000..a061b22
--- /dev/null
@@ -0,0 +1 @@
+LOCK01
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFcommon b/tools/testing/selftests/rcutorture/configs/lock/CFcommon
new file mode 100644 (file)
index 0000000..e372dc2
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_LOCK_TORTURE_TEST=y
+CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK01 b/tools/testing/selftests/rcutorture/configs/lock/LOCK01
new file mode 100644 (file)
index 0000000..a9625e3
--- /dev/null
@@ -0,0 +1,6 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
new file mode 100644 (file)
index 0000000..9746ea1
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# Kernel-version-dependent shell functions for the rest of the scripts.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2014
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+# locktorture_param_onoff bootparam-string config-file
+#
+# Adds onoff locktorture module parameters to kernels having it.
+locktorture_param_onoff () {
+       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
+       then
+               echo CPU-hotplug kernel, adding locktorture onoff. 1>&2
+               echo locktorture.onoff_interval=3 locktorture.onoff_holdoff=30
+       fi
+}
+
+# per_version_boot_params bootparam-string config-file seconds
+#
+# Adds per-version torture-module parameters to kernels supporting them.
+per_version_boot_params () {
+       echo $1 `locktorture_param_onoff "$1" "$2"` \
+               locktorture.stat_interval=15 \
+               locktorture.shutdown_secs=$3 \
+               locktorture.locktorture_runnable=1 \
+               locktorture.verbose=1
+}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED
new file mode 100644 (file)
index 0000000..48d8a24
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_RCU_TRACE=n
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot b/tools/testing/selftests/rcutorture/configs/rcu/BUSTED.boot
new file mode 100644 (file)
index 0000000..6804f9d
--- /dev/null
@@ -0,0 +1 @@
+rcutorture.torture_type=rcu_busted
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
new file mode 100644 (file)
index 0000000..cd3d29c
--- /dev/null
@@ -0,0 +1,13 @@
+TREE01
+TREE02
+TREE03
+TREE04
+TREE05
+TREE06
+TREE07
+TREE08
+TREE09
+SRCU-N
+SRCU-P
+TINY01
+TINY02
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
new file mode 100644 (file)
index 0000000..d2d2a86
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_RCU_TORTURE_TEST=y
+CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N
new file mode 100644 (file)
index 0000000..9fbb41b
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_RCU_TRACE=n
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-N.boot
new file mode 100644 (file)
index 0000000..238bfe3
--- /dev/null
@@ -0,0 +1 @@
+rcutorture.torture_type=srcu
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P
new file mode 100644 (file)
index 0000000..4b6f272
--- /dev/null
@@ -0,0 +1,7 @@
+CONFIG_RCU_TRACE=n
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot b/tools/testing/selftests/rcutorture/configs/rcu/SRCU-P.boot
new file mode 100644 (file)
index 0000000..238bfe3
--- /dev/null
@@ -0,0 +1 @@
+rcutorture.torture_type=srcu
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY01 b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
new file mode 100644 (file)
index 0000000..0a63e07
--- /dev/null
@@ -0,0 +1,12 @@
+CONFIG_SMP=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_TRACE=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
+CONFIG_PREEMPT_COUNT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
new file mode 100644 (file)
index 0000000..f4feaee
--- /dev/null
@@ -0,0 +1,12 @@
+CONFIG_SMP=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_NO_HZ_IDLE=n
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
+CONFIG_PREEMPT_COUNT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
new file mode 100644 (file)
index 0000000..9c827ec
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_FANOUT=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ZERO=y
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_RCU_BOOST=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
new file mode 100644 (file)
index 0000000..0fc8a34
--- /dev/null
@@ -0,0 +1 @@
+rcutorture.torture_type=rcu_bh
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
new file mode 100644 (file)
index 0000000..1a777b5
--- /dev/null
@@ -0,0 +1,25 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_FANOUT=3
+CONFIG_RCU_FANOUT_LEAF=3
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=y
+CONFIG_RCU_BOOST=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
new file mode 100644 (file)
index 0000000..c1f111c
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_NO_HZ_IDLE=n
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_FANOUT=4
+CONFIG_RCU_FANOUT_LEAF=4
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
new file mode 100644 (file)
index 0000000..7dbd27c
--- /dev/null
@@ -0,0 +1,24 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=n
+CONFIG_NO_HZ_FULL=y
+CONFIG_NO_HZ_FULL_ALL=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_FANOUT=2
+CONFIG_RCU_FANOUT_LEAF=2
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_RCU_CPU_STALL_VERBOSE=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
new file mode 100644 (file)
index 0000000..0fc8a34
--- /dev/null
@@ -0,0 +1 @@
+rcutorture.torture_type=rcu_bh
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
new file mode 100644 (file)
index 0000000..d0f32e5
--- /dev/null
@@ -0,0 +1,24 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_FANOUT=6
+CONFIG_RCU_FANOUT_LEAF=6
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_NONE=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_PROVE_RCU_DELAY=y
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
new file mode 100644 (file)
index 0000000..3b42b8b
--- /dev/null
@@ -0,0 +1 @@
+rcutorture.torture_type=sched
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
new file mode 100644 (file)
index 0000000..2e477df
--- /dev/null
@@ -0,0 +1,25 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_FANOUT=6
+CONFIG_RCU_FANOUT_LEAF=6
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
new file mode 100644 (file)
index 0000000..042f86e
--- /dev/null
@@ -0,0 +1,23 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=n
+CONFIG_NO_HZ_FULL=y
+CONFIG_NO_HZ_FULL_ALL=y
+CONFIG_NO_HZ_FULL_SYSIDLE=y
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_FANOUT=2
+CONFIG_RCU_FANOUT_LEAF=2
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
new file mode 100644 (file)
index 0000000..3438cee
--- /dev/null
@@ -0,0 +1,25 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_FANOUT=3
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_RCU_FANOUT_LEAF=2
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_RCU_BOOST=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
new file mode 100644 (file)
index 0000000..bf4523d
--- /dev/null
@@ -0,0 +1,25 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_FAST_NO_HZ=n
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_FANOUT=3
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_RCU_FANOUT_LEAF=2
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_RCU_BOOST=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE09 b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
new file mode 100644 (file)
index 0000000..81e4f7c
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_SMP=n
+CONFIG_NR_CPUS=1
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=n
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_TRACE=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_RCU_DELAY=n
+CONFIG_RCU_CPU_STALL_INFO=n
+CONFIG_RCU_CPU_STALL_VERBOSE=n
+CONFIG_RCU_BOOST=n
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
new file mode 100644 (file)
index 0000000..1822394
--- /dev/null
@@ -0,0 +1,14 @@
+P1-S-T-NH-SD-SMP-HP
+P2-2-t-nh-sd-SMP-hp
+P3-3-T-nh-SD-SMP-hp
+P4-A-t-NH-sd-SMP-HP
+P5-U-T-NH-sd-SMP-hp
+N1-S-T-NH-SD-SMP-HP
+N2-2-t-nh-sd-SMP-hp
+N3-3-T-nh-SD-SMP-hp
+N4-A-t-NH-sd-SMP-HP
+N5-U-T-NH-sd-SMP-hp
+PT1-nh
+PT2-NH
+NT1-nh
+NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..d3ef873
--- /dev/null
@@ -0,0 +1,18 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..02e4185
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b3100f6
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..c56b445
--- /dev/null
@@ -0,0 +1,18 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..90d924f
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
new file mode 100644 (file)
index 0000000..023f312
--- /dev/null
@@ -0,0 +1,23 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
new file mode 100644 (file)
index 0000000..6fd0235
--- /dev/null
@@ -0,0 +1,20 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..f72402d
--- /dev/null
@@ -0,0 +1,19 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..0f3b667
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b035e14
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..3ccf6a9
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..ef624ce
--- /dev/null
@@ -0,0 +1,28 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_RCU_DELAY=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
new file mode 100644 (file)
index 0000000..e3361c3
--- /dev/null
@@ -0,0 +1,23 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
new file mode 100644 (file)
index 0000000..64abfc3
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
new file mode 100644 (file)
index 0000000..5ace37a
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# Kernel-version-dependent shell functions for the rest of the scripts.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2013
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+# per_version_boot_params bootparam-string config-file seconds
+#
+# Adds per-version torture-module parameters to kernels supporting them.
+# Which old kernels do not.
+per_version_boot_params () {
+       echo    rcutorture.stat_interval=15 \
+               rcutorture.shutdown_secs=$3 \
+               rcutorture.rcutorture_runnable=1 \
+               rcutorture.test_no_idle_hz=1 \
+               rcutorture.verbose=1
+}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
new file mode 100644 (file)
index 0000000..da4cbc6
--- /dev/null
@@ -0,0 +1,17 @@
+sysidleY.2013.06.19a
+sysidleN.2013.06.19a
+P1-S-T-NH-SD-SMP-HP
+P2-2-t-nh-sd-SMP-hp
+P3-3-T-nh-SD-SMP-hp
+P4-A-t-NH-sd-SMP-HP
+P5-U-T-NH-sd-SMP-hp
+P6---t-nh-SD-smp-hp
+N1-S-T-NH-SD-SMP-HP
+N2-2-t-nh-sd-SMP-hp
+N3-3-T-nh-SD-SMP-hp
+N4-A-t-NH-sd-SMP-HP
+N5-U-T-NH-sd-SMP-hp
+PT1-nh
+PT2-NH
+NT1-nh
+NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..d81e11d
--- /dev/null
@@ -0,0 +1,19 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..02e4185
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b3100f6
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..c56b445
--- /dev/null
@@ -0,0 +1,18 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..90d924f
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
new file mode 100644 (file)
index 0000000..0ccc36d
--- /dev/null
@@ -0,0 +1,19 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_NR_CPUS=1
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..3f640cf
--- /dev/null
@@ -0,0 +1,26 @@
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=16
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_NONE=y
+CONFIG_RCU_NOCB_CPU_ZERO=n
+CONFIG_RCU_NOCB_CPU_ALL=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..285da2d
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=14
+CONFIG_NR_CPUS=16
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
new file mode 100644 (file)
index 0000000..023f312
--- /dev/null
@@ -0,0 +1,23 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
new file mode 100644 (file)
index 0000000..6fd0235
--- /dev/null
@@ -0,0 +1,20 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..9647c44
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..0f3b667
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b035e14
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..3ccf6a9
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..ef624ce
--- /dev/null
@@ -0,0 +1,28 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_RCU_DELAY=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
new file mode 100644 (file)
index 0000000..f4c9175
--- /dev/null
@@ -0,0 +1,18 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=n
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..77a8c5b
--- /dev/null
@@ -0,0 +1,30 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=16
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_NONE=n
+CONFIG_RCU_NOCB_CPU_ZERO=n
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_SLUB=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
new file mode 100644 (file)
index 0000000..0eecebc
--- /dev/null
@@ -0,0 +1,30 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=16
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_NONE=y
+CONFIG_RCU_NOCB_CPU_ZERO=n
+CONFIG_RCU_NOCB_CPU_ALL=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_SLUB=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
new file mode 100644 (file)
index 0000000..0eecebc
--- /dev/null
@@ -0,0 +1,30 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=16
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_NONE=y
+CONFIG_RCU_NOCB_CPU_ZERO=n
+CONFIG_RCU_NOCB_CPU_ALL=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_SLUB=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
new file mode 100644 (file)
index 0000000..588bc70
--- /dev/null
@@ -0,0 +1,30 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=16
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_NONE=n
+CONFIG_RCU_NOCB_CPU_ZERO=y
+CONFIG_RCU_NOCB_CPU_ALL=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_SLUB=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
new file mode 100644 (file)
index 0000000..e3361c3
--- /dev/null
@@ -0,0 +1,23 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
new file mode 100644 (file)
index 0000000..64abfc3
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
new file mode 100644 (file)
index 0000000..1822394
--- /dev/null
@@ -0,0 +1,14 @@
+P1-S-T-NH-SD-SMP-HP
+P2-2-t-nh-sd-SMP-hp
+P3-3-T-nh-SD-SMP-hp
+P4-A-t-NH-sd-SMP-HP
+P5-U-T-NH-sd-SMP-hp
+N1-S-T-NH-SD-SMP-HP
+N2-2-t-nh-sd-SMP-hp
+N3-3-T-nh-SD-SMP-hp
+N4-A-t-NH-sd-SMP-HP
+N5-U-T-NH-sd-SMP-hp
+PT1-nh
+PT2-NH
+NT1-nh
+NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..d81e11d
--- /dev/null
@@ -0,0 +1,19 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..02e4185
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b3100f6
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..c56b445
--- /dev/null
@@ -0,0 +1,18 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..90d924f
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
new file mode 100644 (file)
index 0000000..023f312
--- /dev/null
@@ -0,0 +1,23 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
new file mode 100644 (file)
index 0000000..6fd0235
--- /dev/null
@@ -0,0 +1,20 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..9647c44
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..0f3b667
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b035e14
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..3ccf6a9
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..ef624ce
--- /dev/null
@@ -0,0 +1,28 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_RCU_DELAY=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
new file mode 100644 (file)
index 0000000..e3361c3
--- /dev/null
@@ -0,0 +1,23 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
new file mode 100644 (file)
index 0000000..64abfc3
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
new file mode 100644 (file)
index 0000000..bae5569
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+#
+# Kernel-version-dependent shell functions for the rest of the scripts.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2013
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+# rcutorture_param_onoff bootparam-string config-file
+#
+# Adds onoff rcutorture module parameters to kernels having it.
+rcutorture_param_onoff () {
+       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
+       then
+               echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
+               echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
+       fi
+}
+
+# per_version_boot_params bootparam-string config-file seconds
+#
+# Adds per-version torture-module parameters to kernels supporting them.
+per_version_boot_params () {
+       echo $1 `rcutorture_param_onoff "$1" "$2"` \
+               rcutorture.stat_interval=15 \
+               rcutorture.shutdown_secs=$3 \
+               rcutorture.rcutorture_runnable=1 \
+               rcutorture.test_no_idle_hz=1 \
+               rcutorture.verbose=1
+}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
new file mode 100644 (file)
index 0000000..1822394
--- /dev/null
@@ -0,0 +1,14 @@
+P1-S-T-NH-SD-SMP-HP
+P2-2-t-nh-sd-SMP-hp
+P3-3-T-nh-SD-SMP-hp
+P4-A-t-NH-sd-SMP-HP
+P5-U-T-NH-sd-SMP-hp
+N1-S-T-NH-SD-SMP-HP
+N2-2-t-nh-sd-SMP-hp
+N3-3-T-nh-SD-SMP-hp
+N4-A-t-NH-sd-SMP-HP
+N5-U-T-NH-sd-SMP-hp
+PT1-nh
+PT2-NH
+NT1-nh
+NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..d81e11d
--- /dev/null
@@ -0,0 +1,19 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..02e4185
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b3100f6
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..c56b445
--- /dev/null
@@ -0,0 +1,18 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..90d924f
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+#CHECK#CONFIG_TREE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
new file mode 100644 (file)
index 0000000..023f312
--- /dev/null
@@ -0,0 +1,23 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
new file mode 100644 (file)
index 0000000..6fd0235
--- /dev/null
@@ -0,0 +1,20 @@
+#CHECK#CONFIG_TINY_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=y
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=n
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
new file mode 100644 (file)
index 0000000..9647c44
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=8
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
new file mode 100644 (file)
index 0000000..0f3b667
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=4
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
new file mode 100644 (file)
index 0000000..b035e14
--- /dev/null
@@ -0,0 +1,20 @@
+CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=n
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=2
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
new file mode 100644 (file)
index 0000000..3ccf6a9
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_RCU_TRACE=n
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=n
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
new file mode 100644 (file)
index 0000000..ef624ce
--- /dev/null
@@ -0,0 +1,28 @@
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_NO_HZ=y
+CONFIG_SMP=y
+CONFIG_RCU_FANOUT=6
+CONFIG_NR_CPUS=8
+CONFIG_RCU_FANOUT_EXACT=y
+CONFIG_HOTPLUG_CPU=n
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_RCU_DELAY=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_RT_MUTEXES=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
new file mode 100644 (file)
index 0000000..e3361c3
--- /dev/null
@@ -0,0 +1,23 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_TRACE=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=n
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
new file mode 100644 (file)
index 0000000..64abfc3
--- /dev/null
@@ -0,0 +1,22 @@
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_MODULE_UNLOAD=y
+CONFIG_SUSPEND=n
+CONFIG_HIBERNATION=n
+#
+CONFIG_SMP=n
+#
+CONFIG_HOTPLUG_CPU=n
+#
+CONFIG_NO_HZ=y
+#
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_PRINTK_TIME=y
+
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
new file mode 100644 (file)
index 0000000..8977d8d
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# Kernel-version-dependent shell functions for the rest of the scripts.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2013
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+# rcutorture_param_n_barrier_cbs bootparam-string
+#
+# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
+rcutorture_param_n_barrier_cbs () {
+       if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
+       then
+               :
+       else
+               echo rcutorture.n_barrier_cbs=4
+       fi
+}
+
+# rcutorture_param_onoff bootparam-string config-file
+#
+# Adds onoff rcutorture module parameters to kernels having it.
+rcutorture_param_onoff () {
+       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
+       then
+               echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
+               echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
+       fi
+}
+
+# per_version_boot_params bootparam-string config-file seconds
+#
+# Adds per-version torture-module parameters to kernels supporting them.
+per_version_boot_params () {
+       echo $1 `rcutorture_param_onoff "$1" "$2"` \
+               `rcutorture_param_n_barrier_cbs "$1"` \
+               rcutorture.stat_interval=15 \
+               rcutorture.shutdown_secs=$3 \
+               rcutorture.rcutorture_runnable=1 \
+               rcutorture.test_no_idle_hz=1 \
+               rcutorture.verbose=1
+}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
new file mode 100644 (file)
index 0000000..8977d8d
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# Kernel-version-dependent shell functions for the rest of the scripts.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the 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, you can access it online at
+# http://www.gnu.org/licenses/gpl-2.0.html.
+#
+# Copyright (C) IBM Corporation, 2013
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+# rcutorture_param_n_barrier_cbs bootparam-string
+#
+# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
+rcutorture_param_n_barrier_cbs () {
+       if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
+       then
+               :
+       else
+               echo rcutorture.n_barrier_cbs=4
+       fi
+}
+
+# rcutorture_param_onoff bootparam-string config-file
+#
+# Adds onoff rcutorture module parameters to kernels having it.
+rcutorture_param_onoff () {
+       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
+       then
+               echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
+               echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
+       fi
+}
+
+# per_version_boot_params bootparam-string config-file seconds
+#
+# Adds per-version torture-module parameters to kernels supporting them.
+per_version_boot_params () {
+       echo $1 `rcutorture_param_onoff "$1" "$2"` \
+               `rcutorture_param_n_barrier_cbs "$1"` \
+               rcutorture.stat_interval=15 \
+               rcutorture.shutdown_secs=$3 \
+               rcutorture.rcutorture_runnable=1 \
+               rcutorture.test_no_idle_hz=1 \
+               rcutorture.verbose=1
+}
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/v0.0/CFLIST
deleted file mode 100644 (file)
index 1822394..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d3ef873..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index f72402d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index ef624ce..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_PROVE_RCU_DELAY=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh
deleted file mode 100644 (file)
index e805253..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# rcutorture_param_n_barrier_cbs bootparam-string
-#
-# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
-rcutorture_param_n_barrier_cbs () {
-       echo $1
-}
-
-# rcutorture_param_onoff bootparam-string config-file
-#
-# Adds onoff rcutorture module parameters to kernels having it.
-rcutorture_param_onoff () {
-       echo $1
-}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/v3.12/CFLIST
deleted file mode 100644 (file)
index da4cbc6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-sysidleY.2013.06.19a
-sysidleN.2013.06.19a
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-P6---t-nh-SD-smp-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d81e11d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp
deleted file mode 100644 (file)
index 0ccc36d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_NR_CPUS=1
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 3f640cf..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 285da2d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=14
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 9647c44..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index ef624ce..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_PROVE_RCU_DELAY=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp
deleted file mode 100644 (file)
index f4c9175..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=n
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 77a8c5b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=n
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all
deleted file mode 100644 (file)
index 0eecebc..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none
deleted file mode 100644 (file)
index 0eecebc..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp
deleted file mode 100644 (file)
index 588bc70..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=n
-CONFIG_RCU_NOCB_CPU_ZERO=y
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/v3.3/CFLIST
deleted file mode 100644 (file)
index 1822394..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d81e11d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 9647c44..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index ef624ce..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_PROVE_RCU_DELAY=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh
deleted file mode 100644 (file)
index c37432f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# rcutorture_param_n_barrier_cbs bootparam-string
-#
-# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
-rcutorture_param_n_barrier_cbs () {
-       echo $1
-}
-
-# rcutorture_param_onoff bootparam-string config-file
-#
-# Adds onoff rcutorture module parameters to kernels having it.
-rcutorture_param_onoff () {
-       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
-       then
-               echo CPU-hotplug kernel, adding rcutorture onoff.
-               echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
-       else
-               echo $1
-       fi
-}
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/v3.5/CFLIST
deleted file mode 100644 (file)
index 1822394..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d81e11d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 9647c44..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index ef624ce..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_PROVE_RCU_DELAY=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh
deleted file mode 100644 (file)
index 6a5f13a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# rcutorture_param_n_barrier_cbs bootparam-string
-#
-# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
-rcutorture_param_n_barrier_cbs () {
-       if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
-       then
-               echo $1
-       else
-               echo $1 rcutorture.n_barrier_cbs=4
-       fi
-}
-
-# rcutorture_param_onoff bootparam-string config-file
-#
-# Adds onoff rcutorture module parameters to kernels having it.
-rcutorture_param_onoff () {
-       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
-       then
-               echo CPU-hotplug kernel, adding rcutorture onoff.
-               echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
-       else
-               echo $1
-       fi
-}
diff --git a/tools/testing/selftests/rcutorture/configs/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/ver_functions.sh
deleted file mode 100644 (file)
index 5e40ead..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# rcutorture_param_n_barrier_cbs bootparam-string
-#
-# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
-rcutorture_param_n_barrier_cbs () {
-       if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
-       then
-               echo $1
-       else
-               echo $1 rcutorture.n_barrier_cbs=4
-       fi
-}
-
-# rcutorture_param_onoff bootparam-string config-file
-#
-# Adds onoff rcutorture module parameters to kernels having it.
-rcutorture_param_onoff () {
-       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
-       then
-               echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
-               echo $1 rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
-       else
-               echo $1
-       fi
-}
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt
deleted file mode 100644 (file)
index adbb76c..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-This document gives a brief rationale for the TREE_RCU-related test
-cases, a group that includes TREE_PREEMPT_RCU.
-
-
-Kconfig Parameters:
-
-CONFIG_DEBUG_LOCK_ALLOC -- Do three, covering CONFIG_PROVE_LOCKING & not.
-CONFIG_DEBUG_OBJECTS_RCU_HEAD -- Do one.
-CONFIG_HOTPLUG_CPU -- Do half.  (Every second.)
-CONFIG_HZ_PERIODIC -- Do one.
-CONFIG_NO_HZ_IDLE -- Do those not otherwise specified. (Groups of two.)
-CONFIG_NO_HZ_FULL -- Do two, one with CONFIG_NO_HZ_FULL_SYSIDLE.
-CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
-CONFIG_PREEMPT -- Do half.  (First three and #8.)
-CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not.
-CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING.
-CONFIG_PROVE_RCU_DELAY -- Do one.
-CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU.
-CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing.
-CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE.
-CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO.
-CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others.
-CONFIG_RCU_FANOUT_EXACT -- Do one.
-CONFIG_RCU_FANOUT_LEAF -- Do one non-default.
-CONFIG_RCU_FAST_NO_HZ -- Do one, but not with CONFIG_RCU_NOCB_CPU_ALL.
-CONFIG_RCU_NOCB_CPU -- Do three, see below.
-CONFIG_RCU_NOCB_CPU_ALL -- Do one.
-CONFIG_RCU_NOCB_CPU_NONE -- Do one.
-CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
-CONFIG_RCU_TRACE -- Do half.
-CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU.
-RCU-bh: Do one with PREEMPT and one with !PREEMPT.
-RCU-sched: Do one with PREEMPT but not BOOST.
-
-
-Hierarchy:
-
-TREE01.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=8, CONFIG_RCU_FANOUT_EXACT=n.
-TREE02.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=n,
-       CONFIG_RCU_FANOUT_LEAF=3.
-TREE03.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=4, CONFIG_RCU_FANOUT_EXACT=n,
-       CONFIG_RCU_FANOUT_LEAF=4.
-TREE04.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n,
-       CONFIG_RCU_FANOUT_LEAF=2.
-TREE05.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=n
-       CONFIG_RCU_FANOUT_LEAF=6.
-TREE06.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=y
-       CONFIG_RCU_FANOUT_LEAF=6.
-TREE07.        CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n,
-       CONFIG_RCU_FANOUT_LEAF=2.
-TREE08.        CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=y,
-       CONFIG_RCU_FANOUT_LEAF=2.
-TREE09.        CONFIG_NR_CPUS=1.
-
-
-Kconfig Parameters Ignored:
-
-CONFIG_64BIT
-
-       Used only to check CONFIG_RCU_FANOUT value, inspection suffices.
-
-CONFIG_NO_HZ_FULL_SYSIDLE_SMALL
-
-       Defer until Frederic uses this.
-
-CONFIG_PREEMPT_COUNT
-CONFIG_PREEMPT_RCU
-
-       Redundant with CONFIG_PREEMPT, ignore.
-
-CONFIG_RCU_BOOST_DELAY
-
-       Inspection suffices, ignore.
-
-CONFIG_RCU_CPU_STALL_TIMEOUT
-
-       Inspection suffices, ignore.
-
-CONFIG_RCU_STALL_COMMON
-
-       Implied by TREE_RCU and TREE_PREEMPT_RCU.
-
-CONFIG_RCU_TORTURE_TEST
-CONFIG_RCU_TORTURE_TEST_RUNNABLE
-
-       Always used in KVM testing.
-
-CONFIG_RCU_USER_QS
-
-       Redundant with CONFIG_NO_HZ_FULL.
-
-CONFIG_TREE_PREEMPT_RCU
-CONFIG_TREE_RCU
-
-       These are controlled by CONFIG_PREEMPT.
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
new file mode 100644 (file)
index 0000000..adbb76c
--- /dev/null
@@ -0,0 +1,95 @@
+This document gives a brief rationale for the TREE_RCU-related test
+cases, a group that includes TREE_PREEMPT_RCU.
+
+
+Kconfig Parameters:
+
+CONFIG_DEBUG_LOCK_ALLOC -- Do three, covering CONFIG_PROVE_LOCKING & not.
+CONFIG_DEBUG_OBJECTS_RCU_HEAD -- Do one.
+CONFIG_HOTPLUG_CPU -- Do half.  (Every second.)
+CONFIG_HZ_PERIODIC -- Do one.
+CONFIG_NO_HZ_IDLE -- Do those not otherwise specified. (Groups of two.)
+CONFIG_NO_HZ_FULL -- Do two, one with CONFIG_NO_HZ_FULL_SYSIDLE.
+CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
+CONFIG_PREEMPT -- Do half.  (First three and #8.)
+CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not.
+CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING.
+CONFIG_PROVE_RCU_DELAY -- Do one.
+CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU.
+CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing.
+CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE.
+CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO.
+CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others.
+CONFIG_RCU_FANOUT_EXACT -- Do one.
+CONFIG_RCU_FANOUT_LEAF -- Do one non-default.
+CONFIG_RCU_FAST_NO_HZ -- Do one, but not with CONFIG_RCU_NOCB_CPU_ALL.
+CONFIG_RCU_NOCB_CPU -- Do three, see below.
+CONFIG_RCU_NOCB_CPU_ALL -- Do one.
+CONFIG_RCU_NOCB_CPU_NONE -- Do one.
+CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
+CONFIG_RCU_TRACE -- Do half.
+CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU.
+RCU-bh: Do one with PREEMPT and one with !PREEMPT.
+RCU-sched: Do one with PREEMPT but not BOOST.
+
+
+Hierarchy:
+
+TREE01.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=8, CONFIG_RCU_FANOUT_EXACT=n.
+TREE02.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=n,
+       CONFIG_RCU_FANOUT_LEAF=3.
+TREE03.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=4, CONFIG_RCU_FANOUT_EXACT=n,
+       CONFIG_RCU_FANOUT_LEAF=4.
+TREE04.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n,
+       CONFIG_RCU_FANOUT_LEAF=2.
+TREE05.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=n
+       CONFIG_RCU_FANOUT_LEAF=6.
+TREE06.        CONFIG_NR_CPUS=8, CONFIG_RCU_FANOUT=6, CONFIG_RCU_FANOUT_EXACT=y
+       CONFIG_RCU_FANOUT_LEAF=6.
+TREE07.        CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=2, CONFIG_RCU_FANOUT_EXACT=n,
+       CONFIG_RCU_FANOUT_LEAF=2.
+TREE08.        CONFIG_NR_CPUS=16, CONFIG_RCU_FANOUT=3, CONFIG_RCU_FANOUT_EXACT=y,
+       CONFIG_RCU_FANOUT_LEAF=2.
+TREE09.        CONFIG_NR_CPUS=1.
+
+
+Kconfig Parameters Ignored:
+
+CONFIG_64BIT
+
+       Used only to check CONFIG_RCU_FANOUT value, inspection suffices.
+
+CONFIG_NO_HZ_FULL_SYSIDLE_SMALL
+
+       Defer until Frederic uses this.
+
+CONFIG_PREEMPT_COUNT
+CONFIG_PREEMPT_RCU
+
+       Redundant with CONFIG_PREEMPT, ignore.
+
+CONFIG_RCU_BOOST_DELAY
+
+       Inspection suffices, ignore.
+
+CONFIG_RCU_CPU_STALL_TIMEOUT
+
+       Inspection suffices, ignore.
+
+CONFIG_RCU_STALL_COMMON
+
+       Implied by TREE_RCU and TREE_PREEMPT_RCU.
+
+CONFIG_RCU_TORTURE_TEST
+CONFIG_RCU_TORTURE_TEST_RUNNABLE
+
+       Always used in KVM testing.
+
+CONFIG_RCU_USER_QS
+
+       Redundant with CONFIG_NO_HZ_FULL.
+
+CONFIG_TREE_PREEMPT_RCU
+CONFIG_TREE_RCU
+
+       These are controlled by CONFIG_PREEMPT.
index be456ce264d0b7cca15b61778f94f7290b33cf98..8ca405cd7c1afce8fbbf38a51bf5cd75b2f32168 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/uaccess.h>
 
 #include <linux/irqchip/arm-gic.h>
 
index 88b2fe3ddf42a3c60bba0a3fbc1d7bd3172a8730..00d86427af0f8bae911c2e41a33303c2d02a3428 100644 (file)
@@ -154,17 +154,13 @@ int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
        list_add_tail(&dev->list, &kvm->coalesced_zones);
        mutex_unlock(&kvm->slots_lock);
 
-       return ret;
+       return 0;
 
 out_free_dev:
        mutex_unlock(&kvm->slots_lock);
-
        kfree(dev);
 
-       if (dev == NULL)
-               return -ENXIO;
-
-       return 0;
+       return ret;
 }
 
 int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
index 03a0381b1cb79a2b09a565d43883bb89c5855950..b5ec7fb986f6a560a258c99b8af3977aff936c2d 100644 (file)
@@ -102,7 +102,7 @@ static void kvm_release_pfn_dirty(pfn_t pfn);
 static void mark_page_dirty_in_slot(struct kvm *kvm,
                                    struct kvm_memory_slot *memslot, gfn_t gfn);
 
-bool kvm_rebooting;
+__visible bool kvm_rebooting;
 EXPORT_SYMBOL_GPL(kvm_rebooting);
 
 static bool largepages_enabled = true;