]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'x86/mpx' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Jan 2014 22:46:32 +0000 (14:46 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Jan 2014 22:46:32 +0000 (14:46 -0800)
Pull x86 cpufeature and mpx updates from Peter Anvin:
 "This includes the basic infrastructure for MPX (Memory Protection
  Extensions) support, but does not include MPX support itself.  It is,
  however, a prerequisite for KVM support for MPX, which I believe will
  be pushed later this merge window by the KVM team.

  This includes moving the functionality in
  futex_atomic_cmpxchg_inatomic() into a new function in uaccess.h so it
  can be reused - this will be used by the final MPX patches.

  The actual MPX functionality (map management and so on) will be pushed
  in a future merge window, when ready"

* 'x86/mpx' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/intel/mpx: Remove unused LWP structure
  x86, mpx: Add MPX related opcodes to the x86 opcode map
  x86: replace futex_atomic_cmpxchg_inatomic() with user_atomic_cmpxchg_inatomic
  x86: add user_atomic_cmpxchg_inatomic at uaccess.h
  x86, xsave: Support eager-only xsave features, add MPX support
  x86, cpufeature: Define the Intel MPX feature flag

2157 files changed:
CREDITS
Documentation/ABI/testing/sysfs-firmware-efi [new file with mode: 0644]
Documentation/ABI/testing/sysfs-firmware-efi-runtime-map [new file with mode: 0644]
Documentation/ABI/testing/sysfs-kernel-boot_params [new file with mode: 0644]
Documentation/DocBook/media/v4l/vidioc-expbuf.xml
Documentation/RCU/trace.txt
Documentation/acpi/apei/einj.txt
Documentation/assoc_array.txt
Documentation/block/null_blk.txt [new file with mode: 0644]
Documentation/circular-buffers.txt
Documentation/device-mapper/cache.txt
Documentation/devicetree/bindings/arm/omap/mpu.txt
Documentation/devicetree/bindings/arm/pmu.txt
Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
Documentation/devicetree/bindings/clock/exynos4-clock.txt
Documentation/devicetree/bindings/clock/exynos5250-clock.txt
Documentation/devicetree/bindings/clock/exynos5420-clock.txt
Documentation/devicetree/bindings/clock/exynos5440-clock.txt
Documentation/devicetree/bindings/gpio/8xxx_gpio.txt
Documentation/devicetree/bindings/mmc/ti-omap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/davinci_emac.txt
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt [deleted file]
Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/gpio/00-INDEX [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/kmsg/s390/zcrypt [new file with mode: 0644]
Documentation/memory-barriers.txt
Documentation/mic/mpssd/mpssd.c
Documentation/module-signing.txt [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
Documentation/networking/packet_mmap.txt
Documentation/robust-futex-ABI.txt
Documentation/sysctl/kernel.txt
Documentation/x86/boot.txt
Documentation/x86/x86_64/mm.txt
Documentation/zorro.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/include/asm/barrier.h
arch/arc/Kconfig
arch/arc/include/asm/Kbuild
arch/arc/include/asm/atomic.h
arch/arc/include/asm/barrier.h
arch/arc/include/uapi/asm/unistd.h
arch/arc/kernel/perf_event.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/misc.c
arch/arm/boot/dts/am335x-base0033.dts
arch/arm/boot/dts/am335x-igep0033.dtsi
arch/arm/boot/dts/am3517-evm.dts
arch/arm/boot/dts/am3517.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-xp-mv78230.dtsi
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/at91sam9x5_usart3.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
arch/arm/boot/dts/omap3-beagle-xm.dts
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020.dts
arch/arm/boot/dts/omap3-igep0030.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap34xx-hs.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap36xx-hs.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/crypto/aesbs-core.S_shipped
arch/arm/crypto/bsaes-armv7.pl
arch/arm/include/asm/barrier.h
arch/arm/include/asm/io.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/unistd.h
arch/arm/include/asm/xen/page.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/devtree.c
arch/arm/kernel/head-nommu.S
arch/arm/kernel/head.S
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_cpu.c
arch/arm/kernel/process.c
arch/arm/kernel/relocate_kernel.S
arch/arm/kernel/setup.c
arch/arm/kernel/sigreturn_codes.S
arch/arm/kernel/stacktrace.c
arch/arm/kernel/traps.c
arch/arm/lib/delay-loop.S
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/sama5d3.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/ebsa285.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/dss-common.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_device.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-pxa/include/mach/lubbock.h
arch/arm/mach-pxa/reset.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-tegra/fuse.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/flush.c
arch/arm/mm/mmap.c
arch/arm/mm/pgd.c
arch/arm/net/bpf_jit_32.c
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/xen/enlighten.c
arch/arm/xen/p2m.c
arch/arm64/Kconfig
arch/arm64/include/asm/barrier.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/xen/page-coherent.h
arch/arm64/kernel/head.S
arch/arm64/kernel/ptrace.c
arch/arm64/mm/proc.S
arch/avr32/boards/favr-32/setup.c
arch/avr32/configs/atngw100_defconfig
arch/avr32/configs/atngw100_evklcd100_defconfig
arch/avr32/configs/atngw100_evklcd101_defconfig
arch/avr32/configs/atngw100_mrmt_defconfig
arch/avr32/configs/atngw100mkii_defconfig
arch/avr32/configs/atngw100mkii_evklcd100_defconfig
arch/avr32/configs/atngw100mkii_evklcd101_defconfig
arch/avr32/configs/atstk1002_defconfig
arch/avr32/configs/atstk1003_defconfig
arch/avr32/configs/atstk1004_defconfig
arch/avr32/configs/atstk1006_defconfig
arch/avr32/configs/favr-32_defconfig
arch/avr32/configs/hammerhead_defconfig
arch/avr32/configs/merisc_defconfig
arch/avr32/configs/mimc200_defconfig
arch/avr32/include/asm/barrier.h
arch/avr32/kernel/time.c
arch/avr32/mach-at32ap/pm.c
arch/blackfin/include/asm/barrier.h
arch/cris/include/asm/Kbuild
arch/cris/include/asm/barrier.h [deleted file]
arch/frv/include/asm/barrier.h
arch/hexagon/include/asm/Kbuild
arch/hexagon/include/asm/atomic.h
arch/hexagon/include/asm/barrier.h
arch/ia64/Kconfig
arch/ia64/Makefile
arch/ia64/configs/xen_domu_defconfig [deleted file]
arch/ia64/include/asm/acpi.h
arch/ia64/include/asm/barrier.h
arch/ia64/include/asm/machvec.h
arch/ia64/include/asm/machvec_xen.h [deleted file]
arch/ia64/include/asm/meminit.h
arch/ia64/include/asm/paravirt.h
arch/ia64/include/asm/pvclock-abi.h
arch/ia64/include/asm/sync_bitops.h [deleted file]
arch/ia64/include/asm/xen/events.h [deleted file]
arch/ia64/include/asm/xen/hypercall.h [deleted file]
arch/ia64/include/asm/xen/hypervisor.h [deleted file]
arch/ia64/include/asm/xen/inst.h [deleted file]
arch/ia64/include/asm/xen/interface.h [deleted file]
arch/ia64/include/asm/xen/irq.h [deleted file]
arch/ia64/include/asm/xen/minstate.h [deleted file]
arch/ia64/include/asm/xen/page-coherent.h [deleted file]
arch/ia64/include/asm/xen/page.h [deleted file]
arch/ia64/include/asm/xen/patchlist.h [deleted file]
arch/ia64/include/asm/xen/privop.h [deleted file]
arch/ia64/include/asm/xen/xcom_hcall.h [deleted file]
arch/ia64/include/asm/xen/xencomm.h [deleted file]
arch/ia64/include/uapi/asm/break.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/head.S
arch/ia64/kernel/nr-irqs.c
arch/ia64/kernel/paravirt_inst.h
arch/ia64/kernel/paravirt_patchlist.h
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/xen/Kconfig [deleted file]
arch/ia64/xen/Makefile [deleted file]
arch/ia64/xen/gate-data.S [deleted file]
arch/ia64/xen/grant-table.c [deleted file]
arch/ia64/xen/hypercall.S [deleted file]
arch/ia64/xen/hypervisor.c [deleted file]
arch/ia64/xen/irq_xen.c [deleted file]
arch/ia64/xen/irq_xen.h [deleted file]
arch/ia64/xen/machvec.c [deleted file]
arch/ia64/xen/suspend.c [deleted file]
arch/ia64/xen/time.c [deleted file]
arch/ia64/xen/time.h [deleted file]
arch/ia64/xen/xcom_hcall.c [deleted file]
arch/ia64/xen/xen_pv_ops.c [deleted file]
arch/ia64/xen/xencomm.c [deleted file]
arch/ia64/xen/xenivt.S [deleted file]
arch/ia64/xen/xensetup.S [deleted file]
arch/m32r/include/asm/barrier.h
arch/m68k/Kconfig
arch/m68k/amiga/chipram.c
arch/m68k/amiga/config.c
arch/m68k/amiga/platform.c
arch/m68k/apollo/config.c
arch/m68k/atari/ataints.c
arch/m68k/atari/config.c
arch/m68k/atari/debug.c
arch/m68k/bvme6000/config.c
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/emu/natfeat.c
arch/m68k/hp300/config.c
arch/m68k/include/asm/amigahw.h
arch/m68k/include/asm/apollohw.h
arch/m68k/include/asm/atarihw.h
arch/m68k/include/asm/barrier.h
arch/m68k/include/asm/bootinfo.h
arch/m68k/include/asm/hp300hw.h
arch/m68k/include/asm/kexec.h [new file with mode: 0644]
arch/m68k/include/asm/mac_via.h
arch/m68k/include/asm/macintosh.h
arch/m68k/include/asm/mc146818rtc.h
arch/m68k/include/asm/mvme16xhw.h
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/timex.h
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/bootinfo-amiga.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-apollo.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-atari.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-hp300.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-mac.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-q40.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-vme.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/setup.h
arch/m68k/kernel/Makefile
arch/m68k/kernel/asm-offsets.c
arch/m68k/kernel/bootinfo_proc.c [new file with mode: 0644]
arch/m68k/kernel/head.S
arch/m68k/kernel/machine_kexec.c [new file with mode: 0644]
arch/m68k/kernel/relocate_kernel.S [new file with mode: 0644]
arch/m68k/kernel/setup_mm.c
arch/m68k/kernel/time.c
arch/m68k/kernel/traps.c
arch/m68k/mac/config.c
arch/m68k/mac/iop.c
arch/m68k/mac/misc.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/mm/fault.c
arch/m68k/mm/init.c
arch/m68k/mm/kmap.c
arch/m68k/mm/motorola.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/sun3/dvma.c
arch/m68k/sun3/mmu_emu.c
arch/m68k/sun3/sun3dvma.c
arch/m68k/sun3x/prom.c
arch/metag/include/asm/barrier.h
arch/metag/include/asm/smp.h
arch/metag/kernel/dma.c
arch/metag/kernel/smp.c
arch/metag/kernel/topology.c
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/asm/barrier.h [deleted file]
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/ar7/setup.c
arch/mips/emma/markeins/setup.c
arch/mips/include/asm/barrier.h
arch/mips/include/asm/cacheops.h
arch/mips/include/asm/r4kcache.h
arch/mips/mm/c-r4k.c
arch/mips/netlogic/xlp/setup.c
arch/mips/netlogic/xlr/setup.c
arch/mips/sibyte/swarm/setup.c
arch/mn10300/include/asm/Kbuild
arch/mn10300/include/asm/barrier.h [deleted file]
arch/parisc/configs/c3000_defconfig
arch/parisc/configs/c8000_defconfig
arch/parisc/configs/generic-64bit_defconfig
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/barrier.h [deleted file]
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/page.h
arch/parisc/include/asm/serial.h
arch/parisc/include/uapi/asm/socket.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/hardware.c
arch/parisc/kernel/head.S
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/unwind.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/boot/dts/mpc5121.dtsi
arch/powerpc/boot/dts/mpc5125twr.dts
arch/powerpc/configs/52xx/cm5200_defconfig
arch/powerpc/configs/52xx/lite5200b_defconfig
arch/powerpc/configs/52xx/motionpro_defconfig
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/include/asm/barrier.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/pgalloc-32.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/setup.h
arch/powerpc/include/asm/spinlock.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/include/asm/unaligned.h
arch/powerpc/include/asm/uprobes.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/uprobes.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/lib/copyuser_64.S
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/opal-lpc.c
arch/powerpc/platforms/powernv/opal-xscom.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/pseries/lparcfg.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/nvram.c
arch/powerpc/platforms/pseries/pci.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/ppc4xx_ocm.c
arch/s390/Kconfig
arch/s390/crypto/aes_s390.c
arch/s390/include/asm/barrier.h
arch/s390/include/asm/compat.h
arch/s390/include/asm/cpu_mf.h
arch/s390/include/asm/css_chars.h
arch/s390/include/asm/pci.h
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/sclp.h
arch/s390/include/asm/smp.h
arch/s390/include/uapi/asm/zcrypt.h
arch/s390/kernel/Makefile
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/entry64.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/perf_cpum_cf_events.c [new file with mode: 0644]
arch/s390/kernel/perf_cpum_sf.c [new file with mode: 0644]
arch/s390/kernel/perf_event.c
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/s390_ksyms.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kvm/priv.c
arch/s390/lib/uaccess_pt.c
arch/s390/mm/pgtable.c
arch/s390/net/bpf_jit_comp.c
arch/s390/oprofile/hwsampler.c
arch/s390/oprofile/hwsampler.h
arch/s390/oprofile/init.c
arch/s390/pci/pci.c
arch/s390/pci/pci_dma.c
arch/s390/pci/pci_event.c
arch/score/include/asm/Kbuild
arch/score/include/asm/barrier.h [deleted file]
arch/sh/Kconfig
arch/sh/Makefile
arch/sh/include/asm/barrier.h
arch/sh/kernel/sh_ksyms_32.c
arch/sh/lib/Makefile
arch/sparc/include/asm/barrier_32.h
arch/sparc/include/asm/barrier_64.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/kernel/iommu.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/kgdb_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/net/bpf_jit_comp.c
arch/tile/include/asm/barrier.h
arch/um/Makefile
arch/um/kernel/sysrq.c
arch/unicore32/include/asm/barrier.h
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/Makefile
arch/x86/boot/bioscall.S
arch/x86/boot/boot.h
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/aslr.c [new file with mode: 0644]
arch/x86/boot/compressed/cmdline.c
arch/x86/boot/compressed/cpuflags.c [new file with mode: 0644]
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/boot/copy.S
arch/x86/boot/cpucheck.c
arch/x86/boot/cpuflags.c [new file with mode: 0644]
arch/x86/boot/cpuflags.h [new file with mode: 0644]
arch/x86/boot/header.S
arch/x86/include/asm/archrandom.h
arch/x86/include/asm/atomic.h
arch/x86/include/asm/atomic64_64.h
arch/x86/include/asm/barrier.h
arch/x86/include/asm/bitops.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/intel-mid.h
arch/x86/include/asm/iosf_mbi.h [new file with mode: 0644]
arch/x86/include/asm/irq.h
arch/x86/include/asm/local.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_amd.h
arch/x86/include/asm/mpspec.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/page.h
arch/x86/include/asm/page_32.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/pgtable-2level.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_64_types.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/preempt.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/rmwcc.h
arch/x86/include/asm/setup.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/timer.h
arch/x86/include/asm/trace/irq_vectors.h
arch/x86/include/asm/tsc.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/cstate.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/io_apic.c
arch/x86/kernel/apic/ipi.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/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/centaur.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/mcheck/mce-apei.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/cpu/mcheck/p5.c
arch/x86/kernel/cpu/mcheck/winchip.c
arch/x86/kernel/cpu/microcode/Makefile [new file with mode: 0644]
arch/x86/kernel/cpu/microcode/amd.c [moved from arch/x86/kernel/microcode_amd.c with 96% similarity]
arch/x86/kernel/cpu/microcode/amd_early.c [moved from arch/x86/kernel/microcode_amd_early.c with 55% similarity]
arch/x86/kernel/cpu/microcode/core.c [moved from arch/x86/kernel/microcode_core.c with 100% similarity]
arch/x86/kernel/cpu/microcode/core_early.c [moved from arch/x86/kernel/microcode_core_early.c with 100% similarity]
arch/x86/kernel/cpu/microcode/intel.c [moved from arch/x86/kernel/microcode_intel.c with 100% similarity]
arch/x86/kernel/cpu/microcode/intel_early.c [moved from arch/x86/kernel/microcode_intel_early.c with 98% similarity]
arch/x86/kernel/cpu/microcode/intel_lib.c [moved from arch/x86/kernel/microcode_intel_lib.c with 100% similarity]
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/cpu/perf_event_intel_rapl.c [new file with mode: 0644]
arch/x86/kernel/cpu/rdrand.c
arch/x86/kernel/cpu/transmeta.c
arch/x86/kernel/cpu/umc.c
arch/x86/kernel/crash.c
arch/x86/kernel/doublefault.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/hw_breakpoint.c
arch/x86/kernel/iosf_mbi.c [new file with mode: 0644]
arch/x86/kernel/irq.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/ksysfs.c [new file with mode: 0644]
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/pci-nommu.c
arch/x86/kernel/process_32.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/tsc_msr.c [new file with mode: 0644]
arch/x86/kernel/tsc_sync.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/copy_user_64.S
arch/x86/lib/delay.c
arch/x86/mm/fault.c
arch/x86/mm/gup.c
arch/x86/mm/hugetlbpage.c
arch/x86/mm/init_32.c
arch/x86/mm/kmmio.c
arch/x86/mm/numa.c
arch/x86/mm/pageattr-test.c
arch/x86/mm/pageattr.c
arch/x86/net/bpf_jit_comp.c
arch/x86/pci/fixup.c
arch/x86/pci/intel_mid_pci.c
arch/x86/platform/efi/early_printk.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/intel-mid/Makefile
arch/x86/platform/intel-mid/device_libs/platform_emc1403.c
arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c
arch/x86/platform/intel-mid/device_libs/platform_lis331.c
arch/x86/platform/intel-mid/device_libs/platform_max7315.c
arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c
arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c
arch/x86/platform/intel-mid/device_libs/platform_tca6416.c
arch/x86/platform/intel-mid/early_printk_intel_mid.c
arch/x86/platform/intel-mid/intel-mid.c
arch/x86/platform/intel-mid/intel_mid_weak_decls.h [new file with mode: 0644]
arch/x86/platform/intel-mid/mfld.c [new file with mode: 0644]
arch/x86/platform/intel-mid/mrfl.c [new file with mode: 0644]
arch/x86/platform/intel-mid/sfi.c
arch/x86/platform/iris/iris.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/realmode/init.c
arch/x86/realmode/rm/Makefile
arch/x86/realmode/rm/reboot.S
arch/x86/realmode/rm/trampoline_32.S
arch/x86/realmode/rm/trampoline_64.S
arch/x86/syscalls/syscall_32.tbl
arch/x86/syscalls/syscall_64.tbl
arch/x86/tools/relocs.c
arch/x86/vdso/vclock_gettime.c
arch/x86/vdso/vdso.S
arch/x86/vdso/vdsox32.S
arch/xtensa/include/asm/barrier.h
block/blk-cgroup.h
block/blk-flush.c
block/blk-mq-sysfs.c
block/blk-mq.c
crypto/algif_hash.c
crypto/algif_skcipher.c
crypto/authenc.c
crypto/ccm.c
crypto/tcrypt.c
crypto/testmgr.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/acpi_extlog.c
drivers/acpi/acpi_pad.c
drivers/acpi/apei/Kconfig
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/einj.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/ghes.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/processor_idle.c
drivers/ata/ahci.c
drivers/ata/ahci_imx.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/sata_sis.c
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap.c
drivers/block/null_blk.c
drivers/block/skd_main.c
drivers/block/xen-blkfront.c
drivers/block/z2ram.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/i8k.c
drivers/char/tpm/tpm_ppi.c
drivers/clk/clk-divider.c
drivers/clk/clk-s2mps11.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/arm_global_timer.c
drivers/clocksource/bcm_kona_timer.c
drivers/clocksource/cadence_ttc_timer.c
drivers/clocksource/clksrc-of.c
drivers/clocksource/cs5535-clockevt.c
drivers/clocksource/dw_apb_timer.c
drivers/clocksource/dw_apb_timer_of.c
drivers/clocksource/nomadik-mtu.c
drivers/clocksource/samsung_pwm_timer.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/sh_tmu.c
drivers/clocksource/sun4i_timer.c
drivers/clocksource/tegra20_timer.c
drivers/clocksource/time-armada-370-xp.c
drivers/clocksource/time-orion.c
drivers/clocksource/timer-sun5i.c [new file with mode: 0644]
drivers/clocksource/vt8500_timer.c
drivers/cpufreq/at32ap-cpufreq.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle-calxeda.c
drivers/cpuidle/cpuidle.c
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/jr.c
drivers/crypto/ixp4xx_crypto.c
drivers/crypto/talitos.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/ioat/dma.c
drivers/dma/mmp_pdma.c
drivers/dma/mv_xor.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/s3c24xx-dma.c
drivers/dma/sh/rcar-hpbdma.c
drivers/dma/txx9dmac.c
drivers/edac/amd64_edac.c
drivers/edac/amd76x_edac.c
drivers/edac/e752x_edac.c
drivers/edac/e7xxx_edac.c
drivers/edac/edac_device.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/edac_stub.c
drivers/edac/i3000_edac.c
drivers/edac/i3200_edac.c
drivers/edac/i5000_edac.c
drivers/edac/i5100_edac.c
drivers/edac/i5400_edac.c
drivers/edac/i7300_edac.c
drivers/edac/i7core_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/i82860_edac.c
drivers/edac/i82875p_edac.c
drivers/edac/i82975x_edac.c
drivers/edac/mpc85xx_edac.c
drivers/edac/mpc85xx_edac.h
drivers/edac/r82600_edac.c
drivers/edac/sb_edac.c
drivers/edac/x38_edac.c
drivers/extcon/extcon-arizona.c
drivers/extcon/extcon-class.c
drivers/firmware/Makefile
drivers/firmware/efi/Kconfig
drivers/firmware/efi/Makefile
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/efivars.c
drivers/firmware/efi/runtime-map.c [new file with mode: 0644]
drivers/firmware/efi/vars.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-msm-v2.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-twl4030.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/armada/armada_drm.h
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/armada/armada_fbdev.c
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/core/subdev.c
drivers/gpu/drm/nouveau/core/engine/device/base.c
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
drivers/gpu/drm/nouveau/core/include/subdev/instmem.h
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
drivers/gpu/drm/nouveau/dispnv04/dfp.c
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/qxl/Kconfig
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_i2c.c
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_hdmi.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/ni_dpm.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_atombios.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_trace.h
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/hw/cdma_hw.c
drivers/gpu/host1x/hw/debug_hw.c
drivers/hid/hid-kye.c
drivers/hid/hid-sensor-hub.c
drivers/hwmon/coretemp.c
drivers/hwmon/da9052-hwmon.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/hih6130.c
drivers/hwmon/k10temp.c
drivers/hwmon/k8temp.c
drivers/hwmon/lm78.c
drivers/hwmon/lm90.c
drivers/hwmon/nct6775.c
drivers/hwmon/sis5595.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83l786ng.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/i2c-mux.c
drivers/ide/buddha.c
drivers/idle/intel_idle.c
drivers/iio/adc/ad7887.c
drivers/iio/common/hid-sensors/Kconfig
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/imu/adis16400_core.c
drivers/iio/light/Kconfig
drivers/iio/light/cm36651.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/ulp/ipoib/ipoib_netlink.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/input/input.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/bf54x-keys.c
drivers/input/misc/adxl34x.c
drivers/input/misc/pcf8574_keypad.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/elantech.c
drivers/input/serio/serio.c
drivers/input/touchscreen/sur40.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/input/touchscreen/zforce_ts.c
drivers/iommu/arm-smmu.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/telespci.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-pwm.c
drivers/macintosh/Kconfig
drivers/md/bcache/alloc.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/movinggc.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/util.c
drivers/md/bcache/util.h
drivers/md/bcache/writeback.c
drivers/md/dm-bufio.c
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-target.c
drivers/md/dm-delay.c
drivers/md/dm-snap.c
drivers/md/dm-stats.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/md.h
drivers/md/persistent-data/dm-array.c
drivers/md/persistent-data/dm-block-manager.c
drivers/md/persistent-data/dm-block-manager.h
drivers/md/persistent-data/dm-space-map-common.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/common/siano/smscoreapi.h
drivers/media/common/siano/smsdvb.h
drivers/media/dvb-core/dvb_demux.c
drivers/media/dvb-frontends/af9033.c
drivers/media/dvb-frontends/cxd2820r_c.c
drivers/media/dvb-frontends/dib8000.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/dvb-frontends/rtl2830.c
drivers/media/i2c/adv7183_regs.h
drivers/media/i2c/adv7604.c
drivers/media/i2c/adv7842.c
drivers/media/i2c/ir-kbd-i2c.c
drivers/media/i2c/m5mols/m5mols_controls.c
drivers/media/i2c/mt9p031.c
drivers/media/i2c/s5c73m3/s5c73m3-core.c
drivers/media/i2c/s5c73m3/s5c73m3.h
drivers/media/i2c/saa7115.c
drivers/media/i2c/soc_camera/ov5642.c
drivers/media/i2c/ths7303.c
drivers/media/i2c/wm8775.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/cx18/cx18-driver.h
drivers/media/pci/cx23885/cx23885-417.c
drivers/media/pci/pluto2/pluto2.c
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/platform/coda.c
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/platform/exynos4-is/media-dev.c
drivers/media/platform/marvell-ccic/mmp-driver.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s5p-mfc/regs-mfc.h
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/platform/s5p-tv/mixer.h
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/soc_camera/omap1_camera.c
drivers/media/platform/vivi.c
drivers/media/platform/vsp1/vsp1_drv.c
drivers/media/platform/vsp1/vsp1_video.c
drivers/media/radio/radio-shark.c
drivers/media/radio/radio-shark2.c
drivers/media/radio/radio-si476x.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/tef6862.c
drivers/media/rc/imon.c
drivers/media/rc/redrat3.c
drivers/media/tuners/mt2063.c
drivers/media/tuners/tuner-xc2028-types.h
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/mxl111sf.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/em28xx/em28xx-video.c
drivers/media/usb/gspca/gl860/gl860.c
drivers/media/usb/gspca/pac207.c
drivers/media/usb/gspca/pac7302.c
drivers/media/usb/gspca/stk1135.c
drivers/media/usb/gspca/stv0680.c
drivers/media/usb/gspca/sunplus.c
drivers/media/usb/gspca/zc3xx.c
drivers/media/usb/pwc/pwc-if.c
drivers/media/usb/usbtv/usbtv.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/mfd/Kconfig
drivers/mfd/lpc_ich.c
drivers/mfd/rtsx_pcr.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/ti-ssp.c
drivers/misc/enclosure.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mic/card/mic_virtio.c
drivers/misc/mic/card/mic_virtio.h
drivers/misc/mic/host/mic_boot.c
drivers/misc/mic/host/mic_virtio.c
drivers/misc/mic/host/mic_x100.c
drivers/mmc/host/omap.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/c_can/c_can.c
drivers/net/can/flexcan.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/usb/ems_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/ethernet/8390/hydra.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/a2065.c
drivers/net/ethernet/amd/ariadne.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/intel/e1000/e1000.h
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_selftest.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi.h
drivers/net/ethernet/sfc/mcdi_mon.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hamradio/yam.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/vitesse.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/dm9601.c
drivers/net/usb/hso.c
drivers/net/usb/mcs7830.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/of/Kconfig
drivers/of/address.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/parport/parport_mfc3.c
drivers/pci/host/pci-mvebu.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/remove.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/pinctrl/pinctrl-abx500.c
drivers/pinctrl/pinctrl-abx500.h
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/sh-pfc/pfc-r8a7740.c
drivers/pinctrl/sh-pfc/pfc-sh7372.c
drivers/pinctrl/sh-pfc/sh_pfc.h
drivers/pnp/driver.c
drivers/power/Kconfig
drivers/power/power_supply_core.c
drivers/powercap/intel_rapl.c
drivers/powercap/powercap_sys.c
drivers/regulator/as3722-regulator.c
drivers/regulator/core.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-s5m.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_genhd.c
drivers/s390/char/sclp.h
drivers/s390/char/sclp_cmd.c
drivers/s390/char/sclp_early.c
drivers/s390/char/tty3270.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/qdio_main.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_cex4.c
drivers/s390/crypto/zcrypt_error.h
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/crypto/zcrypt_msgtype6.h
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcicc.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/a2091.c
drivers/scsi/a3000.c
drivers/scsi/a4000t.c
drivers/scsi/aacraid/linit.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfad_attr.c
drivers/scsi/gdth.c
drivers/scsi/gvp11.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_hwi.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/pm8001/pm80xx_hwi.h
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/sd.c
drivers/scsi/storvsc_drv.c
drivers/scsi/zorro7xx.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mxs.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-txx9.c
drivers/spi/spi.c
drivers/staging/bcm/Bcmnet.c
drivers/staging/comedi/drivers.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-tve.c
drivers/staging/imx-drm/ipu-v3/ipu-common.c
drivers/staging/netlogic/xlr_net.c
drivers/staging/rtl8188eu/os_dep/os_intfs.c
drivers/staging/tidspbridge/rmgr/drv_interface.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_file.h
drivers/target/target_core_tpg.c
drivers/thermal/intel_powerclamp.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_ldsem.c
drivers/uio/uio.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hub.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/storage_common.h
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/gadget/zero.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_gadget.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-am335x.c
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-generic.h
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-rcar-gen2-usb.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/phy/phy-twl6030-usb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/generic.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/zte_ev.c
drivers/usb/wusbcore/devconnect.c
drivers/usb/wusbcore/security.c
drivers/usb/wusbcore/wusbhc.h
drivers/video/amifb.c
drivers/video/atmel_lcdfb.c
drivers/video/cirrusfb.c
drivers/video/kyro/fbdev.c
drivers/video/macfb.c
drivers/video/offb.c
drivers/video/omap2/displays-new/panel-sony-acx565akm.c
drivers/video/sh_mobile_meram.c
drivers/video/valkyriefb.c
drivers/video/vt8500lcdfb.c
drivers/virtio/virtio_balloon.c
drivers/watchdog/bcm2835_wdt.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/ie6xx_wdt.c
drivers/watchdog/jz4740_wdt.c
drivers/watchdog/kempld_wdt.c
drivers/watchdog/max63xx_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/rt2880_wdt.c
drivers/watchdog/sc1200wdt.c
drivers/watchdog/shwdt.c
drivers/watchdog/softdog.c
drivers/watchdog/stmp3xxx_rtc_wdt.c
drivers/watchdog/txx9wdt.c
drivers/watchdog/ux500_wdt.c
drivers/xen/balloon.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
drivers/xen/swiotlb-xen.c
drivers/zorro/Makefile
drivers/zorro/names.c
drivers/zorro/proc.c
drivers/zorro/zorro-driver.c
drivers/zorro/zorro-sysfs.c
drivers/zorro/zorro.c
drivers/zorro/zorro.h
fs/aio.c
fs/btrfs/check-integrity.c
fs/btrfs/check-integrity.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/ceph/addr.c
fs/ceph/inode.c
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/link.c
fs/dcache.c
fs/eventpoll.c
fs/ext2/super.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/fs-writeback.c
fs/gfs2/aops.c
fs/gfs2/glock.c
fs/gfs2/glops.c
fs/gfs2/log.c
fs/gfs2/meta_io.c
fs/gfs2/ops_fstype.c
fs/hfsplus/wrapper.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/transaction.c
fs/logfs/dev_bdev.c
fs/namei.c
fs/namespace.c
fs/nfs/blocklayout/blocklayout.h
fs/nfs/blocklayout/extents.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfsd/nfscache.c
fs/nilfs2/segment.c
fs/pipe.c
fs/proc/inode.c
fs/pstore/platform.c
fs/squashfs/file_direct.c
fs/sysfs/file.c
fs/xfs/xfs_attr_remote.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_ioctl32.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_trans_buf.c
include/acpi/acpi_bus.h
include/asm-generic/barrier.h
include/asm-generic/pgtable.h
include/asm-generic/preempt.h
include/asm-generic/word-at-a-time.h
include/crypto/scatterwalk.h
include/drm/drm_pciids.h
include/linux/assoc_array.h
include/linux/auxvec.h
include/linux/bottom_half.h
include/linux/compiler-intel.h
include/linux/compiler.h
include/linux/context_tracking.h
include/linux/context_tracking_state.h
include/linux/crash_dump.h
include/linux/dcache.h
include/linux/edac.h
include/linux/efi.h
include/linux/ftrace_event.h
include/linux/gpio/driver.h
include/linux/hardirq.h
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/hugetlb.h
include/linux/i2c.h
include/linux/init_task.h
include/linux/ipv6.h
include/linux/irqreturn.h
include/linux/kernel.h
include/linux/kexec.h
include/linux/libata.h
include/linux/lockref.h
include/linux/math64.h
include/linux/mfd/samsung/core.h
include/linux/micrel_phy.h
include/linux/migrate.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/net.h
include/linux/netdevice.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/pci.h
include/linux/percpu-defs.h
include/linux/perf_event.h
include/linux/platform_data/hwmon-s3c.h
include/linux/platform_data/max197.h
include/linux/platform_data/sht15.h
include/linux/preempt.h
include/linux/preempt_mask.h
include/linux/pstore.h
include/linux/rculist.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/reboot.h
include/linux/rtmutex.h
include/linux/rtnetlink.h
include/linux/rwlock_api_smp.h
include/linux/sched.h
include/linux/sched/deadline.h [new file with mode: 0644]
include/linux/sched/rt.h
include/linux/sched/sysctl.h
include/linux/seqlock.h
include/linux/shmem_fs.h
include/linux/skbuff.h
include/linux/spinlock.h
include/linux/spinlock_api_smp.h
include/linux/spinlock_api_up.h
include/linux/syscalls.h
include/linux/tick.h
include/linux/tracepoint.h
include/linux/uaccess.h
include/linux/uprobes.h
include/linux/usb.h
include/linux/usb/wusb.h
include/linux/vtime.h
include/linux/zorro.h
include/media/videobuf2-core.h
include/net/busy_poll.h
include/net/if_inet6.h
include/net/ip.h
include/net/ipv6.h
include/net/llc_pdu.h
include/net/ping.h
include/net/sctp/structs.h
include/net/sock.h
include/rdma/ib_verbs.h
include/scsi/scsi_host.h
include/sound/memalloc.h
include/sound/soc-dapm.h
include/target/target_core_base.h
include/trace/events/ras.h
include/trace/ftrace.h
include/uapi/drm/radeon_drm.h
include/uapi/drm/vmwgfx_drm.h
include/uapi/linux/Kbuild
include/uapi/linux/eventpoll.h
include/uapi/linux/genetlink.h
include/uapi/linux/if_link.h
include/uapi/linux/input.h
include/uapi/linux/kexec.h
include/uapi/linux/mic_common.h
include/uapi/linux/netlink_diag.h
include/uapi/linux/packet_diag.h
include/uapi/linux/perf_event.h
include/uapi/linux/sched.h
include/uapi/linux/unix_diag.h
include/uapi/linux/zorro.h [new file with mode: 0644]
include/uapi/linux/zorro_ids.h [moved from include/linux/zorro_ids.h with 100% similarity]
include/uapi/sound/compress_offload.h
include/xen/interface/callback.h
include/xen/interface/io/blkif.h
include/xen/interface/io/protocols.h
init/Kconfig
kernel/.gitignore
kernel/Makefile
kernel/bounds.c
kernel/cgroup.c
kernel/context_tracking.c
kernel/cpu/idle.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/events/uprobes.c
kernel/fork.c
kernel/freezer.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/pm.c
kernel/kexec.c
kernel/locking/lockdep.c
kernel/locking/mutex-debug.c
kernel/locking/rtmutex-debug.c
kernel/locking/rtmutex.c
kernel/locking/rtmutex_common.h
kernel/panic.c
kernel/posix-cpu-timers.c
kernel/power/console.c
kernel/rcu/rcu.h
kernel/rcu/srcu.c
kernel/rcu/torture.c
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/rcu/tree_trace.c
kernel/rcu/update.c
kernel/reboot.c
kernel/sched/Makefile
kernel/sched/clock.c
kernel/sched/core.c
kernel/sched/cpudeadline.c [new file with mode: 0644]
kernel/sched/cpudeadline.h [new file with mode: 0644]
kernel/sched/deadline.c [new file with mode: 0644]
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/sched/stop_task.c
kernel/softirq.c
kernel/sysctl.c
kernel/system_certificates.S
kernel/system_keyring.c
kernel/time/sched_clock.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_events.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_selftest.c
kernel/trace/trace_syscalls.c
kernel/user.c
kernel/workqueue.c
lib/Kconfig.debug
lib/assoc_array.c
lib/percpu_counter.c
mm/Kconfig
mm/compaction.c
mm/fremap.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mlock.c
mm/mprotect.c
mm/page_alloc.c
mm/pgtable-generic.c
mm/rmap.c
mm/shmem.c
mm/util.c
net/8021q/vlan_dev.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/fragmentation.c
net/batman-adv/icmp_socket.c
net/batman-adv/main.c
net/batman-adv/network-coding.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_sock.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_stp_bpdu.c
net/compat.c
net/core/dev.c
net/core/drop_monitor.c
net/core/filter.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/netpoll.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ipv6.c
net/dccp/probe.c
net/hsr/hsr_framereg.c
net/hsr/hsr_netlink.c
net/ieee802154/6lowpan.c
net/ieee802154/nl-phy.c
net/ipv4/fib_rules.c
net/ipv4/gre_offload.c
net/ipv4/inet_diag.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/netfilter/nft_reject_ipv4.c
net/ipv4/ping.c
net/ipv4/protocol.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_memcontrol.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_offload.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/ping.c
net/ipv6/protocol.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/tcpv6_offload.c
net/ipv6/udp.c
net/l2tp/l2tp_ip6.c
net/llc/af_llc.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/spectmgmt.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_conntrack_seqadj.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_log.c
net/netfilter/nft_exthdr.c
net/netfilter/xt_hashlimit.c
net/netlink/genetlink.c
net/nfc/core.c
net/packet/af_packet.c
net/rds/ib.c
net/rds/ib_recv.c
net/rds/ib_send.c
net/rose/af_rose.c
net/sched/act_api.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sched/sch_netem.c
net/sched/sch_tbf.c
net/sctp/associola.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/probe.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/transport.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/tipc/core.c
net/tipc/handler.c
net/tipc/link.c
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/ibss.c
net/wireless/nl80211.c
net/wireless/radiotap.c
net/wireless/sme.c
scripts/kconfig/streamline_config.pl
scripts/link-vmlinux.sh
scripts/recordmcount.pl
scripts/sortextable.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_template.c
security/keys/big_key.c
security/keys/key.c
security/keys/keyring.c
security/selinux/hooks.c
security/selinux/include/objsec.h
security/selinux/include/xfrm.h
security/selinux/ss/services.c
security/selinux/xfrm.c
sound/atmel/abdac.c
sound/core/pcm_lib.c
sound/firewire/dice.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_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/sam9x5_wm8731.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-wm8962.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/omap/n810.c
sound/soc/sh/Kconfig
sound/soc/soc-core.c
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c
sound/usb/mixer_quirks.c
tools/Makefile
tools/include/asm/bug.h [moved from tools/perf/util/include/asm/bug.h with 81% similarity]
tools/include/linux/compiler.h [moved from tools/perf/util/include/linux/compiler.h with 64% similarity]
tools/lib/api/Makefile [moved from tools/lib/lk/Makefile with 66% similarity]
tools/lib/api/fs/debugfs.c [moved from tools/lib/lk/debugfs.c with 100% similarity]
tools/lib/api/fs/debugfs.h [moved from tools/lib/lk/debugfs.h with 86% similarity]
tools/lib/lockdep/Makefile [new file with mode: 0644]
tools/lib/lockdep/common.c [new file with mode: 0644]
tools/lib/lockdep/include/liblockdep/common.h [new file with mode: 0644]
tools/lib/lockdep/include/liblockdep/mutex.h [new file with mode: 0644]
tools/lib/lockdep/include/liblockdep/rwlock.h [new file with mode: 0644]
tools/lib/lockdep/lockdep [new file with mode: 0755]
tools/lib/lockdep/lockdep.c [new file with mode: 0644]
tools/lib/lockdep/lockdep_internals.h [new file with mode: 0644]
tools/lib/lockdep/lockdep_states.h [new file with mode: 0644]
tools/lib/lockdep/preload.c [new file with mode: 0644]
tools/lib/lockdep/rbtree.c [new file with mode: 0644]
tools/lib/lockdep/run_tests.sh [new file with mode: 0644]
tools/lib/lockdep/tests/AA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBCCA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBCCDDA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABCABC.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABCDBCDA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABCDBDDA.c [new file with mode: 0644]
tools/lib/lockdep/tests/WW.c [new file with mode: 0644]
tools/lib/lockdep/tests/common.h [new file with mode: 0644]
tools/lib/lockdep/tests/unlock_balance.c [new file with mode: 0644]
tools/lib/lockdep/uinclude/asm/hweight.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/asm/sections.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/bitops.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/compiler.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/debug_locks.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/delay.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/export.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/ftrace.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/gfp.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/hardirq.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/hash.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/interrupt.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/irqflags.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kallsyms.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kern_levels.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kernel.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kmemcheck.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/linkage.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/list.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/lockdep.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/module.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/mutex.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/poison.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/prefetch.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/proc_fs.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rbtree.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rbtree_augmented.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rcu.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/seq_file.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/spinlock.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/stacktrace.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/stringify.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/types.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/trace/events/lock.h [new file with mode: 0644]
tools/lib/symbol/kallsyms.c [new file with mode: 0644]
tools/lib/symbol/kallsyms.h [new file with mode: 0644]
tools/lib/traceevent/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/event-plugin.c [new file with mode: 0644]
tools/lib/traceevent/event-utils.h
tools/lib/traceevent/parse-filter.c
tools/lib/traceevent/parse-utils.c
tools/lib/traceevent/plugin_cfg80211.c [new file with mode: 0644]
tools/lib/traceevent/plugin_function.c [new file with mode: 0644]
tools/lib/traceevent/plugin_hrtimer.c [new file with mode: 0644]
tools/lib/traceevent/plugin_jbd2.c [new file with mode: 0644]
tools/lib/traceevent/plugin_kmem.c [new file with mode: 0644]
tools/lib/traceevent/plugin_kvm.c [new file with mode: 0644]
tools/lib/traceevent/plugin_mac80211.c [new file with mode: 0644]
tools/lib/traceevent/plugin_sched_switch.c [new file with mode: 0644]
tools/lib/traceevent/plugin_scsi.c [new file with mode: 0644]
tools/lib/traceevent/plugin_xen.c [new file with mode: 0644]
tools/lib/traceevent/trace-seq.c
tools/perf/Documentation/perf-archive.txt
tools/perf/Documentation/perf-kvm.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf-stat.txt
tools/perf/Documentation/perf-timechart.txt
tools/perf/Documentation/perf-top.txt
tools/perf/MANIFEST
tools/perf/Makefile
tools/perf/Makefile.perf
tools/perf/arch/common.c
tools/perf/builtin-annotate.c
tools/perf/builtin-diff.c
tools/perf/builtin-evlist.c
tools/perf/builtin-inject.c
tools/perf/builtin-kvm.c
tools/perf/builtin-mem.c
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/Makefile
tools/perf/config/Makefile.arch [new file with mode: 0644]
tools/perf/config/feature-checks/.gitignore [new file with mode: 0644]
tools/perf/config/feature-checks/Makefile
tools/perf/config/feature-checks/test-all.c
tools/perf/config/feature-checks/test-stackprotector.c [deleted file]
tools/perf/config/feature-checks/test-volatile-register-var.c [deleted file]
tools/perf/config/utilities.mak
tools/perf/perf-completion.sh [moved from tools/perf/bash_completion with 63% similarity]
tools/perf/perf.c
tools/perf/perf.h
tools/perf/tests/attr/test-record-no-inherit
tools/perf/tests/code-reading.c
tools/perf/tests/evsel-roundtrip-name.c
tools/perf/tests/hists_link.c
tools/perf/tests/keep-tracking.c
tools/perf/tests/make
tools/perf/tests/mmap-basic.c
tools/perf/tests/open-syscall-tp-fields.c
tools/perf/tests/parse-events.c
tools/perf/tests/perf-record.c
tools/perf/tests/perf-targz-src-pkg [new file with mode: 0755]
tools/perf/tests/perf-time-to-tsc.c
tools/perf/tests/sw-clock.c
tools/perf/tests/task-exit.c
tools/perf/ui/browser.c
tools/perf/ui/browser.h
tools/perf/ui/browsers/header.c [new file with mode: 0644]
tools/perf/ui/browsers/hists.c
tools/perf/ui/browsers/scripts.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/gtk/util.c
tools/perf/ui/stdio/hist.c
tools/perf/ui/tui/util.c
tools/perf/util/alias.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/cgroup.c
tools/perf/util/color.c
tools/perf/util/color.h
tools/perf/util/comm.c
tools/perf/util/comm.h
tools/perf/util/data.c
tools/perf/util/data.h
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/help.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/machine.c
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/pmu.c
tools/perf/util/pmu.h
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-finder.c
tools/perf/util/python-ext-sources
tools/perf/util/python.c
tools/perf/util/record.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/srcline.c
tools/perf/util/strbuf.c
tools/perf/util/strfilter.c
tools/perf/util/string.c
tools/perf/util/strlist.c
tools/perf/util/svghelper.c
tools/perf/util/svghelper.h
tools/perf/util/symbol-elf.c
tools/perf/util/symbol-minimal.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/target.c
tools/perf/util/target.h
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/thread_map.c
tools/perf/util/top.c
tools/perf/util/top.h
tools/perf/util/trace-event-info.c
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event-read.c
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.c [new file with mode: 0644]
tools/perf/util/trace-event.h
tools/perf/util/unwind.c
tools/perf/util/util.c
tools/perf/util/util.h
tools/perf/util/values.c
tools/perf/util/vdso.c
tools/power/cpupower/utils/cpupower-set.c
tools/scripts/Makefile.include
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf
tools/testing/selftests/rcutorture/.gitignore [new file with mode: 0644]
tools/testing/selftests/rcutorture/bin/config2frag.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/configcheck.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/configinit.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/cpus2use.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/bin/kvm-build.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/kvm-recheck.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/kvm.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/bin/parse-build.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/parse-console.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/parse-rcutorture.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/configs/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/SRCU-N [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/SRCU-N.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/SRCU-P [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/SRCU-P.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TINY01 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TINY02 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE01 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE01.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE02 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE03 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE04 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE04.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE05 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE05.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE06 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE07 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE08 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE08-T [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/TREE09 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N6---t-nh-SD-smp-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N7-4-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/N8-2-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P6---t-nh-SD-smp-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-all [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-HP-none [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/P7-4-T-NH-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.12/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/CFLIST [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/N1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/N2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/N3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/N4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/N5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/NT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/NT3-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/P1-S-T-NH-SD-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/P2-2-t-nh-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/P3-3-T-nh-SD-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/P4-A-t-NH-sd-SMP-HP [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/P5-U-T-NH-sd-SMP-hp [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/PT1-nh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/PT2-NH [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/ver_functions.sh [new file with mode: 0644]
tools/testing/selftests/rcutorture/doc/TINY_RCU.txt [new file with mode: 0644]
tools/testing/selftests/rcutorture/doc/TREE_RCU-Kconfig.txt [new file with mode: 0644]
tools/testing/selftests/rcutorture/doc/initrd.txt [new file with mode: 0644]
tools/testing/selftests/rcutorture/doc/rcu-test-image.txt [new file with mode: 0644]
tools/usb/Makefile
tools/vm/Makefile
tools/vm/page-types.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 4fc997d58ab2640a4b94fdcb1f363935f8a13395..4c7738f493570eb9d0c70e6db67c527bcbe6e691 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -655,6 +655,11 @@ S: Stanford University
 S: Stanford, California 94305
 S: USA
 
+N: Carlos Chinea
+E: carlos.chinea@nokia.com
+E: cch.devel@gmail.com
+D: Author of HSI Subsystem
+
 N: Randolph Chung
 E: tausq@debian.org
 D: Linux/PA-RISC hacker
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi
new file mode 100644 (file)
index 0000000..05874da
--- /dev/null
@@ -0,0 +1,20 @@
+What:          /sys/firmware/efi/fw_vendor
+Date:          December 2013
+Contact:       Dave Young <dyoung@redhat.com>
+Description:   It shows the physical address of firmware vendor field in the
+               EFI system table.
+Users:         Kexec
+
+What:          /sys/firmware/efi/runtime
+Date:          December 2013
+Contact:       Dave Young <dyoung@redhat.com>
+Description:   It shows the physical address of runtime service table entry in
+               the EFI system table.
+Users:         Kexec
+
+What:          /sys/firmware/efi/config_table
+Date:          December 2013
+Contact:       Dave Young <dyoung@redhat.com>
+Description:   It shows the physical address of config table entry in the EFI
+               system table.
+Users:         Kexec
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi-runtime-map b/Documentation/ABI/testing/sysfs-firmware-efi-runtime-map
new file mode 100644 (file)
index 0000000..c61b9b3
--- /dev/null
@@ -0,0 +1,34 @@
+What:          /sys/firmware/efi/runtime-map/
+Date:          December 2013
+Contact:       Dave Young <dyoung@redhat.com>
+Description:   Switching efi runtime services to virtual mode requires
+               that all efi memory ranges which have the runtime attribute
+               bit set to be mapped to virtual addresses.
+
+               The efi runtime services can only be switched to virtual
+               mode once without rebooting. The kexec kernel must maintain
+               the same physical to virtual address mappings as the first
+               kernel. The mappings are exported to sysfs so userspace tools
+               can reassemble them and pass them into the kexec kernel.
+
+               /sys/firmware/efi/runtime-map/ is the directory the kernel
+               exports that information in.
+
+               subdirectories are named with the number of the memory range:
+
+                       /sys/firmware/efi/runtime-map/0
+                       /sys/firmware/efi/runtime-map/1
+                       /sys/firmware/efi/runtime-map/2
+                       /sys/firmware/efi/runtime-map/3
+                       ...
+
+               Each subdirectory contains five files:
+
+               attribute : The attributes of the memory range.
+               num_pages : The size of the memory range in pages.
+               phys_addr : The physical address of the memory range.
+               type      : The type of the memory range.
+               virt_addr : The virtual address of the memory range.
+
+               Above values are all hexadecimal numbers with the '0x' prefix.
+Users:         Kexec
diff --git a/Documentation/ABI/testing/sysfs-kernel-boot_params b/Documentation/ABI/testing/sysfs-kernel-boot_params
new file mode 100644 (file)
index 0000000..eca38ce
--- /dev/null
@@ -0,0 +1,38 @@
+What:          /sys/kernel/boot_params
+Date:          December 2013
+Contact:       Dave Young <dyoung@redhat.com>
+Description:   The /sys/kernel/boot_params directory contains two
+               files: "data" and "version" and one subdirectory "setup_data".
+               It is used to export the kernel boot parameters of an x86
+               platform to userspace for kexec and debugging purpose.
+
+               If there's no setup_data in boot_params the subdirectory will
+               not be created.
+
+               "data" file is the binary representation of struct boot_params.
+
+               "version" file is the string representation of boot
+               protocol version.
+
+               "setup_data" subdirectory contains the setup_data data
+               structure in boot_params. setup_data is maintained in kernel
+               as a link list. In "setup_data" subdirectory there's one
+               subdirectory for each link list node named with the number
+               of the list nodes. The list node subdirectory contains two
+               files "type" and "data". "type" file is the string
+               representation of setup_data type. "data" file is the binary
+               representation of setup_data payload.
+
+               The whole boot_params directory structure is like below:
+               /sys/kernel/boot_params
+               |__ data
+               |__ setup_data
+               |   |__ 0
+               |   |   |__ data
+               |   |   |__ type
+               |   |__ 1
+               |       |__ data
+               |       |__ type
+               |__ version
+
+Users:         Kexec
index e287c8fc803b437ce34550ba88777183f66ca0cc..4165e7bfa4ff7560c0283213e53a54b1575ab2e8 100644 (file)
@@ -73,7 +73,8 @@ range from zero to the maximal number of valid planes for the currently active
 format. For the single-planar API, applications must set <structfield> plane
 </structfield> to zero.  Additional flags may be posted in the <structfield>
 flags </structfield> field.  Refer to a manual for open() for details.
-Currently only O_CLOEXEC is supported.  All other fields must be set to zero.
+Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported.  All
+other fields must be set to zero.
 In the case of multi-planar API, every plane is exported separately using
 multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
 
@@ -170,8 +171,9 @@ multi-planar API. Otherwise this value must be set to zero. </entry>
            <entry>__u32</entry>
            <entry><structfield>flags</structfield></entry>
            <entry>Flags for the newly created file, currently only <constant>
-O_CLOEXEC </constant> is supported, refer to the manual of open() for more
-details.</entry>
+O_CLOEXEC </constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY
+</constant>, and <constant>O_RDWR</constant> are supported, refer to the manual
+of open() for more details.</entry>
          </row>
          <row>
            <entry>__s32</entry>
index f3778f8952da1b9473897a4a2f392f049b9c544c..910870b15acd25d1b548001759f11e589cd671eb 100644 (file)
@@ -396,14 +396,14 @@ o Each element of the form "3/3 ..>. 0:7 ^0" represents one rcu_node
 
 The output of "cat rcu/rcu_sched/rcu_pending" looks as follows:
 
-  0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903
-  1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113
-  2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889
-  3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469
-  4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042
-  5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422
-  6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699
-  7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147
+  0!np=26111 qsp=29 rpq=5386 cbr=1 cng=570 gpc=3674 gps=577 nn=15903 ndw=0
+  1!np=28913 qsp=35 rpq=6097 cbr=1 cng=448 gpc=3700 gps=554 nn=18113 ndw=0
+  2!np=32740 qsp=37 rpq=6202 cbr=0 cng=476 gpc=4627 gps=546 nn=20889 ndw=0
+  3 np=23679 qsp=22 rpq=5044 cbr=1 cng=415 gpc=3403 gps=347 nn=14469 ndw=0
+  4!np=30714 qsp=4 rpq=5574 cbr=0 cng=528 gpc=3931 gps=639 nn=20042 ndw=0
+  5 np=28910 qsp=2 rpq=5246 cbr=0 cng=428 gpc=4105 gps=709 nn=18422 ndw=0
+  6!np=38648 qsp=5 rpq=7076 cbr=0 cng=840 gpc=4072 gps=961 nn=25699 ndw=0
+  7 np=37275 qsp=2 rpq=6873 cbr=0 cng=868 gpc=3416 gps=971 nn=25147 ndw=0
 
 The fields are as follows:
 
@@ -432,6 +432,10 @@ o  "gpc" is the number of times that an old grace period had
 o      "gps" is the number of times that a new grace period had started,
        but this CPU was not yet aware of it.
 
+o      "ndw" is the number of times that a wakeup of an rcuo
+       callback-offload kthread had to be deferred in order to avoid
+       deadlock.
+
 o      "nn" is the number of times that this CPU needed nothing.
 
 
@@ -443,7 +447,7 @@ The output of "cat rcu/rcuboost" looks as follows:
     balk: nt=0 egt=6541 bt=0 nb=0 ny=126 nos=0
 
 This information is output only for rcu_preempt.  Each two-line entry
-corresponds to a leaf rcu_node strcuture.  The fields are as follows:
+corresponds to a leaf rcu_node structure.  The fields are as follows:
 
 o      "n:m" is the CPU-number range for the corresponding two-line
        entry.  In the sample output above, the first entry covers
index a58b63da1a366ea5dddc8af574779ea68773610a..f51861bcb07bbbc226e0d1af2897f6b49bcf82c5 100644 (file)
@@ -45,11 +45,22 @@ directory apei/einj. The following files are provided.
   injection. Before this, please specify all necessary error
   parameters.
 
+- flags
+  Present for kernel version 3.13 and above. Used to specify which
+  of param{1..4} are valid and should be used by BIOS during injection.
+  Value is a bitmask as specified in ACPI5.0 spec for the
+  SET_ERROR_TYPE_WITH_ADDRESS data structure:
+       Bit 0 - Processor APIC field valid (see param3 below)
+       Bit 1 - Memory address and mask valid (param1 and param2)
+       Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below)
+  If set to zero, legacy behaviour is used where the type of injection
+  specifies just one bit set, and param1 is multiplexed.
+
 - param1
   This file is used to set the first error parameter value. Effect of
   parameter depends on error_type specified. For example, if error
   type is memory related type, the param1 should be a valid physical
-  memory address.
+  memory address. [Unless "flag" is set - see above]
 
 - param2
   This file is used to set the second error parameter value. Effect of
@@ -58,6 +69,12 @@ directory apei/einj. The following files are provided.
   address mask. Linux requires page or narrower granularity, say,
   0xfffffffffffff000.
 
+- param3
+  Used when the 0x1 bit is set in "flag" to specify the APIC id
+
+- param4
+  Used when the 0x4 bit is set in "flag" to specify target PCIe device
+
 - notrigger
   The EINJ mechanism is a two step process. First inject the error, then
   perform some actions to trigger it. Setting "notrigger" to 1 skips the
index f4faec0f66e400dc18c176eb7c567dd2aa18f761..2f2c6cdd73c0c24ab29dcd3f68034f99f17c3125 100644 (file)
@@ -164,10 +164,10 @@ This points to a number of methods, all of which need to be provided:
 
  (4) Diff the index keys of two objects.
 
-       int (*diff_objects)(const void *a, const void *b);
+       int (*diff_objects)(const void *object, const void *index_key);
 
-     Return the bit position at which the index keys of two objects differ or
-     -1 if they are the same.
+     Return the bit position at which the index key of the specified object
+     differs from the given index key or -1 if they are the same.
 
 
  (5) Free an object.
diff --git a/Documentation/block/null_blk.txt b/Documentation/block/null_blk.txt
new file mode 100644 (file)
index 0000000..b2830b4
--- /dev/null
@@ -0,0 +1,72 @@
+Null block device driver
+================================================================================
+
+I. Overview
+
+The null block device (/dev/nullb*) is used for benchmarking the various
+block-layer implementations. It emulates a block device of X gigabytes in size.
+The following instances are possible:
+
+  Single-queue block-layer
+    - Request-based.
+    - Single submission queue per device.
+    - Implements IO scheduling algorithms (CFQ, Deadline, noop).
+  Multi-queue block-layer
+    - Request-based.
+    - Configurable submission queues per device.
+  No block-layer (Known as bio-based)
+    - Bio-based. IO requests are submitted directly to the device driver.
+    - Directly accepts bio data structure and returns them.
+
+All of them have a completion queue for each core in the system.
+
+II. Module parameters applicable for all instances:
+
+queue_mode=[0-2]: Default: 2-Multi-queue
+  Selects which block-layer the module should instantiate with.
+
+  0: Bio-based.
+  1: Single-queue.
+  2: Multi-queue.
+
+home_node=[0--nr_nodes]: Default: NUMA_NO_NODE
+  Selects what CPU node the data structures are allocated from.
+
+gb=[Size in GB]: Default: 250GB
+  The size of the device reported to the system.
+
+bs=[Block size (in bytes)]: Default: 512 bytes
+  The block size reported to the system.
+
+nr_devices=[Number of devices]: Default: 2
+  Number of block devices instantiated. They are instantiated as /dev/nullb0,
+  etc.
+
+irq_mode=[0-2]: Default: 1-Soft-irq
+  The completion mode used for completing IOs to the block-layer.
+
+  0: None.
+  1: Soft-irq. Uses IPI to complete IOs across CPU nodes. Simulates the overhead
+     when IOs are issued from another CPU node than the home the device is
+     connected to.
+  2: Timer: Waits a specific period (completion_nsec) for each IO before
+     completion.
+
+completion_nsec=[ns]: Default: 10.000ns
+  Combined with irq_mode=2 (timer). The time each completion event must wait.
+
+submit_queues=[0..nr_cpus]:
+  The number of submission queues attached to the device driver. If unset, it
+  defaults to 1 on single-queue and bio-based instances. For multi-queue,
+  it is ignored when use_per_node_hctx module parameter is 1.
+
+hw_queue_depth=[0..qdepth]: Default: 64
+  The hardware queue depth of the device.
+
+III: Multi-queue specific parameters
+
+use_per_node_hctx=[0/1]: Default: 0
+  0: The number of submit queues are set to the value of the submit_queues
+     parameter.
+  1: The multi-queue block layer is instantiated with a hardware dispatch
+     queue for each CPU node in the system.
index 8117e5bf6065032daa9ae594ca5679996d7617c3..88951b179262a912fcddf16872f302cf117ca4ba 100644 (file)
@@ -160,6 +160,7 @@ The producer will look something like this:
        spin_lock(&producer_lock);
 
        unsigned long head = buffer->head;
+       /* The spin_unlock() and next spin_lock() provide needed ordering. */
        unsigned long tail = ACCESS_ONCE(buffer->tail);
 
        if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
@@ -168,9 +169,8 @@ The producer will look something like this:
 
                produce_item(item);
 
-               smp_wmb(); /* commit the item before incrementing the head */
-
-               buffer->head = (head + 1) & (buffer->size - 1);
+               smp_store_release(buffer->head,
+                                 (head + 1) & (buffer->size - 1));
 
                /* wake_up() will make sure that the head is committed before
                 * waking anyone up */
@@ -183,9 +183,14 @@ This will instruct the CPU that the contents of the new item must be written
 before the head index makes it available to the consumer and then instructs the
 CPU that the revised head index must be written before the consumer is woken.
 
-Note that wake_up() doesn't have to be the exact mechanism used, but whatever
-is used must guarantee a (write) memory barrier between the update of the head
-index and the change of state of the consumer, if a change of state occurs.
+Note that wake_up() does not guarantee any sort of barrier unless something
+is actually awakened.  We therefore cannot rely on it for ordering.  However,
+there is always one element of the array left empty.  Therefore, the
+producer must produce two elements before it could possibly corrupt the
+element currently being read by the consumer.  Therefore, the unlock-lock
+pair between consecutive invocations of the consumer provides the necessary
+ordering between the read of the index indicating that the consumer has
+vacated a given element and the write by the producer to that same element.
 
 
 THE CONSUMER
@@ -195,21 +200,20 @@ The consumer will look something like this:
 
        spin_lock(&consumer_lock);
 
-       unsigned long head = ACCESS_ONCE(buffer->head);
+       /* Read index before reading contents at that index. */
+       unsigned long head = smp_load_acquire(buffer->head);
        unsigned long tail = buffer->tail;
 
        if (CIRC_CNT(head, tail, buffer->size) >= 1) {
-               /* read index before reading contents at that index */
-               smp_read_barrier_depends();
 
                /* extract one item from the buffer */
                struct item *item = buffer[tail];
 
                consume_item(item);
 
-               smp_mb(); /* finish reading descriptor before incrementing tail */
-
-               buffer->tail = (tail + 1) & (buffer->size - 1);
+               /* Finish reading descriptor before incrementing tail. */
+               smp_store_release(buffer->tail,
+                                 (tail + 1) & (buffer->size - 1));
        }
 
        spin_unlock(&consumer_lock);
@@ -218,12 +222,17 @@ This will instruct the CPU to make sure the index is up to date before reading
 the new item, and then it shall make sure the CPU has finished reading the item
 before it writes the new tail pointer, which will erase the item.
 
-
-Note the use of ACCESS_ONCE() in both algorithms to read the opposition index.
-This prevents the compiler from discarding and reloading its cached value -
-which some compilers will do across smp_read_barrier_depends().  This isn't
-strictly needed if you can be sure that the opposition index will _only_ be
-used the once.
+Note the use of ACCESS_ONCE() and smp_load_acquire() to read the
+opposition index.  This prevents the compiler from discarding and
+reloading its cached value - which some compilers will do across
+smp_read_barrier_depends().  This isn't strictly needed if you can
+be sure that the opposition index will _only_ be used the once.
+The smp_load_acquire() additionally forces the CPU to order against
+subsequent memory references.  Similarly, smp_store_release() is used
+in both algorithms to write the thread's index.  This documents the
+fact that we are writing to something that can be read concurrently,
+prevents the compiler from tearing the store, and enforces ordering
+against previous accesses.
 
 
 ===============
index 274752f8bdf963b0f1757f2df446f6c5a503c6a5..719320b5ed3f36f476bd019781b774c3b4b8ace6 100644 (file)
@@ -266,10 +266,12 @@ E.g.
 Invalidation is removing an entry from the cache without writing it
 back.  Cache blocks can be invalidated via the invalidate_cblocks
 message, which takes an arbitrary number of cblock ranges.  Each cblock
-must be expressed as a decimal value, in the future a variant message
-that takes cblock ranges expressed in hexidecimal may be needed to
-better support efficient invalidation of larger caches.  The cache must
-be in passthrough mode when invalidate_cblocks is used.
+range's end value is "one past the end", meaning 5-10 expresses a range
+of values from 5 to 9.  Each cblock must be expressed as a decimal
+value, in the future a variant message that takes cblock ranges
+expressed in hexidecimal may be needed to better support efficient
+invalidation of larger caches.  The cache must be in passthrough mode
+when invalidate_cblocks is used.
 
    invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
 
index 1a5a42ce21bb0ac7480b07ca9aced96914c33910..83f405bde138a35f824f19ad27873982f8bc0325 100644 (file)
@@ -7,10 +7,18 @@ The MPU contain CPUs, GIC, L2 cache and a local PRCM.
 Required properties:
 - compatible : Should be "ti,omap3-mpu" for OMAP3
                Should be "ti,omap4-mpu" for OMAP4
+              Should be "ti,omap5-mpu" for OMAP5
 - ti,hwmods: "mpu"
 
 Examples:
 
+- For an OMAP5 SMP system:
+
+mpu {
+    compatible = "ti,omap5-mpu";
+    ti,hwmods = "mpu"
+};
+
 - For an OMAP4 SMP system:
 
 mpu {
index 343781b9f246773ce880f9427623ebbd12202f32..3e1e498fea96b357ff990f6fbb682dd43f5254cc 100644 (file)
@@ -7,6 +7,7 @@ representation in the device tree should be done as under:-
 Required properties:
 
 - compatible : should be one of
+       "arm,armv8-pmuv3"
        "arm,cortex-a15-pmu"
        "arm,cortex-a9-pmu"
        "arm,cortex-a8-pmu"
index 47ada1dff2165bfb836600e606adfd79ac7eca3a..5d49f2b37f68dfbd0f63e7e930c3a00b0ad5ac74 100644 (file)
@@ -49,7 +49,7 @@ adc@12D10000 {
        /* NTC thermistor is a hwmon device */
        ncp15wb473@0 {
                compatible = "ntc,ncp15wb473";
-               pullup-uV = <1800000>;
+               pullup-uv = <1800000>;
                pullup-ohm = <47000>;
                pulldown-ohm = <0>;
                io-channels = <&adc 4>;
index c6bf8a6c8f52856b95af14e1e85134a246c1a44b..a2ac2d9ac71a7d0e4566dbc872dc5d4bb771407b 100644 (file)
@@ -6,7 +6,7 @@ SoC's in the Exynos4 family.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
   - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
 
index 24765c146e31d52ea4c732812c420ccdb5d3e670..0f2f920e87348515995cb553ece45cf0949213b7 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5250 SoC.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
 
 - reg: physical base address of the controller and length of memory mapped
@@ -159,6 +159,8 @@ clock which they consume.
   mixer                        343
   hdmi                 344
   g2d                  345
+  mdma0                        346
+  smmu_mdma0           347
 
 
    [Clock Muxes]
index 32aa34ecad364f6d3d0c613c471ec5752096b6ba..458f34789e5d1aa6c6b6944d37f5dad4cfc22cf9 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5420 SoC.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos5420-clock" - controller compatible with Exynos5420 SoC.
 
 - reg: physical base address of the controller and length of memory mapped
index 4499e9966bc9727db13c46d1976db830690625a2..9955dc9c7d969f5cb0888dc8a6c352dc037d81cf 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5440 SoC.
 
 Required Properties:
 
-- comptible: should be "samsung,exynos5440-clock".
+- compatible: should be "samsung,exynos5440-clock".
 
 - reg: physical base address of the controller and length of memory mapped
   region.
index b0019eb5330ee8bdd0ee825255f1a26f13039980..798cfc9d3839c9a24405419a35c935e370a51967 100644 (file)
@@ -5,16 +5,42 @@ This is for the non-QE/CPM/GUTs GPIO controllers as found on
 
 Every GPIO controller node must have #gpio-cells property defined,
 this information will be used to translate gpio-specifiers.
+See bindings/gpio/gpio.txt for details of how to specify GPIO
+information for devices.
+
+The GPIO module usually is connected to the SoC's internal interrupt
+controller, see bindings/interrupt-controller/interrupts.txt (the
+interrupt client nodes section) for details how to specify this GPIO
+module's interrupt.
+
+The GPIO module may serve as another interrupt controller (cascaded to
+the SoC's internal interrupt controller).  See the interrupt controller
+nodes section in bindings/interrupt-controller/interrupts.txt for
+details.
 
 Required properties:
-- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
-  83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
- - interrupts : Interrupt mapping for GPIO IRQ.
- - interrupt-parent : Phandle for the interrupt controller that
-   services interrupts for this device.
-- gpio-controller : Marks the port as GPIO controller.
+- compatible:          "fsl,<chip>-gpio" followed by "fsl,mpc8349-gpio"
+                       for 83xx, "fsl,mpc8572-gpio" for 85xx, or
+                       "fsl,mpc8610-gpio" for 86xx.
+- #gpio-cells:         Should be two. The first cell is the pin number
+                       and the second cell is used to specify optional
+                       parameters (currently unused).
+- interrupt-parent:    Phandle for the interrupt controller that
+                       services interrupts for this device.
+- interrupts:          Interrupt mapping for GPIO IRQ.
+- gpio-controller:     Marks the port as GPIO controller.
+
+Optional properties:
+- interrupt-controller:        Empty boolean property which marks the GPIO
+                       module as an IRQ controller.
+- #interrupt-cells:    Should be two.  Defines the number of integer
+                       cells required to specify an interrupt within
+                       this interrupt controller.  The first cell
+                       defines the pin number, the second cell
+                       defines additional flags (trigger type,
+                       trigger polarity).  Note that the available
+                       set of trigger conditions supported by the
+                       GPIO module depends on the actual SoC.
 
 Example of gpio-controller nodes for a MPC8347 SoC:
 
@@ -22,39 +48,27 @@ Example of gpio-controller nodes for a MPC8347 SoC:
                #gpio-cells = <2>;
                compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
                reg = <0xc00 0x100>;
-               interrupts = <74 0x8>;
                interrupt-parent = <&ipic>;
+               interrupts = <74 0x8>;
                gpio-controller;
+               interrupt-controller;
+               #interrupt-cells = <2>;
        };
 
        gpio2: gpio-controller@d00 {
                #gpio-cells = <2>;
                compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
                reg = <0xd00 0x100>;
-               interrupts = <75 0x8>;
                interrupt-parent = <&ipic>;
+               interrupts = <75 0x8>;
                gpio-controller;
        };
 
-See booting-without-of.txt for details of how to specify GPIO
-information for devices.
-
-To use GPIO pins as interrupt sources for peripherals, specify the
-GPIO controller as the interrupt parent and define GPIO number +
-trigger mode using the interrupts property, which is defined like
-this:
-
-interrupts = <number trigger>, where:
- - number: GPIO pin (0..31)
- - trigger: trigger mode:
-       2 = trigger on falling edge
-       3 = trigger on both edges
-
-Example of device using this is:
+Example of a peripheral using the GPIO module as an IRQ controller:
 
        funkyfpga@0 {
                compatible = "funky-fpga";
                ...
-               interrupts = <4 3>;
                interrupt-parent = <&gpio1>;
+               interrupts = <4 3>;
        };
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap.txt b/Documentation/devicetree/bindings/mmc/ti-omap.txt
new file mode 100644 (file)
index 0000000..8de5799
--- /dev/null
@@ -0,0 +1,54 @@
+* TI MMC host controller for OMAP1 and 2420
+
+The MMC Host Controller on TI OMAP1 and 2420 family provides
+an interface for MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap mmc driver.
+
+Note that this driver will not work with omap2430 or later omaps,
+please see the omap hsmmc driver for the current omaps.
+
+Required properties:
+- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
+- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
+  instance starting 1
+
+Examples:
+
+       msdi1: mmc@4809c000 {
+               compatible = "ti,omap2420-mmc";
+               ti,hwmods = "msdi1";
+               reg = <0x4809c000 0x80>;
+               interrupts = <83>;
+               dmas = <&sdma 61 &sdma 62>;
+               dma-names = "tx", "rx";
+       };
+
+* TI MMC host controller for OMAP1 and 2420
+
+The MMC Host Controller on TI OMAP1 and 2420 family provides
+an interface for MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap mmc driver.
+
+Note that this driver will not work with omap2430 or later omaps,
+please see the omap hsmmc driver for the current omaps.
+
+Required properties:
+- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
+- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
+  instance starting 1
+
+Examples:
+
+       msdi1: mmc@4809c000 {
+               compatible = "ti,omap2420-mmc";
+               ti,hwmods = "msdi1";
+               reg = <0x4809c000 0x80>;
+               interrupts = <83>;
+               dmas = <&sdma 61 &sdma 62>;
+               dma-names = "tx", "rx";
+       };
+
index 48b259e29e873f71f3ccfd0a6877bffa609ebd39..bad381faf036e936d9d99a6baff5d1e053cc2cdd 100644 (file)
@@ -4,7 +4,7 @@ This file provides information, what the device node
 for the davinci_emac interface contains.
 
 Required properties:
-- compatible: "ti,davinci-dm6467-emac";
+- compatible: "ti,davinci-dm6467-emac" or "ti,am3517-emac"
 - reg: Offset and length of the register set for the device
 - ti,davinci-ctrl-reg-offset: offset to control register
 - ti,davinci-ctrl-mod-reg-offset: offset to control module register
index d5363922140322913e171fac6c98f7df2d0b0665..845ff848d8950b546e7243fbc9568847ed2f87ab 100644 (file)
@@ -15,6 +15,7 @@ Optional properties:
   only if property "phy-reset-gpios" is available.  Missing the property
   will have the duration be 1 millisecond.  Numbers greater than 1000 are
   invalid and 1 millisecond will be used instead.
+- phy-supply: regulator that powers the Ethernet PHY.
 
 Example:
 
@@ -25,4 +26,5 @@ ethernet@83fec000 {
        phy-mode = "mii";
        phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
        local-mac-address = [00 04 9F 01 1B B9];
+       phy-supply = <&reg_fec_supply>;
 };
index 953049b4248a71f4c242d56432730e5ae4c7fbc3..5a41a8658daa12087678a7d81f5f60038cbeddf8 100644 (file)
@@ -8,3 +8,7 @@ Required properties:
 Optional properties:
 - phy-device : phandle to Ethernet phy
 - local-mac-address : Ethernet mac address to use
+- reg-io-width : Mask of sizes (in bytes) of the IO accesses that
+  are supported on the device.  Valid value for SMSC LAN91c111 are
+  1, 2 or 4.  If it's omitted or invalid, the size would be 2 meaning
+  16-bit access only.
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt
deleted file mode 100644 (file)
index 6b9e518..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-NVIDIA Tegra 2 SPI device
-
-Required properties:
-- compatible : should be "nvidia,tegra20-spi".
-- gpios : should specify GPIOs used for chipselect.
diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
new file mode 100644 (file)
index 0000000..7c26154
--- /dev/null
@@ -0,0 +1,22 @@
+Allwinner SoCs High Speed Timer Controller
+
+Required properties:
+
+- compatible : should be "allwinner,sun5i-a13-hstimer" or
+               "allwinner,sun7i-a20-hstimer"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : The interrupts of these timers (2 for the sun5i IP, 4 for the sun7i
+               one)
+- clocks: phandle to the source clock (usually the AHB clock)
+
+Example:
+
+timer@01c60000 {
+       compatible = "allwinner,sun7i-a20-hstimer";
+       reg = <0x01c60000 0x1000>;
+       interrupts = <0 51 1>,
+                    <0 52 1>,
+                    <0 53 1>,
+                    <0 54 1>;
+       clocks = <&ahb1_gates 19>;
+};
index ce95ed1c6d3e26578eaca876aa0f7caf26fa101d..edbb8d88c85e90e3e1760ef3d6f25e98d96e3e37 100644 (file)
@@ -32,12 +32,14 @@ est ESTeem Wireless Modems
 fsl    Freescale Semiconductor
 GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+gmt    Global Mixed-mode Technology, Inc.
 hisilicon      Hisilicon Limited.
 hp     Hewlett Packard
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
 img    Imagination Technologies Ltd.
 intercontrol   Inter Control Group
+lg     LG Corporation
 linux  Linux-specific binding
 lsi    LSI Corp. (LSI Logic)
 marvell        Marvell Technology Group Ltd.
diff --git a/Documentation/gpio/00-INDEX b/Documentation/gpio/00-INDEX
new file mode 100644 (file)
index 0000000..1de43ae
--- /dev/null
@@ -0,0 +1,14 @@
+00-INDEX
+       - This file
+gpio.txt
+       - Introduction to GPIOs and their kernel interfaces
+consumer.txt
+       - How to obtain and use GPIOs in a driver
+driver.txt
+       - How to write a GPIO driver
+board.txt
+       - How to assign GPIOs to a consumer device and a function
+sysfs.txt
+       - Information about the GPIO sysfs interface
+gpio-legacy.txt
+       - Historical documentation of the deprecated GPIO integer interface
index 50680a59a2ff9a913e449a1d71ced9fab3004fe4..4252af6ffda18da2559054fdb9b42316afe6e891 100644 (file)
@@ -774,6 +774,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        disable=        [IPV6]
                        See Documentation/networking/ipv6.txt.
 
+       disable_cpu_apicid= [X86,APIC,SMP]
+                       Format: <int>
+                       The number of initial APIC ID for the
+                       corresponding CPU to be disabled at boot,
+                       mostly used for the kdump 2nd kernel to
+                       disable BSP to wake up multiple CPUs without
+                       causing system reset or hang due to sending
+                       INIT from AP to BSP.
+
        disable_ddw     [PPC/PSERIES]
                        Disable Dynamic DMA Window support. Use this if
                        to workaround buggy firmware.
@@ -881,6 +890,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        The xen output can only be used by Xen PV guests.
 
+       edac_report=    [HW,EDAC] Control how to report EDAC event
+                       Format: {"on" | "off" | "force"}
+                       on: enable EDAC to report H/W event. May be overridden
+                       by other higher priority error reporting module.
+                       off: disable H/W event reporting through EDAC.
+                       force: enforce the use of EDAC to report H/W event.
+                       default: on.
+
        ekgdboc=        [X86,KGDB] Allow early kernel console debugging
                        ekgdboc=kbd
 
@@ -890,6 +907,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        edd=            [EDD]
                        Format: {"off" | "on" | "skip[mbr]"}
 
+       efi=            [EFI]
+                       Format: { "old_map" }
+                       old_map [X86-64]: switch to the old ioremap-based EFI
+                       runtime services mapping. 32-bit still uses this one by
+                       default.
+
        efi_no_storage_paranoia [EFI; X86]
                        Using this parameter you can use more than 50% of
                        your efi variable storage. Use this parameter only if
@@ -1529,6 +1552,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        * atapi_dmadir: Enable ATAPI DMADIR bridge support
 
+                       * disable: Disable this device.
+
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
@@ -1992,6 +2017,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        noapic          [SMP,APIC] Tells the kernel to not make use of any
                        IOAPICs that may be present in the system.
 
+       nokaslr         [X86]
+                       Disable kernel base offset ASLR (Address Space
+                       Layout Randomization) if built into the kernel.
+
        noautogroup     Disable scheduler automatic task group creation.
 
        nobats          [PPC] Do not use BATs for mapping kernel lowmem
@@ -2625,7 +2654,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        for RCU-preempt, and "s" for RCU-sched, and "N"
                        is the CPU number.  This reduces OS jitter on the
                        offloaded CPUs, which can be useful for HPC and
-
                        real-time workloads.  It can also improve energy
                        efficiency for asymmetric multiprocessors.
 
@@ -2641,8 +2669,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        periodically wake up to do the polling.
 
        rcutree.blimit= [KNL]
-                       Set maximum number of finished RCU callbacks to process
-                       in one batch.
+                       Set maximum number of finished RCU callbacks to
+                       process in one batch.
 
        rcutree.rcu_fanout_leaf= [KNL]
                        Increase the number of CPUs assigned to each
@@ -2661,8 +2689,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        value is one, and maximum value is HZ.
 
        rcutree.qhimark= [KNL]
-                       Set threshold of queued
-                       RCU callbacks over which batch limiting is disabled.
+                       Set threshold of queued RCU callbacks beyond which
+                       batch limiting is disabled.
 
        rcutree.qlowmark= [KNL]
                        Set threshold of queued RCU callbacks below which
diff --git a/Documentation/kmsg/s390/zcrypt b/Documentation/kmsg/s390/zcrypt
new file mode 100644 (file)
index 0000000..7fb2087
--- /dev/null
@@ -0,0 +1,20 @@
+/*?
+ * Text: "Cryptographic device %x failed and was set offline\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device index
+ * Description:
+ * A cryptographic device failed to process a cryptographic request.
+ * The cryptographic device driver could not correct the error and
+ * set the device offline. The application that issued the
+ * request received an indication that the request has failed.
+ * User action:
+ * Use the lszcrypt command to confirm that the cryptographic
+ * hardware is still configured to your LPAR or z/VM guest virtual
+ * machine. If the device is available to your Linux instance the
+ * command output contains a line that begins with 'card<device index>',
+ * where <device index> is the two-digit decimal number in the message text.
+ * After ensuring that the device is available, use the chzcrypt command to
+ * set it online again.
+ * If the error persists, contact your support organization.
+ */
index c8c42e64e953b4cd47d23da125ac5e057d1c158d..102dc19c411980d0aa17beeb12f0bcdd38447e29 100644 (file)
@@ -194,18 +194,22 @@ There are some minimal guarantees that may be expected of a CPU:
  (*) On any given CPU, dependent memory accesses will be issued in order, with
      respect to itself.  This means that for:
 
-       Q = P; D = *Q;
+       ACCESS_ONCE(Q) = P; smp_read_barrier_depends(); D = ACCESS_ONCE(*Q);
 
      the CPU will issue the following memory operations:
 
        Q = LOAD P, D = LOAD *Q
 
-     and always in that order.
+     and always in that order.  On most systems, smp_read_barrier_depends()
+     does nothing, but it is required for DEC Alpha.  The ACCESS_ONCE()
+     is required to prevent compiler mischief.  Please note that you
+     should normally use something like rcu_dereference() instead of
+     open-coding smp_read_barrier_depends().
 
  (*) Overlapping loads and stores within a particular CPU will appear to be
      ordered within that CPU.  This means that for:
 
-       a = *X; *X = b;
+       a = ACCESS_ONCE(*X); ACCESS_ONCE(*X) = b;
 
      the CPU will only issue the following sequence of memory operations:
 
@@ -213,7 +217,7 @@ There are some minimal guarantees that may be expected of a CPU:
 
      And for:
 
-       *X = c; d = *X;
+       ACCESS_ONCE(*X) = c; d = ACCESS_ONCE(*X);
 
      the CPU will only issue:
 
@@ -224,6 +228,12 @@ There are some minimal guarantees that may be expected of a CPU:
 
 And there are a number of things that _must_ or _must_not_ be assumed:
 
+ (*) It _must_not_ be assumed that the compiler will do what you want with
+     memory references that are not protected by ACCESS_ONCE().  Without
+     ACCESS_ONCE(), the compiler is within its rights to do all sorts
+     of "creative" transformations, which are covered in the Compiler
+     Barrier section.
+
  (*) It _must_not_ be assumed that independent loads and stores will be issued
      in the order given.  This means that for:
 
@@ -371,33 +381,44 @@ Memory barriers come in four basic varieties:
 
 And a couple of implicit varieties:
 
- (5) LOCK operations.
+ (5) ACQUIRE operations.
 
      This acts as a one-way permeable barrier.  It guarantees that all memory
-     operations after the LOCK operation will appear to happen after the LOCK
-     operation with respect to the other components of the system.
+     operations after the ACQUIRE operation will appear to happen after the
+     ACQUIRE operation with respect to the other components of the system.
+     ACQUIRE operations include LOCK operations and smp_load_acquire()
+     operations.
 
-     Memory operations that occur before a LOCK operation may appear to happen
-     after it completes.
+     Memory operations that occur before an ACQUIRE operation may appear to
+     happen after it completes.
 
-     A LOCK operation should almost always be paired with an UNLOCK operation.
+     An ACQUIRE operation should almost always be paired with a RELEASE
+     operation.
 
 
- (6) UNLOCK operations.
+ (6) RELEASE operations.
 
      This also acts as a one-way permeable barrier.  It guarantees that all
-     memory operations before the UNLOCK operation will appear to happen before
-     the UNLOCK operation with respect to the other components of the system.
+     memory operations before the RELEASE operation will appear to happen
+     before the RELEASE operation with respect to the other components of the
+     system. RELEASE operations include UNLOCK operations and
+     smp_store_release() operations.
 
-     Memory operations that occur after an UNLOCK operation may appear to
+     Memory operations that occur after a RELEASE operation may appear to
      happen before it completes.
 
-     LOCK and UNLOCK operations are guaranteed to appear with respect to each
-     other strictly in the order specified.
+     The use of ACQUIRE and RELEASE operations generally precludes the need
+     for other sorts of memory barrier (but note the exceptions mentioned in
+     the subsection "MMIO write barrier").  In addition, a RELEASE+ACQUIRE
+     pair is -not- guaranteed to act as a full memory barrier.  However, after
+     an ACQUIRE on a given variable, all memory accesses preceding any prior
+     RELEASE on that same variable are guaranteed to be visible.  In other
+     words, within a given variable's critical section, all accesses of all
+     previous critical sections for that variable are guaranteed to have
+     completed.
 
-     The use of LOCK and UNLOCK operations generally precludes the need for
-     other sorts of memory barrier (but note the exceptions mentioned in the
-     subsection "MMIO write barrier").
+     This means that ACQUIRE acts as a minimal "acquire" operation and
+     RELEASE acts as a minimal "release" operation.
 
 
 Memory barriers are only required where there's a possibility of interaction
@@ -450,14 +471,14 @@ The usage requirements of data dependency barriers are a little subtle, and
 it's not always obvious that they're needed.  To illustrate, consider the
 following sequence of events:
 
-       CPU 1           CPU 2
-       =============== ===============
+       CPU 1                 CPU 2
+       ===============       ===============
        { A == 1, B == 2, C = 3, P == &A, Q == &C }
        B = 4;
        <write barrier>
-       P = &B
-                       Q = P;
-                       D = *Q;
+       ACCESS_ONCE(P) = &B
+                             Q = ACCESS_ONCE(P);
+                             D = *Q;
 
 There's a clear data dependency here, and it would seem that by the end of the
 sequence, Q must be either &A or &B, and that:
@@ -477,15 +498,15 @@ Alpha).
 To deal with this, a data dependency barrier or better must be inserted
 between the address load and the data load:
 
-       CPU 1           CPU 2
-       =============== ===============
+       CPU 1                 CPU 2
+       ===============       ===============
        { A == 1, B == 2, C = 3, P == &A, Q == &C }
        B = 4;
        <write barrier>
-       P = &B
-                       Q = P;
-                       <data dependency barrier>
-                       D = *Q;
+       ACCESS_ONCE(P) = &B
+                             Q = ACCESS_ONCE(P);
+                             <data dependency barrier>
+                             D = *Q;
 
 This enforces the occurrence of one of the two implications, and prevents the
 third possibility from arising.
@@ -500,25 +521,26 @@ odd-numbered bank is idle, one can see the new value of the pointer P (&B),
 but the old value of the variable B (2).
 
 
-Another example of where data dependency barriers might by required is where a
+Another example of where data dependency barriers might be required is where a
 number is read from memory and then used to calculate the index for an array
 access:
 
-       CPU 1           CPU 2
-       =============== ===============
+       CPU 1                 CPU 2
+       ===============       ===============
        { M[0] == 1, M[1] == 2, M[3] = 3, P == 0, Q == 3 }
        M[1] = 4;
        <write barrier>
-       P = 1
-                       Q = P;
-                       <data dependency barrier>
-                       D = M[Q];
+       ACCESS_ONCE(P) = 1
+                             Q = ACCESS_ONCE(P);
+                             <data dependency barrier>
+                             D = M[Q];
 
 
-The data dependency barrier is very important to the RCU system, for example.
-See rcu_dereference() in include/linux/rcupdate.h.  This permits the current
-target of an RCU'd pointer to be replaced with a new modified target, without
-the replacement target appearing to be incompletely initialised.
+The data dependency barrier is very important to the RCU system,
+for example.  See rcu_assign_pointer() and rcu_dereference() in
+include/linux/rcupdate.h.  This permits the current target of an RCU'd
+pointer to be replaced with a new modified target, without the replacement
+target appearing to be incompletely initialised.
 
 See also the subsection on "Cache Coherency" for a more thorough example.
 
@@ -530,24 +552,190 @@ A control dependency requires a full read memory barrier, not simply a data
 dependency barrier to make it work correctly.  Consider the following bit of
 code:
 
-       q = &a;
-       if (p) {
-               <data dependency barrier>
-               q = &b;
+       q = ACCESS_ONCE(a);
+       if (q) {
+               <data dependency barrier>  /* BUG: No data dependency!!! */
+               p = ACCESS_ONCE(b);
        }
-       x = *q;
 
 This will not have the desired effect because there is no actual data
-dependency, but rather a control dependency that the CPU may short-circuit by
-attempting to predict the outcome in advance.  In such a case what's actually
-required is:
+dependency, but rather a control dependency that the CPU may short-circuit
+by attempting to predict the outcome in advance, so that other CPUs see
+the load from b as having happened before the load from a.  In such a
+case what's actually required is:
 
-       q = &a;
-       if (p) {
+       q = ACCESS_ONCE(a);
+       if (q) {
                <read barrier>
-               q = &b;
+               p = ACCESS_ONCE(b);
+       }
+
+However, stores are not speculated.  This means that ordering -is- provided
+in the following example:
+
+       q = ACCESS_ONCE(a);
+       if (ACCESS_ONCE(q)) {
+               ACCESS_ONCE(b) = p;
+       }
+
+Please note that ACCESS_ONCE() is not optional!  Without the ACCESS_ONCE(),
+the compiler is within its rights to transform this example:
+
+       q = a;
+       if (q) {
+               b = p;  /* BUG: Compiler can reorder!!! */
+               do_something();
+       } else {
+               b = p;  /* BUG: Compiler can reorder!!! */
+               do_something_else();
+       }
+
+into this, which of course defeats the ordering:
+
+       b = p;
+       q = a;
+       if (q)
+               do_something();
+       else
+               do_something_else();
+
+Worse yet, if the compiler is able to prove (say) that the value of
+variable 'a' is always non-zero, it would be well within its rights
+to optimize the original example by eliminating the "if" statement
+as follows:
+
+       q = a;
+       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':
+
+       q = ACCESS_ONCE(a);
+       if (q) {
+               ACCESS_ONCE(b) = p;
+               do_something();
+       } else {
+               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.
+
+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:
+
+       q = ACCESS_ONCE(a);
+       ACCESS_ONCE(b) = p;  /* BUG: No ordering vs. load from a!!! */
+       if (q) {
+               /* ACCESS_ONCE(b) = p; -- moved up, BUG!!! */
+               do_something();
+       } else {
+               /* ACCESS_ONCE(b) = p; -- moved up, BUG!!! */
+               do_something_else();
        }
-       x = *q;
+
+It is of course legal for the prior load to be part of the conditional,
+for example, as follows:
+
+       if (ACCESS_ONCE(a) > 0) {
+               ACCESS_ONCE(b) = q / 2;
+               do_something();
+       } else {
+               ACCESS_ONCE(b) = q / 3;
+               do_something_else();
+       }
+
+This will again ensure that the load from variable 'a' is ordered before the
+stores to variable 'b'.
+
+In addition, you need to be careful what you do with the local variable 'q',
+otherwise the compiler might be able to guess the value and again remove
+the needed conditional.  For example:
+
+       q = ACCESS_ONCE(a);
+       if (q % MAX) {
+               ACCESS_ONCE(b) = p;
+               do_something();
+       } else {
+               ACCESS_ONCE(b) = p;
+               do_something_else();
+       }
+
+If MAX is defined to be 1, then the compiler knows that (q % MAX) is
+equal to zero, in which case the compiler is within its rights to
+transform the above code into the following:
+
+       q = ACCESS_ONCE(a);
+       ACCESS_ONCE(b) = p;
+       do_something_else();
+
+This transformation loses the ordering between the load from variable 'a'
+and the store to variable 'b'.  If you are relying on this ordering, you
+should do something like the following:
+
+       q = ACCESS_ONCE(a);
+       BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */
+       if (q % MAX) {
+               ACCESS_ONCE(b) = p;
+               do_something();
+       } else {
+               ACCESS_ONCE(b) = p;
+               do_something_else();
+       }
+
+Finally, control dependencies do -not- provide transitivity.  This is
+demonstrated by two related examples:
+
+       CPU 0                     CPU 1
+       =====================     =====================
+       r1 = ACCESS_ONCE(x);      r2 = ACCESS_ONCE(y);
+       if (r1 >= 0)              if (r2 >= 0)
+         ACCESS_ONCE(y) = 1;       ACCESS_ONCE(x) = 1;
+
+       assert(!(r1 == 1 && r2 == 1));
+
+The above two-CPU example will never trigger the assert().  However,
+if control dependencies guaranteed transitivity (which they do not),
+then adding the following two CPUs would guarantee a related assertion:
+
+       CPU 2                     CPU 3
+       =====================     =====================
+       ACCESS_ONCE(x) = 2;       ACCESS_ONCE(y) = 2;
+
+       assert(!(r1 == 2 && r2 == 2 && x == 1 && y == 1)); /* FAILS!!! */
+
+But because control dependencies do -not- provide transitivity, the
+above assertion can fail after the combined four-CPU example completes.
+If you need the four-CPU example to provide ordering, you will need
+smp_mb() between the loads and stores in the CPU 0 and CPU 1 code fragments.
+
+In summary:
+
+  (*) Control dependencies can order prior loads against later stores.
+      However, they do -not- guarantee any other sort of ordering:
+      Not prior loads against later loads, nor prior stores against
+      later anything.  If you need these other forms of ordering,
+      use smb_rmb(), smp_wmb(), or, in the case of prior stores and
+      later loads, smp_mb().
+
+  (*) Control dependencies require at least one run-time conditional
+      between the prior load and the subsequent store.  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.
+
+  (*) Control dependencies require that the compiler avoid reordering the
+      dependency into nonexistence.  Careful use of ACCESS_ONCE() or
+      barrier() can help to preserve your control dependency.  Please
+      see the Compiler Barrier section for more information.
+
+  (*) Control dependencies do -not- provide transitivity.  If you
+      need transitivity, use smp_mb().
 
 
 SMP BARRIER PAIRING
@@ -561,23 +749,23 @@ barrier, though a general barrier would also be viable.  Similarly a read
 barrier or a data dependency barrier should always be paired with at least an
 write barrier, though, again, a general barrier is viable:
 
-       CPU 1           CPU 2
-       =============== ===============
-       a = 1;
+       CPU 1                 CPU 2
+       ===============       ===============
+       ACCESS_ONCE(a) = 1;
        <write barrier>
-       b = 2;          x = b;
-                       <read barrier>
-                       y = a;
+       ACCESS_ONCE(b) = 2;   x = ACCESS_ONCE(b);
+                             <read barrier>
+                             y = ACCESS_ONCE(a);
 
 Or:
 
-       CPU 1           CPU 2
-       =============== ===============================
+       CPU 1                 CPU 2
+       ===============       ===============================
        a = 1;
        <write barrier>
-       b = &a;         x = b;
-                       <data dependency barrier>
-                       y = *x;
+       ACCESS_ONCE(b) = &a;  x = ACCESS_ONCE(b);
+                             <data dependency barrier>
+                             y = *x;
 
 Basically, the read barrier always has to be there, even though it can be of
 the "weaker" type.
@@ -586,13 +774,13 @@ the "weaker" type.
 match the loads after the read barrier or the data dependency barrier, and vice
 versa:
 
-       CPU 1                           CPU 2
-       ===============                 ===============
-       a = 1;           }----   --->{  v = c
-       b = 2;           }    \ /    {  w = d
-       <write barrier>        \        <read barrier>
-       c = 3;           }    / \    {  x = a;
-       d = 4;           }----   --->{  y = b;
+       CPU 1                               CPU 2
+       ===================                 ===================
+       ACCESS_ONCE(a) = 1;  }----   --->{  v = ACCESS_ONCE(c);
+       ACCESS_ONCE(b) = 2;  }    \ /    {  w = ACCESS_ONCE(d);
+       <write barrier>            \        <read barrier>
+       ACCESS_ONCE(c) = 3;  }    / \    {  x = ACCESS_ONCE(a);
+       ACCESS_ONCE(d) = 4;  }----   --->{  y = ACCESS_ONCE(b);
 
 
 EXAMPLES OF MEMORY BARRIER SEQUENCES
@@ -882,12 +1070,12 @@ cache it for later use.
 
 Consider:
 
-       CPU 1                   CPU 2
+       CPU 1                   CPU 2
        ======================= =======================
-                               LOAD B
-                               DIVIDE          } Divide instructions generally
-                               DIVIDE          } take a long time to perform
-                               LOAD A
+                               LOAD B
+                               DIVIDE          } Divide instructions generally
+                               DIVIDE          } take a long time to perform
+                               LOAD A
 
 Which might appear as this:
 
@@ -910,13 +1098,13 @@ Which might appear as this:
 Placing a read barrier or a data dependency barrier just before the second
 load:
 
-       CPU 1                   CPU 2
+       CPU 1                   CPU 2
        ======================= =======================
-                               LOAD B
-                               DIVIDE
-                               DIVIDE
+                               LOAD B
+                               DIVIDE
+                               DIVIDE
                                <read barrier>
-                               LOAD A
+                               LOAD A
 
 will force any value speculatively obtained to be reconsidered to an extent
 dependent on the type of barrier used.  If there was no change made to the
@@ -1042,10 +1230,277 @@ compiler from moving the memory accesses either side of it to the other side:
 
        barrier();
 
-This is a general barrier - lesser varieties of compiler barrier do not exist.
+This is a general barrier -- there are no read-read or write-write variants
+of barrier().  However, ACCESS_ONCE() can be thought of as a weak form
+for barrier() that affects only the specific accesses flagged by the
+ACCESS_ONCE().
+
+The barrier() function has the following effects:
+
+ (*) Prevents the compiler from reordering accesses following the
+     barrier() to precede any accesses preceding the barrier().
+     One example use for this property is to ease communication between
+     interrupt-handler code and the code that was interrupted.
+
+ (*) Within a loop, forces the compiler to load the variables used
+     in that loop's conditional on each pass through that loop.
+
+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 merge successive loads from
+     the same variable.  Such merging can cause the compiler to "optimize"
+     the following code:
+
+       while (tmp = a)
+               do_something_with(tmp);
+
+     into the following code, which, although in some sense legitimate
+     for single-threaded code, is almost certainly not what the developer
+     intended:
+
+       if (tmp = a)
+               for (;;)
+                       do_something_with(tmp);
+
+     Use ACCESS_ONCE() to prevent the compiler from doing this to you:
+
+       while (tmp = ACCESS_ONCE(a))
+               do_something_with(tmp);
+
+ (*) The compiler is within its rights to reload a variable, for example,
+     in cases where high register pressure prevents the compiler from
+     keeping all data of interest in registers.  The compiler might
+     therefore optimize the variable 'tmp' out of our previous example:
+
+       while (tmp = a)
+               do_something_with(tmp);
+
+     This could result in the following code, which is perfectly safe in
+     single-threaded code, but can be fatal in concurrent code:
+
+       while (a)
+               do_something_with(a);
+
+     For example, the optimized version of this code could result in
+     passing a zero to do_something_with() in the case where the variable
+     a was modified by some other CPU between the "while" statement and
+     the call to do_something_with().
+
+     Again, use ACCESS_ONCE() to prevent the compiler from doing this:
+
+       while (tmp = ACCESS_ONCE(a))
+               do_something_with(tmp);
+
+     Note that if the compiler runs short of registers, it might save
+     tmp onto the stack.  The overhead of this saving and later restoring
+     is why compilers reload variables.  Doing so is perfectly safe for
+     single-threaded code, so you need to tell the compiler about cases
+     where it is not safe.
+
+ (*) The compiler is within its rights to omit a load entirely if it knows
+     what the value will be.  For example, if the compiler can prove that
+     the value of variable 'a' is always zero, it can optimize this code:
+
+       while (tmp = a)
+               do_something_with(tmp);
 
-The compiler barrier has no direct effect on the CPU, which may then reorder
-things however it wishes.
+     Into this:
+
+       do { } while (0);
+
+     This transformation is a win for single-threaded code because it gets
+     rid of a load and a branch.  The problem is that the compiler will
+     carry out its proof assuming that the current CPU is the only one
+     updating variable 'a'.  If variable 'a' is shared, then the compiler's
+     proof will be erroneous.  Use ACCESS_ONCE() to tell the compiler
+     that it doesn't know as much as it thinks it does:
+
+       while (tmp = ACCESS_ONCE(a))
+               do_something_with(tmp);
+
+     But please note that the compiler is also closely watching what you
+     do with the value after the ACCESS_ONCE().  For example, suppose you
+     do the following and MAX is a preprocessor macro with the value 1:
+
+       while ((tmp = ACCESS_ONCE(a)) % MAX)
+               do_something_with(tmp);
+
+     Then the compiler knows that the result of the "%" operator applied
+     to MAX will always be zero, again allowing the compiler to optimize
+     the code into near-nonexistence.  (It will still load from the
+     variable 'a'.)
+
+ (*) Similarly, the compiler is within its rights to omit a store entirely
+     if it knows that the variable already has the value being stored.
+     Again, the compiler assumes that the current CPU is the only one
+     storing into the variable, which can cause the compiler to do the
+     wrong thing for shared variables.  For example, suppose you have
+     the following:
+
+       a = 0;
+       /* Code that does not store to variable a. */
+       a = 0;
+
+     The compiler sees that the value of variable 'a' is already zero, so
+     it might well omit the second store.  This would come as a fatal
+     surprise if some other CPU might have stored to variable 'a' in the
+     meantime.
+
+     Use ACCESS_ONCE() to prevent the compiler from making this sort of
+     wrong guess:
+
+       ACCESS_ONCE(a) = 0;
+       /* Code that does not store to variable a. */
+       ACCESS_ONCE(a) = 0;
+
+ (*) The compiler is within its rights to reorder memory accesses unless
+     you tell it not to.  For example, consider the following interaction
+     between process-level code and an interrupt handler:
+
+       void process_level(void)
+       {
+               msg = get_message();
+               flag = true;
+       }
+
+       void interrupt_handler(void)
+       {
+               if (flag)
+                       process_message(msg);
+       }
+
+     There is nothing to prevent the the compiler from transforming
+     process_level() to the following, in fact, this might well be a
+     win for single-threaded code:
+
+       void process_level(void)
+       {
+               flag = true;
+               msg = get_message();
+       }
+
+     If the interrupt occurs between these two statement, then
+     interrupt_handler() might be passed a garbled msg.  Use ACCESS_ONCE()
+     to prevent this as follows:
+
+       void process_level(void)
+       {
+               ACCESS_ONCE(msg) = get_message();
+               ACCESS_ONCE(flag) = true;
+       }
+
+       void interrupt_handler(void)
+       {
+               if (ACCESS_ONCE(flag))
+                       process_message(ACCESS_ONCE(msg));
+       }
+
+     Note that the ACCESS_ONCE() wrappers in interrupt_handler()
+     are needed if this interrupt handler can itself be interrupted
+     by something that also accesses 'flag' and 'msg', for example,
+     a nested interrupt or an NMI.  Otherwise, ACCESS_ONCE() is not
+     needed in interrupt_handler() other than for documentation purposes.
+     (Note also that nested interrupts do not typically occur in modern
+     Linux kernels, in fact, if an interrupt handler returns with
+     interrupts enabled, you will get a WARN_ONCE() splat.)
+
+     You should assume that the compiler can move ACCESS_ONCE() past
+     code not containing ACCESS_ONCE(), barrier(), or similar primitives.
+
+     This effect could also be achieved using barrier(), but ACCESS_ONCE()
+     is more selective:  With ACCESS_ONCE(), the compiler need only forget
+     the contents of the indicated memory locations, while with barrier()
+     the compiler must discard the value of all memory locations that
+     it has currented cached in any machine registers.  Of course,
+     the compiler must also respect the order in which the ACCESS_ONCE()s
+     occur, though the CPU of course need not do so.
+
+ (*) The compiler is within its rights to invent stores to a variable,
+     as in the following example:
+
+       if (a)
+               b = a;
+       else
+               b = 42;
+
+     The compiler might save a branch by optimizing this as follows:
+
+       b = 42;
+       if (a)
+               b = a;
+
+     In single-threaded code, this is not only safe, but also saves
+     a branch.  Unfortunately, in concurrent code, this optimization
+     could cause some other CPU to see a spurious value of 42 -- even
+     if variable 'a' was never zero -- when loading variable 'b'.
+     Use ACCESS_ONCE() to prevent this as follows:
+
+       if (a)
+               ACCESS_ONCE(b) = a;
+       else
+               ACCESS_ONCE(b) = 42;
+
+     The compiler can also invent loads.  These are usually less
+     damaging, but they can result in cache-line bouncing and thus in
+     poor performance and scalability.  Use ACCESS_ONCE() to prevent
+     invented loads.
+
+ (*) For aligned memory locations whose size allows them to be accessed
+     with a single memory-reference instruction, prevents "load tearing"
+     and "store tearing," in which a single large access is replaced by
+     multiple smaller accesses.  For example, given an architecture having
+     16-bit store instructions with 7-bit immediate fields, the compiler
+     might be tempted to use two 16-bit store-immediate instructions to
+     implement the following 32-bit store:
+
+       p = 0x00010002;
+
+     Please note that GCC really does use this sort of optimization,
+     which is not surprising given that it would likely take more
+     than two instructions to build the constant and then store it.
+     This optimization can therefore be a win in single-threaded code.
+     In fact, a recent bug (since fixed) caused GCC to incorrectly use
+     this optimization in a volatile store.  In the absence of such bugs,
+     use of ACCESS_ONCE() prevents store tearing in the following example:
+
+       ACCESS_ONCE(p) = 0x00010002;
+
+     Use of packed structures can also result in load and store tearing,
+     as in this example:
+
+       struct __attribute__((__packed__)) foo {
+               short a;
+               int b;
+               short c;
+       };
+       struct foo foo1, foo2;
+       ...
+
+       foo2.a = foo1.a;
+       foo2.b = foo1.b;
+       foo2.c = foo1.c;
+
+     Because there are no ACCESS_ONCE() wrappers and no volatile markings,
+     the compiler would be well within its rights to implement these three
+     assignment statements as a pair of 32-bit loads followed by a pair
+     of 32-bit stores.  This would result in load tearing on 'foo1.b'
+     and store tearing on 'foo2.b'.  ACCESS_ONCE() again prevents tearing
+     in this example:
+
+       foo2.a = foo1.a;
+       ACCESS_ONCE(foo2.b) = ACCESS_ONCE(foo1.b);
+       foo2.c = foo1.c;
+
+All that aside, it is never necessary to use ACCESS_ONCE() on a variable
+that has been marked volatile.  For example, because 'jiffies' is marked
+volatile, it is never necessary to say ACCESS_ONCE(jiffies).  The reason
+for this is that ACCESS_ONCE() is implemented as a volatile cast, which
+has no effect when its argument is already marked volatile.
+
+Please note that these compiler barriers have no direct effect on the CPU,
+which may then reorder things however it wishes.
 
 
 CPU MEMORY BARRIERS
@@ -1135,7 +1590,7 @@ There are some more advanced barrier functions:
        clear_bit( ... );
 
      This prevents memory operations before the clear leaking to after it.  See
-     the subsection on "Locking Functions" with reference to UNLOCK operation
+     the subsection on "Locking Functions" with reference to RELEASE operation
      implications.
 
      See Documentation/atomic_ops.txt for more information.  See the "Atomic
@@ -1169,8 +1624,8 @@ provide more substantial guarantees, but these may not be relied upon outside
 of arch specific code.
 
 
-LOCKING FUNCTIONS
------------------
+ACQUIRING FUNCTIONS
+-------------------
 
 The Linux kernel has a number of locking constructs:
 
@@ -1181,65 +1636,107 @@ The Linux kernel has a number of locking constructs:
  (*) R/W semaphores
  (*) RCU
 
-In all cases there are variants on "LOCK" operations and "UNLOCK" operations
+In all cases there are variants on "ACQUIRE" operations and "RELEASE" operations
 for each construct.  These operations all imply certain barriers:
 
- (1) LOCK operation implication:
+ (1) ACQUIRE operation implication:
 
-     Memory operations issued after the LOCK will be completed after the LOCK
-     operation has completed.
+     Memory operations issued after the ACQUIRE will be completed after the
+     ACQUIRE operation has completed.
 
-     Memory operations issued before the LOCK may be completed after the LOCK
-     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.
 
- (2) UNLOCK operation implication:
+ (2) RELEASE operation implication:
 
-     Memory operations issued before the UNLOCK will be completed before the
-     UNLOCK operation has completed.
+     Memory operations issued before the RELEASE will be completed before the
+     RELEASE operation has completed.
 
-     Memory operations issued after the UNLOCK may be completed before the
-     UNLOCK operation has completed.
+     Memory operations issued after the RELEASE may be completed before the
+     RELEASE operation has completed.
 
- (3) LOCK vs LOCK implication:
+ (3) ACQUIRE vs ACQUIRE implication:
 
-     All LOCK operations issued before another LOCK operation will be completed
-     before that LOCK operation.
+     All ACQUIRE operations issued before another ACQUIRE operation will be
+     completed before that ACQUIRE operation.
 
- (4) LOCK vs UNLOCK implication:
+ (4) ACQUIRE vs RELEASE implication:
 
-     All LOCK operations issued before an UNLOCK operation will be completed
-     before the UNLOCK operation.
+     All ACQUIRE operations issued before a RELEASE operation will be
+     completed before the RELEASE operation.
 
-     All UNLOCK operations issued before a LOCK operation will be completed
-     before the LOCK operation.
+ (5) Failed conditional ACQUIRE implication:
 
- (5) Failed conditional LOCK implication:
-
-     Certain variants of the LOCK operation may fail, either due to being
-     unable to get the lock immediately, or due to receiving an unblocked
+     Certain locking variants of the ACQUIRE operation may fail, either due to
+     being unable to get the lock immediately, or due to receiving an unblocked
      signal whilst asleep waiting for the lock to become available.  Failed
      locks do not imply any sort of barrier.
 
-Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
-equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
-
-[!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way
-    barriers is that the effects of instructions outside of a critical section
-    may seep into the inside of the critical section.
+[!] Note: one of the consequences of lock ACQUIREs and RELEASEs being only
+one-way barriers is that the effects of instructions outside of a critical
+section may seep into the inside of the critical section.
 
-A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
-because it is possible for an access preceding the LOCK to happen after the
-LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
-two accesses can themselves then cross:
+An ACQUIRE followed by a RELEASE may not be assumed to be full memory barrier
+because it is possible for an access preceding the ACQUIRE to happen after the
+ACQUIRE, and an access following the RELEASE to happen before the RELEASE, and
+the two accesses can themselves then cross:
 
        *A = a;
-       LOCK
-       UNLOCK
+       ACQUIRE M
+       RELEASE M
        *B = b;
 
 may occur as:
 
-       LOCK, STORE *B, STORE *A, UNLOCK
+       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:
+
+       *A = a;
+       RELEASE M
+       ACQUIRE N
+       *B = b;
+
+could occur as:
+
+       ACQUIRE N, STORE *B, STORE *A, RELEASE M
+
+With smp_mb__after_unlock_lock(), they cannot, so that:
+
+       *A = a;
+       RELEASE M
+       ACQUIRE N
+       smp_mb__after_unlock_lock();
+       *B = b;
+
+will always occur as either of the following:
+
+       STORE *A, RELEASE, ACQUIRE, STORE *B
+       STORE *A, ACQUIRE, RELEASE, 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.
 
 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
@@ -1253,33 +1750,33 @@ As an example, consider the following:
 
        *A = a;
        *B = b;
-       LOCK
+       ACQUIRE
        *C = c;
        *D = d;
-       UNLOCK
+       RELEASE
        *E = e;
        *F = f;
 
 The following sequence of events is acceptable:
 
-       LOCK, {*F,*A}, *E, {*C,*D}, *B, UNLOCK
+       ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
 
        [+] Note that {*F,*A} indicates a combined access.
 
 But none of the following are:
 
-       {*F,*A}, *B,    LOCK, *C, *D,   UNLOCK, *E
-       *A, *B, *C,     LOCK, *D,       UNLOCK, *E, *F
-       *A, *B,         LOCK, *C,       UNLOCK, *D, *E, *F
-       *B,             LOCK, *C, *D,   UNLOCK, {*F,*A}, *E
+       {*F,*A}, *B,    ACQUIRE, *C, *D,        RELEASE, *E
+       *A, *B, *C,     ACQUIRE, *D,            RELEASE, *E, *F
+       *A, *B,         ACQUIRE, *C,            RELEASE, *D, *E, *F
+       *B,             ACQUIRE, *C, *D,        RELEASE, {*F,*A}, *E
 
 
 
 INTERRUPT DISABLING FUNCTIONS
 -----------------------------
 
-Functions that disable interrupts (LOCK equivalent) and enable interrupts
-(UNLOCK equivalent) will act as compiler barriers only.  So if memory or I/O
+Functions that disable interrupts (ACQUIRE equivalent) and enable interrupts
+(RELEASE equivalent) will act as compiler barriers only.  So if memory or I/O
 barriers are required in such a situation, they must be provided from some
 other means.
 
@@ -1418,75 +1915,81 @@ Other functions that imply barriers:
  (*) schedule() and similar imply full memory barriers.
 
 
-=================================
-INTER-CPU LOCKING BARRIER EFFECTS
-=================================
+===================================
+INTER-CPU ACQUIRING BARRIER EFFECTS
+===================================
 
 On SMP systems locking primitives give a more substantial form of barrier: one
 that does affect memory access ordering on other CPUs, within the context of
 conflict on any particular lock.
 
 
-LOCKS VS MEMORY ACCESSES
-------------------------
+ACQUIRES VS MEMORY ACCESSES
+---------------------------
 
 Consider the following: the system has a pair of spinlocks (M) and (Q), and
 three CPUs; then should the following sequence of events occur:
 
        CPU 1                           CPU 2
        =============================== ===============================
-       *A = a;                         *E = e;
-       LOCK M                          LOCK Q
-       *B = b;                         *F = f;
-       *C = c;                         *G = g;
-       UNLOCK M                        UNLOCK Q
-       *D = d;                         *H = h;
+       ACCESS_ONCE(*A) = a;            ACCESS_ONCE(*E) = e;
+       ACQUIRE M                       ACQUIRE Q
+       ACCESS_ONCE(*B) = b;            ACCESS_ONCE(*F) = f;
+       ACCESS_ONCE(*C) = c;            ACCESS_ONCE(*G) = g;
+       RELEASE M                       RELEASE Q
+       ACCESS_ONCE(*D) = d;            ACCESS_ONCE(*H) = h;
 
 Then there is no guarantee as to what order CPU 3 will see the accesses to *A
 through *H occur in, other than the constraints imposed by the separate locks
 on the separate CPUs. It might, for example, see:
 
-       *E, LOCK M, LOCK Q, *G, *C, *F, *A, *B, UNLOCK Q, *D, *H, UNLOCK M
+       *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
 
 But it won't see any of:
 
-       *B, *C or *D preceding LOCK M
-       *A, *B or *C following UNLOCK M
-       *F, *G or *H preceding LOCK Q
-       *E, *F or *G following UNLOCK Q
+       *B, *C or *D preceding ACQUIRE M
+       *A, *B or *C following RELEASE M
+       *F, *G or *H preceding ACQUIRE Q
+       *E, *F or *G following RELEASE Q
 
 
 However, if the following occurs:
 
        CPU 1                           CPU 2
        =============================== ===============================
-       *A = a;
-       LOCK M          [1]
-       *B = b;
-       *C = c;
-       UNLOCK M        [1]
-       *D = d;                         *E = e;
-                                       LOCK M          [2]
-                                       *F = f;
-                                       *G = g;
-                                       UNLOCK M        [2]
-                                       *H = h;
+       ACCESS_ONCE(*A) = a;
+       ACQUIRE M                    [1]
+       ACCESS_ONCE(*B) = b;
+       ACCESS_ONCE(*C) = c;
+       RELEASE M            [1]
+       ACCESS_ONCE(*D) = d;            ACCESS_ONCE(*E) = e;
+                                       ACQUIRE M                    [2]
+                                       smp_mb__after_unlock_lock();
+                                       ACCESS_ONCE(*F) = f;
+                                       ACCESS_ONCE(*G) = g;
+                                       RELEASE M            [2]
+                                       ACCESS_ONCE(*H) = h;
 
 CPU 3 might see:
 
-       *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
-               LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
+       *E, ACQUIRE M [1], *C, *B, *A, RELEASE M [1],
+               ACQUIRE M [2], *H, *F, *G, RELEASE M [2], *D
 
 But assuming CPU 1 gets the lock first, CPU 3 won't see any of:
 
-       *B, *C, *D, *F, *G or *H preceding LOCK M [1]
-       *A, *B or *C following UNLOCK M [1]
-       *F, *G or *H preceding LOCK M [2]
-       *A, *B, *C, *E, *F or *G following UNLOCK M [2]
+       *B, *C, *D, *F, *G or *H preceding ACQUIRE M [1]
+       *A, *B or *C following RELEASE M [1]
+       *F, *G or *H preceding ACQUIRE M [2]
+       *A, *B, *C, *E, *F or *G following RELEASE M [2]
 
+Note that the smp_mb__after_unlock_lock() is critically important
+here: Without it CPU 3 might see some of the above orderings.
+Without smp_mb__after_unlock_lock(), the accesses are not guaranteed
+to be seen in order unless CPU 3 holds lock M.
 
-LOCKS VS I/O ACCESSES
----------------------
+
+ACQUIRES VS I/O ACCESSES
+------------------------
 
 Under certain circumstances (especially involving NUMA), I/O accesses within
 two spinlocked sections on two different CPUs may be seen as interleaved by the
@@ -1687,28 +2190,30 @@ explicit lock operations, described later).  These include:
 
        xchg();
        cmpxchg();
-       atomic_xchg();
-       atomic_cmpxchg();
-       atomic_inc_return();
-       atomic_dec_return();
-       atomic_add_return();
-       atomic_sub_return();
-       atomic_inc_and_test();
-       atomic_dec_and_test();
-       atomic_sub_and_test();
-       atomic_add_negative();
-       atomic_add_unless();    /* when succeeds (returns 1) */
+       atomic_xchg();                  atomic_long_xchg();
+       atomic_cmpxchg();               atomic_long_cmpxchg();
+       atomic_inc_return();            atomic_long_inc_return();
+       atomic_dec_return();            atomic_long_dec_return();
+       atomic_add_return();            atomic_long_add_return();
+       atomic_sub_return();            atomic_long_sub_return();
+       atomic_inc_and_test();          atomic_long_inc_and_test();
+       atomic_dec_and_test();          atomic_long_dec_and_test();
+       atomic_sub_and_test();          atomic_long_sub_and_test();
+       atomic_add_negative();          atomic_long_add_negative();
        test_and_set_bit();
        test_and_clear_bit();
        test_and_change_bit();
 
-These are used for such things as implementing LOCK-class and UNLOCK-class
+       /* when succeeds (returns 1) */
+       atomic_add_unless();            atomic_long_add_unless();
+
+These are used for such things as implementing ACQUIRE-class and RELEASE-class
 operations and adjusting reference counters towards object destruction, and as
 such the implicit memory barrier effects are necessary.
 
 
 The following operations are potential problems as they do _not_ imply memory
-barriers, but might be used for implementing such things as UNLOCK-class
+barriers, but might be used for implementing such things as RELEASE-class
 operations:
 
        atomic_set();
@@ -1750,7 +2255,7 @@ The following operations are special locking primitives:
        clear_bit_unlock();
        __clear_bit_unlock();
 
-These implement LOCK-class and UNLOCK-class operations. These should be used in
+These implement ACQUIRE-class and RELEASE-class operations. These should be used in
 preference to other operations when implementing locking primitives, because
 their implementations can be optimised on many architectures.
 
@@ -1887,8 +2392,8 @@ functions:
      space should suffice for PCI.
 
      [*] NOTE! attempting to load from the same location as was written to may
-        cause a malfunction - consider the 16550 Rx/Tx serial registers for
-        example.
+        cause a malfunction - consider the 16550 Rx/Tx serial registers for
+        example.
 
      Used with prefetchable I/O memory, an mmiowb() barrier may be required to
      force stores to be ordered.
@@ -1955,19 +2460,19 @@ barriers for the most part act at the interface between the CPU and its cache
                                  :
        +--------+    +--------+  :   +--------+    +-----------+
        |        |    |        |  :   |        |    |           |    +--------+
-       |  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
-       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+       |  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
+       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
        |        |    | Queue  |  :   |        |    |           |--->| Memory |
-       |        |    |        |  :   |        |    |           |    |        |
-       +--------+    +--------+  :   +--------+    |           |    |        |
+       |        |    |        |  :   |        |    |           |    |        |
+       +--------+    +--------+  :   +--------+    |           |    |        |
                                  :                 | Cache     |    +--------+
                                  :                 | Coherency |
                                  :                 | Mechanism |    +--------+
        +--------+    +--------+  :   +--------+    |           |    |        |
        |        |    |        |  :   |        |    |           |    |        |
        |  CPU   |    | Memory |  :   | CPU    |    |           |--->| Device |
-       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
-       |        |    | Queue  |  :   |        |    |           |    |        |
+       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+       |        |    | Queue  |  :   |        |    |           |    |        |
        |        |    |        |  :   |        |    |           |    +--------+
        +--------+    +--------+  :   +--------+    +-----------+
                                  :
@@ -2090,7 +2595,7 @@ CPU's caches by some other cache event:
        p = &v;         q = p;
                        <D:request p>
        <B:modify p=&v> <D:commit p=&v>
-                       <D:read p>
+                       <D:read p>
                        x = *q;
                        <C:read *q>     Reads from v before v updated in cache
                        <C:unbusy>
@@ -2115,7 +2620,7 @@ queue before processing any further requests:
        p = &v;         q = p;
                        <D:request p>
        <B:modify p=&v> <D:commit p=&v>
-                       <D:read p>
+                       <D:read p>
                        smp_read_barrier_depends()
                        <C:unbusy>
                        <C:commit v=2>
@@ -2177,11 +2682,11 @@ A programmer might take it for granted that the CPU will perform memory
 operations in exactly the order specified, so that if the CPU is, for example,
 given the following piece of code to execute:
 
-       a = *A;
-       *B = b;
-       c = *C;
-       d = *D;
-       *E = e;
+       a = ACCESS_ONCE(*A);
+       ACCESS_ONCE(*B) = b;
+       c = ACCESS_ONCE(*C);
+       d = ACCESS_ONCE(*D);
+       ACCESS_ONCE(*E) = e;
 
 they would then expect that the CPU will complete the memory operation for each
 instruction before moving on to the next one, leading to a definite sequence of
@@ -2228,12 +2733,12 @@ However, it is guaranteed that a CPU will be self-consistent: it will see its
 _own_ accesses appear to be correctly ordered, without the need for a memory
 barrier.  For instance with the following code:
 
-       U = *A;
-       *A = V;
-       *A = W;
-       X = *A;
-       *A = Y;
-       Z = *A;
+       U = ACCESS_ONCE(*A);
+       ACCESS_ONCE(*A) = V;
+       ACCESS_ONCE(*A) = W;
+       X = ACCESS_ONCE(*A);
+       ACCESS_ONCE(*A) = Y;
+       Z = ACCESS_ONCE(*A);
 
 and assuming no intervention by an external influence, it can be assumed that
 the final result will appear to be:
@@ -2250,7 +2755,12 @@ accesses:
 
 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.
+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,
+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.
 
 The compiler may also combine, discard or defer elements of the sequence before
 the CPU even sees them.
@@ -2264,13 +2774,13 @@ may be reduced to:
 
        *A = W;
 
-since, without a write barrier, it can be assumed that the effect of the
-storage of V to *A is lost.  Similarly:
+since, without either a write barrier or an ACCESS_ONCE(), it can be
+assumed that the effect of the storage of V to *A is lost.  Similarly:
 
        *A = Y;
        Z = *A;
 
-may, without a memory barrier, be reduced to:
+may, without a memory barrier or an ACCESS_ONCE(), be reduced to:
 
        *A = Y;
        Z = Y;
index 0c980ad40b17be5c34a271c87c7983e112620d6b..4d17487d5ad9e5b4f10008c6b817636fcae53494 100644 (file)
@@ -313,7 +313,7 @@ static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
        int i;
        void *dp = get_dp(mic, type);
 
-       for (i = mic_aligned_size(struct mic_bootparam); i < PAGE_SIZE;
+       for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
                i += mic_total_desc_size(d)) {
                d = dp + i;
 
@@ -445,8 +445,8 @@ init_vr(struct mic_info *mic, int fd, int type,
                __func__, mic->name, vr0->va, vr0->info, vr_size,
                vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
        mpsslog("magic 0x%x expected 0x%x\n",
-               vr0->info->magic, MIC_MAGIC + type);
-       assert(vr0->info->magic == MIC_MAGIC + type);
+               le32toh(vr0->info->magic), MIC_MAGIC + type);
+       assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
        if (vr1) {
                vr1->va = (struct mic_vring *)
                        &va[MIC_DEVICE_PAGE_END + vr_size];
@@ -458,8 +458,8 @@ init_vr(struct mic_info *mic, int fd, int type,
                        __func__, mic->name, vr1->va, vr1->info, vr_size,
                        vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
                mpsslog("magic 0x%x expected 0x%x\n",
-                       vr1->info->magic, MIC_MAGIC + type + 1);
-               assert(vr1->info->magic == MIC_MAGIC + type + 1);
+                       le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
+               assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
        }
 done:
        return va;
@@ -520,7 +520,7 @@ static void *
 virtio_net(void *arg)
 {
        static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
-       static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __aligned(64);
+       static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((aligned(64)));
        struct iovec vnet_iov[2][2] = {
                { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
                  { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
@@ -1412,6 +1412,12 @@ mic_config(void *arg)
        }
 
        do {
+               ret = lseek(fd, 0, SEEK_SET);
+               if (ret < 0) {
+                       mpsslog("%s: Failed to seek to file start '%s': %s\n",
+                               mic->name, pathname, strerror(errno));
+                       goto close_error1;
+               }
                ret = read(fd, value, sizeof(value));
                if (ret < 0) {
                        mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
new file mode 100644 (file)
index 0000000..2b40e04
--- /dev/null
@@ -0,0 +1,240 @@
+                       ==============================
+                       KERNEL MODULE SIGNING FACILITY
+                       ==============================
+
+CONTENTS
+
+ - Overview.
+ - Configuring module signing.
+ - Generating signing keys.
+ - Public keys in the kernel.
+ - Manually signing modules.
+ - Signed modules and stripping.
+ - Loading signed modules.
+ - Non-valid signatures and unsigned modules.
+ - Administering/protecting the private key.
+
+
+========
+OVERVIEW
+========
+
+The kernel module signing facility cryptographically signs modules during
+installation and then checks the signature upon loading the module.  This
+allows increased kernel security by disallowing the loading of unsigned modules
+or modules signed with an invalid key.  Module signing increases security by
+making it harder to load a malicious module into the kernel.  The module
+signature checking is done by the kernel so that it is not necessary to have
+trusted userspace bits.
+
+This facility uses X.509 ITU-T standard certificates to encode the public keys
+involved.  The signatures are not themselves encoded in any industrial standard
+type.  The facility currently only supports the RSA public key encryption
+standard (though it is pluggable and permits others to be used).  The possible
+hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
+SHA-512 (the algorithm is selected by data in the signature).
+
+
+==========================
+CONFIGURING MODULE SIGNING
+==========================
+
+The module signing facility is enabled by going to the "Enable Loadable Module
+Support" section of the kernel configuration and turning on
+
+       CONFIG_MODULE_SIG       "Module signature verification"
+
+This has a number of options available:
+
+ (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
+
+     This specifies how the kernel should deal with a module that has a
+     signature for which the key is not known or a module that is unsigned.
+
+     If this is off (ie. "permissive"), then modules for which the key is not
+     available and modules that are unsigned are permitted, but the kernel will
+     be marked as being tainted.
+
+     If this is on (ie. "restrictive"), only modules that have a valid
+     signature that can be verified by a public key in the kernel's possession
+     will be loaded.  All other modules will generate an error.
+
+     Irrespective of the setting here, if the module has a signature block that
+     cannot be parsed, it will be rejected out of hand.
+
+
+ (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
+
+     If this is on then modules will be automatically signed during the
+     modules_install phase of a build.  If this is off, then the modules must
+     be signed manually using:
+
+       scripts/sign-file
+
+
+ (3) "Which hash algorithm should modules be signed with?"
+
+     This presents a choice of which hash algorithm the installation phase will
+     sign the modules with:
+
+       CONFIG_SIG_SHA1         "Sign modules with SHA-1"
+       CONFIG_SIG_SHA224       "Sign modules with SHA-224"
+       CONFIG_SIG_SHA256       "Sign modules with SHA-256"
+       CONFIG_SIG_SHA384       "Sign modules with SHA-384"
+       CONFIG_SIG_SHA512       "Sign modules with SHA-512"
+
+     The algorithm selected here will also be built into the kernel (rather
+     than being a module) so that modules signed with that algorithm can have
+     their signatures checked without causing a dependency loop.
+
+
+=======================
+GENERATING SIGNING KEYS
+=======================
+
+Cryptographic keypairs are required to generate and check signatures.  A
+private key is used to generate a signature and the corresponding public key is
+used to check it.  The private key is only needed during the build, after which
+it can be deleted or stored securely.  The public key gets built into the
+kernel so that it can be used to check the signatures as the modules are
+loaded.
+
+Under normal conditions, the kernel build will automatically generate a new
+keypair using openssl if one does not exist in the files:
+
+       signing_key.priv
+       signing_key.x509
+
+during the building of vmlinux (the public part of the key needs to be built
+into vmlinux) using parameters in the:
+
+       x509.genkey
+
+file (which is also generated if it does not already exist).
+
+It is strongly recommended that you provide your own x509.genkey file.
+
+Most notably, in the x509.genkey file, the req_distinguished_name section
+should be altered from the default:
+
+       [ req_distinguished_name ]
+       O = Magrathea
+       CN = Glacier signing key
+       emailAddress = slartibartfast@magrathea.h2g2
+
+The generated RSA key size can also be set with:
+
+       [ req ]
+       default_bits = 4096
+
+
+It is also possible to manually generate the key private/public files using the
+x509.genkey key generation configuration file in the root node of the Linux
+kernel sources tree and the openssl command.  The following is an example to
+generate the public/private key files:
+
+       openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
+          -config x509.genkey -outform DER -out signing_key.x509 \
+          -keyout signing_key.priv
+
+
+=========================
+PUBLIC KEYS IN THE KERNEL
+=========================
+
+The kernel contains a ring of public keys that can be viewed by root.  They're
+in a keyring called ".system_keyring" that can be seen by:
+
+       [root@deneb ~]# cat /proc/keys
+       ...
+       223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
+       302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
+       ...
+
+Beyond the public key generated specifically for module signing, any file
+placed in the kernel source root directory or the kernel build root directory
+whose name is suffixed with ".x509" will be assumed to be an X.509 public key
+and will be added to the keyring.
+
+Further, the architecture code may take public keys from a hardware store and
+add those in also (e.g. from the UEFI key database).
+
+Finally, it is possible to add additional public keys by doing:
+
+       keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
+
+e.g.:
+
+       keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
+
+Note, however, that the kernel will only permit keys to be added to
+.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
+that is already resident in the .system_keyring at the time the key was added.
+
+
+=========================
+MANUALLY SIGNING MODULES
+=========================
+
+To manually sign a module, use the scripts/sign-file tool available in
+the Linux kernel source tree.  The script requires 4 arguments:
+
+       1.  The hash algorithm (e.g., sha256)
+       2.  The private key filename
+       3.  The public key filename
+       4.  The kernel module to be signed
+
+The following is an example to sign a kernel module:
+
+       scripts/sign-file sha512 kernel-signkey.priv \
+               kernel-signkey.x509 module.ko
+
+The hash algorithm used does not have to match the one configured, but if it
+doesn't, you should make sure that hash algorithm is either built into the
+kernel or can be loaded without requiring itself.
+
+
+============================
+SIGNED MODULES AND STRIPPING
+============================
+
+A signed module has a digital signature simply appended at the end.  The string
+"~Module signature appended~." at the end of the module's file confirms that a
+signature is present but it does not confirm that the signature is valid!
+
+Signed modules are BRITTLE as the signature is outside of the defined ELF
+container.  Thus they MAY NOT be stripped once the signature is computed and
+attached.  Note the entire module is the signed payload, including any and all
+debug information present at the time of signing.
+
+
+======================
+LOADING SIGNED MODULES
+======================
+
+Modules are loaded with insmod, modprobe, init_module() or finit_module(),
+exactly as for unsigned modules as no processing is done in userspace.  The
+signature checking is all done within the kernel.
+
+
+=========================================
+NON-VALID SIGNATURES AND UNSIGNED MODULES
+=========================================
+
+If CONFIG_MODULE_SIG_FORCE is enabled or enforcemodulesig=1 is supplied on
+the kernel command line, the kernel will only load validly signed modules
+for which it has a public key.   Otherwise, it will also load modules that are
+unsigned.   Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load.
+
+Any module that has an unparseable signature will be rejected.
+
+
+=========================================
+ADMINISTERING/PROTECTING THE PRIVATE KEY
+=========================================
+
+Since the private key is used to sign modules, viruses and malware could use
+the private key to sign modules and compromise the operating system.  The
+private key must be either destroyed or moved to a secure location and not kept
+in the root node of the kernel source tree.
index 3c12d9a7ed00391d5c3f49ef80d7b1ae9abc40fe..8a984e994e61616a9dba0a4f425a5b4371b3ae99 100644 (file)
@@ -16,8 +16,12 @@ ip_default_ttl - INTEGER
        Default: 64 (as recommended by RFC1700)
 
 ip_no_pmtu_disc - BOOLEAN
-       Disable Path MTU Discovery.
-       default FALSE
+       Disable Path MTU Discovery. If enabled and a
+       fragmentation-required ICMP is received, the PMTU to this
+       destination will be set to min_pmtu (see below). You will need
+       to raise min_pmtu to the smallest interface MTU on your system
+       manually if you want to avoid locally generated fragments.
+       Default: FALSE
 
 min_pmtu - INTEGER
        default 552 - minimum discovered Path MTU
index c01223628a87ae5e522b714c8a3a86edda15dea5..8e48e3b142275ff1500df754301d39c7f1639d71 100644 (file)
@@ -123,6 +123,16 @@ Transmission process is similar to capture as shown below.
 [shutdown]  close() --------> destruction of the transmission socket and
                               deallocation of all associated resources.
 
+Socket creation and destruction is also straight forward, and is done
+the same way as in capturing described in the previous paragraph:
+
+ int fd = socket(PF_PACKET, mode, 0);
+
+The protocol can optionally be 0 in case we only want to transmit
+via this socket, which avoids an expensive call to packet_rcv().
+In this case, you also need to bind(2) the TX_RING with sll_protocol = 0
+set. Otherwise, htons(ETH_P_ALL) or any other protocol, for example.
+
 Binding the socket to your network interface is mandatory (with zero copy) to
 know the header size of frames used in the circular buffer.
 
index fd1cd8aae4eb584b3b963a884f477f22cd037b2d..16eb314f56cc45ce923d9354960bdf67ea4e6b98 100644 (file)
@@ -146,8 +146,8 @@ On removal:
  1) set the 'list_op_pending' word to the address of the 'lock entry'
     to be removed,
  2) remove the lock entry for this lock from the 'head' list,
2) release the futex lock, and
2) clear the 'lock_op_pending' word.
3) release the futex lock, and
4) clear the 'lock_op_pending' word.
 
 On exit, the kernel will consider the address stored in
 'list_op_pending' and the address of each 'lock word' found by walking
index 26b7ee491df8912d070b5b9d33252e78f606e2ab..6d486404200e9bbd71a20e97f1e85e74615014a5 100644 (file)
@@ -428,11 +428,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_settle_count is how many scan periods must complete before
-the schedule balancer stops pushing the task towards a preferred node. This
-gives the scheduler a chance to place the task on an alternative node if the
-preferred node is overloaded.
-
 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
index f4f268c2b826de7f03b1c2bd2478a85eacd58f2e..cb81741d3b0bd92b70aa87918e632edd0bfef3f1 100644 (file)
@@ -608,6 +608,9 @@ Protocol:       2.12+
        - If 1, the kernel supports the 64-bit EFI handoff entry point
           given at handover_offset + 0x200.
 
+  Bit 4 (read): XLF_EFI_KEXEC
+       - If 1, the kernel supports kexec EFI boot with EFI runtime support.
+
 Field name:    cmdline_size
 Type:          read
 Offset/size:   0x238/4
index 881582f75c9ceb14e6eaacc48f3edecef31b3e3a..c584a51add15ad1ca8033207e46bf497abb33570 100644 (file)
@@ -28,4 +28,11 @@ reference.
 Current X86-64 implementations only support 40 bits of address space,
 but we support up to 46 bits. This expands into MBZ space in the page tables.
 
+->trampoline_pgd:
+
+We map EFI runtime services in the aforementioned PGD in the virtual
+range of 64Gb (arbitrarily set, can be raised if needed)
+
+0xffffffef00000000 - 0xffffffff00000000
+
 -Andi Kleen, Jul 2004
index d5829d14774a676e3f2ae93602756f2f2df8c4cb..90a64d52bea2f33464f86e4dc93954b2bc105f50 100644 (file)
@@ -95,8 +95,9 @@ The treatment of these regions depends on the type of Zorro space:
 -------------
 
 linux/include/linux/zorro.h
-linux/include/asm-{m68k,ppc}/zorro.h
-linux/include/linux/zorro_ids.h
+linux/include/uapi/linux/zorro.h
+linux/include/uapi/linux/zorro_ids.h
+linux/arch/m68k/include/asm/zorro.h
 linux/drivers/zorro
 /proc/bus/zorro
 
index f216db8470227446313fc15b75b8501835bd6cf4..ce1645ebe70cf6d5136b164fdac1bdfa4d86b370 100644 (file)
@@ -783,7 +783,7 @@ F:  arch/arm/boot/dts/sama*.dts
 F:     arch/arm/boot/dts/sama*.dtsi
 
 ARM/CALXEDA HIGHBANK ARCHITECTURE
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-highbank/
@@ -893,20 +893,15 @@ 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:     Sascha Hauer <kernel@pengutronix.de>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
+T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
 F:     arch/arm/mach-imx/
+F:     arch/arm/boot/dts/imx*
 F:     arch/arm/configs/imx*_defconfig
 
-ARM/FREESCALE IMX6
-M:     Shawn Guo <shawn.guo@linaro.org>
-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
-F:     arch/arm/mach-imx/*imx6*
-
 ARM/FREESCALE MXS ARM ARCHITECTURE
 M:     Shawn Guo <shawn.guo@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1013,6 +1008,8 @@ M:        Santosh Shilimkar <santosh.shilimkar@ti.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-keystone/
+F:     drivers/clk/keystone/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
 
 ARM/LOGICPD PXA270 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -1371,6 +1368,9 @@ T:        git git://git.xilinx.com/linux-xlnx.git
 S:     Supported
 F:     arch/arm/mach-zynq/
 F:     drivers/cpuidle/cpuidle-zynq.c
+N:     zynq
+N:     xilinx
+F:     drivers/clocksource/cadence_ttc_timer.c
 
 ARM SMMU DRIVER
 M:     Will Deacon <will.deacon@arm.com>
@@ -1934,7 +1934,8 @@ S:        Maintained
 F:     drivers/gpio/gpio-bt8xx.c
 
 BTRFS FILE SYSTEM
-M:     Chris Mason <chris.mason@fusionio.com>
+M:     Chris Mason <clm@fb.com>
+M:     Josef Bacik <jbacik@fb.com>
 L:     linux-btrfs@vger.kernel.org
 W:     http://btrfs.wiki.kernel.org/
 Q:     http://patchwork.kernel.org/project/linux-btrfs/list/
@@ -2137,7 +2138,8 @@ S:        Maintained
 F:     Documentation/zh_CN/
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
-M:     Alexander Shishkin <alexander.shishkin@linux.intel.com>
+M:     Peter Chen <Peter.Chen@freescale.com>
+T:     git://github.com/hzpeterchen/linux-usb.git
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/chipidea/
@@ -2826,8 +2828,10 @@ F:       include/uapi/drm/
 
 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
 S:     Supported
 F:     drivers/gpu/drm/i915/
@@ -3764,9 +3768,11 @@ F:       include/uapi/linux/gigaset_dev.h
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
-S:     Maintained
+M:     Alexandre Courbot <gnurou@gmail.com>
 L:     linux-gpio@vger.kernel.org
-F:     Documentation/gpio.txt
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
+S:     Maintained
+F:     Documentation/gpio/
 F:     drivers/gpio/
 F:     include/linux/gpio*
 F:     include/asm-generic/gpio.h
@@ -3834,6 +3840,12 @@ T:       git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/usb/gspca/
 
+GUID PARTITION TABLE (GPT)
+M:     Davidlohr Bueso <davidlohr@hp.com>
+L:     linux-efi@vger.kernel.org
+S:     Maintained
+F:     block/partitions/efi.*
+
 STK1160 USB VIDEO CAPTURE DRIVER
 M:     Ezequiel Garcia <elezegarcia@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -4043,12 +4055,26 @@ W:      http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:     Maintained
 F:     fs/hpfs/
 
+HSI SUBSYSTEM
+M:     Sebastian Reichel <sre@debian.org>
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-bus-hsi
+F:     drivers/hsi/
+F:     include/linux/hsi/
+F:     include/uapi/linux/hsi/
+
 HSO 3G MODEM DRIVER
 M:     Jan Dumon <j.dumon@option.com>
 W:     http://www.pharscape.org
 S:     Maintained
 F:     drivers/net/usb/hso.c
 
+HSR NETWORK PROTOCOL
+M:     Arvid Brodin <arvid.brodin@alten.se>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     net/hsr/
+
 HTCPEN TOUCHSCREEN DRIVER
 M:     Pau Oliva Fora <pof@eslack.org>
 L:     linux-input@vger.kernel.org
@@ -4455,10 +4481,8 @@ M:       Bruce Allan <bruce.w.allan@intel.com>
 M:     Carolyn Wyborny <carolyn.wyborny@intel.com>
 M:     Don Skidmore <donald.c.skidmore@intel.com>
 M:     Greg Rose <gregory.v.rose@intel.com>
-M:     Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
-M:     Tushar Dave <tushar.n.dave@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
@@ -5117,6 +5141,11 @@ F:       drivers/lguest/
 F:     include/linux/lguest*.h
 F:     tools/lguest/
 
+LIBLOCKDEP
+M:     Sasha Levin <sasha.levin@oracle.com>
+S:     Maintained
+F:     tools/lib/lockdep/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:     Paul Mackerras <paulus@au.ibm.com>
 W:     http://www.ibm.com/linux/ltc/projects/ppc
@@ -5261,7 +5290,7 @@ S:        Maintained
 F:     Documentation/lockdep*.txt
 F:     Documentation/lockstat.txt
 F:     include/linux/lockdep.h
-F:     kernel/lockdep*
+F:     kernel/locking/
 
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
 M:     "Richard Russon (FlatCap)" <ldm@flatcap.org>
@@ -5902,12 +5931,21 @@ M:      Steffen Klassert <steffen.klassert@secunet.com>
 M:     Herbert Xu <herbert@gondor.apana.org.au>
 M:     "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
 S:     Maintained
 F:     net/xfrm/
 F:     net/key/
 F:     net/ipv4/xfrm*
+F:     net/ipv4/esp4.c
+F:     net/ipv4/ah4.c
+F:     net/ipv4/ipcomp.c
+F:     net/ipv4/ip_vti.c
 F:     net/ipv6/xfrm*
+F:     net/ipv6/esp6.c
+F:     net/ipv6/ah6.c
+F:     net/ipv6/ipcomp6.c
+F:     net/ipv6/ip6_vti.c
 F:     include/uapi/linux/xfrm.h
 F:     include/net/xfrm.h
 
@@ -5973,10 +6011,10 @@ F:      drivers/nfc/
 F:     include/linux/platform_data/pn544.h
 
 NFS, SUNRPC, AND LOCKD CLIENTS
-M:     Trond Myklebust <Trond.Myklebust@netapp.com>
+M:     Trond Myklebust <trond.myklebust@primarydata.com>
 L:     linux-nfs@vger.kernel.org
 W:     http://client.linux-nfs.org
-T:     git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
+T:     git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
 S:     Maintained
 F:     fs/lockd/
 F:     fs/nfs/
@@ -6228,7 +6266,7 @@ F:        drivers/i2c/busses/i2c-ocores.c
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -6240,11 +6278,11 @@ K:      of_get_property
 K:     of_match_table
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
-M:     Stephen Warren <swarren@wwwdotorg.org>
 M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
+M:     Kumar Gala <galak@codeaurora.org>
 L:     devicetree@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/
@@ -6454,19 +6492,52 @@ F:      drivers/pci/
 F:     include/linux/pci*
 F:     arch/x86/pci/
 
+PCI DRIVER FOR IMX6
+M:     Richard Zhu <r65037@freescale.com>
+M:     Shawn Guo <shawn.guo@linaro.org>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pci/host/*imx6*
+
+PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
+M:     Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+M:     Jason Cooper <jason@lakedaemon.net>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pci/host/*mvebu*
+
 PCI DRIVER FOR NVIDIA TEGRA
 M:     Thierry Reding <thierry.reding@gmail.com>
 L:     linux-tegra@vger.kernel.org
+L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
 F:     drivers/pci/host/pci-tegra.c
 
+PCI DRIVER FOR RENESAS R-CAR
+M:     Simon Horman <horms@verge.net.au>
+L:     linux-pci@vger.kernel.org
+L:     linux-sh@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/*rcar*
+
 PCI DRIVER FOR SAMSUNG EXYNOS
 M:     Jingoo Han <jg1.han@samsung.com>
 L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/pci/host/pci-exynos.c
 
+PCI DRIVER FOR SYNOPSIS DESIGNWARE
+M:     Mohit Kumar <mohit.kumar@st.com>
+M:     Jingoo Han <jg1.han@samsung.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     drivers/pci/host/*designware*
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     linux-pcmcia@lists.infradead.org
@@ -7033,6 +7104,12 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
 F:     Documentation/RCU/torture.txt
 F:     kernel/rcu/torture.c
 
+RCUTORTURE TEST FRAMEWORK
+M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
+F:     tools/testing/selftests/rcutorture
+
 RDC R-321X SoC
 M:     Florian Fainelli <florian@openwrt.org>
 S:     Maintained
@@ -7385,7 +7462,6 @@ S:        Maintained
 F:     kernel/sched/
 F:     include/linux/sched.h
 F:     include/uapi/linux/sched.h
-F:     kernel/wait.c
 F:     include/linux/wait.h
 
 SCORE ARCHITECTURE
@@ -9166,6 +9242,7 @@ F:        include/media/videobuf2-*
 
 VIRTIO CONSOLE DRIVER
 M:     Amit Shah <amit.shah@redhat.com>
+L:     virtio-dev@lists.oasis-open.org
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/char/virtio_console.c
@@ -9175,6 +9252,7 @@ F:        include/uapi/linux/virtio_console.h
 VIRTIO CORE, NET AND BLOCK DRIVERS
 M:     Rusty Russell <rusty@rustcorp.com.au>
 M:     "Michael S. Tsirkin" <mst@redhat.com>
+L:     virtio-dev@lists.oasis-open.org
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/virtio/
@@ -9187,6 +9265,7 @@ F:        include/uapi/linux/virtio_*.h
 VIRTIO HOST (VHOST)
 M:     "Michael S. Tsirkin" <mst@redhat.com>
 L:     kvm@vger.kernel.org
+L:     virtio-dev@lists.oasis-open.org
 L:     virtualization@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -9530,7 +9609,7 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Dave Chinner <dchinner@fromorbit.com>
+M:     Dave Chinner <david@fromorbit.com>
 M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
index 2c88e44a1dd4d9dbf726ab1f071db8accb805884..455fd484b20edb92a0c916c1be3cc7adffc6cfa4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION =
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
@@ -595,10 +595,24 @@ ifneq ($(CONFIG_FRAME_WARN),0)
 KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
 endif
 
-# Force gcc to behave correct even for buggy distributions
-ifndef CONFIG_CC_STACKPROTECTOR
-KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
+# Handle stack protector mode.
+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))
+  endif
+else ifdef CONFIG_CC_STACKPROTECTOR_STRONG
+  stackp-flag := -fstack-protector-strong
+  ifeq ($(call cc-option, $(stackp-flag)),)
+    $(warning Cannot use CONFIG_CC_STACKPROTECTOR_STRONG: \
+             -fstack-protector-strong not supported by compiler)
+  endif
+else
+  # Force off for distro compilers that enable stack protector by default.
+  stackp-flag := $(call cc-option, -fno-stack-protector)
 endif
+KBUILD_CFLAGS += $(stackp-flag)
 
 # This warning generated too much noise in a regular build.
 # Use make W=1 to enable this warning (see scripts/Makefile.build)
@@ -732,19 +746,15 @@ export mod_strip_cmd
 # Select initial ramdisk compression format, default is gzip(1).
 # This shall be used by the dracut(8) tool while creating an initramfs image.
 #
-INITRD_COMPRESS=gzip
-ifeq ($(CONFIG_RD_BZIP2), y)
-        INITRD_COMPRESS=bzip2
-else ifeq ($(CONFIG_RD_LZMA), y)
-        INITRD_COMPRESS=lzma
-else ifeq ($(CONFIG_RD_XZ), y)
-        INITRD_COMPRESS=xz
-else ifeq ($(CONFIG_RD_LZO), y)
-        INITRD_COMPRESS=lzo
-else ifeq ($(CONFIG_RD_LZ4), y)
-        INITRD_COMPRESS=lz4
-endif
-export INITRD_COMPRESS
+INITRD_COMPRESS-y                  := gzip
+INITRD_COMPRESS-$(CONFIG_RD_BZIP2) := bzip2
+INITRD_COMPRESS-$(CONFIG_RD_LZMA)  := lzma
+INITRD_COMPRESS-$(CONFIG_RD_XZ)    := xz
+INITRD_COMPRESS-$(CONFIG_RD_LZO)   := lzo
+INITRD_COMPRESS-$(CONFIG_RD_LZ4)   := lz4
+# do not export INITRD_COMPRESS, since we didn't actually
+# choose a sane default compression above.
+# export INITRD_COMPRESS := $(INITRD_COMPRESS-y)
 
 ifdef CONFIG_MODULE_SIG_ALL
 MODSECKEY = ./signing_key.priv
index f1cf895c040fb674ed1c07e5cc43459e9244a8f6..80bbb8ccd0d10b319d932d1be08a2d742f957cfa 100644 (file)
@@ -336,6 +336,73 @@ config SECCOMP_FILTER
 
          See Documentation/prctl/seccomp_filter.txt for details.
 
+config HAVE_CC_STACKPROTECTOR
+       bool
+       help
+         An arch should select this symbol if:
+         - its compiler supports the -fstack-protector option
+         - it has implemented a stack canary (e.g. __stack_chk_guard)
+
+config CC_STACKPROTECTOR
+       def_bool n
+       help
+         Set when a stack-protector mode is enabled, so that the build
+         can enable kernel-side support for the GCC feature.
+
+choice
+       prompt "Stack Protector buffer overflow detection"
+       depends on HAVE_CC_STACKPROTECTOR
+       default CC_STACKPROTECTOR_NONE
+       help
+         This option turns on the "stack-protector" GCC feature. This
+         feature puts, at the beginning of functions, a canary value on
+         the stack just before the return address, and validates
+         the value just before actually returning.  Stack based buffer
+         overflows (that need to overwrite this return address) now also
+         overwrite the canary, which gets detected and the attack is then
+         neutralized via a kernel panic.
+
+config CC_STACKPROTECTOR_NONE
+       bool "None"
+       help
+         Disable "stack-protector" GCC feature.
+
+config CC_STACKPROTECTOR_REGULAR
+       bool "Regular"
+       select CC_STACKPROTECTOR
+       help
+         Functions will have the stack-protector canary logic added if they
+         have an 8-byte or larger character array on the stack.
+
+         This feature requires gcc version 4.2 or above, or a distribution
+         gcc with the feature backported ("-fstack-protector").
+
+         On an x86 "defconfig" build, this feature adds canary checks to
+         about 3% of all kernel functions, which increases kernel code size
+         by about 0.3%.
+
+config CC_STACKPROTECTOR_STRONG
+       bool "Strong"
+       select CC_STACKPROTECTOR
+       help
+         Functions will have the stack-protector canary logic added in any
+         of the following conditions:
+
+         - local variable's address used as part of the right hand side of an
+           assignment or function argument
+         - local variable is an array (or union containing an array),
+           regardless of array type or length
+         - uses register local variables
+
+         This feature requires gcc version 4.9 or above, or a distribution
+         gcc with the feature backported ("-fstack-protector-strong").
+
+         On an x86 "defconfig" build, this feature adds canary checks to
+         about 20% of all kernel functions, which increases the kernel code
+         size by about 2%.
+
+endchoice
+
 config HAVE_CONTEXT_TRACKING
        bool
        help
index ce8860a0b32db64bf0b8f8663717fd30df635b05..3832bdb794fec83d0df010413b009a311b57fec4 100644 (file)
@@ -3,33 +3,18 @@
 
 #include <asm/compiler.h>
 
-#define mb() \
-__asm__ __volatile__("mb": : :"memory")
+#define mb()   __asm__ __volatile__("mb": : :"memory")
+#define rmb()  __asm__ __volatile__("mb": : :"memory")
+#define wmb()  __asm__ __volatile__("wmb": : :"memory")
 
-#define rmb() \
-__asm__ __volatile__("mb": : :"memory")
-
-#define wmb() \
-__asm__ __volatile__("wmb": : :"memory")
-
-#define read_barrier_depends() \
-__asm__ __volatile__("mb": : :"memory")
+#define read_barrier_depends() __asm__ __volatile__("mb": : :"memory")
 
 #ifdef CONFIG_SMP
 #define __ASM_SMP_MB   "\tmb\n"
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
 #else
 #define __ASM_SMP_MB
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
 #endif
 
-#define set_mb(var, value) \
-do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
 
 #endif         /* __BARRIER_H */
index 2ee0c9bfd0325537a5d9299649abac4992b722f5..9063ae6553ccb7a0a220b8db667ac770627addbf 100644 (file)
@@ -8,6 +8,7 @@
 
 config ARC
        def_bool y
+       select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
        # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
        select DEVTMPFS if !INITRAMFS_SOURCE=""
index 5943f7f9d32550313a5ef767e29ead6e64f5e3f6..9ae21c198007758b07cde32b2b06eebd271d4ec5 100644 (file)
@@ -1,4 +1,5 @@
 generic-y += auxvec.h
+generic-y += barrier.h
 generic-y += bugs.h
 generic-y += bitsperlong.h
 generic-y += clkdev.h
index 83f03ca6caf6c7f09f171a66581d062a7333ccdd..03e494f695d1d1ecabe7be6df8057ae21504f413 100644 (file)
@@ -190,6 +190,11 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
 #endif /* !CONFIG_ARC_HAS_LLSC */
 
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 /**
  * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
index f6cb7c4ffb35029316d2c549c2a6db5d95f86e0e..c32245c3d1e9b59263dfee9fdfcbb78040e866f6 100644 (file)
 #define smp_wmb()       barrier()
 #endif
 
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec()     barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc()     barrier()
-
 #define smp_read_barrier_depends()      do { } while (0)
 
 #endif
index 6f30484f34b78c5fa5052e68bbcbd3b4280a193f..39e58d1cdf90b7d8f84d108d8024d8974c3b800c 100644 (file)
@@ -8,6 +8,13 @@
 
 /******** no-legacy-syscalls-ABI *******/
 
+/*
+ * Non-typical guard macro to enable inclusion twice in ARCH sys.c
+ * That is how the Generic syscall wrapper generator works
+ */
+#if !defined(_UAPI_ASM_ARC_UNISTD_H) || defined(__SYSCALL)
+#define _UAPI_ASM_ARC_UNISTD_H
+
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_VFORK
@@ -32,3 +39,7 @@ __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
 /* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
 #define __NR_sysfs             (__NR_arch_specific_syscall + 3)
 __SYSCALL(__NR_sysfs, sys_sysfs)
+
+#undef __SYSCALL
+
+#endif
index e46d81f709797a868b7cc68cc81ef71277a0f070..63177e4cb66d0d3a323b3e53081d4caaf2550ac0 100644 (file)
@@ -79,9 +79,9 @@ static int arc_pmu_cache_event(u64 config)
        cache_result    = (config >> 16) & 0xff;
        if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
                return -EINVAL;
-       if (cache_type >= PERF_COUNT_HW_CACHE_OP_MAX)
+       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
                return -EINVAL;
-       if (cache_type >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                return -EINVAL;
 
        ret = arc_pmu_cache_map[cache_type][cache_op][cache_result];
index c1f1a7eee953de4378b1f74bd4907c969f96dceb..9c909fc292720a9ac9a2d5ee0a7be0b6ab2a5b27 100644 (file)
@@ -30,6 +30,7 @@ config ARM
        select HAVE_BPF_JIT
        select HAVE_CONTEXT_TRACKING
        select HAVE_C_RECORDMCOUNT
+       select HAVE_CC_STACKPROTECTOR
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_API_DEBUG
        select HAVE_DMA_ATTRS
@@ -1856,18 +1857,6 @@ config SECCOMP
          and the task is only allowed to execute a few safe syscalls
          defined by each seccomp mode.
 
-config CC_STACKPROTECTOR
-       bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
-       help
-         This option turns on the -fstack-protector GCC feature. This
-         feature puts, at the beginning of functions, a canary value on
-         the stack just before the return address, and validates
-         the value just before actually returning.  Stack based buffer
-         overflows (that need to overwrite this return address) now also
-         overwrite the canary, which gets detected and the attack is then
-         neutralized via a kernel panic.
-         This feature requires gcc version 4.2 or above.
-
 config SWIOTLB
        def_bool y
 
index c99b1086d83dfa8c0c407bab392ff5bb12927ab5..55b4255ad6ed9dd3e911d45b72acd822e81422f0 100644 (file)
@@ -40,10 +40,6 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
 KBUILD_CFLAGS  +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
 endif
 
-ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
-KBUILD_CFLAGS  +=-fstack-protector
-endif
-
 ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
 KBUILD_CPPFLAGS        += -mbig-endian
 AS             += -EB
index 31bd43b8209585d807d745309057013ba627b8a5..d4f891f5699655efd8dbce63e25e509859ccbc71 100644 (file)
@@ -127,6 +127,18 @@ asmlinkage void __div0(void)
        error("Attempting division by 0!");
 }
 
+unsigned long __stack_chk_guard;
+
+void __stack_chk_guard_setup(void)
+{
+       __stack_chk_guard = 0x000a0dff;
+}
+
+void __stack_chk_fail(void)
+{
+       error("stack-protector: Kernel stack is corrupted\n");
+}
+
 extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
 
 
@@ -137,6 +149,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 {
        int ret;
 
+       __stack_chk_guard_setup();
+
        output_data             = (unsigned char *)output_start;
        free_mem_ptr            = free_mem_ptr_p;
        free_mem_end_ptr        = free_mem_ptr_end_p;
index b4f95c2bbf74696577b544fd69bd41ed94dda4a9..72a9b3fc425111ec9924fb47defeffee169672e2 100644 (file)
 / {
        model = "IGEP COM AM335x on AQUILA Expansion";
        compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
+
+       hdmi {
+               compatible = "ti,tilcdc,slave";
+               i2c = <&i2c0>;
+               pinctrl-names = "default", "off";
+               pinctrl-0 = <&nxp_hdmi_pins>;
+               pinctrl-1 = <&nxp_hdmi_off_pins>;
+               status = "okay";
+       };
+
+       leds_base {
+               pinctrl-names = "default";
+               pinctrl-0 = <&leds_base_pins>;
+
+               compatible = "gpio-leds";
+
+               led@0 {
+                       label = "base:red:user";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;   /* gpio1_21 */
+                       default-state = "off";
+               };
+
+               led@1 {
+                       label = "base:green:user";
+                       gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;    /* gpio2_0 */
+                       default-state = "off";
+               };
+       };
+};
+
+&am33xx_pinmux {
+       nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
+               pinctrl-single,pins = <
+                       0x1b0 (PIN_OUTPUT | MUX_MODE3)  /* xdma_event_intr0.clkout1 */
+                       0xa0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data0 */
+                       0xa4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data1 */
+                       0xa8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data2 */
+                       0xac (PIN_OUTPUT | MUX_MODE0)   /* lcd_data3 */
+                       0xb0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data4 */
+                       0xb4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data5 */
+                       0xb8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data6 */
+                       0xbc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data7 */
+                       0xc0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data8 */
+                       0xc4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data9 */
+                       0xc8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data10 */
+                       0xcc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data11 */
+                       0xd0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data12 */
+                       0xd4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data13 */
+                       0xd8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data14 */
+                       0xdc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data15 */
+                       0xe0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_vsync */
+                       0xe4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_hsync */
+                       0xe8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_pclk */
+                       0xec (PIN_OUTPUT | MUX_MODE0)   /* lcd_ac_bias_en */
+               >;
+       };
+       nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
+               pinctrl-single,pins = <
+                       0x1b0 (PIN_OUTPUT | MUX_MODE3)  /* xdma_event_intr0.clkout1 */
+               >;
+       };
+
+       leds_base_pins: pinmux_leds_base_pins {
+               pinctrl-single,pins = <
+                       0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a5.gpio1_21 */
+                       0x88 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_csn3.gpio2_0 */
+               >;
+       };
+};
+
+&lcdc {
+       status = "okay";
+};
+
+&i2c0 {
+       eeprom: eeprom@50 {
+               compatible = "at,24c256";
+               reg = <0x50>;
+       };
 };
index 6196244793113cfb8c0aac21dcf2259558174ed6..7063311a58d96785dd297f89b982970a59a185bb 100644 (file)
        pinctrl-0 = <&uart0_pins>;
 };
 
+&usb {
+       status = "okay";
+
+       control@44e10000 {
+               status = "okay";
+       };
+
+       usb-phy@47401300 {
+               status = "okay";
+       };
+
+       usb-phy@47401b00 {
+               status = "okay";
+       };
+
+       usb@47401000 {
+               status = "okay";
+       };
+
+       usb@47401800 {
+               status = "okay";
+               dr_mode = "host";
+       };
+
+       dma-controller@07402000  {
+               status = "okay";
+       };
+};
+
 #include "tps65910.dtsi"
 
 &tps {
index e99dfaf70052f3dd993aa93588b6e47470befee2..03fcbf0a88a8ef24565257d32be79ab75dd4aa79 100644 (file)
@@ -7,11 +7,11 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "am3517.dtsi"
 
 / {
-       model = "TI AM3517 EVM (AM3517/05)";
-       compatible = "ti,am3517-evm", "ti,omap3";
+       model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
+       compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
 
        memory {
                device_type = "memory";
diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi
new file mode 100644 (file)
index 0000000..2fbe02f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for am3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+       aliases {
+               serial3 = &uart4;
+       };
+
+       ocp {
+               am35x_otg_hs: am35x_otg_hs@5c040000 {
+                       compatible = "ti,omap3-musb";
+                       ti,hwmods = "am35x_otg_hs";
+                       status = "disabled";
+                       reg = <0x5c040000 0x1000>;
+                       interrupts = <71>;
+                       interrupt-names = "mc";
+               };
+
+               davinci_emac: ethernet@0x5c000000 {
+                       compatible = "ti,am3517-emac";
+                       ti,hwmods = "davinci_emac";
+                       status = "disabled";
+                       reg = <0x5c000000 0x30000>;
+                       interrupts = <67 68 69 70>;
+                       ti,davinci-ctrl-reg-offset = <0x10000>;
+                       ti,davinci-ctrl-mod-reg-offset = <0>;
+                       ti,davinci-ctrl-ram-offset = <0x20000>;
+                       ti,davinci-ctrl-ram-size = <0x2000>;
+                       ti,davinci-rmii-en = /bits/ 8 <1>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+               };
+
+               davinci_mdio: ethernet@0x5c030000 {
+                       compatible = "ti,davinci_mdio";
+                       ti,hwmods = "davinci_mdio";
+                       status = "disabled";
+                       reg = <0x5c030000 0x1000>;
+                       bus_freq = <1000000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               uart4: serial@4809e000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart4";
+                       status = "disabled";
+                       reg = <0x4809e000 0x400>;
+                       interrupts = <84>;
+                       dmas = <&sdma 55 &sdma 54>;
+                       dma-names = "tx", "rx";
+                       clock-frequency = <48000000>;
+               };
+       };
+};
index 90ce29dbe119e4680b6f7b9b61d177319d8251c1..08a56bcfc7248704b34ad1789418308819b3bcbf 100644 (file)
                                        spi-max-frequency = <50000000>;
                                };
                        };
+               };
 
-                       pcie-controller {
+               pcie-controller {
+                       status = "okay";
+                       /*
+                        * The two PCIe units are accessible through
+                        * both standard PCIe slots and mini-PCIe
+                        * slots on the board.
+                        */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+                       pcie@2,0 {
+                               /* Port 1, Lane 0 */
                                status = "okay";
-                               /*
-                                * The two PCIe units are accessible through
-                                * both standard PCIe slots and mini-PCIe
-                                * slots on the board.
-                                */
-                               pcie@1,0 {
-                                       /* Port 0, Lane 0 */
-                                       status = "okay";
-                               };
-                               pcie@2,0 {
-                                       /* Port 1, Lane 0 */
-                                       status = "okay";
-                               };
                        };
                };
        };
index 00d6a798c705b9b04408a8d28af70cd7b7cc6868..7f10f627ae5b72b7f560732c6e8d5bb35b943e69 100644 (file)
 
                        coherency-fabric@20200 {
                                compatible = "marvell,coherency-fabric";
-                               reg = <0x20200 0xb0>, <0x21810 0x1c>;
+                               reg = <0x20200 0xb0>, <0x21010 0x1c>;
                        };
 
                        serial@12000 {
index 3f5e6121c730a21ae2079acff268da2be20518ef..98335fb34b7ad5a11d9f40b6564bddc161431455 100644 (file)
@@ -47,7 +47,7 @@
                /*
                 * MV78230 has 2 PCIe units Gen2.0: One unit can be
                 * configured as x4 or quad x1 lanes. One unit is
-                * x4/x1.
+                * x1 only.
                 */
                pcie-controller {
                        compatible = "marvell,armada-xp-pcie";
 
                        ranges =
                               <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
-                               0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
                                0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
                                0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
                                0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+                               0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
                                0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
                                0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
                                0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
@@ -74,8 +74,8 @@
                                0x81000000 0x3 0       MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
                                0x82000000 0x4 0       MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
                                0x81000000 0x4 0       MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
-                               0x82000000 0x9 0       MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
-                               0x81000000 0x9 0       MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
+                               0x82000000 0x5 0       MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+                               0x81000000 0x5 0       MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */>;
 
                        pcie@1,0 {
                                device_type = "pci";
                                status = "disabled";
                        };
 
-                       pcie@9,0 {
+                       pcie@5,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-                               reg = <0x4800 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x2800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
-                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+                                         0x81000000 0 0 0x81000000 0x5 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 99>;
-                               marvell,pcie-port = <2>;
+                               interrupt-map = <0 0 0 0 &mpic 62>;
+                               marvell,pcie-port = <1>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 26>;
+                               clocks = <&gateclk 9>;
                                status = "disabled";
                        };
                };
index 3e9fd1353f895d6778972e95518850268ef6eb4e..66609684d41b59ef701530fd2076553ffc4e9b6b 100644 (file)
@@ -48,7 +48,7 @@
                /*
                 * MV78260 has 3 PCIe units Gen2.0: Two units can be
                 * configured as x4 or quad x1 lanes. One unit is
-                * x4/x1.
+                * x4 only.
                 */
                pcie-controller {
                        compatible = "marvell,armada-xp-pcie";
@@ -68,7 +68,9 @@
                                0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
                                0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
                                0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
-                               0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000   /* Port 3.0 registers */
+                               0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000   /* Port 1.1 registers */
+                               0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000   /* Port 1.2 registers */
+                               0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000   /* Port 1.3 registers */
                                0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
                                0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
                                0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
                                0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
                                0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
                                0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
-                               0x82000000 0x9 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
-                               0x81000000 0x9 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
-                               0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
-                               0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
+
+                               0x82000000 0x5 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+                               0x81000000 0x5 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+                               0x82000000 0x6 0     MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
+                               0x81000000 0x6 0     MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO  */
+                               0x82000000 0x7 0     MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
+                               0x81000000 0x7 0     MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO  */
+                               0x82000000 0x8 0     MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
+                               0x81000000 0x8 0     MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO  */
+
+                               0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+                               0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
 
                        pcie@1,0 {
                                device_type = "pci";
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                                ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
-                                          0x81000000 0 0 0x81000000 0x2 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+                                         0x81000000 0 0 0x81000000 0x2 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
                                interrupt-map = <0 0 0 0 &mpic 59>;
                                marvell,pcie-port = <0>;
                                status = "disabled";
                        };
 
-                       pcie@9,0 {
+                       pcie@5,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-                               reg = <0x4800 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x2800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
-                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+                                         0x81000000 0 0 0x81000000 0x5 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 99>;
-                               marvell,pcie-port = <2>;
+                               interrupt-map = <0 0 0 0 &mpic 62>;
+                               marvell,pcie-port = <1>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 26>;
+                               clocks = <&gateclk 9>;
                                status = "disabled";
                        };
 
-                       pcie@10,0 {
+                       pcie@6,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
-                               reg = <0x5000 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
+                               reg = <0x3000 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
-                                         0x81000000 0 0 0x81000000 0xa 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
+                                         0x81000000 0 0 0x81000000 0x6 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 103>;
-                               marvell,pcie-port = <3>;
+                               interrupt-map = <0 0 0 0 &mpic 63>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <1>;
+                               clocks = <&gateclk 10>;
+                               status = "disabled";
+                       };
+
+                       pcie@7,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
+                               reg = <0x3800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
+                                         0x81000000 0 0 0x81000000 0x7 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 64>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <2>;
+                               clocks = <&gateclk 11>;
+                               status = "disabled";
+                       };
+
+                       pcie@8,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
+                               reg = <0x4000 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
+                                         0x81000000 0 0 0x81000000 0x8 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 65>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <3>;
+                               clocks = <&gateclk 12>;
+                               status = "disabled";
+                       };
+
+                       pcie@9,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+                               reg = <0x4800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 99>;
+                               marvell,pcie-port = <2>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 27>;
+                               clocks = <&gateclk 26>;
                                status = "disabled";
                        };
                };
index 2347e9563cef62bc760a94c6be2ba2d940cd8c89..6801106fa1f8a0fee541e33da838a15033ddb33c 100644 (file)
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+       aliases {
+               serial4 = &usart3;
+       };
+
        ahb {
                apb {
                        pinctrl@fffff400 {
index 9db5047812f3d6c05a36643abbea0e1fb33e8195..177becde7a268bdcee91be7b049567d17daf9809 100644 (file)
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x10800000 0x1000>;
                        interrupts = <0 33 0>;
-                       clocks = <&clock 271>;
+                       clocks = <&clock 346>;
                        clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
index 9c18adf788f774101daa7a7ee4389cfb235bd561..f577b7df9a29e4f5f4e74ca86aef4b4ba61ceb87 100644 (file)
@@ -44,8 +44,8 @@
                gpmc,wr-access-ns = <186>;
                gpmc,cycle2cycle-samecsen;
                gpmc,cycle2cycle-diffcsen;
-               vmmc-supply = <&vddvario>;
-               vmmc_aux-supply = <&vdd33a>;
+               vddvario-supply = <&vddvario>;
+               vdd33a-supply = <&vdd33a>;
                reg-io-width = <4>;
                smsc,save-mac-address;
        };
index 31a632f7effbf239f298ff3619cdacdc5587356e..df33a50bc070b508fd8dacd8a3c72f645c18d3e0 100644 (file)
 &usbhsehci {
        phys = <0 &hsusb2_phy>;
 };
+
+&vaux2 {
+       regulator-name = "usb_1v8";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index fa532aaacc68943989241b92a6e31743e3e854fe..3ba4a625ea5b9714ce4371e8a9637c108349158c 100644 (file)
                vcc-supply = <&hsusb2_power>;
        };
 
+       sound {
+               compatible = "ti,omap-twl4030";
+               ti,model = "omap3beagle";
+
+               ti,mcbsp = <&mcbsp2>;
+               ti,codec = <&twl_audio>;
+       };
+
        gpio_keys {
                compatible = "gpio-keys";
 
                reg = <0x48>;
                interrupts = <7>; /* SYS_NIRQ cascaded to intc */
                interrupt-parent = <&intc>;
+
+               twl_audio: audio {
+                       compatible = "ti,twl4030-audio";
+                       codec {
+                       };
+               };
        };
 };
 
        mode = <3>;
        power = <50>;
 };
+
+&vaux2 {
+       regulator-name = "vdd_ehci";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index ba1e58b7b7e35ddbdf4825853cf72cef6a951939..165aaf7591ba8ef51856474d85db8754710a33ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP Technology devices
+ * Common device tree for IGEP boards based on AM/DM37x
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -10,7 +10,7 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "omap36xx.dtsi"
 
 / {
        memory {
                ti,mcbsp = <&mcbsp2>;
                ti,codec = <&twl_audio>;
        };
+
+       vdd33: regulator-vdd33 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd33";
+               regulator-always-on;
+       };
+
+       lbee1usjyc_vmmc: lbee1usjyc_vmmc {
+               pinctrl-names = "default";
+               pinctrl-0 = <&lbee1usjyc_pins>;
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;    /* gpio_138 WIFI_PDN */
+               startup-delay-us = <10000>;
+               enable-active-high;
+               vin-supply = <&vdd33>;
+       };
 };
 
 &omap3_pmx_core {
                >;
        };
 
+       /* WiFi/BT combo */
+       lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
+               pinctrl-single,pins = <
+                       0x136 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat5.gpio_137 */
+                       0x138 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat6.gpio_138 */
+                       0x13a (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat7.gpio_139 */
+               >;
+       };
+
        mcbsp2_pins: pinmux_mcbsp2_pins {
                pinctrl-single,pins = <
                        0x10c (PIN_INPUT | MUX_MODE0)           /* mcbsp2_fsx.mcbsp2_fsx */
                        0x11a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat1.sdmmc1_dat1 */
                        0x11c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat2.sdmmc1_dat2 */
                        0x11e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat3.sdmmc1_dat3 */
-                       0x120 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat4.sdmmc1_dat4 */
-                       0x122 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat5.sdmmc1_dat5 */
-                       0x124 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat6.sdmmc1_dat6 */
-                       0x126 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat7.sdmmc1_dat7 */
+               >;
+       };
+
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_clk.sdmmc2_clk */
+                       0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_cmd.sdmmc2_cmd */
+                       0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat0.sdmmc2_dat0 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat1.sdmmc2_dat1 */
+                       0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat2.sdmmc2_dat2 */
+                       0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat3.sdmmc2_dat3 */
                >;
        };
 
                >;
        };
 
+       i2c1_pins: pinmux_i2c1_pins {
+               pinctrl-single,pins = <
+                       0x18a (PIN_INPUT | MUX_MODE0)   /* i2c1_scl.i2c1_scl */
+                       0x18c (PIN_INPUT | MUX_MODE0)   /* i2c1_sda.i2c1_sda */
+               >;
+       };
+
+       i2c2_pins: pinmux_i2c2_pins {
+               pinctrl-single,pins = <
+                       0x18e (PIN_INPUT | MUX_MODE0)   /* i2c2_scl.i2c2_scl */
+                       0x190 (PIN_INPUT | MUX_MODE0)   /* i2c2_sda.i2c2_sda */
+               >;
+       };
+
+       i2c3_pins: pinmux_i2c3_pins {
+               pinctrl-single,pins = <
+                       0x192 (PIN_INPUT | MUX_MODE0)   /* i2c3_scl.i2c3_scl */
+                       0x194 (PIN_INPUT | MUX_MODE0)   /* i2c3_sda.i2c3_sda */
+               >;
+       };
+
        leds_pins: pinmux_leds_pins { };
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        clock-frequency = <2600000>;
 
        twl: twl@48 {
 #include "twl4030_omap3.dtsi"
 
 &i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
        clock-frequency = <400000>;
 };
 
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c3_pins>;
+};
+
 &mcbsp2 {
        pinctrl-names = "default";
        pinctrl-0 = <&mcbsp2_pins>;
       pinctrl-0 = <&mmc1_pins>;
       vmmc-supply = <&vmmc1>;
       vmmc_aux-supply = <&vsim>;
-      bus-width = <8>;
+      bus-width = <4>;
 };
 
 &mmc2 {
-       status = "disabled";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&lbee1usjyc_vmmc>;
+       bus-width = <4>;
+       non-removable;
 };
 
 &mmc3 {
index d5cc792672501012f2a368b4d27b17bbb7669d95..1c7e74d2d2bc7bd03f1a970cea9442f715c0f3eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEPv2 board
+ * Device Tree Source for IGEPv2 Rev. (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -13,7 +13,7 @@
 #include "omap-gpmc-smsc911x.dtsi"
 
 / {
-       model = "IGEPv2";
+       model = "IGEPv2 (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0020", "ti,omap3";
 
        leds {
@@ -67,6 +67,8 @@
        pinctrl-names = "default";
        pinctrl-0 = <
                &hsusbb1_pins
+               &tfp410_pins
+               &dss_pins
        >;
 
        hsusbb1_pins: pinmux_hsusbb1_pins {
                        0x5ba (PIN_INPUT_PULLDOWN | MUX_MODE3)  /* etk_d7.hsusb1_data3 */
                >;
        };
+
+       tfp410_pins: tfp410_dvi_pins {
+               pinctrl-single,pins = <
+                       0x196 (PIN_OUTPUT | MUX_MODE4)   /* hdq_sio.gpio_170 */
+               >;
+       };
+
+       dss_pins: pinmux_dss_dvi_pins {
+               pinctrl-single,pins = <
+                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
+                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
+                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
+                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
+                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
+                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+               >;
+       };
 };
 
 &leds_pins {
 &usbhsehci {
        phys = <&hsusb1_phy>;
 };
+
+&vpll2 {
+        /* Needed for DSS */
+        regulator-name = "vdds_dsi";
+};
index 525e6d9b09784c721b4660554a17abdda14273e9..02a23f8a3384255abca5d54ecf53417226a8347f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP COM Module
+ * Device Tree Source for IGEP COM MODULE (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -12,7 +12,7 @@
 #include "omap3-igep.dtsi"
 
 / {
-       model = "IGEP COM Module";
+       model = "IGEP COM MODULE (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0030", "ti,omap3";
 
        leds {
index c4f20bfe4cce15e641af5ef08c92ca939973b9c3..6fc85f96353024ad61d04d74d7ca51f8afb1c7ce 100644 (file)
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "omap34xx-hs.dtsi"
 
 / {
        model = "Nokia N900";
                >;
        };
 
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_clk */
+                       0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_cmd */
+                       0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat0 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat1 */
+                       0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat2 */
+                       0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat3 */
+                       0x134 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat4 */
+                       0x136 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat5 */
+                       0x138 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat6 */
+                       0x13a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat7 */
+               >;
+       };
+
        display_pins: pinmux_display_pins {
                pinctrl-single,pins = <
                        0x0d4 (PIN_OUTPUT | MUX_MODE4)          /* RX51_LCD_RESET_GPIO */
        cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
 };
 
+/* most boards use vaux3, only some old versions use vmmc2 instead */
 &mmc2 {
-       status = "disabled";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&vaux3>;
+       vmmc_aux-supply = <&vsim>;
+       bus-width = <8>;
+       non-removable;
 };
 
 &mmc3 {
index 94eb77d3b9ddc5a2c506f271834103cb06b4881e..5c26c184f2c18b50a18cdd51bd53b20f9b3f359b 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "omap36xx.dtsi"
+#include "omap36xx-hs.dtsi"
 
 / {
        cpus {
index f3a0c26ed0c2bcd6d6df65dcecc3f18329abec18..daabf99d402a8e4ff645824dcad9d56fc693b17d 100644 (file)
                ranges;
                ti,hwmods = "l3_main";
 
+               aes: aes@480c5000 {
+                       compatible = "ti,omap3-aes";
+                       ti,hwmods = "aes";
+                       reg = <0x480c5000 0x50>;
+                       interrupts = <0>;
+               };
+
                counter32k: counter@48320000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x48320000 0x20>;
                        ti,hwmods = "i2c3";
                };
 
+               mailbox: mailbox@48094000 {
+                       compatible = "ti,omap3-mailbox";
+                       ti,hwmods = "mailbox";
+                       reg = <0x48094000 0x200>;
+                       interrupts = <26>;
+               };
+
                mcspi1: spi@48098000 {
                        compatible = "ti,omap2-mcspi";
                        reg = <0x48098000 0x100>;
                        dma-names = "tx", "rx";
                };
 
+               mmu_isp: mmu@480bd400 {
+                       compatible = "ti,omap3-mmu-isp";
+                       ti,hwmods = "mmu_isp";
+                       reg = <0x480bd400 0x80>;
+                       interrupts = <8>;
+               };
+
                wdt2: wdt@48314000 {
                        compatible = "ti,omap3-wdt";
                        reg = <0x48314000 0x80>;
                        dma-names = "tx", "rx";
                };
 
+               sham: sham@480c3000 {
+                       compatible = "ti,omap3-sham";
+                       ti,hwmods = "sham";
+                       reg = <0x480c3000 0x64>;
+                       interrupts = <49>;
+               };
+
+               smartreflex_core: smartreflex@480cb000 {
+                       compatible = "ti,omap3-smartreflex-core";
+                       ti,hwmods = "smartreflex_core";
+                       reg = <0x480cb000 0x400>;
+                       interrupts = <19>;
+               };
+
+               smartreflex_mpu_iva: smartreflex@480c9000 {
+                       compatible = "ti,omap3-smartreflex-iva";
+                       ti,hwmods = "smartreflex_mpu_iva";
+                       reg = <0x480c9000 0x400>;
+                       interrupts = <18>;
+               };
+
                timer1: timer@48318000 {
                        compatible = "ti,omap3430-timer";
                        reg = <0x48318000 0x400>;
diff --git a/arch/arm/boot/dts/omap34xx-hs.dtsi b/arch/arm/boot/dts/omap34xx-hs.dtsi
new file mode 100644 (file)
index 0000000..1ff6264
--- /dev/null
@@ -0,0 +1,16 @@
+/* Disabled modules for secure omaps */
+
+#include "omap34xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
+
+&timer12 {
+       status = "disabled";
+};
diff --git a/arch/arm/boot/dts/omap36xx-hs.dtsi b/arch/arm/boot/dts/omap36xx-hs.dtsi
new file mode 100644 (file)
index 0000000..2c7febb
--- /dev/null
@@ -0,0 +1,16 @@
+/* Disabled modules for secure omaps */
+
+#include "omap36xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
+
+&timer12 {
+       status = "disabled";
+};
index 298e85020e1b20bec89b8ecc52b38886e4656467..88c6a05cab415f3cb04cdec0fb2bc3c504ec8d7f 100644 (file)
                        0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)     /* i2c4_sda */
                >;
        };
-};
-
-&omap4_pmx_wkup {
-       led_wkgpio_pins: pinmux_leds_wkpins {
-               pinctrl-single,pins = <
-                       0x1a (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk7 */
-                       0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
-               >;
-       };
 
        /*
         * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP
                pinctrl-single,pins = <
                        0x38 (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs2.gpio_52 */
                        0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
-                       0x108 (PIN_OUTPUT | MUX_MODE0)          /* sdmmc5_clk.sdmmc5_clk */
+                       0x108 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_clk.sdmmc5_clk */
                        0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
                        0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
                        0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
        };
 };
 
+&omap4_pmx_wkup {
+       led_wkgpio_pins: pinmux_leds_wkpins {
+               pinctrl-single,pins = <
+                       0x1a (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk7 */
+                       0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
+               >;
+       };
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1_pins>;
index 5fc3f43c5a81d4c9256b063f31bb32fc544dde38..dbc81fb6ef033428ce6b02d7287b7efa46ebfa1e 100644 (file)
        wl12xx_pins: pinmux_wl12xx_pins {
                pinctrl-single,pins = <
                        0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
-                       0x108 (PIN_OUTPUT | MUX_MODE3)          /* sdmmc5_clk.sdmmc5_clk */
-                       0x10a (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_cmd.sdmmc5_cmd */
-                       0x10c (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat0.sdmmc5_dat0 */
-                       0x10e (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat1.sdmmc5_dat1 */
-                       0x110 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat2.sdmmc5_dat2 */
-                       0x112 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat3.sdmmc5_dat3 */
+                       0x108 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_clk.sdmmc5_clk */
+                       0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
+                       0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
+                       0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
+                       0x110 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat2.sdmmc5_dat2 */
+                       0x112 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat3.sdmmc5_dat3 */
                >;
        };
 };
index ee845fad939b895a1bfb907c6597f9f916d926f8..9987dd0e9c599929042b1ce70d4b1d6c3ec1ebfb 100644 (file)
@@ -87,9 +87,9 @@
                interrupts = <1 9 0xf04>;
        };
 
-       gpio0: gpio@ffc40000 {
+       gpio0: gpio@e6050000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc40000 0 0x2c>;
+               reg = <0 0xe6050000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 4 0x4>;
                #gpio-cells = <2>;
@@ -99,9 +99,9 @@
                interrupt-controller;
        };
 
-       gpio1: gpio@ffc41000 {
+       gpio1: gpio@e6051000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc41000 0 0x2c>;
+               reg = <0 0xe6051000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 5 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio2: gpio@ffc42000 {
+       gpio2: gpio@e6052000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc42000 0 0x2c>;
+               reg = <0 0xe6052000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 6 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio3: gpio@ffc43000 {
+       gpio3: gpio@e6053000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc43000 0 0x2c>;
+               reg = <0 0xe6053000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 7 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio4: gpio@ffc44000 {
+       gpio4: gpio@e6054000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc44000 0 0x2c>;
+               reg = <0 0xe6054000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 8 0x4>;
                #gpio-cells = <2>;
                interrupt-controller;
        };
 
-       gpio5: gpio@ffc45000 {
+       gpio5: gpio@e6055000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc45000 0 0x2c>;
+               reg = <0 0xe6055000 0 0x50>;
                interrupt-parent = <&gic>;
                interrupts = <0 9 0x4>;
                #gpio-cells = <2>;
 
        sdhi0: sdhi@ee100000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee100000 0 0x100>;
+               reg = <0 0xee100000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 165 4>;
                cap-sd-highspeed;
 
        sdhi1: sdhi@ee120000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee120000 0 0x100>;
+               reg = <0 0xee120000 0 0x200>;
                interrupt-parent = <&gic>;
                interrupts = <0 166 4>;
                cap-sd-highspeed;
index 6d09b8d42fdd123da5e3b5e4b315983c42f9c6eb..f936476c2753ff380ab7cfe04064fba2598d87c4 100644 (file)
 
                                        mpu_periph_clk: mpu_periph_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mpuclk>;
                                                fixed-divider = <4>;
                                        };
 
                                        mpu_l2_ram_clk: mpu_l2_ram_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mpuclk>;
                                                fixed-divider = <2>;
                                        };
 
                                        l3_main_clk: l3_main_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mainclk>;
+                                               fixed-divider = <1>;
                                        };
 
                                        l3_mp_clk: l3_mp_clk {
index 52476742a1043e5e9703505d03b2eae5d2a5bc1a..e674c94c720698e70b8a934ef5e560e4b725d0c7 100644 (file)
                        clock-frequency = <100000>;
                        status = "disabled";
                };
+
+               timer@01c60000 {
+                       compatible = "allwinner,sun5i-a13-hstimer";
+                       reg = <0x01c60000 0x1000>;
+                       interrupts = <82>, <83>;
+                       clocks = <&ahb_gates 28>;
+               };
        };
 };
index ce8ef2a45be098a35521db6d7fa41c472cd0b85a..1ccd75d37f49d4aeffbec39f0c518d62fd49b22b 100644 (file)
                        clock-frequency = <100000>;
                        status = "disabled";
                };
+
+               timer@01c60000 {
+                       compatible = "allwinner,sun5i-a13-hstimer";
+                       reg = <0x01c60000 0x1000>;
+                       interrupts = <82>, <83>;
+                       clocks = <&ahb_gates 28>;
+               };
        };
 };
index c1751a64889a615612101613d63145b15903bfc7..7f5878c2784ab28eff69c2a278dfa408fe70bc4d 100644 (file)
                pio: pinctrl@01c20800 {
                        compatible = "allwinner,sun6i-a31-pinctrl";
                        reg = <0x01c20800 0x400>;
-                       interrupts = <0 11 1>, <0 15 1>, <0 16 1>, <0 17 1>;
+                       interrupts = <0 11 4>,
+                                    <0 15 4>,
+                                    <0 16 4>,
+                                    <0 17 4>;
                        clocks = <&apb1_gates 5>;
                        gpio-controller;
                        interrupt-controller;
                timer@01c20c00 {
                        compatible = "allwinner,sun4i-timer";
                        reg = <0x01c20c00 0xa0>;
-                       interrupts = <0 18 1>,
-                                    <0 19 1>,
-                                    <0 20 1>,
-                                    <0 21 1>,
-                                    <0 22 1>;
+                       interrupts = <0 18 4>,
+                                    <0 19 4>,
+                                    <0 20 4>,
+                                    <0 21 4>,
+                                    <0 22 4>;
                        clocks = <&osc24M>;
                };
 
                uart0: serial@01c28000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28000 0x400>;
-                       interrupts = <0 0 1>;
+                       interrupts = <0 0 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 16>;
                uart1: serial@01c28400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
-                       interrupts = <0 1 1>;
+                       interrupts = <0 1 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 17>;
                uart2: serial@01c28800 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28800 0x400>;
-                       interrupts = <0 2 1>;
+                       interrupts = <0 2 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 18>;
                uart3: serial@01c28c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28c00 0x400>;
-                       interrupts = <0 3 1>;
+                       interrupts = <0 3 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 19>;
                uart4: serial@01c29000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29000 0x400>;
-                       interrupts = <0 4 1>;
+                       interrupts = <0 4 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 20>;
                uart5: serial@01c29400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29400 0x400>;
-                       interrupts = <0 5 1>;
+                       interrupts = <0 5 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb2_gates 21>;
index e46cfedde74c220b698c829458dfa40cef916159..0135039eff96440dfc5b2fbb7813a137bd51122d 100644 (file)
                emac: ethernet@01c0b000 {
                        compatible = "allwinner,sun4i-emac";
                        reg = <0x01c0b000 0x1000>;
-                       interrupts = <0 55 1>;
+                       interrupts = <0 55 4>;
                        clocks = <&ahb_gates 17>;
                        status = "disabled";
                };
                pio: pinctrl@01c20800 {
                        compatible = "allwinner,sun7i-a20-pinctrl";
                        reg = <0x01c20800 0x400>;
-                       interrupts = <0 28 1>;
+                       interrupts = <0 28 4>;
                        clocks = <&apb0_gates 5>;
                        gpio-controller;
                        interrupt-controller;
                timer@01c20c00 {
                        compatible = "allwinner,sun4i-timer";
                        reg = <0x01c20c00 0x90>;
-                       interrupts = <0 22 1>,
-                                    <0 23 1>,
-                                    <0 24 1>,
-                                    <0 25 1>,
-                                    <0 67 1>,
-                                    <0 68 1>;
+                       interrupts = <0 22 4>,
+                                    <0 23 4>,
+                                    <0 24 4>,
+                                    <0 25 4>,
+                                    <0 67 4>,
+                                    <0 68 4>;
                        clocks = <&osc24M>;
                };
 
                uart0: serial@01c28000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28000 0x400>;
-                       interrupts = <0 1 1>;
+                       interrupts = <0 1 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 16>;
                uart1: serial@01c28400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
-                       interrupts = <0 2 1>;
+                       interrupts = <0 2 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 17>;
                uart2: serial@01c28800 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28800 0x400>;
-                       interrupts = <0 3 1>;
+                       interrupts = <0 3 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 18>;
                uart3: serial@01c28c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28c00 0x400>;
-                       interrupts = <0 4 1>;
+                       interrupts = <0 4 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 19>;
                uart4: serial@01c29000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29000 0x400>;
-                       interrupts = <0 17 1>;
+                       interrupts = <0 17 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 20>;
                uart5: serial@01c29400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29400 0x400>;
-                       interrupts = <0 18 1>;
+                       interrupts = <0 18 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 21>;
                uart6: serial@01c29800 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29800 0x400>;
-                       interrupts = <0 19 1>;
+                       interrupts = <0 19 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 22>;
                uart7: serial@01c29c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c29c00 0x400>;
-                       interrupts = <0 20 1>;
+                       interrupts = <0 20 4>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clocks = <&apb1_gates 23>;
                i2c0: i2c@01c2ac00 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2ac00 0x400>;
-                       interrupts = <0 7 1>;
+                       interrupts = <0 7 4>;
                        clocks = <&apb1_gates 0>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c1: i2c@01c2b000 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2b000 0x400>;
-                       interrupts = <0 8 1>;
+                       interrupts = <0 8 4>;
                        clocks = <&apb1_gates 1>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c2: i2c@01c2b400 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2b400 0x400>;
-                       interrupts = <0 9 1>;
+                       interrupts = <0 9 4>;
                        clocks = <&apb1_gates 2>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c3: i2c@01c2b800 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2b800 0x400>;
-                       interrupts = <0 88 1>;
+                       interrupts = <0 88 4>;
                        clocks = <&apb1_gates 3>;
                        clock-frequency = <100000>;
                        status = "disabled";
                i2c4: i2c@01c2bc00 {
                        compatible = "allwinner,sun4i-i2c";
                        reg = <0x01c2bc00 0x400>;
-                       interrupts = <0 89 1>;
+                       interrupts = <0 89 4>;
                        clocks = <&apb1_gates 15>;
                        clock-frequency = <100000>;
                        status = "disabled";
                };
 
+               hstimer@01c60000 {
+                       compatible = "allwinner,sun7i-a20-hstimer";
+                       reg = <0x01c60000 0x1000>;
+                       interrupts = <0 81 1>,
+                                    <0 82 1>,
+                                    <0 83 1>,
+                                    <0 84 1>;
+                       clocks = <&ahb_gates 28>;
+               };
+
                gic: interrupt-controller@01c81000 {
                        compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
                        reg = <0x01c81000 0x1000>,
index 4a5903e048272429bf58d753419bddda18d2f586..c1df4e9db140831e45e5b91b2c280b1a1d813fef 100644 (file)
@@ -69,6 +69,7 @@ CONFIG_KS8851=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=y
 CONFIG_MDIO_SUN4I=y
+CONFIG_TI_CPSW=y
 CONFIG_KEYBOARD_SPEAR=y
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIAL_8250=y
@@ -133,12 +134,14 @@ CONFIG_USB_GPIO_VBUS=y
 CONFIG_USB_ISP1301=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_EDAC=y
index 98a50c309b90ad72b710fdeddc4117208fa6c29c..bfa80a11e8c76304c800f2df62090f1f50d089c1 100644 (file)
@@ -173,6 +173,7 @@ CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
index d57a85badb5ef49959ad5bc8049768330367a920..3e2259b60236d76af041a1a6eb3ef99cab7975a6 100644 (file)
@@ -12,6 +12,9 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
@@ -58,4 +61,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_COMMON_CLK_DEBUG=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS=y
+CONFIG_PRINTK_TIME=y
index ac632cc38f249767bcedfc1232a4e4b8e6bc70d9..c6ebc184bf68201c69a0791ed83f0bbfc64b4348 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_IDLE=y
+CONFIG_ARM_U8500_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_PM_RUNTIME=y
@@ -109,6 +110,8 @@ CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_MISC_FILESYSTEMS is not set
index 64205d453260d12ec1e2d43c424fab1c3251788a..71e5fc7cfb18f489f3adadb20c6f8049421fb079 100644 (file)
@@ -58,7 +58,7 @@
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index f3d96d9325737fba399dc5e6613d223e03fcb7a1..be068db960ee0006ac1aa25a4e69b95265404844 100644 (file)
@@ -701,7 +701,7 @@ $code.=<<___;
 # define VFP_ABI_FRAME 0
 # define BSAES_ASM_EXTENDED_KEY
 # define XTS_CHAIN_TWEAK
-# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+# define __ARM_ARCH__  7
 #endif
 
 #ifdef __thumb__
index 60f15e274e6d461814eb467cc84dc8b0f0395163..2f59f74433964016003167007badbeffcbba465a 100644 (file)
 #define smp_wmb()      dmb(ishst)
 #endif
 
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ___p1;                                                          \
+})
+
 #define read_barrier_depends()         do { } while(0)
 #define smp_read_barrier_depends()     do { } while(0)
 
index 3c597c222ef278a8eb170a4169b5e54dcc158ac0..fbeb39c869e9fdcedace1d61688247c14141cab3 100644 (file)
@@ -329,7 +329,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  */
 #define ioremap(cookie,size)           __arm_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_cache(cookie,size)     __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)                __arm_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap                                __arm_iounmap
 
index 9ecccc865046a2c257277cd03a8f607ed5e0217d..8756e4bcdba0609ff789a4f1efaa551faa39ed98 100644 (file)
 #define TASK_UNMAPPED_BASE     UL(0x00000000)
 #endif
 
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET            UL(CONFIG_DRAM_BASE)
-#endif
-
 #ifndef END_MEM
 #define END_MEM                (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
 #endif
 
 #ifndef PAGE_OFFSET
-#define PAGE_OFFSET            (PHYS_OFFSET)
+#define PAGE_OFFSET            PLAT_PHYS_OFFSET
 #endif
 
 /*
  * The module can be at any place in ram in nommu mode.
  */
 #define MODULES_END            (END_MEM)
-#define MODULES_VADDR          (PHYS_OFFSET)
+#define MODULES_VADDR          PAGE_OFFSET
 
 #define XIP_VIRT_ADDR(physaddr)  (physaddr)
 
 #endif
 #define ARCH_PGD_MASK          ((1 << ARCH_PGD_SHIFT) - 1)
 
+/*
+ * PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
+ * memory.  This is used for XIP and NoMMU kernels, or by kernels which
+ * have their own mach/memory.h.  Assembly code must always use
+ * PLAT_PHYS_OFFSET and not PHYS_OFFSET.
+ */
+#ifndef PLAT_PHYS_OFFSET
+#define PLAT_PHYS_OFFSET       UL(CONFIG_PHYS_OFFSET)
+#endif
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -239,6 +245,8 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
 
 #else
 
+#define PHYS_OFFSET    PLAT_PHYS_OFFSET
+
 static inline phys_addr_t __virt_to_phys(unsigned long x)
 {
        return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET;
@@ -251,17 +259,6 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
 
 #endif
 #endif
-#endif /* __ASSEMBLY__ */
-
-#ifndef PHYS_OFFSET
-#ifdef PLAT_PHYS_OFFSET
-#define PHYS_OFFSET    PLAT_PHYS_OFFSET
-#else
-#define PHYS_OFFSET    UL(CONFIG_PHYS_OFFSET)
-#endif
-#endif
-
-#ifndef __ASSEMBLY__
 
 /*
  * PFNs are used to describe any physical page; this means
@@ -350,7 +347,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
 #define ARCH_PFN_OFFSET                PHYS_PFN_OFFSET
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+#define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \
+                                       && pfn_valid(__pa(kaddr) >> PAGE_SHIFT) )
 
 #endif
 
index be956dbf6baea3a7481baa11c58233d0741702d1..1571d126e9ddb08b77c99955538209212755ebfd 100644 (file)
@@ -61,7 +61,7 @@ extern void __pgd_error(const char *file, int line, pgd_t);
  * mapping to be mapped at.  This is particularly important for
  * non-high vector CPUs.
  */
-#define FIRST_USER_ADDRESS     PAGE_SIZE
+#define FIRST_USER_ADDRESS     (PAGE_SIZE * 2)
 
 /*
  * Use TASK_SIZE as the ceiling argument for free_pgtables() and
index 141baa3f9a72d1d931da67c30c600fa85bc4bfc5..acabef1a75df00637def7a94af9f1425d281b7f0 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <uapi/asm/unistd.h>
 
-#define __NR_syscalls  (380)
+#define __NR_syscalls  (384)
 #define __ARM_NR_cmpxchg               (__ARM_NR_BASE+0x00fff0)
 
 #define __ARCH_WANT_STAT64
index 75579a9d6f76cba3cc84ad61d01ed103269378bd..3759cacdd7f8601322b98ffed6598d97ee8bd016 100644 (file)
@@ -117,6 +117,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
        return __set_phys_to_machine(pfn, mfn);
 }
 
-#define xen_remap(cookie, size) ioremap_cached((cookie), (size));
+#define xen_remap(cookie, size) ioremap_cache((cookie), (size));
 
 #endif /* _ASM_ARM_XEN_PAGE_H */
index af33b44990ed4a395662f0c5e7021049e5755a78..fb5584d0cc050a6c55b30ff8342615a5a39a1c2f 100644 (file)
 #define __NR_process_vm_writev         (__NR_SYSCALL_BASE+377)
 #define __NR_kcmp                      (__NR_SYSCALL_BASE+378)
 #define __NR_finit_module              (__NR_SYSCALL_BASE+379)
+#define __NR_sched_setattr             (__NR_SYSCALL_BASE+380)
+#define __NR_sched_getattr             (__NR_SYSCALL_BASE+381)
 
 /*
  * This may need to be greater than __NR_last_syscall+1 in order to
index c6ca7e376773fcc73ef619e1c5a97793d97b41b4..166e945de832f22b603d6b0de2ca3eb92f2ec732 100644 (file)
                CALL(sys_process_vm_writev)
                CALL(sys_kcmp)
                CALL(sys_finit_module)
+/* 380 */      CALL(sys_sched_setattr)
+               CALL(sys_sched_getattr)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 739c3dfc1da25c6145268809459c567aa80e543f..34d5fd585bbb1d472015838c2665dea5aad376f7 100644 (file)
@@ -171,7 +171,7 @@ void __init arm_dt_init_cpu_maps(void)
 
 bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
 {
-       return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
+       return phys_id == cpu_logical_map(cpu);
 }
 
 static const void * __init arch_get_next_mach(const char *const **match)
index 14235ba64a90736ecebad575f5d88ea4568e8eaf..716249cc2ee18c178643e7e6c4a0cd0eb6a48c00 100644 (file)
@@ -68,7 +68,7 @@ ENTRY(stext)
 
 #ifdef CONFIG_ARM_MPU
        /* Calculate the size of a region covering just the kernel */
-       ldr     r5, =PHYS_OFFSET                @ Region start: PHYS_OFFSET
+       ldr     r5, =PLAT_PHYS_OFFSET           @ Region start: PHYS_OFFSET
        ldr     r6, =(_end)                     @ Cover whole kernel
        sub     r6, r6, r5                      @ Minimum size of region to map
        clz     r6, r6                          @ Region size must be 2^N...
@@ -213,7 +213,7 @@ ENTRY(__setup_mpu)
        set_region_nr r0, #MPU_RAM_REGION
        isb
        /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
-       ldr     r0, =PHYS_OFFSET                @ RAM starts at PHYS_OFFSET
+       ldr     r0, =PLAT_PHYS_OFFSET           @ RAM starts at PHYS_OFFSET
        ldr     r5,=(MPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL)
 
        setup_region r0, r5, r6, MPU_DATA_SIDE  @ PHYS_OFFSET, shared, enabled
index 11d59b32fb8dca45613ed00fb225a72359c19216..32f317e5828adafc2bdec200705a9d12c686711c 100644 (file)
@@ -110,7 +110,7 @@ ENTRY(stext)
        sub     r4, r3, r4                      @ (PHYS_OFFSET - PAGE_OFFSET)
        add     r8, r8, r4                      @ PHYS_OFFSET
 #else
-       ldr     r8, =PHYS_OFFSET                @ always constant in this case
+       ldr     r8, =PLAT_PHYS_OFFSET           @ always constant in this case
 #endif
 
        /*
index 57221e349a7ce0eec03445cd56de2845e5d23358..f0d180d8b29f4e22558a98fdf9366ebaf1c0c0cb 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
+#include <asm/fncpy.h>
 #include <asm/mach-types.h>
 #include <asm/smp_plat.h>
 #include <asm/system_misc.h>
 
-extern const unsigned char relocate_new_kernel[];
+extern void relocate_new_kernel(void);
 extern const unsigned int relocate_new_kernel_size;
 
 extern unsigned long kexec_start_address;
@@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image)
 {
        unsigned long page_list;
        unsigned long reboot_code_buffer_phys;
+       unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
+       unsigned long reboot_entry_phys;
        void *reboot_code_buffer;
 
        /*
@@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image)
 
 
        /* copy our kernel relocation code to the control code page */
-       memcpy(reboot_code_buffer,
-              relocate_new_kernel, relocate_new_kernel_size);
+       reboot_entry = fncpy(reboot_code_buffer,
+                            reboot_entry,
+                            relocate_new_kernel_size);
+       reboot_entry_phys = (unsigned long)reboot_entry +
+               (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);
 
-
-       flush_icache_range((unsigned long) reboot_code_buffer,
-                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
 
        if (kexec_reinit)
                kexec_reinit();
 
-       soft_restart(reboot_code_buffer_phys);
+       soft_restart(reboot_entry_phys);
 }
index bc3f2efa0d86b4ff55d6b19833eae688b111fd27..789d846a9184531a1c9c05cc97a54966101a13e2 100644 (file)
@@ -99,10 +99,6 @@ int armpmu_event_set_period(struct perf_event *event)
        s64 period = hwc->sample_period;
        int ret = 0;
 
-       /* The period may have been changed by PERF_EVENT_IOC_PERIOD */
-       if (unlikely(period != hwc->last_period))
-               left = period - (hwc->last_period - left);
-
        if (unlikely(left <= -period)) {
                left = period;
                local64_set(&hwc->period_left, left);
index d85055cd24bacc55cde9e99f1547afbfe33317ae..20d553c9f5e2928a0c4321878a30520dde87656d 100644 (file)
@@ -254,7 +254,7 @@ static int probe_current_pmu(struct arm_pmu *pmu)
 static int cpu_pmu_device_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id;
-       int (*init_fn)(struct arm_pmu *);
+       const int (*init_fn)(struct arm_pmu *);
        struct device_node *node = pdev->dev.of_node;
        struct arm_pmu *pmu;
        int ret = -ENODEV;
index 94f6b05f9e24e8cd1d79063f03a9b2dd16791c67..92f7b15dd22121d4aa674fd78cd95cac8924c07f 100644 (file)
@@ -404,6 +404,7 @@ EXPORT_SYMBOL(dump_fpu);
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
+       unsigned long stack_page;
        int count = 0;
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
@@ -412,9 +413,11 @@ unsigned long get_wchan(struct task_struct *p)
        frame.sp = thread_saved_sp(p);
        frame.lr = 0;                   /* recovered from the stack */
        frame.pc = thread_saved_pc(p);
+       stack_page = (unsigned long)task_stack_page(p);
        do {
-               int ret = unwind_frame(&frame);
-               if (ret < 0)
+               if (frame.sp < stack_page ||
+                   frame.sp >= stack_page + THREAD_SIZE ||
+                   unwind_frame(&frame) < 0)
                        return 0;
                if (!in_sched_functions(frame.pc))
                        return frame.pc;
index d0cdedf4864dc52092355e105f3ba04bba5c5704..95858966d84ec0f10d392a3356cb0367fcee0b85 100644 (file)
@@ -2,10 +2,12 @@
  * relocate_kernel.S - put the kernel image in place to boot
  */
 
+#include <linux/linkage.h>
 #include <asm/kexec.h>
 
-       .globl relocate_new_kernel
-relocate_new_kernel:
+       .align  3       /* not needed for this code, but keeps fncpy() happy */
+
+ENTRY(relocate_new_kernel)
 
        ldr     r0,kexec_indirection_page
        ldr     r1,kexec_start_address
@@ -79,6 +81,8 @@ kexec_mach_type:
 kexec_boot_atags:
        .long   0x0
 
+ENDPROC(relocate_new_kernel)
+
 relocate_new_kernel_end:
 
        .globl relocate_new_kernel_size
index 6a1b8a81b1ae448168572a9558aaf026f9e7e47e..987a7f5bce5f1759d73c01a80099cea57a94025d 100644 (file)
@@ -873,8 +873,6 @@ void __init setup_arch(char **cmdline_p)
        machine_desc = mdesc;
        machine_name = mdesc->name;
 
-       setup_dma_zone(mdesc);
-
        if (mdesc->reboot_mode != REBOOT_HARD)
                reboot_mode = mdesc->reboot_mode;
 
@@ -892,6 +890,7 @@ void __init setup_arch(char **cmdline_p)
        sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
 
        early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
+       setup_dma_zone(mdesc);
        sanity_check_meminfo();
        arm_memblock_init(&meminfo, mdesc);
 
index 3c5d0f2170fd7ee309260c2d2c0a6108a24e54f8..b84d0cb13682ccd42e41a22894cb8d2c1821496d 100644 (file)
  * snippets.
  */
 
+/*
+ * In CPU_THUMBONLY case kernel arm opcodes are not allowed.
+ * Note in this case codes skips those instructions but it uses .org
+ * directive to keep correct layout of sigreturn_codes array.
+ */
+#ifndef CONFIG_CPU_THUMBONLY
+#define ARM_OK(code...)        code
+#else
+#define ARM_OK(code...)
+#endif
+
+       .macro arm_slot n
+       .org    sigreturn_codes + 12 * (\n)
+ARM_OK(        .arm    )
+       .endm
+
+       .macro thumb_slot n
+       .org    sigreturn_codes + 12 * (\n) + 8
+       .thumb
+       .endm
+
 #if __LINUX_ARM_ARCH__ <= 4
        /*
         * Note we manually set minimally required arch that supports
        .global sigreturn_codes
        .type   sigreturn_codes, #object
 
-       .arm
+       .align
 
 sigreturn_codes:
 
        /* ARM sigreturn syscall code snippet */
-       mov     r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
-       swi     #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)
+       arm_slot 0
+ARM_OK(        mov     r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)       )
+ARM_OK(        swi     #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)      )
 
        /* Thumb sigreturn syscall code snippet */
-       .thumb
+       thumb_slot 0
        movs    r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
        swi     #0
 
        /* ARM sigreturn_rt syscall code snippet */
-       .arm
-       mov     r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
-       swi     #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)
+       arm_slot 1
+ARM_OK(        mov     r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)    )
+ARM_OK(        swi     #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)   )
 
        /* Thumb sigreturn_rt syscall code snippet */
-       .thumb
+       thumb_slot 1
        movs    r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
        swi     #0
 
@@ -74,7 +96,7 @@ sigreturn_codes:
         * it is thumb case or not, so we need additional
         * word after real last entry.
         */
-       .arm
+       arm_slot 2
        .space  4
 
        .size   sigreturn_codes, . - sigreturn_codes
index 00f79e59985bccaf54bd3b1c8f2e292f49014a47..af4e8c8a5422c4383396f7f4b3a836a67426b7de 100644 (file)
@@ -31,7 +31,7 @@ int notrace unwind_frame(struct stackframe *frame)
        high = ALIGN(low, THREAD_SIZE);
 
        /* check current frame pointer is within bounds */
-       if (fp < (low + 12) || fp + 4 >= high)
+       if (fp < low + 12 || fp > high - 4)
                return -EINVAL;
 
        /* restore the registers from the stack frame */
index dbf0923e8d76bda9392b902e0c8e500025d70402..4636d56af2db63f64703b7417a551d78dffecbe0 100644 (file)
 #include <asm/system_misc.h>
 #include <asm/opcodes.h>
 
-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+static const char *handler[]= {
+       "prefetch abort",
+       "data abort",
+       "address exception",
+       "interrupt",
+       "undefined instruction",
+};
 
 void *vectors_page;
 
@@ -425,9 +431,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
                        instr2 = __mem_to_opcode_thumb16(instr2);
                        instr = __opcode_thumb32_compose(instr, instr2);
                }
-       } else if (get_user(instr, (u32 __user *)pc)) {
+       } else {
+               if (get_user(instr, (u32 __user *)pc))
+                       goto die_sig;
                instr = __mem_to_opcode_arm(instr);
-               goto die_sig;
        }
 
        if (call_undef_hook(regs, instr) == 0)
@@ -509,9 +516,10 @@ static inline int
 __do_cache_op(unsigned long start, unsigned long end)
 {
        int ret;
-       unsigned long chunk = PAGE_SIZE;
 
        do {
+               unsigned long chunk = min(PAGE_SIZE, end - start);
+
                if (signal_pending(current)) {
                        struct thread_info *ti = current_thread_info();
 
index 36b668d8e121ee7450c8beffb5e9661923102038..bc1033b897b44510b16a8ab202f0c1b989cc15e5 100644 (file)
@@ -40,6 +40,7 @@ ENTRY(__loop_const_udelay)                    @ 0 <= r0 <= 0x7fffff06
 /*
  * loops = r0 * HZ * loops_per_jiffy / 1000000
  */
+               .align 3
 
 @ Delay routine
 ENTRY(__loop_delay)
index f607deb40f4da6a88a0778b203cdcfbbc8518ecc..bc7b363a3083bfdab31591786fe38991c199e2dc 100644 (file)
@@ -174,7 +174,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 static struct clock_event_device clkevt = {
        .name           = "at91_tick",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 150,
        .set_next_event = clkevt32k_next_event,
        .set_mode       = clkevt32k_mode,
@@ -265,11 +264,9 @@ void __init at91rm9200_timer_init(void)
        at91_st_write(AT91_ST_RTMR, 1);
 
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
-       clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
-       clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
-       clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
        clkevt.cpumask = cpumask_of(0);
-       clockevents_register_device(&clkevt);
+       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
+                                       2, AT91_ST_ALMV);
 
        /* register clocksource */
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
index 3ed190ce062bd5add5a426e07b1cf6c5d1e5b89a..c5101dcb4fb04d8d9af68bea524043feb3c289a9 100644 (file)
 #include <mach/at91_ramc.h>
 #include <mach/at91rm9200_sdramc.h>
 
+#ifdef CONFIG_PM
 extern void at91_pm_set_standby(void (*at91_standby)(void));
+#else
+static inline void at91_pm_set_standby(void (*at91_standby)(void)) { }
+#endif
 
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
index 3ea86428ee0964f11d0955a90d0348626e68da58..a28873fe30491334e9feaad188901bea37d34d24 100644 (file)
@@ -95,19 +95,19 @@ static struct clk twi0_clk = {
        .name           = "twi0_clk",
        .pid            = SAMA5D3_ID_TWI0,
        .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
+       .div            = AT91_PMC_PCR_DIV8,
 };
 static struct clk twi1_clk = {
        .name           = "twi1_clk",
        .pid            = SAMA5D3_ID_TWI1,
        .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
+       .div            = AT91_PMC_PCR_DIV8,
 };
 static struct clk twi2_clk = {
        .name           = "twi2_clk",
        .pid            = SAMA5D3_ID_TWI2,
        .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
+       .div            = AT91_PMC_PCR_DIV8,
 };
 static struct clk mmc0_clk = {
        .name           = "mci0_clk",
index c46eccbbd51226f5ae6ab5a16e1c89668c35fa1d..78829c513fdc354bce631d67f45922efff84368d 100644 (file)
@@ -487,7 +487,7 @@ int __init da8xx_register_emac(void)
 
 static struct resource da830_mcasp1_resources[] = {
        {
-               .name   = "mcasp1",
+               .name   = "mpu",
                .start  = DAVINCI_DA830_MCASP1_REG_BASE,
                .end    = DAVINCI_DA830_MCASP1_REG_BASE + (SZ_1K * 12) - 1,
                .flags  = IORESOURCE_MEM,
@@ -515,7 +515,7 @@ static struct platform_device da830_mcasp1_device = {
 
 static struct resource da850_mcasp_resources[] = {
        {
-               .name   = "mcasp",
+               .name   = "mpu",
                .start  = DAVINCI_DA8XX_MCASP0_REG_BASE,
                .end    = DAVINCI_DA8XX_MCASP0_REG_BASE + (SZ_1K * 12) - 1,
                .flags  = IORESOURCE_MEM,
index ef9ff1fb6f52a2533378ba37563c06e877b32ea3..6117fc644188d9aa81c2397dbb60538db190beea 100644 (file)
@@ -641,6 +641,7 @@ static struct platform_device dm355_edma_device = {
 
 static struct resource dm355_asp1_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_ASP1_BASE,
                .end    = DAVINCI_ASP1_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
@@ -906,7 +907,7 @@ static struct davinci_gpio_platform_data dm355_gpio_platform_data = {
 int __init dm355_gpio_register(void)
 {
        return davinci_gpio_register(dm355_gpio_resources,
-                                    sizeof(dm355_gpio_resources),
+                                    ARRAY_SIZE(dm355_gpio_resources),
                                     &dm355_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 1511a0680f9a1d399cf3094b538c3c52caa06547..d7c6f85d3fc9d5c4347ec214ae8e71a310f89b62 100644 (file)
@@ -720,7 +720,7 @@ static struct davinci_gpio_platform_data dm365_gpio_platform_data = {
 int __init dm365_gpio_register(void)
 {
        return davinci_gpio_register(dm365_gpio_resources,
-                                    sizeof(dm365_gpio_resources),
+                                    ARRAY_SIZE(dm365_gpio_resources),
                                     &dm365_gpio_platform_data);
 }
 
@@ -942,6 +942,7 @@ static struct platform_device dm365_edma_device = {
 
 static struct resource dm365_asp_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_DM365_ASP0_BASE,
                .end    = DAVINCI_DM365_ASP0_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
index 143a3217e8efb8fde1aa417700c45840d242aac0..3ce47997bb46150e82f40e718474feeae52b6d5e 100644 (file)
@@ -572,6 +572,7 @@ static struct platform_device dm644x_edma_device = {
 /* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
 static struct resource dm644x_asp_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_ASP0_BASE,
                .end    = DAVINCI_ASP0_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
@@ -792,7 +793,7 @@ static struct davinci_gpio_platform_data dm644_gpio_platform_data = {
 int __init dm644x_gpio_register(void)
 {
        return davinci_gpio_register(dm644_gpio_resources,
-                                    sizeof(dm644_gpio_resources),
+                                    ARRAY_SIZE(dm644_gpio_resources),
                                     &dm644_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 2a73f299c1d094615236359d6ac27959cdd16295..0e81fea65e7fb484cda893f0a4cd91d0b74fc0ad 100644 (file)
@@ -621,7 +621,7 @@ static struct platform_device dm646x_edma_device = {
 
 static struct resource dm646x_mcasp0_resources[] = {
        {
-               .name   = "mcasp0",
+               .name   = "mpu",
                .start  = DAVINCI_DM646X_MCASP0_REG_BASE,
                .end    = DAVINCI_DM646X_MCASP0_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
@@ -641,7 +641,7 @@ static struct resource dm646x_mcasp0_resources[] = {
 
 static struct resource dm646x_mcasp1_resources[] = {
        {
-               .name   = "mcasp1",
+               .name   = "mpu",
                .start  = DAVINCI_DM646X_MCASP1_REG_BASE,
                .end    = DAVINCI_DM646X_MCASP1_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
@@ -769,7 +769,7 @@ static struct davinci_gpio_platform_data dm646x_gpio_platform_data = {
 int __init dm646x_gpio_register(void)
 {
        return davinci_gpio_register(dm646x_gpio_resources,
-                                    sizeof(dm646x_gpio_resources),
+                                    ARRAY_SIZE(dm646x_gpio_resources),
                                     &dm646x_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 2739ca2c13346f1ed4bdce26916ae4e2270900ad..e0091685fd4861c8eb6f41b00c5f316865c1668b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <video/vga.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -196,6 +197,8 @@ void __init footbridge_map_io(void)
                iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
                pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
        }
+
+       vga_base = PCIMEM_BASE;
 }
 
 void footbridge_restart(enum reboot_mode mode, const char *cmd)
index 9ee78f7b4990751386cf7f29337ec075297349dd..782f6c71fa0a6c761269cfc4b74fc6cdd0839e75 100644 (file)
@@ -96,11 +96,12 @@ static struct irqaction footbridge_timer_irq = {
 void __init footbridge_timer_init(void)
 {
        struct clock_event_device *ce = &ckevt_dc21285;
+       unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
 
-       clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
+       clocksource_register_hz(&cksrc_dc21285, rate);
 
        setup_irq(ce->irq, &footbridge_timer_irq);
 
        ce->cpumask = cpumask_of(smp_processor_id());
-       clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
+       clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
 }
index 3490a24f969e4a0b450ef146cee72f37e1cb6c9f..7c2fdae9a38b63454523277a005dcf6c5c1c65ab 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
-#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
@@ -291,7 +290,6 @@ void __init dc21285_preinit(void)
        int cfn_mode;
 
        pcibios_min_mem = 0x81000000;
-       vga_base = PCIMEM_BASE;
 
        mem_size = (unsigned int)high_memory - PAGE_OFFSET;
        for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
index b08243500e2e9bc8f7196d6e6c5484b3ba7dadb4..1a7235fb52acb3cb8ae784dbeeda4fb3c940594a 100644 (file)
@@ -30,21 +30,24 @@ static const struct {
        const char *name;
        const char *trigger;
 } ebsa285_leds[] = {
-       { "ebsa285:amber", "heartbeat", },
-       { "ebsa285:green", "cpu0", },
+       { "ebsa285:amber", "cpu0", },
+       { "ebsa285:green", "heartbeat", },
        { "ebsa285:red",},
 };
 
+static unsigned char hw_led_state;
+
 static void ebsa285_led_set(struct led_classdev *cdev,
                enum led_brightness b)
 {
        struct ebsa285_led *led = container_of(cdev,
                        struct ebsa285_led, cdev);
 
-       if (b != LED_OFF)
-               *XBUS_LEDS |= led->mask;
+       if (b == LED_OFF)
+               hw_led_state |= led->mask;
        else
-               *XBUS_LEDS &= ~led->mask;
+               hw_led_state &= ~led->mask;
+       *XBUS_LEDS = hw_led_state;
 }
 
 static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
@@ -52,18 +55,19 @@ static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
        struct ebsa285_led *led = container_of(cdev,
                        struct ebsa285_led, cdev);
 
-       return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF;
+       return hw_led_state & led->mask ? LED_OFF : LED_FULL;
 }
 
 static int __init ebsa285_leds_init(void)
 {
        int i;
 
-       if (machine_is_ebsa285())
+       if (!machine_is_ebsa285())
                return -ENODEV;
 
-       /* 3 LEDS All ON */
-       *XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+       /* 3 LEDS all off */
+       hw_led_state = XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+       *XBUS_LEDS = hw_led_state;
 
        for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
                struct ebsa285_led *led;
index b3d7e5634b83cb02ce568040099027007820a45b..c7de89b263dd3b3e8e69e554b00b9af7d8079aee 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
+#include <linux/input.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
+#include <linux/mailbox.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
+#include <linux/reboot.h>
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
 
@@ -50,6 +53,7 @@ static void __init highbank_scu_map_io(void)
 
 static void highbank_l2x0_disable(void)
 {
+       outer_flush_all();
        /* Disable PL310 L2 Cache controller */
        highbank_smc1(0x102, 0x0);
 }
@@ -130,6 +134,24 @@ static struct platform_device highbank_cpuidle_device = {
        .name = "cpuidle-calxeda",
 };
 
+static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data)
+{
+       u32 key = *(u32 *)data;
+
+       if (event != 0x1000)
+               return 0;
+
+       if (key == KEY_POWER)
+               orderly_poweroff(false);
+       else if (key == 0xffff)
+               ctrl_alt_del();
+
+       return 0;
+}
+static struct notifier_block hb_keys_nb = {
+       .notifier_call = hb_keys_notifier,
+};
+
 static void __init highbank_init(void)
 {
        struct device_node *np;
@@ -145,6 +167,8 @@ static void __init highbank_init(void)
        bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
        bus_register_notifier(&amba_bustype, &highbank_amba_nb);
 
+       pl320_ipc_register_notifier(&hb_keys_nb);
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        if (psci_ops.cpu_suspend)
index 19f1652e94cfbf5e1f09d2d4cc27e44087cc68d7..8d972ff18c561111317aa96d61c0b9fda2d8cade 100644 (file)
@@ -131,6 +131,24 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
        .dt_compat      = omap3_gp_boards_compat,
        .restart        = omap3xxx_restart,
 MACHINE_END
+
+static const char *am3517_boards_compat[] __initdata = {
+       "ti,am3517",
+       NULL,
+};
+
+DT_MACHINE_START(AM3517_DT, "Generic AM3517 (Flattened Device Tree)")
+       .reserve        = omap_reserve,
+       .map_io         = omap3_map_io,
+       .init_early     = am35xx_init_early,
+       .init_irq       = omap_intc_of_init,
+       .handle_irq     = omap3_intc_handle_irq,
+       .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
+       .init_time      = omap3_gptimer_timer_init,
+       .dt_compat      = am3517_boards_compat,
+       .restart        = omap3xxx_restart,
+MACHINE_END
 #endif
 
 #ifdef CONFIG_SOC_AM33XX
index 4ec8d82b0492f3e66e75bec0aa7cff8cd25a5faa..44a59c3abfb0535e8c9168284a5bf67ed0f13bb6 100644 (file)
@@ -242,12 +242,18 @@ static void __init ldp_display_init(void)
 
 static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 {
+       int res;
+
        /* LCD enable GPIO */
        ldp_lcd_pdata.enable_gpio = gpio + 7;
 
        /* Backlight enable GPIO */
        ldp_lcd_pdata.backlight_gpio = gpio + 15;
 
+       res = platform_device_register(&ldp_lcd_device);
+       if (res)
+               pr_err("Unable to register LCD: %d\n", res);
+
        return 0;
 }
 
@@ -346,7 +352,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 
 static struct platform_device *ldp_devices[] __initdata = {
        &ldp_gpio_keys_device,
-       &ldp_lcd_device,
 };
 
 #ifdef CONFIG_OMAP_MUX
index 58347bb874a01dcd4d203f4f191712d473a338a3..4cf165502b35cfdd06c09696a20b09758d974169 100644 (file)
@@ -101,13 +101,51 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
+{
+       u32 enable_mask, enable_shift;
+       u32 pipd_mask, pipd_shift;
+       u32 reg;
+
+       if (dsi_id == 0) {
+               enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI1_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI1_PIPD_MASK;
+               pipd_shift = OMAP4_DSI1_PIPD_SHIFT;
+       } else if (dsi_id == 1) {
+               enable_mask = OMAP4_DSI2_LANEENABLE_MASK;
+               enable_shift = OMAP4_DSI2_LANEENABLE_SHIFT;
+               pipd_mask = OMAP4_DSI2_PIPD_MASK;
+               pipd_shift = OMAP4_DSI2_PIPD_SHIFT;
+       } else {
+               return -ENODEV;
+       }
+
+       reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       reg &= ~enable_mask;
+       reg &= ~pipd_mask;
+
+       reg |= (lanes << enable_shift) & enable_mask;
+       reg |= (lanes << pipd_shift) & pipd_mask;
+
+       omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+
+       return 0;
+}
+
 static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
+       if (cpu_is_omap44xx())
+               return omap4_dsi_mux_pads(dsi_id, lane_mask);
+
        return 0;
 }
 
 static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
+       if (cpu_is_omap44xx())
+               omap4_dsi_mux_pads(dsi_id, 0);
 }
 
 static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
index 365bfd3d9c68b8486f23049a71889484c60eb793..dadccc91488c64e94c06e9bf93b54bc5c294e26e 100644 (file)
@@ -223,7 +223,7 @@ void __init omap_4430sdp_display_init_of(void)
 static struct connector_dvi_platform_data omap3_igep2_dvi_connector_pdata = {
        .name                   = "dvi",
        .source                 = "tfp410.0",
-       .i2c_bus_num            = 3,
+       .i2c_bus_num            = 2,
 };
 
 static struct platform_device omap3_igep2_dvi_connector_device = {
index b39efd46abf991827169a6c17a6aa91f3dfeb39f..c0ab9b26be3da9f0c50630cfacf5b371467fd015 100644 (file)
@@ -162,6 +162,7 @@ void __iomem *omap4_get_l2cache_base(void)
 
 static void omap4_l2x0_disable(void)
 {
+       outer_flush_all();
        /* Disable PL310 L2 Cache controller */
        omap_smc1(0x102, 0x0);
 }
index 53f0735817bb7cf984f3fada24c7e8960941860c..e0a398cf28d80a409e25055c19ad44baef25d7fc 100644 (file)
@@ -183,6 +183,10 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 odbfd_exit1:
        kfree(hwmods);
 odbfd_exit:
+       /* if data/we are at fault.. load up a fail handler */
+       if (ret)
+               pdev->dev.pm_domain = &omap_device_fail_pm_domain;
+
        return ret;
 }
 
@@ -604,6 +608,19 @@ static int _od_runtime_resume(struct device *dev)
 
        return pm_generic_runtime_resume(dev);
 }
+
+static int _od_fail_runtime_suspend(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
+static int _od_fail_runtime_resume(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
 #endif
 
 #ifdef CONFIG_SUSPEND
@@ -657,6 +674,13 @@ static int _od_resume_noirq(struct device *dev)
 #define _od_resume_noirq NULL
 #endif
 
+struct dev_pm_domain omap_device_fail_pm_domain = {
+       .ops = {
+               SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
+                                  _od_fail_runtime_resume, NULL)
+       }
+};
+
 struct dev_pm_domain omap_device_pm_domain = {
        .ops = {
                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
index 17ca1aec271033d7551c2ffd4cf22fd0c4724fb2..78c02b355179894126f5e2e75f835fc1d753060a 100644 (file)
@@ -29,6 +29,7 @@
 #include "omap_hwmod.h"
 
 extern struct dev_pm_domain omap_device_pm_domain;
+extern struct dev_pm_domain omap_device_fail_pm_domain;
 
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN      0
index e3f0ecaf87dd76c3b075c389173ac89faff04a6a..8a1b5e0bad40df2adbab8b202e0dd87602fe7921 100644 (file)
@@ -399,7 +399,7 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
 }
 
 /**
- * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
+ * _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v
  * @oh: struct omap_hwmod *
  * @v: pointer to register contents to modify
  *
@@ -426,6 +426,36 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v
+ * @oh: struct omap_hwmod *
+ * @v: pointer to register contents to modify
+ *
+ * Clear the SOFTRESET bit in @v for hwmod @oh.  Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int _clear_softreset(struct omap_hwmod *oh, u32 *v)
+{
+       u32 softrst_mask;
+
+       if (!oh->class->sysc ||
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
+               return -EINVAL;
+
+       if (!oh->class->sysc->sysc_fields) {
+               WARN(1,
+                    "omap_hwmod: %s: sysc_fields absent for sysconfig class\n",
+                    oh->name);
+               return -EINVAL;
+       }
+
+       softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
+
+       *v &= ~softrst_mask;
+
+       return 0;
+}
+
 /**
  * _wait_softreset_complete - wait for an OCP softreset to complete
  * @oh: struct omap_hwmod * to wait on
@@ -785,6 +815,7 @@ static int _init_interface_clks(struct omap_hwmod *oh)
                        pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
                                   oh->name, os->clk);
                        ret = -EINVAL;
+                       continue;
                }
                os->_clk = c;
                /*
@@ -821,6 +852,7 @@ static int _init_opt_clks(struct omap_hwmod *oh)
                        pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
                                   oh->name, oc->clk);
                        ret = -EINVAL;
+                       continue;
                }
                oc->_clk = c;
                /*
@@ -1911,6 +1943,12 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        ret = _set_softreset(oh, &v);
        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)
@@ -2326,38 +2364,80 @@ static int _shutdown(struct omap_hwmod *oh)
        return 0;
 }
 
+static int of_dev_find_hwmod(struct device_node *np,
+                            struct omap_hwmod *oh)
+{
+       int count, i, res;
+       const char *p;
+
+       count = of_property_count_strings(np, "ti,hwmods");
+       if (count < 1)
+               return -ENODEV;
+
+       for (i = 0; i < count; i++) {
+               res = of_property_read_string_index(np, "ti,hwmods",
+                                                   i, &p);
+               if (res)
+                       continue;
+               if (!strcmp(p, oh->name)) {
+                       pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n",
+                                np->name, i, oh->name);
+                       return i;
+               }
+       }
+
+       return -ENODEV;
+}
+
 /**
  * of_dev_hwmod_lookup - look up needed hwmod from dt blob
  * @np: struct device_node *
  * @oh: struct omap_hwmod *
+ * @index: index of the entry found
+ * @found: struct device_node * found or NULL
  *
  * Parse the dt blob and find out needed hwmod. Recursive function is
  * implemented to take care hierarchical dt blob parsing.
- * Return: The device node on success or NULL on failure.
+ * Return: Returns 0 on success, -ENODEV when not found.
  */
-static struct device_node *of_dev_hwmod_lookup(struct device_node *np,
-                                               struct omap_hwmod *oh)
+static int of_dev_hwmod_lookup(struct device_node *np,
+                              struct omap_hwmod *oh,
+                              int *index,
+                              struct device_node **found)
 {
-       struct device_node *np0 = NULL, *np1 = NULL;
-       const char *p;
+       struct device_node *np0 = NULL;
+       int res;
+
+       res = of_dev_find_hwmod(np, oh);
+       if (res >= 0) {
+               *found = np;
+               *index = res;
+               return 0;
+       }
 
        for_each_child_of_node(np, np0) {
-               if (of_find_property(np0, "ti,hwmods", NULL)) {
-                       p = of_get_property(np0, "ti,hwmods", NULL);
-                       if (!strcmp(p, oh->name))
-                               return np0;
-                       np1 = of_dev_hwmod_lookup(np0, oh);
-                       if (np1)
-                               return np1;
+               struct device_node *fc;
+               int i;
+
+               res = of_dev_hwmod_lookup(np0, oh, &i, &fc);
+               if (res == 0) {
+                       *found = fc;
+                       *index = i;
+                       return 0;
                }
        }
-       return NULL;
+
+       *found = NULL;
+       *index = 0;
+
+       return -ENODEV;
 }
 
 /**
  * _init_mpu_rt_base - populate the virtual address for a hwmod
  * @oh: struct omap_hwmod * to locate the virtual address
  * @data: (unused, caller should pass NULL)
+ * @index: index of the reg entry iospace in device tree
  * @np: struct device_node * of the IP block's device node in the DT data
  *
  * Cache the virtual address used by the MPU to access this IP block's
@@ -2368,7 +2448,7 @@ static struct device_node *of_dev_hwmod_lookup(struct device_node *np,
  * -ENXIO on absent or invalid register target address space.
  */
 static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
-                                   struct device_node *np)
+                                   int index, struct device_node *np)
 {
        struct omap_hwmod_addr_space *mem;
        void __iomem *va_start = NULL;
@@ -2390,13 +2470,17 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
                if (!np)
                        return -ENXIO;
 
-               va_start = of_iomap(np, oh->mpu_rt_idx);
+               va_start = of_iomap(np, index + oh->mpu_rt_idx);
        } else {
                va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
        }
 
        if (!va_start) {
-               pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+               if (mem)
+                       pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+               else
+                       pr_err("omap_hwmod: %s: Missing dt reg%i for %s\n",
+                              oh->name, index, np->full_name);
                return -ENXIO;
        }
 
@@ -2422,17 +2506,29 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
  */
 static int __init _init(struct omap_hwmod *oh, void *data)
 {
-       int r;
+       int r, index;
        struct device_node *np = NULL;
 
        if (oh->_state != _HWMOD_STATE_REGISTERED)
                return 0;
 
-       if (of_have_populated_dt())
-               np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
+       if (of_have_populated_dt()) {
+               struct device_node *bus;
+
+               bus = of_find_node_by_name(NULL, "ocp");
+               if (!bus)
+                       return -ENODEV;
+
+               r = of_dev_hwmod_lookup(bus, oh, &index, &np);
+               if (r)
+                       pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
+               else if (np && index)
+                       pr_warn("omap_hwmod: %s using broken dt data from %s\n",
+                               oh->name, np->name);
+       }
 
        if (oh->class->sysc) {
-               r = _init_mpu_rt_base(oh, NULL, np);
+               r = _init_mpu_rt_base(oh, NULL, index, np);
                if (r < 0) {
                        WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
                             oh->name);
@@ -3169,6 +3265,11 @@ int omap_hwmod_softreset(struct omap_hwmod *oh)
                goto error;
        _write_sysconfig(v, oh);
 
+       ret = _clear_softreset(oh, &v);
+       if (ret)
+               goto error;
+       _write_sysconfig(v, oh);
+
 error:
        return ret;
 }
index 56cebb05509e15c0054f342e158a21214b7a6603..d23c77fadb31036058ab7b750cf02495d2ef33ab 100644 (file)
@@ -796,7 +796,7 @@ struct omap_hwmod omap2xxx_counter_32k_hwmod = {
 
 /* gpmc */
 static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -841,7 +841,7 @@ static struct omap_hwmod_class omap2_rng_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap2_rng_mpu_irqs[] = {
-       { .irq = 52 },
+       { .irq = 52 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index 9e56fabd7fa3b834fbe09a463facd521592107a7..4c3b1e6df50806700cbcfc3c4f582650b36cc3a3 100644 (file)
@@ -1943,7 +1943,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_usb_host_hs_sysc = {
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
        .sysc_fields    = &omap_hwmod_sysc_type1,
@@ -2021,15 +2022,7 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 };
 
 /*
@@ -2172,7 +2165,7 @@ static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
-       { .irq = 20 },
+       { .irq = 20 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -3006,7 +2999,7 @@ static struct omap_mmu_dev_attr mmu_isp_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_isp_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_isp_irqs[] = {
-       { .irq = 24 },
+       { .irq = 24 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
@@ -3048,7 +3041,7 @@ static struct omap_mmu_dev_attr mmu_iva_dev_attr = {
 
 static struct omap_hwmod omap3xxx_mmu_iva_hwmod;
 static struct omap_hwmod_irq_info omap3xxx_mmu_iva_irqs[] = {
-       { .irq = 28 },
+       { .irq = 28 + OMAP_INTC_START, },
        { .irq = -1 }
 };
 
index 1e5b12cb8246290cc8e2865036e0f4a291513f9c..3318cae96e7d1e94a8699192d1c00512c8f34f38 100644 (file)
@@ -2937,7 +2937,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET),
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
                           MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
@@ -3001,15 +3001,7 @@ static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 };
 
 /*
index 9e08d6994a0b09c44760e03323c9543f720ad026..e297d6231c3aa3c35910d25f3115466be2d453ab 100644 (file)
@@ -1544,7 +1544,8 @@ static struct omap_hwmod_class_sysconfig omap54xx_usb_host_hs_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
                           MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
@@ -1598,15 +1599,7 @@ static struct omap_hwmod omap54xx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
        .main_clk       = "l3init_60m_fclk",
        .prcm = {
                .omap4 = {
index db32d5380b118cda247e6f8e863bc14906eed6bc..18f333c440db3b72ff49577ef71d24b64dbcc916 100644 (file)
@@ -1637,7 +1637,7 @@ static struct omap_hwmod dra7xx_uart1_hwmod = {
        .class          = &dra7xx_uart_hwmod_class,
        .clkdm_name     = "l4per_clkdm",
        .main_clk       = "uart1_gfclk_mux",
-       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .flags          = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP2UART1_FLAGS,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
index 10c71450cf632c2816c40ab22207ad65ef09dd0b..39f020c982e8b3a41d547d9d45b60c46cb08877b 100644 (file)
@@ -139,6 +139,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 
 static struct pdata_init pdata_quirks[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP3
+       { "nokia,omap3-n900", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n9", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n950", hsmmc2_internal_input_clk, },
        { "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
index e233dfcbc18670ff6f0e507df07b6f9c09289534..93a2a6e4260f46c6b1580d7dbf50188dbc7154a3 100644 (file)
@@ -128,7 +128,8 @@ skip_voltdm:
        for (i = 0; i < pwrdm->banks; i++)
                pwrdm->ret_mem_off_counter[i] = 0;
 
-       arch_pwrdm->pwrdm_wait_transition(pwrdm);
+       if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
+               arch_pwrdm->pwrdm_wait_transition(pwrdm);
        pwrdm->state = pwrdm_read_pwrst(pwrdm);
        pwrdm->state_counter[pwrdm->state] = 1;
 
index 2a086e8373eb7bf1104892784aba7a5236a3bd5b..958cd6af93842566308a33d11f1799dd78f332d9 100644 (file)
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <mach/irqs.h>
+
 #define LUBBOCK_ETH_PHYS       PXA_CS3_PHYS
 
 #define LUBBOCK_FPGA_PHYS      PXA_CS2_PHYS
index 0d5dd646f61fa7d5aa743d4c68f162a2453d00e0..263b15249b5b803436709e1e5e268b9552bedef0 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <mach/regs-ost.h>
 #include <mach/reset.h>
+#include <mach/smemc.h>
 
 unsigned int reset_status;
 EXPORT_SYMBOL(reset_status);
@@ -81,6 +82,12 @@ static void do_hw_reset(void)
        writel_relaxed(OSSR_M3, OSSR);
        /* ... in 100 ms */
        writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3);
+       /*
+        * SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71)
+        * we put SDRAM into self-refresh to prevent that
+        */
+       while (1)
+               writel_relaxed(MDREFR_SLFRSH, MDREFR);
 }
 
 void pxa_restart(enum reboot_mode mode, const char *cmd)
@@ -104,4 +111,3 @@ void pxa_restart(enum reboot_mode mode, const char *cmd)
                break;
        }
 }
-
index 0206b915a6f6e07e3de75854617284f9c56aa870..ef5557b807ed95bbfce94ecc1c3ec17549767aec 100644 (file)
@@ -425,57 +425,57 @@ static struct platform_device tosa_power_device = {
  * Tosa Keyboard
  */
 static const uint32_t tosakbd_keymap[] = {
-       KEY(0, 2, KEY_W),
-       KEY(0, 6, KEY_K),
-       KEY(0, 7, KEY_BACKSPACE),
-       KEY(0, 8, KEY_P),
-       KEY(1, 1, KEY_Q),
-       KEY(1, 2, KEY_E),
-       KEY(1, 3, KEY_T),
-       KEY(1, 4, KEY_Y),
-       KEY(1, 6, KEY_O),
-       KEY(1, 7, KEY_I),
-       KEY(1, 8, KEY_COMMA),
-       KEY(2, 1, KEY_A),
-       KEY(2, 2, KEY_D),
-       KEY(2, 3, KEY_G),
-       KEY(2, 4, KEY_U),
-       KEY(2, 6, KEY_L),
-       KEY(2, 7, KEY_ENTER),
-       KEY(2, 8, KEY_DOT),
-       KEY(3, 1, KEY_Z),
-       KEY(3, 2, KEY_C),
-       KEY(3, 3, KEY_V),
-       KEY(3, 4, KEY_J),
-       KEY(3, 5, TOSA_KEY_ADDRESSBOOK),
-       KEY(3, 6, TOSA_KEY_CANCEL),
-       KEY(3, 7, TOSA_KEY_CENTER),
-       KEY(3, 8, TOSA_KEY_OK),
-       KEY(3, 9, KEY_LEFTSHIFT),
-       KEY(4, 1, KEY_S),
-       KEY(4, 2, KEY_R),
-       KEY(4, 3, KEY_B),
-       KEY(4, 4, KEY_N),
-       KEY(4, 5, TOSA_KEY_CALENDAR),
-       KEY(4, 6, TOSA_KEY_HOMEPAGE),
-       KEY(4, 7, KEY_LEFTCTRL),
-       KEY(4, 8, TOSA_KEY_LIGHT),
-       KEY(4, 10, KEY_RIGHTSHIFT),
-       KEY(5, 1, KEY_TAB),
-       KEY(5, 2, KEY_SLASH),
-       KEY(5, 3, KEY_H),
-       KEY(5, 4, KEY_M),
-       KEY(5, 5, TOSA_KEY_MENU),
-       KEY(5, 7, KEY_UP),
-       KEY(5, 11, TOSA_KEY_FN),
-       KEY(6, 1, KEY_X),
-       KEY(6, 2, KEY_F),
-       KEY(6, 3, KEY_SPACE),
-       KEY(6, 4, KEY_APOSTROPHE),
-       KEY(6, 5, TOSA_KEY_MAIL),
-       KEY(6, 6, KEY_LEFT),
-       KEY(6, 7, KEY_DOWN),
-       KEY(6, 8, KEY_RIGHT),
+       KEY(0, 1, KEY_W),
+       KEY(0, 5, KEY_K),
+       KEY(0, 6, KEY_BACKSPACE),
+       KEY(0, 7, KEY_P),
+       KEY(1, 0, KEY_Q),
+       KEY(1, 1, KEY_E),
+       KEY(1, 2, KEY_T),
+       KEY(1, 3, KEY_Y),
+       KEY(1, 5, KEY_O),
+       KEY(1, 6, KEY_I),
+       KEY(1, 7, KEY_COMMA),
+       KEY(2, 0, KEY_A),
+       KEY(2, 1, KEY_D),
+       KEY(2, 2, KEY_G),
+       KEY(2, 3, KEY_U),
+       KEY(2, 5, KEY_L),
+       KEY(2, 6, KEY_ENTER),
+       KEY(2, 7, KEY_DOT),
+       KEY(3, 0, KEY_Z),
+       KEY(3, 1, KEY_C),
+       KEY(3, 2, KEY_V),
+       KEY(3, 3, KEY_J),
+       KEY(3, 4, TOSA_KEY_ADDRESSBOOK),
+       KEY(3, 5, TOSA_KEY_CANCEL),
+       KEY(3, 6, TOSA_KEY_CENTER),
+       KEY(3, 7, TOSA_KEY_OK),
+       KEY(3, 8, KEY_LEFTSHIFT),
+       KEY(4, 0, KEY_S),
+       KEY(4, 1, KEY_R),
+       KEY(4, 2, KEY_B),
+       KEY(4, 3, KEY_N),
+       KEY(4, 4, TOSA_KEY_CALENDAR),
+       KEY(4, 5, TOSA_KEY_HOMEPAGE),
+       KEY(4, 6, KEY_LEFTCTRL),
+       KEY(4, 7, TOSA_KEY_LIGHT),
+       KEY(4, 9, KEY_RIGHTSHIFT),
+       KEY(5, 0, KEY_TAB),
+       KEY(5, 1, KEY_SLASH),
+       KEY(5, 2, KEY_H),
+       KEY(5, 3, KEY_M),
+       KEY(5, 4, TOSA_KEY_MENU),
+       KEY(5, 6, KEY_UP),
+       KEY(5, 10, TOSA_KEY_FN),
+       KEY(6, 0, KEY_X),
+       KEY(6, 1, KEY_F),
+       KEY(6, 2, KEY_SPACE),
+       KEY(6, 3, KEY_APOSTROPHE),
+       KEY(6, 4, TOSA_KEY_MAIL),
+       KEY(6, 5, KEY_LEFT),
+       KEY(6, 6, KEY_DOWN),
+       KEY(6, 7, KEY_RIGHT),
 };
 
 static struct matrix_keymap_data tosakbd_keymap_data = {
index 7eb9a10fc1af68d81b1dd308ebfd352d28c9e416..2fddf38192df3ad0f67bc646914e7d4121a6b41c 100644 (file)
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/clk-provider.h>
-#include <linux/irqchip.h>
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
@@ -48,15 +46,9 @@ static void __init s3c64xx_dt_map_io(void)
                panic("SoC is not S3C64xx!");
 }
 
-static void __init s3c64xx_dt_init_irq(void)
-{
-       of_clk_init(NULL);
-       samsung_wdt_reset_of_init();
-       irqchip_init();
-};
-
 static void __init s3c64xx_dt_init_machine(void)
 {
+       samsung_wdt_reset_of_init();
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -79,7 +71,6 @@ DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
        /* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
        .dt_compat      = s3c64xx_dt_compat,
        .map_io         = s3c64xx_dt_map_io,
-       .init_irq       = s3c64xx_dt_init_irq,
        .init_machine   = s3c64xx_dt_init_machine,
        .restart        = s3c64xx_dt_restart,
 MACHINE_END
index 958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8..8ea87bd45c330abd37df9eba0b30b8f4efc8dc47 100644 (file)
@@ -483,7 +483,7 @@ static struct platform_device lcdc0_device = {
        .id             = 0,
        .dev    = {
                .platform_data  = &lcdc0_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -580,7 +580,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -614,6 +614,11 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
        REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
 };
 
+/* Fixed 3.3V regulator used by LCD backlight */
+static struct regulator_consumer_supply fixed5v0_power_consumers[] = {
+       REGULATOR_SUPPLY("power", "pwm-backlight.0"),
+};
+
 /* Fixed 3.3V regulator to be used by SDHI0 */
 static struct regulator_consumer_supply vcc_sdhi0_consumers[] = {
        REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
@@ -1196,6 +1201,8 @@ static void __init eva_init(void)
 
        regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
                                     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+       regulator_register_always_on(3, "fixed-5.0V", fixed5v0_power_consumers,
+                                    ARRAY_SIZE(fixed5v0_power_consumers), 5000000);
 
        pinctrl_register_mappings(eva_pinctrl_map, ARRAY_SIZE(eva_pinctrl_map));
        pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
index 38611526fe9a55953372afcd2662aa668b34e080..3c4995aebd220870406934ba905d90d5949d18ca 100644 (file)
@@ -679,7 +679,7 @@ static void __init bockw_init(void)
                        .id             = i,
                        .data           = &rsnd_card_info[i],
                        .size_data      = sizeof(struct asoc_simple_card_info),
-                       .dma_mask       = ~0,
+                       .dma_mask       = DMA_BIT_MASK(32),
                };
 
                platform_device_register_full(&cardinfo);
index fe689b7fdc9e715ecd724edcc746913010627fb4..bc40b853ffd3cff2204bdfdc283863a9577f51bc 100644 (file)
@@ -334,7 +334,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index a8d3ce646fb900514fa983964bf8d70d0e88c278..e0406fd373906e4d43d53769a7d7cfa548b6f388 100644 (file)
@@ -245,7 +245,9 @@ static void __init lager_init(void)
 {
        lager_add_standard_devices();
 
-       phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
+       if (IS_ENABLED(CONFIG_PHYLIB))
+               phy_register_fixup_for_id("r8a7790-ether-ff:01",
+                                         lager_ksz8041_fixup);
 }
 
 static const char * const lager_boards_compat_dt[] __initconst = {
index af06753eb8092500de41707ac68216bd3ed244a0..e721d2ccceaef8c1d57bd0d671fa097a2c0f539a 100644 (file)
@@ -409,7 +409,7 @@ static struct platform_device lcdc_device = {
        .resource       = lcdc_resources,
        .dev    = {
                .platform_data  = &lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
@@ -499,7 +499,7 @@ static struct platform_device hdmi_lcdc_device = {
        .id             = 1,
        .dev    = {
                .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = ~0,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
        },
 };
 
index 037100a1563aca5f52dd2e68f42c711dc71484c2..aee77f06f887da5d8f73e2112333a015640e93ab 100644 (file)
@@ -10,6 +10,7 @@ config ARCH_SOCFPGA
        select GENERIC_CLOCKEVENTS
        select GPIO_PL061 if GPIOLIB
        select HAVE_ARM_SCU
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MFD_SYSCON
        select SPARSE_IRQ
index c9e72c89066ad78b4f7890dcdcebc28157835e79..bce0d4277f71974ceefb7a2f9ec8e31ef75ceb9d 100644 (file)
@@ -12,3 +12,4 @@ config ARCH_SUNXI
        select PINCTRL_SUNXI
        select SPARSE_IRQ
        select SUN4I_TIMER
+       select SUN5I_HSTIMER
index 9a4e910c3796154c8fa6c167851a8f6b112265f3..3a9c1f1c219dd47bd79ecb1c3bb9f1538abe4463 100644 (file)
@@ -198,10 +198,12 @@ void __init tegra_init_fuse(void)
        switch (tegra_chip_id) {
        case TEGRA20:
                tegra20_fuse_init_randomness();
+               break;
        case TEGRA30:
        case TEGRA114:
        default:
                tegra30_fuse_init_randomness();
+               break;
        }
 
        pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
index 2e85c1e72535138a1b90c543ec3e95e2b36a6fa6..12c7e5c03ea488336eac954daab98f4b6a22c649 100644 (file)
@@ -140,6 +140,10 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        /* Requires call-back bindings. */
        OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
        /* Requires DMA bindings. */
+       OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  &mop500_sdi1_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  &mop500_sdi2_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
                       "ux500-msp-i2s.0", &msp0_platform_data),
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
index 79f8b39801a8e570bd86ea80e566ee939bbb600b..f61a5707823a40e0af9474d4f18809f9196b1264 100644 (file)
@@ -9,6 +9,7 @@
  *
  *  DMA uncached mapping support.
  */
+#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/gfp.h>
@@ -157,6 +158,44 @@ struct dma_map_ops arm_coherent_dma_ops = {
 };
 EXPORT_SYMBOL(arm_coherent_dma_ops);
 
+static int __dma_supported(struct device *dev, u64 mask, bool warn)
+{
+       unsigned long max_dma_pfn;
+
+       /*
+        * If the mask allows for more memory than we can address,
+        * and we actually have that much memory, then we must
+        * indicate that DMA to this device is not supported.
+        */
+       if (sizeof(mask) != sizeof(dma_addr_t) &&
+           mask > (dma_addr_t)~0 &&
+           dma_to_pfn(dev, ~0) < max_pfn) {
+               if (warn) {
+                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
+                                mask);
+                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
+               }
+               return 0;
+       }
+
+       max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
+
+       /*
+        * Translate the device's DMA mask to a PFN limit.  This
+        * PFN number includes the page which we can DMA to.
+        */
+       if (dma_to_pfn(dev, mask) < max_dma_pfn) {
+               if (warn)
+                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
+                                mask,
+                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
+                                max_dma_pfn + 1);
+               return 0;
+       }
+
+       return 1;
+}
+
 static u64 get_coherent_dma_mask(struct device *dev)
 {
        u64 mask = (u64)DMA_BIT_MASK(32);
@@ -173,32 +212,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
                        return 0;
                }
 
-               /*
-                * If the mask allows for more memory than we can address,
-                * and we actually have that much memory, then fail the
-                * allocation.
-                */
-               if (sizeof(mask) != sizeof(dma_addr_t) &&
-                   mask > (dma_addr_t)~0 &&
-                   dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) {
-                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
-                                mask);
-                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
-                       return 0;
-               }
-
-               /*
-                * Now check that the mask, when translated to a PFN,
-                * fits within the allowable addresses which we can
-                * allocate.
-                */
-               if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) {
-                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
-                                mask,
-                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
-                                arm_dma_pfn_limit + 1);
+               if (!__dma_supported(dev, mask, true))
                        return 0;
-               }
        }
 
        return mask;
@@ -1027,28 +1042,7 @@ void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-       unsigned long limit;
-
-       /*
-        * If the mask allows for more memory than we can address,
-        * and we actually have that much memory, then we must
-        * indicate that DMA to this device is not supported.
-        */
-       if (sizeof(mask) != sizeof(dma_addr_t) &&
-           mask > (dma_addr_t)~0 &&
-           dma_to_pfn(dev, ~0) > arm_dma_pfn_limit)
-               return 0;
-
-       /*
-        * Translate the device's DMA mask to a PFN limit.  This
-        * PFN number includes the page which we can DMA to.
-        */
-       limit = dma_to_pfn(dev, mask);
-
-       if (limit < arm_dma_pfn_limit)
-               return 0;
-
-       return 1;
+       return __dma_supported(dev, mask, false);
 }
 EXPORT_SYMBOL(dma_supported);
 
index 6d5ba9afb16a4409d50dbdbc03d08c83642df9b4..3387e60e4ea381c579725774ebab8d587eeded0c 100644 (file)
@@ -175,16 +175,16 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
                unsigned long i;
                if (cache_is_vipt_nonaliasing()) {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_atomic(page);
+                               void *addr = kmap_atomic(page + i);
                                __cpuc_flush_dcache_area(addr, PAGE_SIZE);
                                kunmap_atomic(addr);
                        }
                } else {
                        for (i = 0; i < (1 << compound_order(page)); i++) {
-                               void *addr = kmap_high_get(page);
+                               void *addr = kmap_high_get(page + i);
                                if (addr) {
                                        __cpuc_flush_dcache_area(addr, PAGE_SIZE);
-                                       kunmap_high(page);
+                                       kunmap_high(page + i);
                                }
                        }
                }
index d27158c38eb0b190b869e028b93d8265fb90969e..5e85ed371364c17657be7d7155139a5e3f536437 100644 (file)
@@ -146,7 +146,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 
        info.flags = VM_UNMAPPED_AREA_TOPDOWN;
        info.length = len;
-       info.low_limit = PAGE_SIZE;
+       info.low_limit = FIRST_USER_ADDRESS;
        info.high_limit = mm->mmap_base;
        info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
        info.align_offset = pgoff << PAGE_SHIFT;
index 0acb089d0f70db818ce487fa67b0fb90b1b0b69d..1046b373d1aedb2823e3bb62f106681f9b63fc2a 100644 (file)
@@ -87,7 +87,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
                init_pud = pud_offset(init_pgd, 0);
                init_pmd = pmd_offset(init_pud, 0);
                init_pte = pte_offset_map(init_pmd, 0);
-               set_pte_ext(new_pte, *init_pte, 0);
+               set_pte_ext(new_pte + 0, init_pte[0], 0);
+               set_pte_ext(new_pte + 1, init_pte[1], 0);
                pte_unmap(init_pte);
                pte_unmap(new_pte);
        }
index 9ed155ad0f97c42c80fd903919a51dac8b0298d4..271b5e9715682ab40869a1ea8a02c9696eaebf07 100644 (file)
@@ -641,10 +641,10 @@ load_ind:
                        emit(ARM_MUL(r_A, r_A, r_X), ctx);
                        break;
                case BPF_S_ALU_DIV_K:
-                       /* current k == reciprocal_value(userspace k) */
+                       if (k == 1)
+                               break;
                        emit_mov_i(r_scratch, k, ctx);
-                       /* A = top 32 bits of the product */
-                       emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+                       emit_udiv(r_A, r_A, r_scratch, ctx);
                        break;
                case BPF_S_ALU_DIV_X:
                        update_on_xread(ctx);
index fb92abb91628a2e06f6aebc54f03a724a79c23ee..2861b155485aefa0adeb1029d6657b4081179af6 100644 (file)
@@ -336,8 +336,11 @@ static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
        if (timer->posted)
                return;
 
-       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
+       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) {
+               timer->posted = OMAP_TIMER_NONPOSTED;
+               __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0);
                return;
+       }
 
        __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
                              OMAP_TIMER_CTRL_POSTED, 0);
index 83e4f959ee47c6b9b18a77d9f50995b7b4fc5ab0..85501238b4258316272f9448ad8829b18a1111b2 100644 (file)
@@ -96,7 +96,7 @@ static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
        struct remap_data *info = data;
        struct page *page = info->pages[info->index++];
        unsigned long pfn = page_to_pfn(page);
-       pte_t pte = pfn_pte(pfn, info->prot);
+       pte_t pte = pte_mkspecial(pfn_pte(pfn, info->prot));
 
        if (map_foreign_page(pfn, info->fgmfn, info->domid))
                return -EFAULT;
@@ -224,10 +224,10 @@ static int __init xen_guest_init(void)
        }
        if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res))
                return 0;
-       xen_hvm_resume_frames = res.start >> PAGE_SHIFT;
+       xen_hvm_resume_frames = res.start;
        xen_events_irq = irq_of_parse_and_map(node, 0);
        pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
-                       version, xen_events_irq, xen_hvm_resume_frames);
+                       version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT));
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
index 23732cdff5511ff3c20bf1cbd403034797faf296..b31ee1b275b011d7010dbcac1eea3ab206290908 100644 (file)
@@ -25,8 +25,9 @@ struct xen_p2m_entry {
        struct rb_node rbnode_phys;
 };
 
-rwlock_t p2m_lock;
+static rwlock_t p2m_lock;
 struct rb_root phys_to_mach = RB_ROOT;
+EXPORT_SYMBOL_GPL(phys_to_mach);
 static struct rb_root mach_to_phys = RB_ROOT;
 
 static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
@@ -200,7 +201,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 }
 EXPORT_SYMBOL_GPL(__set_phys_to_machine);
 
-int p2m_init(void)
+static int p2m_init(void)
 {
        rwlock_init(&p2m_lock);
        return 0;
index 88c8b6c1341a445bdc425955383a8563033edd90..6d4dd22ee4b7bc70622f3fe95538bcba0ff6b99e 100644 (file)
@@ -159,8 +159,7 @@ config NR_CPUS
        range 2 32
        depends on SMP
        # These have to remain sorted largest to smallest
-       default "8" if ARCH_XGENE
-       default "4"
+       default "8"
 
 config HOTPLUG_CPU
        bool "Support for hot-pluggable CPUs"
index d4a63338a53c49a1085c4c72ce7330f207e3b3bf..78e20ba8806b8b86338ee1ccafc1c3aa97b5a034 100644 (file)
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
 #define smp_wmb()      barrier()
+
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ___p1;                                                          \
+})
+
 #else
+
 #define smp_mb()       asm volatile("dmb ish" : : : "memory")
 #define smp_rmb()      asm volatile("dmb ishld" : : : "memory")
 #define smp_wmb()      asm volatile("dmb ishst" : : : "memory")
+
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       switch (sizeof(*p)) {                                           \
+       case 4:                                                         \
+               asm volatile ("stlr %w1, %0"                            \
+                               : "=Q" (*p) : "r" (v) : "memory");      \
+               break;                                                  \
+       case 8:                                                         \
+               asm volatile ("stlr %1, %0"                             \
+                               : "=Q" (*p) : "r" (v) : "memory");      \
+               break;                                                  \
+       }                                                               \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1;                                               \
+       compiletime_assert_atomic_type(*p);                             \
+       switch (sizeof(*p)) {                                           \
+       case 4:                                                         \
+               asm volatile ("ldar %w0, %1"                            \
+                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+               break;                                                  \
+       case 8:                                                         \
+               asm volatile ("ldar %0, %1"                             \
+                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+               break;                                                  \
+       }                                                               \
+       ___p1;                                                          \
+})
+
 #endif
 
 #define read_barrier_depends()         do { } while(0)
index 755f86143320167038e24e9be093e61b8b307e65..b1d2e26c3c883e7259f0ab679efe33ffe2935429 100644 (file)
@@ -43,7 +43,7 @@
  * Section
  */
 #define PMD_SECT_VALID         (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 58)
 #define PMD_SECT_USER          (_AT(pmdval_t, 1) << 6)         /* AP[1] */
 #define PMD_SECT_RDONLY                (_AT(pmdval_t, 1) << 7)         /* AP[2] */
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
index 2820f1a6eebe0252d280e5d56e0a6bc60ac14182..dde3fc9c49f015c80b43f9ca21f1d996b9d2a910 100644 (file)
@@ -23,25 +23,21 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir,
             struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
 }
 
 static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir,
                struct dma_attrs *attrs)
 {
-       __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
 }
 
 static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
 }
 
 static inline void xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
-       __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
 }
 #endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 7009387348b7c416f9dc8732a18c7563eac4af4e..c68cca5c3523221421e93460805a3c4d9cbac5a4 100644 (file)
@@ -282,8 +282,9 @@ ENDPROC(secondary_holding_pen)
         * be used where CPUs are brought online dynamically by the kernel.
         */
 ENTRY(secondary_entry)
-       bl      __calc_phys_offset              // x2=phys offset
        bl      el2_setup                       // Drop to EL1
+       bl      __calc_phys_offset              // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+       bl      set_cpu_boot_mode_flag
        b       secondary_startup
 ENDPROC(secondary_entry)
 
index 6777a2192b83846f1065f442f5777d4092e9bc0c..6a8928bba03c9e8135c4481b497268f7018ca393 100644 (file)
@@ -214,31 +214,29 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
 {
        int err, len, type, disabled = !ctrl.enabled;
 
-       if (disabled) {
-               len = 0;
-               type = HW_BREAKPOINT_EMPTY;
-       } else {
-               err = arch_bp_generic_fields(ctrl, &len, &type);
-               if (err)
-                       return err;
-
-               switch (note_type) {
-               case NT_ARM_HW_BREAK:
-                       if ((type & HW_BREAKPOINT_X) != type)
-                               return -EINVAL;
-                       break;
-               case NT_ARM_HW_WATCH:
-                       if ((type & HW_BREAKPOINT_RW) != type)
-                               return -EINVAL;
-                       break;
-               default:
+       attr->disabled = disabled;
+       if (disabled)
+               return 0;
+
+       err = arch_bp_generic_fields(ctrl, &len, &type);
+       if (err)
+               return err;
+
+       switch (note_type) {
+       case NT_ARM_HW_BREAK:
+               if ((type & HW_BREAKPOINT_X) != type)
                        return -EINVAL;
-               }
+               break;
+       case NT_ARM_HW_WATCH:
+               if ((type & HW_BREAKPOINT_RW) != type)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
        }
 
        attr->bp_len    = len;
        attr->bp_type   = type;
-       attr->disabled  = disabled;
 
        return 0;
 }
index 421b99fd635dfae60c36d4c45837d73ca71a7187..0f7fec52c7f84030afb9958cdd4627bb2ceb9546 100644 (file)
@@ -111,12 +111,12 @@ ENTRY(__cpu_setup)
        bl      __flush_dcache_all
        mov     lr, x28
        ic      iallu                           // I+BTB cache invalidate
+       tlbi    vmalle1is                       // invalidate I + D TLBs
        dsb     sy
 
        mov     x0, #3 << 20
        msr     cpacr_el1, x0                   // Enable FP/ASIMD
        msr     mdscr_el1, xzr                  // Reset mdscr_el1
-       tlbi    vmalle1is                       // invalidate I + D TLBs
        /*
         * Memory region attributes for LPAE:
         *
index 7b1f2cd854008c16117cf5c39c06f4bd2115a9fa..1f121497b5177c4a3ac30d715dd98a1f623686cd 100644 (file)
@@ -298,8 +298,10 @@ static int __init set_abdac_rate(struct platform_device *pdev)
         */
        retval = clk_round_rate(pll1,
                        CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16);
-       if (retval < 0)
+       if (retval <= 0) {
+               retval = -EINVAL;
                goto out_abdac;
+       }
 
        retval = clk_set_rate(pll1, retval);
        if (retval != 0)
index d5aff36ade922f07ca18c34552b140919d598dfc..4733e38e7ae62cb111324ef17877bbd90b97a712 100644 (file)
@@ -59,7 +59,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 4abcf435d599a4a88b26ae1049b401dfcfa8a2e8..1be0ee31bd91c277753a5be27510ced4554712bf 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 18f3fa0470ff294a9755cd263d30c4a4080198e7..796e536f7bc43576d7079a41237356eb5977dbfe 100644 (file)
@@ -60,7 +60,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 06e389cfcd126e4c75111398758a5813d7fe2275..9a57da44eb6fd3390a5df2ce4d905bec1ec88c79 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 2518a1368d7caea758cfba9b152abe07b59870d0..97fe1b399b069d2965552ef78a7c3e29da1dd084 100644 (file)
@@ -59,7 +59,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 245ef6bd0fa61f56de23c1b4ce57abb51771489c..a176d24467e9d28f25e31364aa8e92b0fd3d8de0 100644 (file)
@@ -62,7 +62,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index fa6cbac6e4189c2e5a39eed8b6cb49ec44a3dd96..d1bf6dcfc47d4c289fca01896377d67cfbc62a94 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index bbd5131021a57d840bed7dede2db9d61b074e8f4..2813dd2b913876b0604c31751204b16ac6eb12fe 100644 (file)
@@ -53,7 +53,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index c1cd726f901233b1dd552cb3d28f3375682f3ad9..f8ff3a3baad4cc702ed4b374b95c21c943b0a84f 100644 (file)
@@ -42,7 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 754ae56b276739a58113bc89b87395d0b35b6ab2..992228e54e38cf56dc0cc1567c129d5ec907543b 100644 (file)
@@ -42,7 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 58589d8cc0acd829af7612b782368a907f6c3e64..b8e698b0d1fa30e2563fff8e9a0792a36b8ec3a1 100644 (file)
@@ -54,7 +54,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index c90fbf6d35bc16d60f12d1e5be4cf836f2fc9391..07bed3f7eb5e6022372ed35b6a8e303356cbbc8a 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index ba7c31e269cb0aed7b0ba9a72c1ce641cf0e346a..18db853386c81e73087c2c106d7271a415c3dce2 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 65de4431108c837334dc07facfc578fb815d55cd..91df6b2986be2a1691449bfe47953715e387060d 100644 (file)
@@ -46,7 +46,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
index 0a8bfdc420e0e6730c4ba1464de3ee92fafd8a2f..d630e089dd322c6ab735831a4ebd5424308a9a75 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 0961275373dbb6afb355edccbcbeaa24c611ec5a..715100790fd05c4746cd366513ad53f9e6ad93a9 100644 (file)
@@ -8,22 +8,15 @@
 #ifndef __ASM_AVR32_BARRIER_H
 #define __ASM_AVR32_BARRIER_H
 
-#define nop()                  asm volatile("nop")
-
-#define mb()                   asm volatile("" : : : "memory")
-#define rmb()                  mb()
-#define wmb()                  asm volatile("sync 0" : : : "memory")
-#define read_barrier_depends()  do { } while(0)
-#define set_mb(var, value)      do { var = value; mb(); } while(0)
+/*
+ * Weirdest thing ever.. no full barrier, but it has a write barrier!
+ */
+#define wmb()  asm volatile("sync 0" : : : "memory")
 
 #ifdef CONFIG_SMP
 # error "The AVR32 port does not support SMP"
-#else
-# define smp_mb()              barrier()
-# define smp_rmb()             barrier()
-# define smp_wmb()             barrier()
-# define smp_read_barrier_depends() do { } while(0)
 #endif
 
+#include <asm-generic/barrier.h>
 
 #endif /* __ASM_AVR32_BARRIER_H */
index 12f828ad5058d09158f8d3e2007b76a7a42cbb4a..d0f771be9e96eda02c1045bbb5702cc9b9f74b8d 100644 (file)
@@ -59,7 +59,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 static struct irqaction timer_irqaction = {
        .handler        = timer_interrupt,
        /* Oprofile uses the same irq as the timer, so allow it to be shared */
-       .flags          = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
+       .flags          = IRQF_TIMER | IRQF_SHARED,
        .name           = "avr32_comparator",
 };
 
index 32d680eb6f4842be56d17f40197c2a6fd4f77f37..db190842b80c74e026784037516df9b27471f4b8 100644 (file)
@@ -181,7 +181,7 @@ static const struct platform_suspend_ops avr32_pm_ops = {
        .enter  = avr32_pm_enter,
 };
 
-static unsigned long avr32_pm_offset(void *symbol)
+static unsigned long __init avr32_pm_offset(void *symbol)
 {
        extern u8 pm_exception[];
 
index ebb189507dd73f76ac4bf871e7f2da602639f3d1..19283a16ac08062ca0185495ff0c1126036f749c 100644 (file)
 # define rmb() do { barrier(); smp_check_barrier(); } while (0)
 # define wmb() do { barrier(); smp_mark_barrier(); } while (0)
 # define read_barrier_depends()        do { barrier(); smp_check_barrier(); } while (0)
-#else
-# define mb()  barrier()
-# define rmb() barrier()
-# define wmb() barrier()
-# define read_barrier_depends()        do { } while (0)
 #endif
 
-#else /* !CONFIG_SMP */
-
-#define mb()   barrier()
-#define rmb()  barrier()
-#define wmb()  barrier()
-#define read_barrier_depends() do { } while (0)
-
 #endif /* !CONFIG_SMP */
 
-#define smp_mb()  mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define smp_read_barrier_depends()     read_barrier_depends()
+#include <asm-generic/barrier.h>
 
 #endif /* _BLACKFIN_BARRIER_H */
index b06caf649a954a6c1678b192dc947adeed692c5e..199b1a9dab8922b307cca53b1d2dbf3ccf83faee 100644 (file)
@@ -3,6 +3,7 @@ header-y += arch-v10/
 header-y += arch-v32/
 
 
+generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += kvm_para.h
diff --git a/arch/cris/include/asm/barrier.h b/arch/cris/include/asm/barrier.h
deleted file mode 100644 (file)
index 198ad7f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __ASM_CRIS_BARRIER_H
-#define __ASM_CRIS_BARRIER_H
-
-#define nop() __asm__ __volatile__ ("nop");
-
-#define barrier() __asm__ __volatile__("": : :"memory")
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()        mb()
-#define smp_rmb()       rmb()
-#define smp_wmb()       wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()        barrier()
-#define smp_rmb()       barrier()
-#define smp_wmb()       barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#endif /* __ASM_CRIS_BARRIER_H */
index 06776ad9f5e9caed56f829d543ec3ea00b96c359..abbef470154cd356f7118266f5944d249ebfd974 100644 (file)
 #define mb()                   asm volatile ("membar" : : :"memory")
 #define rmb()                  asm volatile ("membar" : : :"memory")
 #define wmb()                  asm volatile ("membar" : : :"memory")
-#define read_barrier_depends() do { } while (0)
 
-#define smp_mb()                       barrier()
-#define smp_rmb()                      barrier()
-#define smp_wmb()                      barrier()
-#define smp_read_barrier_depends()     do {} while(0)
-#define set_mb(var, value) \
-       do { var = (value); barrier(); } while (0)
+#include <asm-generic/barrier.h>
 
 #endif /* _ASM_BARRIER_H */
index 67c3450309b7454881d09a162ecb2e5123b4395b..ada843c701ef56380c40d0cba6a611752542335c 100644 (file)
@@ -2,6 +2,7 @@
 header-y += ucontext.h
 
 generic-y += auxvec.h
+generic-y += barrier.h
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += clkdev.h
index 8a64ff2337f651dda91e1d55396e5578262fb9e9..7aae4cb2a29a217a82b3ac482bfe7a1ea079327a 100644 (file)
@@ -160,8 +160,12 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 #define atomic_sub_and_test(i, v) (atomic_sub_return(i, (v)) == 0)
 #define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
 
-
 #define atomic_inc_return(v) (atomic_add_return(1, v))
 #define atomic_dec_return(v) (atomic_sub_return(1, v))
 
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
 #endif
index 1041a8e70ce85cea7e8b2d9372dbb8fef19c8496..4e863daea25b70e709a80623cd8cd1996a624005 100644 (file)
 #define smp_read_barrier_depends()     barrier()
 #define smp_wmb()                      barrier()
 #define smp_mb()                       barrier()
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec()     barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc()     barrier()
 
 /*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
 #define set_mb(var, value) \
index 4e4119b0e6915fc7e05c1536d9248d638cb4fe16..a8c3a11dc5aba2f850dd6e90cd69c634075eb3e0 100644 (file)
@@ -147,9 +147,6 @@ config PARAVIRT
          over full virtualization.  However, when run without a hypervisor
          the kernel is theoretically slower and slightly larger.
 
-
-source "arch/ia64/xen/Kconfig"
-
 endif
 
 choice
@@ -175,7 +172,6 @@ config IA64_GENERIC
          SGI-SN2               For SGI Altix systems
          SGI-UV                For SGI UV systems
          Ski-simulator         For the HP simulator <http://www.hpl.hp.com/research/linux/ski/>
-         Xen-domU              For xen domU system
 
          If you don't know what to do, choose "generic".
 
@@ -231,14 +227,6 @@ config IA64_HP_SIM
        bool "Ski-simulator"
        select SWIOTLB
 
-config IA64_XEN_GUEST
-       bool "Xen guest"
-       select SWIOTLB
-       depends on XEN
-       help
-         Build a kernel that runs on Xen guest domain. At this moment only
-         16KB page size in supported.
-
 endchoice
 
 choice
index be7bfa12b7053263e903dd70e247a365fd05f917..f37238f45bcd0879c8c32d6f5ca42363ece9e468 100644 (file)
@@ -51,11 +51,9 @@ core-$(CONFIG_IA64_DIG_VTD)  += arch/ia64/dig/
 core-$(CONFIG_IA64_GENERIC)    += arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1)     += arch/ia64/dig/
 core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
-core-$(CONFIG_IA64_XEN_GUEST)  += arch/ia64/dig/
 core-$(CONFIG_IA64_SGI_SN2)    += arch/ia64/sn/
 core-$(CONFIG_IA64_SGI_UV)     += arch/ia64/uv/
 core-$(CONFIG_KVM)             += arch/ia64/kvm/
-core-$(CONFIG_XEN)             += arch/ia64/xen/
 
 drivers-$(CONFIG_PCI)          += arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)  += arch/ia64/hp/sim/
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig
deleted file mode 100644 (file)
index b025acf..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=20
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARAVIRT_GUEST=y
-CONFIG_IA64_XEN_GUEST=y
-CONFIG_MCKINLEY=y
-CONFIG_IA64_CYCLONE=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PERMIT_BSP_REMOVE=y
-CONFIG_FORCE_CPEI_RETARGET=y
-CONFIG_IA64_MCA_RECOVERY=y
-CONFIG_PERFMON=y
-CONFIG_IA64_PALINFO=y
-CONFIG_KEXEC=y
-CONFIG_EFI_VARS=y
-CONFIG_BINFMT_MISC=m
-CONFIG_ACPI_PROCFS=y
-CONFIG_ACPI_BUTTON=m
-CONFIG_ACPI_FAN=m
-CONFIG_ACPI_PROCESSOR=m
-CONFIG_ACPI_CONTAINER=m
-CONFIG_HOTPLUG_PCI=y
-CONFIG_HOTPLUG_PCI_ACPI=m
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_ARPD=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_QLOGIC_1280=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_CRYPT=m
-CONFIG_DM_SNAPSHOT=m
-CONFIG_DM_MIRROR=m
-CONFIG_DM_ZERO=m
-CONFIG_FUSION=y
-CONFIG_FUSION_SPI=y
-CONFIG_FUSION_FC=y
-CONFIG_FUSION_CTL=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=m
-CONFIG_NET_PCI=y
-CONFIG_NET_VENDOR_INTEL=y
-CONFIG_E100=m
-CONFIG_E1000=y
-CONFIG_TIGON3=y
-CONFIG_NETCONSOLE=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_GAMEPORT=m
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_EFI_RTC=y
-CONFIG_RAW_DRIVER=m
-CONFIG_HPET=y
-CONFIG_AGP=m
-CONFIG_DRM=m
-CONFIG_DRM_TDFX=m
-CONFIG_DRM_R128=m
-CONFIG_DRM_RADEON=m
-CONFIG_DRM_MGA=m
-CONFIG_DRM_SIS=m
-CONFIG_HID_GYRATION=y
-CONFIG_HID_NTRIG=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_HID_TOPSEED=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_UHCI_HCD=y
-CONFIG_USB_STORAGE=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=y
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_XFS_FS=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_UDF_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_NTFS_FS=m
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_CIFS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_SGI_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_IA64_GRANULE_16MB=y
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
index faa1bf0da8153ffd1a0a1ebbae690308b6a9c962..d651102a4d4579434ce01fe3bd6f27c9108629c9 100644 (file)
@@ -111,8 +111,6 @@ static inline const char *acpi_get_sysname (void)
        return "uv";
 # elif defined (CONFIG_IA64_DIG)
        return "dig";
-# elif defined (CONFIG_IA64_XEN_GUEST)
-       return "xen";
 # elif defined(CONFIG_IA64_DIG_VTD)
        return "dig_vtd";
 # else
index 60576e06b6fb4b3205292f621c727626a6232c92..d0a69aa35e27decc3eacb83e299a910945221480 100644 (file)
 # define smp_rmb()     rmb()
 # define smp_wmb()     wmb()
 # define smp_read_barrier_depends()    read_barrier_depends()
+
 #else
+
 # define smp_mb()      barrier()
 # define smp_rmb()     barrier()
 # define smp_wmb()     barrier()
 # define smp_read_barrier_depends()    do { } while(0)
+
 #endif
 
+/*
+ * IA64 GCC turns volatile stores into st.rel and volatile loads into ld.acq no
+ * need for asm trickery!
+ */
+
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ___p1;                                                          \
+})
+
 /*
  * XXX check on this ---I suspect what Linus really wants here is
  * acquire vs release semantics but we can't discuss this stuff with
index 2d1ad4b11a85a9e9e4083c67f9c30ccf921659fa..9c39bdfc2da894ad9c03f3f01ba2ae097b97ce18 100644 (file)
@@ -113,8 +113,6 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
 #  include <asm/machvec_sn2.h>
 # elif defined (CONFIG_IA64_SGI_UV)
 #  include <asm/machvec_uv.h>
-# elif defined (CONFIG_IA64_XEN_GUEST)
-#  include <asm/machvec_xen.h>
 # elif defined (CONFIG_IA64_GENERIC)
 
 # ifdef MACHVEC_PLATFORM_HEADER
diff --git a/arch/ia64/include/asm/machvec_xen.h b/arch/ia64/include/asm/machvec_xen.h
deleted file mode 100644 (file)
index 8b8bd0e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _ASM_IA64_MACHVEC_XEN_h
-#define _ASM_IA64_MACHVEC_XEN_h
-
-extern ia64_mv_setup_t                 dig_setup;
-extern ia64_mv_cpu_init_t              xen_cpu_init;
-extern ia64_mv_irq_init_t              xen_irq_init;
-extern ia64_mv_send_ipi_t              xen_platform_send_ipi;
-
-/*
- * This stuff has dual use!
- *
- * For a generic kernel, the macros are used to initialize the
- * platform's machvec structure.  When compiling a non-generic kernel,
- * the macros are used directly.
- */
-#define ia64_platform_name                     "xen"
-#define platform_setup                         dig_setup
-#define platform_cpu_init                      xen_cpu_init
-#define platform_irq_init                      xen_irq_init
-#define platform_send_ipi                      xen_platform_send_ipi
-
-#endif /* _ASM_IA64_MACHVEC_XEN_h */
index 61c7b1750b169f33ccb544b5cb83c83e1dd432ee..092f1c91b36c02e890ca2417a5e2c841bf750691 100644 (file)
@@ -18,7 +18,6 @@
  *     - crash dumping code reserved region
  *     - Kernel memory map built from EFI memory map
  *     - ELF core header
- *     - xen start info if CONFIG_XEN
  *
  * More could be added if necessary
  */
index b149b88ea7953e980943c64c346c2914504ee00d..b53518a98026fa53447f891b1ac454f98afb7d76 100644 (file)
@@ -75,7 +75,6 @@ void *paravirt_get_gate_section(void);
 #ifdef CONFIG_PARAVIRT_GUEST
 
 #define PARAVIRT_HYPERVISOR_TYPE_DEFAULT       0
-#define PARAVIRT_HYPERVISOR_TYPE_XEN           1
 
 #ifndef __ASSEMBLY__
 
index 44ef9ef8f5b3ceb6b00505f49e443057385d91a5..42b233bedeb5ee864e636af07d05b3e83fb0fa17 100644 (file)
@@ -11,7 +11,7 @@
 /*
  * These structs MUST NOT be changed.
  * They are the ABI between hypervisor and guest OS.
- * Both Xen and KVM are using this.
+ * KVM is using this.
  *
  * pvclock_vcpu_time_info holds the system time and the tsc timestamp
  * of the last update. So the guest can use the tsc delta to get a
diff --git a/arch/ia64/include/asm/sync_bitops.h b/arch/ia64/include/asm/sync_bitops.h
deleted file mode 100644 (file)
index 593c12e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef _ASM_IA64_SYNC_BITOPS_H
-#define _ASM_IA64_SYNC_BITOPS_H
-
-/*
- * Copyright (C) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *
- * Based on synch_bitops.h which Dan Magenhaimer wrote.
- *
- * bit operations which provide guaranteed strong synchronisation
- * when communicating with Xen or other guest OSes running on other CPUs.
- */
-
-static inline void sync_set_bit(int nr, volatile void *addr)
-{
-       set_bit(nr, addr);
-}
-
-static inline void sync_clear_bit(int nr, volatile void *addr)
-{
-       clear_bit(nr, addr);
-}
-
-static inline void sync_change_bit(int nr, volatile void *addr)
-{
-       change_bit(nr, addr);
-}
-
-static inline int sync_test_and_set_bit(int nr, volatile void *addr)
-{
-       return test_and_set_bit(nr, addr);
-}
-
-static inline int sync_test_and_clear_bit(int nr, volatile void *addr)
-{
-       return test_and_clear_bit(nr, addr);
-}
-
-static inline int sync_test_and_change_bit(int nr, volatile void *addr)
-{
-       return test_and_change_bit(nr, addr);
-}
-
-static inline int sync_test_bit(int nr, const volatile void *addr)
-{
-       return test_bit(nr, addr);
-}
-
-#define sync_cmpxchg(ptr, old, new)                            \
-       ((__typeof__(*(ptr)))cmpxchg_acq((ptr), (old), (new)))
-
-#endif /* _ASM_IA64_SYNC_BITOPS_H */
diff --git a/arch/ia64/include/asm/xen/events.h b/arch/ia64/include/asm/xen/events.h
deleted file mode 100644 (file)
index baa74c8..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/events.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- */
-#ifndef _ASM_IA64_XEN_EVENTS_H
-#define _ASM_IA64_XEN_EVENTS_H
-
-enum ipi_vector {
-       XEN_RESCHEDULE_VECTOR,
-       XEN_IPI_VECTOR,
-       XEN_CMCP_VECTOR,
-       XEN_CPEP_VECTOR,
-
-       XEN_NR_IPIS,
-};
-
-static inline int xen_irqs_disabled(struct pt_regs *regs)
-{
-       return !(ia64_psr(regs)->i);
-}
-
-#define irq_ctx_init(cpu)      do { } while (0)
-
-#endif /* _ASM_IA64_XEN_EVENTS_H */
diff --git a/arch/ia64/include/asm/xen/hypercall.h b/arch/ia64/include/asm/xen/hypercall.h
deleted file mode 100644 (file)
index ed28bcd..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/******************************************************************************
- * hypercall.h
- *
- * Linux-specific hypervisor handling.
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * 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 _ASM_IA64_XEN_HYPERCALL_H
-#define _ASM_IA64_XEN_HYPERCALL_H
-
-#include <xen/interface/xen.h>
-#include <xen/interface/physdev.h>
-#include <xen/interface/sched.h>
-#include <asm/xen/xcom_hcall.h>
-struct xencomm_handle;
-extern unsigned long __hypercall(unsigned long a1, unsigned long a2,
-                                unsigned long a3, unsigned long a4,
-                                unsigned long a5, unsigned long cmd);
-
-/*
- * Assembler stubs for hyper-calls.
- */
-
-#define _hypercall0(type, name)                                        \
-({                                                             \
-       long __res;                                             \
-       __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\
-       (type)__res;                                            \
-})
-
-#define _hypercall1(type, name, a1)                            \
-({                                                             \
-       long __res;                                             \
-       __res = __hypercall((unsigned long)a1,                  \
-                            0, 0, 0, 0, __HYPERVISOR_##name);  \
-       (type)__res;                                            \
-})
-
-#define _hypercall2(type, name, a1, a2)                                \
-({                                                             \
-       long __res;                                             \
-       __res = __hypercall((unsigned long)a1,                  \
-                           (unsigned long)a2,                  \
-                           0, 0, 0, __HYPERVISOR_##name);      \
-       (type)__res;                                            \
-})
-
-#define _hypercall3(type, name, a1, a2, a3)                    \
-({                                                             \
-       long __res;                                             \
-       __res = __hypercall((unsigned long)a1,                  \
-                           (unsigned long)a2,                  \
-                           (unsigned long)a3,                  \
-                           0, 0, __HYPERVISOR_##name);         \
-       (type)__res;                                            \
-})
-
-#define _hypercall4(type, name, a1, a2, a3, a4)                        \
-({                                                             \
-       long __res;                                             \
-       __res = __hypercall((unsigned long)a1,                  \
-                           (unsigned long)a2,                  \
-                           (unsigned long)a3,                  \
-                           (unsigned long)a4,                  \
-                           0, __HYPERVISOR_##name);            \
-       (type)__res;                                            \
-})
-
-#define _hypercall5(type, name, a1, a2, a3, a4, a5)            \
-({                                                             \
-       long __res;                                             \
-       __res = __hypercall((unsigned long)a1,                  \
-                           (unsigned long)a2,                  \
-                           (unsigned long)a3,                  \
-                           (unsigned long)a4,                  \
-                           (unsigned long)a5,                  \
-                           __HYPERVISOR_##name);               \
-       (type)__res;                                            \
-})
-
-
-static inline int
-xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg)
-{
-       return _hypercall2(int, sched_op, cmd, arg);
-}
-
-static inline long
-HYPERVISOR_set_timer_op(u64 timeout)
-{
-       unsigned long timeout_hi = (unsigned long)(timeout >> 32);
-       unsigned long timeout_lo = (unsigned long)timeout;
-       return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
-}
-
-static inline int
-xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list,
-                                int nr_calls)
-{
-       return _hypercall2(int, multicall, call_list, nr_calls);
-}
-
-static inline int
-xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg)
-{
-       return _hypercall2(int, memory_op, cmd, arg);
-}
-
-static inline int
-xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg)
-{
-       return _hypercall2(int, event_channel_op, cmd, arg);
-}
-
-static inline int
-xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg)
-{
-       return _hypercall2(int, xen_version, cmd, arg);
-}
-
-static inline int
-xencomm_arch_hypercall_console_io(int cmd, int count,
-                                 struct xencomm_handle *str)
-{
-       return _hypercall3(int, console_io, cmd, count, str);
-}
-
-static inline int
-xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg)
-{
-       return _hypercall2(int, physdev_op, cmd, arg);
-}
-
-static inline int
-xencomm_arch_hypercall_grant_table_op(unsigned int cmd,
-                                     struct xencomm_handle *uop,
-                                     unsigned int count)
-{
-       return _hypercall3(int, grant_table_op, cmd, uop, count);
-}
-
-int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
-
-extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg);
-
-static inline int
-xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg)
-{
-       return _hypercall2(int, callback_op, cmd, arg);
-}
-
-static inline long
-xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg)
-{
-       return _hypercall3(long, vcpu_op, cmd, cpu, arg);
-}
-
-static inline int
-HYPERVISOR_physdev_op(int cmd, void *arg)
-{
-       switch (cmd) {
-       case PHYSDEVOP_eoi:
-               return _hypercall1(int, ia64_fast_eoi,
-                                  ((struct physdev_eoi *)arg)->irq);
-       default:
-               return xencomm_hypercall_physdev_op(cmd, arg);
-       }
-}
-
-static inline long
-xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg)
-{
-       return _hypercall1(long, opt_feature, arg);
-}
-
-/* for balloon driver */
-#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
-
-/* Use xencomm to do hypercalls.  */
-#define HYPERVISOR_sched_op xencomm_hypercall_sched_op
-#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op
-#define HYPERVISOR_callback_op xencomm_hypercall_callback_op
-#define HYPERVISOR_multicall xencomm_hypercall_multicall
-#define HYPERVISOR_xen_version xencomm_hypercall_xen_version
-#define HYPERVISOR_console_io xencomm_hypercall_console_io
-#define HYPERVISOR_memory_op xencomm_hypercall_memory_op
-#define HYPERVISOR_suspend xencomm_hypercall_suspend
-#define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op
-#define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature
-
-/* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */
-#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; })
-
-static inline int
-HYPERVISOR_shutdown(
-       unsigned int reason)
-{
-       struct sched_shutdown sched_shutdown = {
-               .reason = reason
-       };
-
-       int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
-
-       return rc;
-}
-
-/* for netfront.c, netback.c */
-#define MULTI_UVMFLAGS_INDEX 0 /* XXX any value */
-
-static inline void
-MULTI_update_va_mapping(
-       struct multicall_entry *mcl, unsigned long va,
-       pte_t new_val, unsigned long flags)
-{
-       mcl->op = __HYPERVISOR_update_va_mapping;
-       mcl->result = 0;
-}
-
-static inline void
-MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
-       void *uop, unsigned int count)
-{
-       mcl->op = __HYPERVISOR_grant_table_op;
-       mcl->args[0] = cmd;
-       mcl->args[1] = (unsigned long)uop;
-       mcl->args[2] = count;
-}
-
-static inline void
-MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
-                int count, int *success_count, domid_t domid)
-{
-       mcl->op = __HYPERVISOR_mmu_update;
-       mcl->args[0] = (unsigned long)req;
-       mcl->args[1] = count;
-       mcl->args[2] = (unsigned long)success_count;
-       mcl->args[3] = domid;
-}
-
-#endif /* _ASM_IA64_XEN_HYPERCALL_H */
diff --git a/arch/ia64/include/asm/xen/hypervisor.h b/arch/ia64/include/asm/xen/hypervisor.h
deleted file mode 100644 (file)
index 67455c2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/******************************************************************************
- * hypervisor.h
- *
- * Linux-specific hypervisor handling.
- *
- * Copyright (c) 2002-2004, K A Fraser
- *
- * 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 _ASM_IA64_XEN_HYPERVISOR_H
-#define _ASM_IA64_XEN_HYPERVISOR_H
-
-#include <linux/err.h>
-#include <xen/interface/xen.h>
-#include <xen/interface/version.h>     /* to compile feature.c */
-#include <xen/features.h>              /* to comiple xen-netfront.c */
-#include <xen/xen.h>
-#include <asm/xen/hypercall.h>
-
-#ifdef CONFIG_XEN
-extern struct shared_info *HYPERVISOR_shared_info;
-extern struct start_info *xen_start_info;
-
-void __init xen_setup_vcpu_info_placement(void);
-void force_evtchn_callback(void);
-
-/* for drivers/xen/balloon/balloon.c */
-#ifdef CONFIG_XEN_SCRUB_PAGES
-#define scrub_pages(_p, _n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
-#else
-#define scrub_pages(_p, _n) ((void)0)
-#endif
-
-/* For setup_arch() in arch/ia64/kernel/setup.c */
-void xen_ia64_enable_opt_feature(void);
-#endif
-
-#endif /* _ASM_IA64_XEN_HYPERVISOR_H */
diff --git a/arch/ia64/include/asm/xen/inst.h b/arch/ia64/include/asm/xen/inst.h
deleted file mode 100644 (file)
index c53a476..0000000
+++ /dev/null
@@ -1,486 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/inst.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <asm/xen/privop.h>
-
-#define ia64_ivt                               xen_ivt
-#define DO_SAVE_MIN                            XEN_DO_SAVE_MIN
-
-#define __paravirt_switch_to                   xen_switch_to
-#define __paravirt_leave_syscall               xen_leave_syscall
-#define __paravirt_work_processed_syscall      xen_work_processed_syscall
-#define __paravirt_leave_kernel                        xen_leave_kernel
-#define __paravirt_pending_syscall_end         xen_work_pending_syscall_end
-#define __paravirt_work_processed_syscall_target \
-                                               xen_work_processed_syscall
-
-#define paravirt_fsyscall_table                        xen_fsyscall_table
-#define paravirt_fsys_bubble_down              xen_fsys_bubble_down
-
-#define MOV_FROM_IFA(reg)      \
-       movl reg = XSI_IFA;     \
-       ;;                      \
-       ld8 reg = [reg]
-
-#define MOV_FROM_ITIR(reg)     \
-       movl reg = XSI_ITIR;    \
-       ;;                      \
-       ld8 reg = [reg]
-
-#define MOV_FROM_ISR(reg)      \
-       movl reg = XSI_ISR;     \
-       ;;                      \
-       ld8 reg = [reg]
-
-#define MOV_FROM_IHA(reg)      \
-       movl reg = XSI_IHA;     \
-       ;;                      \
-       ld8 reg = [reg]
-
-#define MOV_FROM_IPSR(pred, reg)       \
-(pred) movl reg = XSI_IPSR;            \
-       ;;                              \
-(pred) ld8 reg = [reg]
-
-#define MOV_FROM_IIM(reg)      \
-       movl reg = XSI_IIM;     \
-       ;;                      \
-       ld8 reg = [reg]
-
-#define MOV_FROM_IIP(reg)      \
-       movl reg = XSI_IIP;     \
-       ;;                      \
-       ld8 reg = [reg]
-
-.macro __MOV_FROM_IVR reg, clob
-       .ifc "\reg", "r8"
-               XEN_HYPER_GET_IVR
-               .exitm
-       .endif
-       .ifc "\clob", "r8"
-               XEN_HYPER_GET_IVR
-               ;;
-               mov \reg = r8
-               .exitm
-       .endif
-
-       mov \clob = r8
-       ;;
-       XEN_HYPER_GET_IVR
-       ;;
-       mov \reg = r8
-       ;;
-       mov r8 = \clob
-.endm
-#define MOV_FROM_IVR(reg, clob)        __MOV_FROM_IVR reg, clob
-
-.macro __MOV_FROM_PSR pred, reg, clob
-       .ifc "\reg", "r8"
-               (\pred) XEN_HYPER_GET_PSR;
-               .exitm
-       .endif
-       .ifc "\clob", "r8"
-               (\pred) XEN_HYPER_GET_PSR
-               ;;
-               (\pred) mov \reg = r8
-               .exitm
-       .endif
-
-       (\pred) mov \clob = r8
-       (\pred) XEN_HYPER_GET_PSR
-       ;;
-       (\pred) mov \reg = r8
-       (\pred) mov r8 = \clob
-.endm
-#define MOV_FROM_PSR(pred, reg, clob)  __MOV_FROM_PSR pred, reg, clob
-
-/* assuming ar.itc is read with interrupt disabled. */
-#define MOV_FROM_ITC(pred, pred_clob, reg, clob)               \
-(pred) movl clob = XSI_ITC_OFFSET;                             \
-       ;;                                                      \
-(pred) ld8 clob = [clob];                                      \
-(pred) mov reg = ar.itc;                                       \
-       ;;                                                      \
-(pred) add reg = reg, clob;                                    \
-       ;;                                                      \
-(pred) movl clob = XSI_ITC_LAST;                               \
-       ;;                                                      \
-(pred) ld8 clob = [clob];                                      \
-       ;;                                                      \
-(pred) cmp.geu.unc pred_clob, p0 = clob, reg;                  \
-       ;;                                                      \
-(pred_clob)    add reg = 1, clob;                              \
-       ;;                                                      \
-(pred) movl clob = XSI_ITC_LAST;                               \
-       ;;                                                      \
-(pred) st8 [clob] = reg
-
-
-#define MOV_TO_IFA(reg, clob)  \
-       movl clob = XSI_IFA;    \
-       ;;                      \
-       st8 [clob] = reg        \
-
-#define MOV_TO_ITIR(pred, reg, clob)   \
-(pred) movl clob = XSI_ITIR;           \
-       ;;                              \
-(pred) st8 [clob] = reg
-
-#define MOV_TO_IHA(pred, reg, clob)    \
-(pred) movl clob = XSI_IHA;            \
-       ;;                              \
-(pred) st8 [clob] = reg
-
-#define MOV_TO_IPSR(pred, reg, clob)   \
-(pred) movl clob = XSI_IPSR;           \
-       ;;                              \
-(pred) st8 [clob] = reg;               \
-       ;;
-
-#define MOV_TO_IFS(pred, reg, clob)    \
-(pred) movl clob = XSI_IFS;            \
-       ;;                              \
-(pred) st8 [clob] = reg;               \
-       ;;
-
-#define MOV_TO_IIP(reg, clob)  \
-       movl clob = XSI_IIP;    \
-       ;;                      \
-       st8 [clob] = reg
-
-.macro ____MOV_TO_KR kr, reg, clob0, clob1
-       .ifc "\clob0", "r9"
-               .error "clob0 \clob0 must not be r9"
-       .endif
-       .ifc "\clob1", "r8"
-               .error "clob1 \clob1 must not be r8"
-       .endif
-
-       .ifnc "\reg", "r9"
-               .ifnc "\clob1", "r9"
-                       mov \clob1 = r9
-               .endif
-               mov r9 = \reg
-       .endif
-       .ifnc "\clob0", "r8"
-               mov \clob0 = r8
-       .endif
-       mov r8 = \kr
-       ;;
-       XEN_HYPER_SET_KR
-
-       .ifnc "\reg", "r9"
-               .ifnc "\clob1", "r9"
-                       mov r9 = \clob1
-               .endif
-       .endif
-       .ifnc "\clob0", "r8"
-               mov r8 = \clob0
-       .endif
-.endm
-
-.macro __MOV_TO_KR kr, reg, clob0, clob1
-       .ifc "\clob0", "r9"
-               ____MOV_TO_KR \kr, \reg, \clob1, \clob0
-               .exitm
-       .endif
-       .ifc "\clob1", "r8"
-               ____MOV_TO_KR \kr, \reg, \clob1, \clob0
-               .exitm
-       .endif
-
-       ____MOV_TO_KR \kr, \reg, \clob0, \clob1
-.endm
-
-#define MOV_TO_KR(kr, reg, clob0, clob1) \
-       __MOV_TO_KR IA64_KR_ ## kr, reg, clob0, clob1
-
-
-.macro __ITC_I pred, reg, clob
-       .ifc "\reg", "r8"
-               (\pred) XEN_HYPER_ITC_I
-               .exitm
-       .endif
-       .ifc "\clob", "r8"
-               (\pred) mov r8 = \reg
-               ;;
-               (\pred) XEN_HYPER_ITC_I
-               .exitm
-       .endif
-
-       (\pred) mov \clob = r8
-       (\pred) mov r8 = \reg
-       ;;
-       (\pred) XEN_HYPER_ITC_I
-       ;;
-       (\pred) mov r8 = \clob
-       ;;
-.endm
-#define ITC_I(pred, reg, clob) __ITC_I pred, reg, clob
-
-.macro __ITC_D pred, reg, clob
-       .ifc "\reg", "r8"
-               (\pred) XEN_HYPER_ITC_D
-               ;;
-               .exitm
-       .endif
-       .ifc "\clob", "r8"
-               (\pred) mov r8 = \reg
-               ;;
-               (\pred) XEN_HYPER_ITC_D
-               ;;
-               .exitm
-       .endif
-
-       (\pred) mov \clob = r8
-       (\pred) mov r8 = \reg
-       ;;
-       (\pred) XEN_HYPER_ITC_D
-       ;;
-       (\pred) mov r8 = \clob
-       ;;
-.endm
-#define ITC_D(pred, reg, clob) __ITC_D pred, reg, clob
-
-.macro __ITC_I_AND_D pred_i, pred_d, reg, clob
-       .ifc "\reg", "r8"
-               (\pred_i)XEN_HYPER_ITC_I
-               ;;
-               (\pred_d)XEN_HYPER_ITC_D
-               ;;
-               .exitm
-       .endif
-       .ifc "\clob", "r8"
-               mov r8 = \reg
-               ;;
-               (\pred_i)XEN_HYPER_ITC_I
-               ;;
-               (\pred_d)XEN_HYPER_ITC_D
-               ;;
-               .exitm
-       .endif
-
-       mov \clob = r8
-       mov r8 = \reg
-       ;;
-       (\pred_i)XEN_HYPER_ITC_I
-       ;;
-       (\pred_d)XEN_HYPER_ITC_D
-       ;;
-       mov r8 = \clob
-       ;;
-.endm
-#define ITC_I_AND_D(pred_i, pred_d, reg, clob) \
-       __ITC_I_AND_D pred_i, pred_d, reg, clob
-
-.macro __THASH pred, reg0, reg1, clob
-       .ifc "\reg0", "r8"
-               (\pred) mov r8 = \reg1
-               (\pred) XEN_HYPER_THASH
-               .exitm
-       .endc
-       .ifc "\reg1", "r8"
-               (\pred) XEN_HYPER_THASH
-               ;;
-               (\pred) mov \reg0 = r8
-               ;;
-               .exitm
-       .endif
-       .ifc "\clob", "r8"
-               (\pred) mov r8 = \reg1
-               (\pred) XEN_HYPER_THASH
-               ;;
-               (\pred) mov \reg0 = r8
-               ;;
-               .exitm
-       .endif
-
-       (\pred) mov \clob = r8
-       (\pred) mov r8 = \reg1
-       (\pred) XEN_HYPER_THASH
-       ;;
-       (\pred) mov \reg0 = r8
-       (\pred) mov r8 = \clob
-       ;;
-.endm
-#define THASH(pred, reg0, reg1, clob) __THASH pred, reg0, reg1, clob
-
-#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1)   \
-       mov clob0 = 1;                                          \
-       movl clob1 = XSI_PSR_IC;                                \
-       ;;                                                      \
-       st4 [clob1] = clob0                                     \
-       ;;
-
-#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1)    \
-       ;;                                      \
-       srlz.d;                                 \
-       mov clob1 = 1;                          \
-       movl clob0 = XSI_PSR_IC;                \
-       ;;                                      \
-       st4 [clob0] = clob1
-
-#define RSM_PSR_IC(clob)       \
-       movl clob = XSI_PSR_IC; \
-       ;;                      \
-       st4 [clob] = r0;        \
-       ;;
-
-/* pred will be clobbered */
-#define MASK_TO_PEND_OFS    (-1)
-#define SSM_PSR_I(pred, pred_clob, clob)                               \
-(pred) movl clob = XSI_PSR_I_ADDR                                      \
-       ;;                                                              \
-(pred) ld8 clob = [clob]                                               \
-       ;;                                                              \
-       /* if (pred) vpsr.i = 1 */                                      \
-       /* if (pred) (vcpu->vcpu_info->evtchn_upcall_mask)=0 */         \
-(pred) st1 [clob] = r0, MASK_TO_PEND_OFS                               \
-       ;;                                                              \
-       /* if (vcpu->vcpu_info->evtchn_upcall_pending) */               \
-(pred) ld1 clob = [clob]                                               \
-       ;;                                                              \
-(pred) cmp.ne.unc pred_clob, p0 = clob, r0                             \
-       ;;                                                              \
-(pred_clob)XEN_HYPER_SSM_I     /* do areal ssm psr.i */
-
-#define RSM_PSR_I(pred, clob0, clob1)  \
-       movl clob0 = XSI_PSR_I_ADDR;    \
-       mov clob1 = 1;                  \
-       ;;                              \
-       ld8 clob0 = [clob0];            \
-       ;;                              \
-(pred) st1 [clob0] = clob1
-
-#define RSM_PSR_I_IC(clob0, clob1, clob2)              \
-       movl clob0 = XSI_PSR_I_ADDR;                    \
-       movl clob1 = XSI_PSR_IC;                        \
-       ;;                                              \
-       ld8 clob0 = [clob0];                            \
-       mov clob2 = 1;                                  \
-       ;;                                              \
-       /* note: clears both vpsr.i and vpsr.ic! */     \
-       st1 [clob0] = clob2;                            \
-       st4 [clob1] = r0;                               \
-       ;;
-
-#define RSM_PSR_DT             \
-       XEN_HYPER_RSM_PSR_DT
-
-#define RSM_PSR_BE_I(clob0, clob1)     \
-       RSM_PSR_I(p0, clob0, clob1);    \
-       rum psr.be
-
-#define SSM_PSR_DT_AND_SRLZ_I  \
-       XEN_HYPER_SSM_PSR_DT
-
-#define BSW_0(clob0, clob1, clob2)                     \
-       ;;                                              \
-       /* r16-r31 all now hold bank1 values */         \
-       mov clob2 = ar.unat;                            \
-       movl clob0 = XSI_BANK1_R16;                     \
-       movl clob1 = XSI_BANK1_R16 + 8;                 \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r16, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r17, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r18, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r19, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r20, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r21, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r22, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r23, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r24, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r25, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r26, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r27, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r28, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r29, 16;         \
-       ;;                                              \
-.mem.offset 0, 0; st8.spill [clob0] = r30, 16;         \
-.mem.offset 8, 0; st8.spill [clob1] = r31, 16;         \
-       ;;                                              \
-       mov clob1 = ar.unat;                            \
-       movl clob0 = XSI_B1NAT;                         \
-       ;;                                              \
-       st8 [clob0] = clob1;                            \
-       mov ar.unat = clob2;                            \
-       movl clob0 = XSI_BANKNUM;                       \
-       ;;                                              \
-       st4 [clob0] = r0
-
-
-       /* FIXME: THIS CODE IS NOT NaT SAFE! */
-#define XEN_BSW_1(clob)                        \
-       mov clob = ar.unat;             \
-       movl r30 = XSI_B1NAT;           \
-       ;;                              \
-       ld8 r30 = [r30];                \
-       mov r31 = 1;                    \
-       ;;                              \
-       mov ar.unat = r30;              \
-       movl r30 = XSI_BANKNUM;         \
-       ;;                              \
-       st4 [r30] = r31;                \
-       movl r30 = XSI_BANK1_R16;       \
-       movl r31 = XSI_BANK1_R16+8;     \
-       ;;                              \
-       ld8.fill r16 = [r30], 16;       \
-       ld8.fill r17 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r18 = [r30], 16;       \
-       ld8.fill r19 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r20 = [r30], 16;       \
-       ld8.fill r21 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r22 = [r30], 16;       \
-       ld8.fill r23 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r24 = [r30], 16;       \
-       ld8.fill r25 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r26 = [r30], 16;       \
-       ld8.fill r27 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r28 = [r30], 16;       \
-       ld8.fill r29 = [r31], 16;       \
-       ;;                              \
-       ld8.fill r30 = [r30];           \
-       ld8.fill r31 = [r31];           \
-       ;;                              \
-       mov ar.unat = clob
-
-#define BSW_1(clob0, clob1)    XEN_BSW_1(clob1)
-
-
-#define COVER  \
-       XEN_HYPER_COVER
-
-#define RFI                    \
-       XEN_HYPER_RFI;          \
-       dv_serialize_data
diff --git a/arch/ia64/include/asm/xen/interface.h b/arch/ia64/include/asm/xen/interface.h
deleted file mode 100644 (file)
index e88c5de..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/******************************************************************************
- * arch-ia64/hypervisor-if.h
- *
- * Guest OS interface to IA64 Xen.
- *
- * 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 by those who contributed. (in alphabetical order)
- *
- * Anthony Xu <anthony.xu@intel.com>
- * Eddie Dong <eddie.dong@intel.com>
- * Fred Yang <fred.yang@intel.com>
- * Kevin Tian <kevin.tian@intel.com>
- * Alex Williamson <alex.williamson@hp.com>
- * Chris Wright <chrisw@sous-sol.org>
- * Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
- * Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
- * Hollis Blanchard <hollisb@us.ibm.com>
- * Isaku Yamahata <yamahata@valinux.co.jp>
- * Jan Beulich <jbeulich@novell.com>
- * John Levon <john.levon@sun.com>
- * Kazuhiro Suzuki <kaz@jp.fujitsu.com>
- * Keir Fraser <keir.fraser@citrix.com>
- * Kouya Shimura <kouya@jp.fujitsu.com>
- * Masaki Kanno <kanno.masaki@jp.fujitsu.com>
- * Matt Chapman <matthewc@hp.com>
- * Matthew Chapman <matthewc@hp.com>
- * Samuel Thibault <samuel.thibault@eu.citrix.com>
- * Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
- * Tristan Gingold <tgingold@free.fr>
- * Tsunehisa Doi <Doi.Tsunehisa@jp.fujitsu.com>
- * Yutaka Ezaki <yutaka.ezaki@jp.fujitsu.com>
- * Zhang Xin <xing.z.zhang@intel.com>
- * Zhang xiantao <xiantao.zhang@intel.com>
- * dan.magenheimer@hp.com
- * ian.pratt@cl.cam.ac.uk
- * michael.fetterman@cl.cam.ac.uk
- */
-
-#ifndef _ASM_IA64_XEN_INTERFACE_H
-#define _ASM_IA64_XEN_INTERFACE_H
-
-#define __DEFINE_GUEST_HANDLE(name, type)      \
-       typedef struct { type *p; } __guest_handle_ ## name
-
-#define DEFINE_GUEST_HANDLE_STRUCT(name)       \
-       __DEFINE_GUEST_HANDLE(name, struct name)
-#define DEFINE_GUEST_HANDLE(name)      __DEFINE_GUEST_HANDLE(name, name)
-#define GUEST_HANDLE(name)             __guest_handle_ ## name
-#define GUEST_HANDLE_64(name)          GUEST_HANDLE(name)
-#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
-
-#ifndef __ASSEMBLY__
-/* Explicitly size integers that represent pfns in the public interface
- * with Xen so that we could have one ABI that works for 32 and 64 bit
- * guests. */
-typedef unsigned long xen_pfn_t;
-typedef unsigned long xen_ulong_t;
-/* Guest handles for primitive C types. */
-__DEFINE_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_GUEST_HANDLE(uint, unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
-
-DEFINE_GUEST_HANDLE(char);
-DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
-DEFINE_GUEST_HANDLE(void);
-DEFINE_GUEST_HANDLE(uint64_t);
-DEFINE_GUEST_HANDLE(uint32_t);
-
-DEFINE_GUEST_HANDLE(xen_pfn_t);
-#define PRI_xen_pfn    "lx"
-#endif
-
-/* Arch specific VIRQs definition */
-#define VIRQ_ITC       VIRQ_ARCH_0     /* V. Virtual itc timer */
-#define VIRQ_MCA_CMC   VIRQ_ARCH_1     /* MCA cmc interrupt */
-#define VIRQ_MCA_CPE   VIRQ_ARCH_2     /* MCA cpe interrupt */
-
-/* Maximum number of virtual CPUs in multi-processor guests. */
-/* keep sizeof(struct shared_page) <= PAGE_SIZE.
- * this is checked in arch/ia64/xen/hypervisor.c. */
-#define MAX_VIRT_CPUS  64
-
-#ifndef __ASSEMBLY__
-
-#define INVALID_MFN    (~0UL)
-
-union vac {
-       unsigned long value;
-       struct {
-               int a_int:1;
-               int a_from_int_cr:1;
-               int a_to_int_cr:1;
-               int a_from_psr:1;
-               int a_from_cpuid:1;
-               int a_cover:1;
-               int a_bsw:1;
-               long reserved:57;
-       };
-};
-
-union vdc {
-       unsigned long value;
-       struct {
-               int d_vmsw:1;
-               int d_extint:1;
-               int d_ibr_dbr:1;
-               int d_pmc:1;
-               int d_to_pmd:1;
-               int d_itm:1;
-               long reserved:58;
-       };
-};
-
-struct mapped_regs {
-       union vac vac;
-       union vdc vdc;
-       unsigned long virt_env_vaddr;
-       unsigned long reserved1[29];
-       unsigned long vhpi;
-       unsigned long reserved2[95];
-       union {
-               unsigned long vgr[16];
-               unsigned long bank1_regs[16];   /* bank1 regs (r16-r31)
-                                                  when bank0 active */
-       };
-       union {
-               unsigned long vbgr[16];
-               unsigned long bank0_regs[16];   /* bank0 regs (r16-r31)
-                                                  when bank1 active */
-       };
-       unsigned long vnat;
-       unsigned long vbnat;
-       unsigned long vcpuid[5];
-       unsigned long reserved3[11];
-       unsigned long vpsr;
-       unsigned long vpr;
-       unsigned long reserved4[76];
-       union {
-               unsigned long vcr[128];
-               struct {
-                       unsigned long dcr;      /* CR0 */
-                       unsigned long itm;
-                       unsigned long iva;
-                       unsigned long rsv1[5];
-                       unsigned long pta;      /* CR8 */
-                       unsigned long rsv2[7];
-                       unsigned long ipsr;     /* CR16 */
-                       unsigned long isr;
-                       unsigned long rsv3;
-                       unsigned long iip;
-                       unsigned long ifa;
-                       unsigned long itir;
-                       unsigned long iipa;
-                       unsigned long ifs;
-                       unsigned long iim;      /* CR24 */
-                       unsigned long iha;
-                       unsigned long rsv4[38];
-                       unsigned long lid;      /* CR64 */
-                       unsigned long ivr;
-                       unsigned long tpr;
-                       unsigned long eoi;
-                       unsigned long irr[4];
-                       unsigned long itv;      /* CR72 */
-                       unsigned long pmv;
-                       unsigned long cmcv;
-                       unsigned long rsv5[5];
-                       unsigned long lrr0;     /* CR80 */
-                       unsigned long lrr1;
-                       unsigned long rsv6[46];
-               };
-       };
-       union {
-               unsigned long reserved5[128];
-               struct {
-                       unsigned long precover_ifs;
-                       unsigned long unat;     /* not sure if this is needed
-                                                  until NaT arch is done */
-                       int interrupt_collection_enabled; /* virtual psr.ic */
-
-                       /* virtual interrupt deliverable flag is
-                        * evtchn_upcall_mask in shared info area now.
-                        * interrupt_mask_addr is the address
-                        * of evtchn_upcall_mask for current vcpu
-                        */
-                       unsigned char *interrupt_mask_addr;
-                       int pending_interruption;
-                       unsigned char vpsr_pp;
-                       unsigned char vpsr_dfh;
-                       unsigned char hpsr_dfh;
-                       unsigned char hpsr_mfh;
-                       unsigned long reserved5_1[4];
-                       int metaphysical_mode;  /* 1 = use metaphys mapping
-                                                  0 = use virtual */
-                       int banknum;            /* 0 or 1, which virtual
-                                                  register bank is active */
-                       unsigned long rrs[8];   /* region registers */
-                       unsigned long krs[8];   /* kernel registers */
-                       unsigned long tmp[16];  /* temp registers
-                                                  (e.g. for hyperprivops) */
-
-                       /* itc paravirtualization
-                        * vAR.ITC = mAR.ITC + itc_offset
-                        * itc_last is one which was lastly passed to
-                        * the guest OS in order to prevent it from
-                        * going backwords.
-                        */
-                       unsigned long itc_offset;
-                       unsigned long itc_last;
-               };
-       };
-};
-
-struct arch_vcpu_info {
-       /* nothing */
-};
-
-/*
- * This structure is used for magic page in domain pseudo physical address
- * space and the result of XENMEM_machine_memory_map.
- * As the XENMEM_machine_memory_map result,
- * xen_memory_map::nr_entries indicates the size in bytes
- * including struct xen_ia64_memmap_info. Not the number of entries.
- */
-struct xen_ia64_memmap_info {
-       uint64_t efi_memmap_size;       /* size of EFI memory map */
-       uint64_t efi_memdesc_size;      /* size of an EFI memory map
-                                        * descriptor */
-       uint32_t efi_memdesc_version;   /* memory descriptor version */
-       void *memdesc[0];               /* array of efi_memory_desc_t */
-};
-
-struct arch_shared_info {
-       /* PFN of the start_info page.  */
-       unsigned long start_info_pfn;
-
-       /* Interrupt vector for event channel.  */
-       int evtchn_vector;
-
-       /* PFN of memmap_info page */
-       unsigned int memmap_info_num_pages;     /* currently only = 1 case is
-                                                  supported. */
-       unsigned long memmap_info_pfn;
-
-       uint64_t pad[31];
-};
-
-struct xen_callback {
-       unsigned long ip;
-};
-typedef struct xen_callback xen_callback_t;
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/pvclock-abi.h>
-
-/* Size of the shared_info area (this is not related to page size).  */
-#define XSI_SHIFT                      14
-#define XSI_SIZE                       (1 << XSI_SHIFT)
-/* Log size of mapped_regs area (64 KB - only 4KB is used).  */
-#define XMAPPEDREGS_SHIFT              12
-#define XMAPPEDREGS_SIZE               (1 << XMAPPEDREGS_SHIFT)
-/* Offset of XASI (Xen arch shared info) wrt XSI_BASE. */
-#define XMAPPEDREGS_OFS                        XSI_SIZE
-
-/* Hyperprivops.  */
-#define HYPERPRIVOP_START              0x1
-#define HYPERPRIVOP_RFI                        (HYPERPRIVOP_START + 0x0)
-#define HYPERPRIVOP_RSM_DT             (HYPERPRIVOP_START + 0x1)
-#define HYPERPRIVOP_SSM_DT             (HYPERPRIVOP_START + 0x2)
-#define HYPERPRIVOP_COVER              (HYPERPRIVOP_START + 0x3)
-#define HYPERPRIVOP_ITC_D              (HYPERPRIVOP_START + 0x4)
-#define HYPERPRIVOP_ITC_I              (HYPERPRIVOP_START + 0x5)
-#define HYPERPRIVOP_SSM_I              (HYPERPRIVOP_START + 0x6)
-#define HYPERPRIVOP_GET_IVR            (HYPERPRIVOP_START + 0x7)
-#define HYPERPRIVOP_GET_TPR            (HYPERPRIVOP_START + 0x8)
-#define HYPERPRIVOP_SET_TPR            (HYPERPRIVOP_START + 0x9)
-#define HYPERPRIVOP_EOI                        (HYPERPRIVOP_START + 0xa)
-#define HYPERPRIVOP_SET_ITM            (HYPERPRIVOP_START + 0xb)
-#define HYPERPRIVOP_THASH              (HYPERPRIVOP_START + 0xc)
-#define HYPERPRIVOP_PTC_GA             (HYPERPRIVOP_START + 0xd)
-#define HYPERPRIVOP_ITR_D              (HYPERPRIVOP_START + 0xe)
-#define HYPERPRIVOP_GET_RR             (HYPERPRIVOP_START + 0xf)
-#define HYPERPRIVOP_SET_RR             (HYPERPRIVOP_START + 0x10)
-#define HYPERPRIVOP_SET_KR             (HYPERPRIVOP_START + 0x11)
-#define HYPERPRIVOP_FC                 (HYPERPRIVOP_START + 0x12)
-#define HYPERPRIVOP_GET_CPUID          (HYPERPRIVOP_START + 0x13)
-#define HYPERPRIVOP_GET_PMD            (HYPERPRIVOP_START + 0x14)
-#define HYPERPRIVOP_GET_EFLAG          (HYPERPRIVOP_START + 0x15)
-#define HYPERPRIVOP_SET_EFLAG          (HYPERPRIVOP_START + 0x16)
-#define HYPERPRIVOP_RSM_BE             (HYPERPRIVOP_START + 0x17)
-#define HYPERPRIVOP_GET_PSR            (HYPERPRIVOP_START + 0x18)
-#define HYPERPRIVOP_SET_RR0_TO_RR4     (HYPERPRIVOP_START + 0x19)
-#define HYPERPRIVOP_MAX                        (0x1a)
-
-/* Fast and light hypercalls.  */
-#define __HYPERVISOR_ia64_fast_eoi     __HYPERVISOR_arch_1
-
-/* Xencomm macros.  */
-#define XENCOMM_INLINE_MASK            0xf800000000000000UL
-#define XENCOMM_INLINE_FLAG            0x8000000000000000UL
-
-#ifndef __ASSEMBLY__
-
-/*
- * Optimization features.
- * The hypervisor may do some special optimizations for guests. This hypercall
- * can be used to switch on/of these special optimizations.
- */
-#define __HYPERVISOR_opt_feature       0x700UL
-
-#define XEN_IA64_OPTF_OFF              0x0
-#define XEN_IA64_OPTF_ON               0x1
-
-/*
- * If this feature is switched on, the hypervisor inserts the
- * tlb entries without calling the guests traphandler.
- * This is useful in guests using region 7 for identity mapping
- * like the linux kernel does.
- */
-#define XEN_IA64_OPTF_IDENT_MAP_REG7   1
-
-/* Identity mapping of region 4 addresses in HVM. */
-#define XEN_IA64_OPTF_IDENT_MAP_REG4   2
-
-/* Identity mapping of region 5 addresses in HVM. */
-#define XEN_IA64_OPTF_IDENT_MAP_REG5   3
-
-#define XEN_IA64_OPTF_IDENT_MAP_NOT_SET         (0)
-
-struct xen_ia64_opt_feature {
-       unsigned long cmd;      /* Which feature */
-       unsigned char on;       /* Switch feature on/off */
-       union {
-               struct {
-                       /* The page protection bit mask of the pte.
-                        * This will be or'ed with the pte. */
-                       unsigned long pgprot;
-                       unsigned long key;      /* A protection key for itir.*/
-               };
-       };
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_IA64_XEN_INTERFACE_H */
diff --git a/arch/ia64/include/asm/xen/irq.h b/arch/ia64/include/asm/xen/irq.h
deleted file mode 100644 (file)
index a904509..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/irq.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- */
-
-#ifndef _ASM_IA64_XEN_IRQ_H
-#define _ASM_IA64_XEN_IRQ_H
-
-/*
- * The flat IRQ space is divided into two regions:
- *  1. A one-to-one mapping of real physical IRQs. This space is only used
- *     if we have physical device-access privilege. This region is at the
- *     start of the IRQ space so that existing device drivers do not need
- *     to be modified to translate physical IRQ numbers into our IRQ space.
- *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
- *     are bound using the provided bind/unbind functions.
- */
-
-#define XEN_PIRQ_BASE          0
-#define XEN_NR_PIRQS           256
-
-#define XEN_DYNIRQ_BASE                (XEN_PIRQ_BASE + XEN_NR_PIRQS)
-#define XEN_NR_DYNIRQS         (NR_CPUS * 8)
-
-#define XEN_NR_IRQS            (XEN_NR_PIRQS + XEN_NR_DYNIRQS)
-
-#endif /* _ASM_IA64_XEN_IRQ_H */
diff --git a/arch/ia64/include/asm/xen/minstate.h b/arch/ia64/include/asm/xen/minstate.h
deleted file mode 100644 (file)
index 00cf03e..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
-/* read ar.itc in advance, and use it before leaving bank 0 */
-#define XEN_ACCOUNT_GET_STAMP          \
-       MOV_FROM_ITC(pUStk, p6, r20, r2);
-#else
-#define XEN_ACCOUNT_GET_STAMP
-#endif
-
-/*
- * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
- * the minimum state necessary that allows us to turn psr.ic back
- * on.
- *
- * Assumed state upon entry:
- *     psr.ic: off
- *     r31:    contains saved predicates (pr)
- *
- * Upon exit, the state is as follows:
- *     psr.ic: off
- *      r2 = points to &pt_regs.r16
- *      r8 = contents of ar.ccv
- *      r9 = contents of ar.csd
- *     r10 = contents of ar.ssd
- *     r11 = FPSR_DEFAULT
- *     r12 = kernel sp (kernel virtual address)
- *     r13 = points to current task_struct (kernel virtual address)
- *     p15 = TRUE if psr.i is set in cr.ipsr
- *     predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
- *             preserved
- * CONFIG_XEN note: p6/p7 are not preserved
- *
- * Note that psr.ic is NOT turned on by this macro.  This is so that
- * we can pass interruption state as arguments to a handler.
- */
-#define XEN_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND)                                     \
-       mov r16=IA64_KR(CURRENT);       /* M */                                                 \
-       mov r27=ar.rsc;                 /* M */                                                 \
-       mov r20=r1;                     /* A */                                                 \
-       mov r25=ar.unat;                /* M */                                                 \
-       MOV_FROM_IPSR(p0,r29);          /* M */                                                 \
-       MOV_FROM_IIP(r28);              /* M */                                                 \
-       mov r21=ar.fpsr;                /* M */                                                 \
-       mov r26=ar.pfs;                 /* I */                                                 \
-       __COVER;                        /* B;; (or nothing) */                                  \
-       adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16;                                         \
-       ;;                                                                                      \
-       ld1 r17=[r16];                          /* load current->thread.on_ustack flag */       \
-       st1 [r16]=r0;                           /* clear current->thread.on_ustack flag */      \
-       adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16                                          \
-       /* switch from user to kernel RBS: */                                                   \
-       ;;                                                                                      \
-       invala;                         /* M */                                                 \
-       /* SAVE_IFS;*/ /* see xen special handling below */                                     \
-       cmp.eq pKStk,pUStk=r0,r17;              /* are we in kernel mode already? */            \
-       ;;                                                                                      \
-(pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
-       ;;                                                                                      \
-(pUStk)        mov.m r24=ar.rnat;                                                                      \
-(pUStk)        addl r22=IA64_RBS_OFFSET,r1;                    /* compute base of RBS */               \
-(pKStk) mov r1=sp;                                     /* get sp  */                           \
-       ;;                                                                                      \
-(pUStk) lfetch.fault.excl.nt1 [r22];                                                           \
-(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;   /* compute base of memory stack */      \
-(pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
-       ;;                                                                                      \
-(pUStk)        mov ar.bspstore=r22;                            /* switch to kernel RBS */              \
-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1;                 /* if in kernel mode, use sp (r12) */   \
-       ;;                                                                                      \
-(pUStk)        mov r18=ar.bsp;                                                                         \
-(pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */             \
-       adds r17=2*L1_CACHE_BYTES,r1;           /* really: biggest cache-line size */           \
-       adds r16=PT(CR_IPSR),r1;                                                                \
-       ;;                                                                                      \
-       lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES;                                             \
-       st8 [r16]=r29;          /* save cr.ipsr */                                              \
-       ;;                                                                                      \
-       lfetch.fault.excl.nt1 [r17];                                                            \
-       tbit.nz p15,p0=r29,IA64_PSR_I_BIT;                                                      \
-       mov r29=b0                                                                              \
-       ;;                                                                                      \
-       WORKAROUND;                                                                             \
-       adds r16=PT(R8),r1;     /* initialize first base pointer */                             \
-       adds r17=PT(R9),r1;     /* initialize second base pointer */                            \
-(pKStk)        mov r18=r0;             /* make sure r18 isn't NaT */                                   \
-       ;;                                                                                      \
-.mem.offset 0,0; st8.spill [r16]=r8,16;                                                                \
-.mem.offset 8,0; st8.spill [r17]=r9,16;                                                                \
-        ;;                                                                                     \
-.mem.offset 0,0; st8.spill [r16]=r10,24;                                                       \
-       movl r8=XSI_PRECOVER_IFS;                                                               \
-.mem.offset 8,0; st8.spill [r17]=r11,24;                                                       \
-        ;;                                                                                     \
-       /* xen special handling for possibly lazy cover */                                      \
-       /* SAVE_MIN case in dispatch_ia32_handler: mov r30=r0 */                                \
-       ld8 r30=[r8];                                                                           \
-(pUStk)        sub r18=r18,r22;        /* r18=RSE.ndirty*8 */                                          \
-       st8 [r16]=r28,16;       /* save cr.iip */                                               \
-       ;;                                                                                      \
-       st8 [r17]=r30,16;       /* save cr.ifs */                                               \
-       mov r8=ar.ccv;                                                                          \
-       mov r9=ar.csd;                                                                          \
-       mov r10=ar.ssd;                                                                         \
-       movl r11=FPSR_DEFAULT;   /* L-unit */                                                   \
-       ;;                                                                                      \
-       st8 [r16]=r25,16;       /* save ar.unat */                                              \
-       st8 [r17]=r26,16;       /* save ar.pfs */                                               \
-       shl r18=r18,16;         /* compute ar.rsc to be used for "loadrs" */                    \
-       ;;                                                                                      \
-       st8 [r16]=r27,16;       /* save ar.rsc */                                               \
-(pUStk)        st8 [r17]=r24,16;       /* save ar.rnat */                                              \
-(pKStk)        adds r17=16,r17;        /* skip over ar_rnat field */                                   \
-       ;;                      /* avoid RAW on r16 & r17 */                                    \
-(pUStk)        st8 [r16]=r23,16;       /* save ar.bspstore */                                          \
-       st8 [r17]=r31,16;       /* save predicates */                                           \
-(pKStk)        adds r16=16,r16;        /* skip over ar_bspstore field */                               \
-       ;;                                                                                      \
-       st8 [r16]=r29,16;       /* save b0 */                                                   \
-       st8 [r17]=r18,16;       /* save ar.rsc value for "loadrs" */                            \
-       cmp.eq pNonSys,pSys=r0,r0       /* initialize pSys=0, pNonSys=1 */                      \
-       ;;                                                                                      \
-.mem.offset 0,0; st8.spill [r16]=r20,16;       /* save original r1 */                          \
-.mem.offset 8,0; st8.spill [r17]=r12,16;                                                       \
-       adds r12=-16,r1;        /* switch to kernel memory stack (with 16 bytes of scratch) */  \
-       ;;                                                                                      \
-.mem.offset 0,0; st8.spill [r16]=r13,16;                                                       \
-.mem.offset 8,0; st8.spill [r17]=r21,16;       /* save ar.fpsr */                              \
-       mov r13=IA64_KR(CURRENT);       /* establish `current' */                               \
-       ;;                                                                                      \
-.mem.offset 0,0; st8.spill [r16]=r15,16;                                                       \
-.mem.offset 8,0; st8.spill [r17]=r14,16;                                                       \
-       ;;                                                                                      \
-.mem.offset 0,0; st8.spill [r16]=r2,16;                                                                \
-.mem.offset 8,0; st8.spill [r17]=r3,16;                                                                \
-       XEN_ACCOUNT_GET_STAMP                                                                   \
-       adds r2=IA64_PT_REGS_R16_OFFSET,r1;                                                     \
-       ;;                                                                                      \
-       EXTRA;                                                                                  \
-       movl r1=__gp;           /* establish kernel global pointer */                           \
-       ;;                                                                                      \
-       ACCOUNT_SYS_ENTER                                                                       \
-       BSW_1(r3,r14);  /* switch back to bank 1 (must be last in insn group) */                \
-       ;;
diff --git a/arch/ia64/include/asm/xen/page-coherent.h b/arch/ia64/include/asm/xen/page-coherent.h
deleted file mode 100644 (file)
index 96e42f9..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef _ASM_IA64_XEN_PAGE_COHERENT_H
-#define _ASM_IA64_XEN_PAGE_COHERENT_H
-
-#include <asm/page.h>
-#include <linux/dma-attrs.h>
-#include <linux/dma-mapping.h>
-
-static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
-               dma_addr_t *dma_handle, gfp_t flags,
-               struct dma_attrs *attrs)
-{
-       void *vstart = (void*)__get_free_pages(flags, get_order(size));
-       *dma_handle = virt_to_phys(vstart);
-       return vstart;
-}
-
-static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
-               void *cpu_addr, dma_addr_t dma_handle,
-               struct dma_attrs *attrs)
-{
-       free_pages((unsigned long) cpu_addr, get_order(size));
-}
-
-static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
-            unsigned long offset, size_t size, enum dma_data_direction dir,
-            struct dma_attrs *attrs) { }
-
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir,
-               struct dma_attrs *attrs) { }
-
-static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
-
-static inline void xen_dma_sync_single_for_device(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
-
-#endif /* _ASM_IA64_XEN_PAGE_COHERENT_H */
diff --git a/arch/ia64/include/asm/xen/page.h b/arch/ia64/include/asm/xen/page.h
deleted file mode 100644 (file)
index 03441a7..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/page.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- */
-
-#ifndef _ASM_IA64_XEN_PAGE_H
-#define _ASM_IA64_XEN_PAGE_H
-
-#define INVALID_P2M_ENTRY      (~0UL)
-
-static inline unsigned long mfn_to_pfn(unsigned long mfn)
-{
-       return mfn;
-}
-
-static inline unsigned long pfn_to_mfn(unsigned long pfn)
-{
-       return pfn;
-}
-
-#define phys_to_machine_mapping_valid(_x)      (1)
-
-static inline void *mfn_to_virt(unsigned long mfn)
-{
-       return __va(mfn << PAGE_SHIFT);
-}
-
-static inline unsigned long virt_to_mfn(void *virt)
-{
-       return __pa(virt) >> PAGE_SHIFT;
-}
-
-/* for tpmfront.c */
-static inline unsigned long virt_to_machine(void *virt)
-{
-       return __pa(virt);
-}
-
-static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
-{
-       /* nothing */
-}
-
-#define pte_mfn(_x)    pte_pfn(_x)
-#define mfn_pte(_x, _y)        __pte_ma(0)             /* unmodified use */
-#define __pte_ma(_x)   ((pte_t) {(_x)})        /* unmodified use */
-
-#endif /* _ASM_IA64_XEN_PAGE_H */
diff --git a/arch/ia64/include/asm/xen/patchlist.h b/arch/ia64/include/asm/xen/patchlist.h
deleted file mode 100644 (file)
index eae944e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************
- * arch/ia64/include/asm/xen/patchlist.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- */
-
-#define __paravirt_start_gate_fsyscall_patchlist               \
-       __xen_start_gate_fsyscall_patchlist
-#define __paravirt_end_gate_fsyscall_patchlist                 \
-       __xen_end_gate_fsyscall_patchlist
-#define __paravirt_start_gate_brl_fsys_bubble_down_patchlist   \
-       __xen_start_gate_brl_fsys_bubble_down_patchlist
-#define __paravirt_end_gate_brl_fsys_bubble_down_patchlist     \
-       __xen_end_gate_brl_fsys_bubble_down_patchlist
-#define __paravirt_start_gate_vtop_patchlist                   \
-       __xen_start_gate_vtop_patchlist
-#define __paravirt_end_gate_vtop_patchlist                     \
-       __xen_end_gate_vtop_patchlist
-#define __paravirt_start_gate_mckinley_e9_patchlist            \
-       __xen_start_gate_mckinley_e9_patchlist
-#define __paravirt_end_gate_mckinley_e9_patchlist              \
-       __xen_end_gate_mckinley_e9_patchlist
diff --git a/arch/ia64/include/asm/xen/privop.h b/arch/ia64/include/asm/xen/privop.h
deleted file mode 100644 (file)
index fb4ec5e..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _ASM_IA64_XEN_PRIVOP_H
-#define _ASM_IA64_XEN_PRIVOP_H
-
-/*
- * Copyright (C) 2005 Hewlett-Packard Co
- *     Dan Magenheimer <dan.magenheimer@hp.com>
- *
- * Paravirtualizations of privileged operations for Xen/ia64
- *
- *
- * inline privop and paravirt_alt support
- * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- */
-
-#ifndef __ASSEMBLY__
-#include <linux/types.h>               /* arch-ia64.h requires uint64_t */
-#endif
-#include <asm/xen/interface.h>
-
-/* At 1 MB, before per-cpu space but still addressable using addl instead
-   of movl. */
-#define XSI_BASE                       0xfffffffffff00000
-
-/* Address of mapped regs.  */
-#define XMAPPEDREGS_BASE               (XSI_BASE + XSI_SIZE)
-
-#ifdef __ASSEMBLY__
-#define XEN_HYPER_RFI                  break HYPERPRIVOP_RFI
-#define XEN_HYPER_RSM_PSR_DT           break HYPERPRIVOP_RSM_DT
-#define XEN_HYPER_SSM_PSR_DT           break HYPERPRIVOP_SSM_DT
-#define XEN_HYPER_COVER                        break HYPERPRIVOP_COVER
-#define XEN_HYPER_ITC_D                        break HYPERPRIVOP_ITC_D
-#define XEN_HYPER_ITC_I                        break HYPERPRIVOP_ITC_I
-#define XEN_HYPER_SSM_I                        break HYPERPRIVOP_SSM_I
-#define XEN_HYPER_GET_IVR              break HYPERPRIVOP_GET_IVR
-#define XEN_HYPER_THASH                        break HYPERPRIVOP_THASH
-#define XEN_HYPER_ITR_D                        break HYPERPRIVOP_ITR_D
-#define XEN_HYPER_SET_KR               break HYPERPRIVOP_SET_KR
-#define XEN_HYPER_GET_PSR              break HYPERPRIVOP_GET_PSR
-#define XEN_HYPER_SET_RR0_TO_RR4       break HYPERPRIVOP_SET_RR0_TO_RR4
-
-#define XSI_IFS                                (XSI_BASE + XSI_IFS_OFS)
-#define XSI_PRECOVER_IFS               (XSI_BASE + XSI_PRECOVER_IFS_OFS)
-#define XSI_IFA                                (XSI_BASE + XSI_IFA_OFS)
-#define XSI_ISR                                (XSI_BASE + XSI_ISR_OFS)
-#define XSI_IIM                                (XSI_BASE + XSI_IIM_OFS)
-#define XSI_ITIR                       (XSI_BASE + XSI_ITIR_OFS)
-#define XSI_PSR_I_ADDR                 (XSI_BASE + XSI_PSR_I_ADDR_OFS)
-#define XSI_PSR_IC                     (XSI_BASE + XSI_PSR_IC_OFS)
-#define XSI_IPSR                       (XSI_BASE + XSI_IPSR_OFS)
-#define XSI_IIP                                (XSI_BASE + XSI_IIP_OFS)
-#define XSI_B1NAT                      (XSI_BASE + XSI_B1NATS_OFS)
-#define XSI_BANK1_R16                  (XSI_BASE + XSI_BANK1_R16_OFS)
-#define XSI_BANKNUM                    (XSI_BASE + XSI_BANKNUM_OFS)
-#define XSI_IHA                                (XSI_BASE + XSI_IHA_OFS)
-#define XSI_ITC_OFFSET                 (XSI_BASE + XSI_ITC_OFFSET_OFS)
-#define XSI_ITC_LAST                   (XSI_BASE + XSI_ITC_LAST_OFS)
-#endif
-
-#ifndef __ASSEMBLY__
-
-/************************************************/
-/* Instructions paravirtualized for correctness */
-/************************************************/
-
-/* "fc" and "thash" are privilege-sensitive instructions, meaning they
- *  may have different semantics depending on whether they are executed
- *  at PL0 vs PL!=0.  When paravirtualized, these instructions mustn't
- *  be allowed to execute directly, lest incorrect semantics result. */
-extern void xen_fc(void *addr);
-extern unsigned long xen_thash(unsigned long addr);
-
-/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
- * is not currently used (though it may be in a long-format VHPT system!)
- * and the semantics of cover only change if psr.ic is off which is very
- * rare (and currently non-existent outside of assembly code */
-
-/* There are also privilege-sensitive registers.  These registers are
- * readable at any privilege level but only writable at PL0. */
-extern unsigned long xen_get_cpuid(int index);
-extern unsigned long xen_get_pmd(int index);
-
-#ifndef ASM_SUPPORTED
-extern unsigned long xen_get_eflag(void);      /* see xen_ia64_getreg */
-extern void xen_set_eflag(unsigned long);      /* see xen_ia64_setreg */
-#endif
-
-/************************************************/
-/* Instructions paravirtualized for performance */
-/************************************************/
-
-/* Xen uses memory-mapped virtual privileged registers for access to many
- * performance-sensitive privileged registers.  Some, like the processor
- * status register (psr), are broken up into multiple memory locations.
- * Others, like "pend", are abstractions based on privileged registers.
- * "Pend" is guaranteed to be set if reading cr.ivr would return a
- * (non-spurious) interrupt. */
-#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE)
-
-#define XSI_PSR_I                      \
-       (*XEN_MAPPEDREGS->interrupt_mask_addr)
-#define xen_get_virtual_psr_i()                \
-       (!XSI_PSR_I)
-#define xen_set_virtual_psr_i(_val)    \
-       ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; })
-#define xen_set_virtual_psr_ic(_val)   \
-       ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; })
-#define xen_get_virtual_pend()         \
-       (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1))
-
-#ifndef ASM_SUPPORTED
-/* Although all privileged operations can be left to trap and will
- * be properly handled by Xen, some are frequent enough that we use
- * hyperprivops for performance. */
-extern unsigned long xen_get_psr(void);
-extern unsigned long xen_get_ivr(void);
-extern unsigned long xen_get_tpr(void);
-extern void xen_hyper_ssm_i(void);
-extern void xen_set_itm(unsigned long);
-extern void xen_set_tpr(unsigned long);
-extern void xen_eoi(unsigned long);
-extern unsigned long xen_get_rr(unsigned long index);
-extern void xen_set_rr(unsigned long index, unsigned long val);
-extern void xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1,
-                              unsigned long val2, unsigned long val3,
-                              unsigned long val4);
-extern void xen_set_kr(unsigned long index, unsigned long val);
-extern void xen_ptcga(unsigned long addr, unsigned long size);
-#endif /* !ASM_SUPPORTED */
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_IA64_XEN_PRIVOP_H */
diff --git a/arch/ia64/include/asm/xen/xcom_hcall.h b/arch/ia64/include/asm/xen/xcom_hcall.h
deleted file mode 100644 (file)
index 20b2950..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 Tristan Gingold <tristan.gingold@bull.net>, Bull SAS
- *
- * This 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
- */
-
-#ifndef _ASM_IA64_XEN_XCOM_HCALL_H
-#define _ASM_IA64_XEN_XCOM_HCALL_H
-
-/* These function creates inline or mini descriptor for the parameters and
-   calls the corresponding xencomm_arch_hypercall_X.
-   Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless
-   they want to use their own wrapper.  */
-extern int xencomm_hypercall_console_io(int cmd, int count, char *str);
-
-extern int xencomm_hypercall_event_channel_op(int cmd, void *op);
-
-extern int xencomm_hypercall_xen_version(int cmd, void *arg);
-
-extern int xencomm_hypercall_physdev_op(int cmd, void *op);
-
-extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
-                                           unsigned int count);
-
-extern int xencomm_hypercall_sched_op(int cmd, void *arg);
-
-extern int xencomm_hypercall_multicall(void *call_list, int nr_calls);
-
-extern int xencomm_hypercall_callback_op(int cmd, void *arg);
-
-extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg);
-
-extern int xencomm_hypercall_suspend(unsigned long srec);
-
-extern long xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg);
-
-extern long xencomm_hypercall_opt_feature(void *arg);
-
-#endif /* _ASM_IA64_XEN_XCOM_HCALL_H */
diff --git a/arch/ia64/include/asm/xen/xencomm.h b/arch/ia64/include/asm/xen/xencomm.h
deleted file mode 100644 (file)
index cded677..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM 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
- * 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
- */
-
-#ifndef _ASM_IA64_XEN_XENCOMM_H
-#define _ASM_IA64_XEN_XENCOMM_H
-
-#include <xen/xencomm.h>
-#include <asm/pgtable.h>
-
-/* Must be called before any hypercall.  */
-extern void xencomm_initialize(void);
-extern int xencomm_is_initialized(void);
-
-/* Check if virtual contiguity means physical contiguity
- * where the passed address is a pointer value in virtual address.
- * On ia64, identity mapping area in region 7 or the piece of region 5
- * that is mapped by itr[IA64_TR_KERNEL]/dtr[IA64_TR_KERNEL]
- */
-static inline int xencomm_is_phys_contiguous(unsigned long addr)
-{
-       return (PAGE_OFFSET <= addr &&
-               addr < (PAGE_OFFSET + (1UL << IA64_MAX_PHYS_BITS))) ||
-               (KERNEL_START <= addr &&
-                addr < KERNEL_START + KERNEL_TR_PAGE_SIZE);
-}
-
-#endif /* _ASM_IA64_XEN_XENCOMM_H */
index e90c40ec9edf282903cbd3099faac3131ea6de25..f034020398962d34987431971c4f9c33006597aa 100644 (file)
  */
 #define __IA64_BREAK_SYSCALL           0x100000
 
-/*
- * Xen specific break numbers:
- */
-#define __IA64_XEN_HYPERCALL           0x1000
-/* [__IA64_XEN_HYPERPRIVOP_START, __IA64_XEN_HYPERPRIVOP_MAX] is used
-   for xen hyperprivops */
-#define __IA64_XEN_HYPERPRIVOP_START   0x1
-#define __IA64_XEN_HYPERPRIVOP_MAX     0x1a
-
 #endif /* _ASM_IA64_BREAK_H */
index 59d52e3aef125b79b67afdaf1fcffd2b892367ff..bfa19311e09c809c1ea2214d796c5f22124c8b13 100644 (file)
@@ -53,7 +53,6 @@
 #include <asm/numa.h>
 #include <asm/sal.h>
 #include <asm/cyclone.h>
-#include <asm/xen/hypervisor.h>
 
 #define BAD_MADT_ENTRY(entry, end) (                                        \
                (!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
@@ -120,8 +119,6 @@ acpi_get_sysname(void)
                        return "uv";
                else
                        return "sn2";
-       } else if (xen_pv_domain() && !strcmp(hdr->oem_id, "XEN")) {
-               return "xen";
        }
 
 #ifdef CONFIG_INTEL_IOMMU
index 46c9e3007315dedc0ca9c7aa38f8a1e522b3ca58..60ef83e6db71eb458970c1f061c696565ec80d19 100644 (file)
@@ -16,9 +16,6 @@
 #include <asm/sigcontext.h>
 #include <asm/mca.h>
 
-#include <asm/xen/interface.h>
-#include <asm/xen/hypervisor.h>
-
 #include "../kernel/sigframe.h"
 #include "../kernel/fsyscall_gtod_data.h"
 
@@ -290,33 +287,4 @@ void foo(void)
        DEFINE(IA64_ITC_LASTCYCLE_OFFSET,
                offsetof (struct itc_jitter_data_t, itc_lastcycle));
 
-#ifdef CONFIG_XEN
-       BLANK();
-
-       DEFINE(XEN_NATIVE_ASM, XEN_NATIVE);
-       DEFINE(XEN_PV_DOMAIN_ASM, XEN_PV_DOMAIN);
-
-#define DEFINE_MAPPED_REG_OFS(sym, field) \
-       DEFINE(sym, (XMAPPEDREGS_OFS + offsetof(struct mapped_regs, field)))
-
-       DEFINE_MAPPED_REG_OFS(XSI_PSR_I_ADDR_OFS, interrupt_mask_addr);
-       DEFINE_MAPPED_REG_OFS(XSI_IPSR_OFS, ipsr);
-       DEFINE_MAPPED_REG_OFS(XSI_IIP_OFS, iip);
-       DEFINE_MAPPED_REG_OFS(XSI_IFS_OFS, ifs);
-       DEFINE_MAPPED_REG_OFS(XSI_PRECOVER_IFS_OFS, precover_ifs);
-       DEFINE_MAPPED_REG_OFS(XSI_ISR_OFS, isr);
-       DEFINE_MAPPED_REG_OFS(XSI_IFA_OFS, ifa);
-       DEFINE_MAPPED_REG_OFS(XSI_IIPA_OFS, iipa);
-       DEFINE_MAPPED_REG_OFS(XSI_IIM_OFS, iim);
-       DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha);
-       DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir);
-       DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled);
-       DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum);
-       DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]);
-       DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]);
-       DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat);
-       DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat);
-       DEFINE_MAPPED_REG_OFS(XSI_ITC_OFFSET_OFS, itc_offset);
-       DEFINE_MAPPED_REG_OFS(XSI_ITC_LAST_OFS, itc_last);
-#endif /* CONFIG_XEN */
 }
index 991ca336b8a2971ccddbc12c3f5be1ca96ecceb6..e6f80fcf013bbbf16a30d7dd804c4b181685e15a 100644 (file)
@@ -416,8 +416,6 @@ start_ap:
 
 default_setup_hook = 0         // Currently nothing needs to be done.
 
-       .weak xen_setup_hook
-
        .global hypervisor_type
 hypervisor_type:
        data8           PARAVIRT_HYPERVISOR_TYPE_DEFAULT
@@ -426,7 +424,6 @@ hypervisor_type:
 
 hypervisor_setup_hooks:
        data8           default_setup_hook
-       data8           xen_setup_hook
 num_hypervisor_hooks = (. - hypervisor_setup_hooks) / 8
        .previous
 
index ee564575148ed54da0b03cfdddae484acbcb9b1a..f6769cd54bd93ce70f698d233ca7c1d16a39e3b2 100644 (file)
 #include <linux/kbuild.h>
 #include <linux/threads.h>
 #include <asm/native/irq.h>
-#include <asm/xen/irq.h>
 
 void foo(void)
 {
        union paravirt_nr_irqs_max {
                char ia64_native_nr_irqs[IA64_NATIVE_NR_IRQS];
-#ifdef CONFIG_XEN
-               char xen_nr_irqs[XEN_NR_IRQS];
-#endif
        };
 
        DEFINE(NR_IRQS, sizeof (union paravirt_nr_irqs_max));
index 64d6d810c64b8e06d16a04c21e48da954570de17..1ad7512b5f656af63335d897454d038f6ca5b49e 100644 (file)
@@ -22,9 +22,6 @@
 
 #ifdef __IA64_ASM_PARAVIRTUALIZED_PVCHECK
 #include <asm/native/pvchk_inst.h>
-#elif defined(__IA64_ASM_PARAVIRTUALIZED_XEN)
-#include <asm/xen/inst.h>
-#include <asm/xen/minstate.h>
 #else
 #include <asm/native/inst.h>
 #endif
index 0684aa6c6507a3522c2814794cb381a4e2395287..67cffc3643a32f98351b46ffa32b8516586ecbf2 100644 (file)
@@ -20,9 +20,5 @@
  *
  */
 
-#if defined(__IA64_GATE_PARAVIRTUALIZED_XEN)
-#include <asm/xen/patchlist.h>
-#else
 #include <asm/native/patchlist.h>
-#endif
 
index 0ccb28fab27e7376bbf09be5a89c0b59078539e6..84f8a52ac5ae2bdb65004691813aed4ed008ea9f 100644 (file)
@@ -182,12 +182,6 @@ SECTIONS {
                __start_gate_section = .;
                *(.data..gate)
                __stop_gate_section = .;
-#ifdef CONFIG_XEN
-               . = ALIGN(PAGE_SIZE);
-               __xen_start_gate_section = .;
-               *(.data..gate.xen)
-               __xen_stop_gate_section = .;
-#endif
        }
        /*
         * make sure the gate page doesn't expose
diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig
deleted file mode 100644 (file)
index 5d8a06b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# This Kconfig describes xen/ia64 options
-#
-
-config XEN
-       bool "Xen hypervisor support"
-       default y
-       depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB
-       select XEN_XENCOMM
-       select NO_IDLE_HZ
-       # followings are required to save/restore.
-       select ARCH_SUSPEND_POSSIBLE
-       select SUSPEND
-       select PM_SLEEP
-       help
-         Enable Xen hypervisor support.  Resulting kernel runs
-         both as a guest OS on Xen and natively on hardware.
-
-config XEN_XENCOMM
-       depends on XEN
-       bool
-
-config NO_IDLE_HZ
-       depends on XEN
-       bool
diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile
deleted file mode 100644 (file)
index e6f4a0a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Makefile for Xen components
-#
-
-obj-y := hypercall.o xenivt.o xensetup.o xen_pv_ops.o irq_xen.o \
-        hypervisor.o xencomm.o xcom_hcall.o grant-table.o time.o suspend.o \
-        gate-data.o
-
-obj-$(CONFIG_IA64_GENERIC) += machvec.o
-
-# The gate DSO image is built using a special linker script.
-include $(srctree)/arch/ia64/kernel/Makefile.gate
-
-# tell compiled for xen
-CPPFLAGS_gate.lds += -D__IA64_GATE_PARAVIRTUALIZED_XEN
-AFLAGS_gate.o += -D__IA64_ASM_PARAVIRTUALIZED_XEN -D__IA64_GATE_PARAVIRTUALIZED_XEN
-
-# use same file of native.
-$(obj)/gate.o: $(src)/../kernel/gate.S FORCE
-       $(call if_changed_dep,as_o_S)
-$(obj)/gate.lds: $(src)/../kernel/gate.lds.S FORCE
-       $(call if_changed_dep,cpp_lds_S)
-
-
-AFLAGS_xenivt.o += -D__IA64_ASM_PARAVIRTUALIZED_XEN
-
-# xen multi compile
-ASM_PARAVIRT_MULTI_COMPILE_SRCS = ivt.S entry.S fsys.S
-ASM_PARAVIRT_OBJS = $(addprefix xen-,$(ASM_PARAVIRT_MULTI_COMPILE_SRCS:.S=.o))
-obj-y += $(ASM_PARAVIRT_OBJS)
-define paravirtualized_xen
-AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_XEN
-endef
-$(foreach o,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_xen,$(o))))
-
-$(obj)/xen-%.o: $(src)/../kernel/%.S FORCE
-       $(call if_changed_dep,as_o_S)
diff --git a/arch/ia64/xen/gate-data.S b/arch/ia64/xen/gate-data.S
deleted file mode 100644 (file)
index 6f95b6b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-       .section .data..gate.xen, "aw"
-
-       .incbin "arch/ia64/xen/gate.so"
diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c
deleted file mode 100644 (file)
index c182813..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/grant-table.c
- *
- * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-
-#include <xen/interface/xen.h>
-#include <xen/interface/memory.h>
-#include <xen/grant_table.h>
-
-#include <asm/xen/hypervisor.h>
-
-/****************************************************************************
- * grant table hack
- * cmd: GNTTABOP_xxx
- */
-
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
-                          unsigned long max_nr_gframes,
-                          struct grant_entry **__shared)
-{
-       *__shared = __va(frames[0] << PAGE_SHIFT);
-       return 0;
-}
-
-void arch_gnttab_unmap_shared(struct grant_entry *shared,
-                             unsigned long nr_gframes)
-{
-       /* nothing */
-}
-
-static void
-gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
-{
-       uint32_t flags;
-
-       flags = uop->flags;
-
-       if (flags & GNTMAP_host_map) {
-               if (flags & GNTMAP_application_map) {
-                       printk(KERN_DEBUG
-                              "GNTMAP_application_map is not supported yet: "
-                              "flags 0x%x\n", flags);
-                       BUG();
-               }
-               if (flags & GNTMAP_contains_pte) {
-                       printk(KERN_DEBUG
-                              "GNTMAP_contains_pte is not supported yet: "
-                              "flags 0x%x\n", flags);
-                       BUG();
-               }
-       } else if (flags & GNTMAP_device_map) {
-               printk("GNTMAP_device_map is not supported yet 0x%x\n", flags);
-               BUG();  /* not yet. actually this flag is not used. */
-       } else {
-               BUG();
-       }
-}
-
-int
-HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
-{
-       if (cmd == GNTTABOP_map_grant_ref) {
-               unsigned int i;
-               for (i = 0; i < count; i++) {
-                       gnttab_map_grant_ref_pre(
-                               (struct gnttab_map_grant_ref *)uop + i);
-               }
-       }
-       return xencomm_hypercall_grant_table_op(cmd, uop, count);
-}
-
-EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
deleted file mode 100644 (file)
index 08847aa..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Support routines for Xen hypercalls
- *
- * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
- * Copyright (C) 2008 Yaozu (Eddie) Dong <eddie.dong@intel.com>
- */
-
-#include <asm/asmmacro.h>
-#include <asm/intrinsics.h>
-#include <asm/xen/privop.h>
-
-#ifdef __INTEL_COMPILER
-/*
- * Hypercalls without parameter.
- */
-#define __HCALL0(name,hcall)           \
-       GLOBAL_ENTRY(name);             \
-       break   hcall;                  \
-       br.ret.sptk.many rp;            \
-       END(name)
-
-/*
- * Hypercalls with 1 parameter.
- */
-#define __HCALL1(name,hcall)           \
-       GLOBAL_ENTRY(name);             \
-       mov r8=r32;                     \
-       break   hcall;                  \
-       br.ret.sptk.many rp;            \
-       END(name)
-
-/*
- * Hypercalls with 2 parameters.
- */
-#define __HCALL2(name,hcall)           \
-       GLOBAL_ENTRY(name);             \
-       mov r8=r32;                     \
-       mov r9=r33;                     \
-       break   hcall;                  \
-       br.ret.sptk.many rp;            \
-       END(name)
-
-__HCALL0(xen_get_psr, HYPERPRIVOP_GET_PSR)
-__HCALL0(xen_get_ivr, HYPERPRIVOP_GET_IVR)
-__HCALL0(xen_get_tpr, HYPERPRIVOP_GET_TPR)
-__HCALL0(xen_hyper_ssm_i, HYPERPRIVOP_SSM_I)
-
-__HCALL1(xen_set_tpr, HYPERPRIVOP_SET_TPR)
-__HCALL1(xen_eoi, HYPERPRIVOP_EOI)
-__HCALL1(xen_thash, HYPERPRIVOP_THASH)
-__HCALL1(xen_set_itm, HYPERPRIVOP_SET_ITM)
-__HCALL1(xen_get_rr, HYPERPRIVOP_GET_RR)
-__HCALL1(xen_fc, HYPERPRIVOP_FC)
-__HCALL1(xen_get_cpuid, HYPERPRIVOP_GET_CPUID)
-__HCALL1(xen_get_pmd, HYPERPRIVOP_GET_PMD)
-
-__HCALL2(xen_ptcga, HYPERPRIVOP_PTC_GA)
-__HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR)
-__HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR)
-
-GLOBAL_ENTRY(xen_set_rr0_to_rr4)
-       mov r8=r32
-       mov r9=r33
-       mov r10=r34
-       mov r11=r35
-       mov r14=r36
-       XEN_HYPER_SET_RR0_TO_RR4
-       br.ret.sptk.many rp
-       ;;
-END(xen_set_rr0_to_rr4)
-#endif
-
-GLOBAL_ENTRY(xen_send_ipi)
-       mov r14=r32
-       mov r15=r33
-       mov r2=0x400
-       break 0x1000
-       ;;
-       br.ret.sptk.many rp
-       ;;
-END(xen_send_ipi)
-
-GLOBAL_ENTRY(__hypercall)
-       mov r2=r37
-       break 0x1000
-       br.ret.sptk.many b0
-       ;;
-END(__hypercall)
diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c
deleted file mode 100644 (file)
index fab6252..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/hypervisor.c
- *
- * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/efi.h>
-#include <linux/export.h>
-#include <asm/xen/hypervisor.h>
-#include <asm/xen/privop.h>
-
-#include "irq_xen.h"
-
-struct shared_info *HYPERVISOR_shared_info __read_mostly =
-       (struct shared_info *)XSI_BASE;
-EXPORT_SYMBOL(HYPERVISOR_shared_info);
-
-DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
-
-struct start_info *xen_start_info;
-EXPORT_SYMBOL(xen_start_info);
-
-EXPORT_SYMBOL(xen_domain_type);
-
-EXPORT_SYMBOL(__hypercall);
-
-/* Stolen from arch/x86/xen/enlighten.c */
-/*
- * Flag to determine whether vcpu info placement is available on all
- * VCPUs.  We assume it is to start with, and then set it to zero on
- * the first failure.  This is because it can succeed on some VCPUs
- * and not others, since it can involve hypervisor memory allocation,
- * or because the guest failed to guarantee all the appropriate
- * constraints on all VCPUs (ie buffer can't cross a page boundary).
- *
- * Note that any particular CPU may be using a placed vcpu structure,
- * but we can only optimise if the all are.
- *
- * 0: not available, 1: available
- */
-
-static void __init xen_vcpu_setup(int cpu)
-{
-       /*
-        * WARNING:
-        * before changing MAX_VIRT_CPUS,
-        * check that shared_info fits on a page
-        */
-       BUILD_BUG_ON(sizeof(struct shared_info) > PAGE_SIZE);
-       per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
-}
-
-void __init xen_setup_vcpu_info_placement(void)
-{
-       int cpu;
-
-       for_each_possible_cpu(cpu)
-               xen_vcpu_setup(cpu);
-}
-
-void
-xen_cpu_init(void)
-{
-       xen_smp_intr_init();
-}
-
-/**************************************************************************
- * opt feature
- */
-void
-xen_ia64_enable_opt_feature(void)
-{
-       /* Enable region 7 identity map optimizations in Xen */
-       struct xen_ia64_opt_feature optf;
-
-       optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7;
-       optf.on = XEN_IA64_OPTF_ON;
-       optf.pgprot = pgprot_val(PAGE_KERNEL);
-       optf.key = 0;   /* No key on linux. */
-       HYPERVISOR_opt_feature(&optf);
-}
diff --git a/arch/ia64/xen/irq_xen.c b/arch/ia64/xen/irq_xen.c
deleted file mode 100644 (file)
index efb74da..0000000
+++ /dev/null
@@ -1,443 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/irq_xen.c
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/cpu.h>
-
-#include <xen/interface/xen.h>
-#include <xen/interface/callback.h>
-#include <xen/events.h>
-
-#include <asm/xen/privop.h>
-
-#include "irq_xen.h"
-
-/***************************************************************************
- * pv_irq_ops
- * irq operations
- */
-
-static int
-xen_assign_irq_vector(int irq)
-{
-       struct physdev_irq irq_op;
-
-       irq_op.irq = irq;
-       if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
-               return -ENOSPC;
-
-       return irq_op.vector;
-}
-
-static void
-xen_free_irq_vector(int vector)
-{
-       struct physdev_irq irq_op;
-
-       if (vector < IA64_FIRST_DEVICE_VECTOR ||
-           vector > IA64_LAST_DEVICE_VECTOR)
-               return;
-
-       irq_op.vector = vector;
-       if (HYPERVISOR_physdev_op(PHYSDEVOP_free_irq_vector, &irq_op))
-               printk(KERN_WARNING "%s: xen_free_irq_vector fail vector=%d\n",
-                      __func__, vector);
-}
-
-
-static DEFINE_PER_CPU(int, xen_timer_irq) = -1;
-static DEFINE_PER_CPU(int, xen_ipi_irq) = -1;
-static DEFINE_PER_CPU(int, xen_resched_irq) = -1;
-static DEFINE_PER_CPU(int, xen_cmc_irq) = -1;
-static DEFINE_PER_CPU(int, xen_cmcp_irq) = -1;
-static DEFINE_PER_CPU(int, xen_cpep_irq) = -1;
-#define NAME_SIZE      15
-static DEFINE_PER_CPU(char[NAME_SIZE], xen_timer_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], xen_ipi_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], xen_resched_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmc_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmcp_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], xen_cpep_name);
-#undef NAME_SIZE
-
-struct saved_irq {
-       unsigned int irq;
-       struct irqaction *action;
-};
-/* 16 should be far optimistic value, since only several percpu irqs
- * are registered early.
- */
-#define MAX_LATE_IRQ   16
-static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ];
-static unsigned short late_irq_cnt;
-static unsigned short saved_irq_cnt;
-static int xen_slab_ready;
-
-#ifdef CONFIG_SMP
-#include <linux/sched.h>
-
-/* Dummy stub. Though we may check XEN_RESCHEDULE_VECTOR before __do_IRQ,
- * it ends up to issue several memory accesses upon percpu data and
- * thus adds unnecessary traffic to other paths.
- */
-static irqreturn_t
-xen_dummy_handler(int irq, void *dev_id)
-{
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t
-xen_resched_handler(int irq, void *dev_id)
-{
-       scheduler_ipi();
-       return IRQ_HANDLED;
-}
-
-static struct irqaction xen_ipi_irqaction = {
-       .handler =      handle_IPI,
-       .flags =        IRQF_DISABLED,
-       .name =         "IPI"
-};
-
-static struct irqaction xen_resched_irqaction = {
-       .handler =      xen_resched_handler,
-       .flags =        IRQF_DISABLED,
-       .name =         "resched"
-};
-
-static struct irqaction xen_tlb_irqaction = {
-       .handler =      xen_dummy_handler,
-       .flags =        IRQF_DISABLED,
-       .name =         "tlb_flush"
-};
-#endif
-
-/*
- * This is xen version percpu irq registration, which needs bind
- * to xen specific evtchn sub-system. One trick here is that xen
- * evtchn binding interface depends on kmalloc because related
- * port needs to be freed at device/cpu down. So we cache the
- * registration on BSP before slab is ready and then deal them
- * at later point. For rest instances happening after slab ready,
- * we hook them to xen evtchn immediately.
- *
- * FIXME: MCA is not supported by far, and thus "nomca" boot param is
- * required.
- */
-static void
-__xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
-                       struct irqaction *action, int save)
-{
-       int irq = 0;
-
-       if (xen_slab_ready) {
-               switch (vec) {
-               case IA64_TIMER_VECTOR:
-                       snprintf(per_cpu(xen_timer_name, cpu),
-                                sizeof(per_cpu(xen_timer_name, cpu)),
-                                "%s%d", action->name, cpu);
-                       irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
-                               action->handler, action->flags,
-                               per_cpu(xen_timer_name, cpu), action->dev_id);
-                       per_cpu(xen_timer_irq, cpu) = irq;
-                       break;
-               case IA64_IPI_RESCHEDULE:
-                       snprintf(per_cpu(xen_resched_name, cpu),
-                                sizeof(per_cpu(xen_resched_name, cpu)),
-                                "%s%d", action->name, cpu);
-                       irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu,
-                               action->handler, action->flags,
-                               per_cpu(xen_resched_name, cpu), action->dev_id);
-                       per_cpu(xen_resched_irq, cpu) = irq;
-                       break;
-               case IA64_IPI_VECTOR:
-                       snprintf(per_cpu(xen_ipi_name, cpu),
-                                sizeof(per_cpu(xen_ipi_name, cpu)),
-                                "%s%d", action->name, cpu);
-                       irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu,
-                               action->handler, action->flags,
-                               per_cpu(xen_ipi_name, cpu), action->dev_id);
-                       per_cpu(xen_ipi_irq, cpu) = irq;
-                       break;
-               case IA64_CMC_VECTOR:
-                       snprintf(per_cpu(xen_cmc_name, cpu),
-                                sizeof(per_cpu(xen_cmc_name, cpu)),
-                                "%s%d", action->name, cpu);
-                       irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu,
-                                               action->handler,
-                                               action->flags,
-                                               per_cpu(xen_cmc_name, cpu),
-                                               action->dev_id);
-                       per_cpu(xen_cmc_irq, cpu) = irq;
-                       break;
-               case IA64_CMCP_VECTOR:
-                       snprintf(per_cpu(xen_cmcp_name, cpu),
-                                sizeof(per_cpu(xen_cmcp_name, cpu)),
-                                "%s%d", action->name, cpu);
-                       irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu,
-                                               action->handler,
-                                               action->flags,
-                                               per_cpu(xen_cmcp_name, cpu),
-                                               action->dev_id);
-                       per_cpu(xen_cmcp_irq, cpu) = irq;
-                       break;
-               case IA64_CPEP_VECTOR:
-                       snprintf(per_cpu(xen_cpep_name, cpu),
-                                sizeof(per_cpu(xen_cpep_name, cpu)),
-                                "%s%d", action->name, cpu);
-                       irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu,
-                                               action->handler,
-                                               action->flags,
-                                               per_cpu(xen_cpep_name, cpu),
-                                               action->dev_id);
-                       per_cpu(xen_cpep_irq, cpu) = irq;
-                       break;
-               case IA64_CPE_VECTOR:
-               case IA64_MCA_RENDEZ_VECTOR:
-               case IA64_PERFMON_VECTOR:
-               case IA64_MCA_WAKEUP_VECTOR:
-               case IA64_SPURIOUS_INT_VECTOR:
-                       /* No need to complain, these aren't supported. */
-                       break;
-               default:
-                       printk(KERN_WARNING "Percpu irq %d is unsupported "
-                              "by xen!\n", vec);
-                       break;
-               }
-               BUG_ON(irq < 0);
-
-               if (irq > 0) {
-                       /*
-                        * Mark percpu.  Without this, migrate_irqs() will
-                        * mark the interrupt for migrations and trigger it
-                        * on cpu hotplug.
-                        */
-                       irq_set_status_flags(irq, IRQ_PER_CPU);
-               }
-       }
-
-       /* For BSP, we cache registered percpu irqs, and then re-walk
-        * them when initializing APs
-        */
-       if (!cpu && save) {
-               BUG_ON(saved_irq_cnt == MAX_LATE_IRQ);
-               saved_percpu_irqs[saved_irq_cnt].irq = vec;
-               saved_percpu_irqs[saved_irq_cnt].action = action;
-               saved_irq_cnt++;
-               if (!xen_slab_ready)
-                       late_irq_cnt++;
-       }
-}
-
-static void
-xen_register_percpu_irq(ia64_vector vec, struct irqaction *action)
-{
-       __xen_register_percpu_irq(smp_processor_id(), vec, action, 1);
-}
-
-static void
-xen_bind_early_percpu_irq(void)
-{
-       int i;
-
-       xen_slab_ready = 1;
-       /* There's no race when accessing this cached array, since only
-        * BSP will face with such step shortly
-        */
-       for (i = 0; i < late_irq_cnt; i++)
-               __xen_register_percpu_irq(smp_processor_id(),
-                                         saved_percpu_irqs[i].irq,
-                                         saved_percpu_irqs[i].action, 0);
-}
-
-/* FIXME: There's no obvious point to check whether slab is ready. So
- * a hack is used here by utilizing a late time hook.
- */
-
-#ifdef CONFIG_HOTPLUG_CPU
-static int unbind_evtchn_callback(struct notifier_block *nfb,
-                                 unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (unsigned long)hcpu;
-
-       if (action == CPU_DEAD) {
-               /* Unregister evtchn.  */
-               if (per_cpu(xen_cpep_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(xen_cpep_irq, cpu),
-                                              NULL);
-                       per_cpu(xen_cpep_irq, cpu) = -1;
-               }
-               if (per_cpu(xen_cmcp_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(xen_cmcp_irq, cpu),
-                                              NULL);
-                       per_cpu(xen_cmcp_irq, cpu) = -1;
-               }
-               if (per_cpu(xen_cmc_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(xen_cmc_irq, cpu), NULL);
-                       per_cpu(xen_cmc_irq, cpu) = -1;
-               }
-               if (per_cpu(xen_ipi_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(xen_ipi_irq, cpu), NULL);
-                       per_cpu(xen_ipi_irq, cpu) = -1;
-               }
-               if (per_cpu(xen_resched_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu),
-                                              NULL);
-                       per_cpu(xen_resched_irq, cpu) = -1;
-               }
-               if (per_cpu(xen_timer_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(xen_timer_irq, cpu),
-                                              NULL);
-                       per_cpu(xen_timer_irq, cpu) = -1;
-               }
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block unbind_evtchn_notifier = {
-       .notifier_call = unbind_evtchn_callback,
-       .priority = 0
-};
-#endif
-
-void xen_smp_intr_init_early(unsigned int cpu)
-{
-#ifdef CONFIG_SMP
-       unsigned int i;
-
-       for (i = 0; i < saved_irq_cnt; i++)
-               __xen_register_percpu_irq(cpu, saved_percpu_irqs[i].irq,
-                                         saved_percpu_irqs[i].action, 0);
-#endif
-}
-
-void xen_smp_intr_init(void)
-{
-#ifdef CONFIG_SMP
-       unsigned int cpu = smp_processor_id();
-       struct callback_register event = {
-               .type = CALLBACKTYPE_event,
-               .address = { .ip = (unsigned long)&xen_event_callback },
-       };
-
-       if (cpu == 0) {
-               /* Initialization was already done for boot cpu.  */
-#ifdef CONFIG_HOTPLUG_CPU
-               /* Register the notifier only once.  */
-               register_cpu_notifier(&unbind_evtchn_notifier);
-#endif
-               return;
-       }
-
-       /* This should be piggyback when setup vcpu guest context */
-       BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
-#endif /* CONFIG_SMP */
-}
-
-void __init
-xen_irq_init(void)
-{
-       struct callback_register event = {
-               .type = CALLBACKTYPE_event,
-               .address = { .ip = (unsigned long)&xen_event_callback },
-       };
-
-       xen_init_IRQ();
-       BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
-       late_time_init = xen_bind_early_percpu_irq;
-}
-
-void
-xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect)
-{
-#ifdef CONFIG_SMP
-       /* TODO: we need to call vcpu_up here */
-       if (unlikely(vector == ap_wakeup_vector)) {
-               /* XXX
-                * This should be in __cpu_up(cpu) in ia64 smpboot.c
-                * like x86. But don't want to modify it,
-                * keep it untouched.
-                */
-               xen_smp_intr_init_early(cpu);
-
-               xen_send_ipi(cpu, vector);
-               /* vcpu_prepare_and_up(cpu); */
-               return;
-       }
-#endif
-
-       switch (vector) {
-       case IA64_IPI_VECTOR:
-               xen_send_IPI_one(cpu, XEN_IPI_VECTOR);
-               break;
-       case IA64_IPI_RESCHEDULE:
-               xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
-               break;
-       case IA64_CMCP_VECTOR:
-               xen_send_IPI_one(cpu, XEN_CMCP_VECTOR);
-               break;
-       case IA64_CPEP_VECTOR:
-               xen_send_IPI_one(cpu, XEN_CPEP_VECTOR);
-               break;
-       case IA64_TIMER_VECTOR: {
-               /* this is used only once by check_sal_cache_flush()
-                  at boot time */
-               static int used = 0;
-               if (!used) {
-                       xen_send_ipi(cpu, IA64_TIMER_VECTOR);
-                       used = 1;
-                       break;
-               }
-               /* fallthrough */
-       }
-       default:
-               printk(KERN_WARNING "Unsupported IPI type 0x%x\n",
-                      vector);
-               notify_remote_via_irq(0); /* defaults to 0 irq */
-               break;
-       }
-}
-
-static void __init
-xen_register_ipi(void)
-{
-#ifdef CONFIG_SMP
-       register_percpu_irq(IA64_IPI_VECTOR, &xen_ipi_irqaction);
-       register_percpu_irq(IA64_IPI_RESCHEDULE, &xen_resched_irqaction);
-       register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &xen_tlb_irqaction);
-#endif
-}
-
-static void
-xen_resend_irq(unsigned int vector)
-{
-       (void)resend_irq_on_evtchn(vector);
-}
-
-const struct pv_irq_ops xen_irq_ops __initconst = {
-       .register_ipi = xen_register_ipi,
-
-       .assign_irq_vector = xen_assign_irq_vector,
-       .free_irq_vector = xen_free_irq_vector,
-       .register_percpu_irq = xen_register_percpu_irq,
-
-       .resend_irq = xen_resend_irq,
-};
diff --git a/arch/ia64/xen/irq_xen.h b/arch/ia64/xen/irq_xen.h
deleted file mode 100644 (file)
index 1778517..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/irq_xen.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- */
-
-#ifndef IRQ_XEN_H
-#define IRQ_XEN_H
-
-extern void (*late_time_init)(void);
-extern char xen_event_callback;
-void __init xen_init_IRQ(void);
-
-extern const struct pv_irq_ops xen_irq_ops __initconst;
-extern void xen_smp_intr_init(void);
-extern void xen_send_ipi(int cpu, int vec);
-
-#endif /* IRQ_XEN_H */
diff --git a/arch/ia64/xen/machvec.c b/arch/ia64/xen/machvec.c
deleted file mode 100644 (file)
index 4ad588a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#define MACHVEC_PLATFORM_NAME           xen
-#define MACHVEC_PLATFORM_HEADER         <asm/machvec_xen.h>
-#include <asm/machvec_init.h>
-
diff --git a/arch/ia64/xen/suspend.c b/arch/ia64/xen/suspend.c
deleted file mode 100644 (file)
index 419c862..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/suspend.c
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- * suspend/resume
- */
-
-#include <xen/xen-ops.h>
-#include <asm/xen/hypervisor.h>
-#include "time.h"
-
-void
-xen_mm_pin_all(void)
-{
-       /* nothing */
-}
-
-void
-xen_mm_unpin_all(void)
-{
-       /* nothing */
-}
-
-void
-xen_arch_pre_suspend()
-{
-       /* nothing */
-}
-
-void
-xen_arch_post_suspend(int suspend_cancelled)
-{
-       if (suspend_cancelled)
-               return;
-
-       xen_ia64_enable_opt_feature();
-       /* add more if necessary */
-}
-
-void xen_arch_resume(void)
-{
-       xen_timer_resume_on_aps();
-}
diff --git a/arch/ia64/xen/time.c b/arch/ia64/xen/time.c
deleted file mode 100644 (file)
index 1f8244a..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/time.c
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/delay.h>
-#include <linux/kernel_stat.h>
-#include <linux/posix-timers.h>
-#include <linux/irq.h>
-#include <linux/clocksource.h>
-
-#include <asm/timex.h>
-
-#include <asm/xen/hypervisor.h>
-
-#include <xen/interface/vcpu.h>
-
-#include "../kernel/fsyscall_gtod_data.h"
-
-static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
-static DEFINE_PER_CPU(unsigned long, xen_stolen_time);
-static DEFINE_PER_CPU(unsigned long, xen_blocked_time);
-
-/* taken from i386/kernel/time-xen.c */
-static void xen_init_missing_ticks_accounting(int cpu)
-{
-       struct vcpu_register_runstate_memory_area area;
-       struct vcpu_runstate_info *runstate = &per_cpu(xen_runstate, cpu);
-       int rc;
-
-       memset(runstate, 0, sizeof(*runstate));
-
-       area.addr.v = runstate;
-       rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu,
-                               &area);
-       WARN_ON(rc && rc != -ENOSYS);
-
-       per_cpu(xen_blocked_time, cpu) = runstate->time[RUNSTATE_blocked];
-       per_cpu(xen_stolen_time, cpu) = runstate->time[RUNSTATE_runnable]
-                                           + runstate->time[RUNSTATE_offline];
-}
-
-/*
- * Runstate accounting
- */
-/* stolen from arch/x86/xen/time.c */
-static void get_runstate_snapshot(struct vcpu_runstate_info *res)
-{
-       u64 state_time;
-       struct vcpu_runstate_info *state;
-
-       BUG_ON(preemptible());
-
-       state = &__get_cpu_var(xen_runstate);
-
-       /*
-        * The runstate info is always updated by the hypervisor on
-        * the current CPU, so there's no need to use anything
-        * stronger than a compiler barrier when fetching it.
-        */
-       do {
-               state_time = state->state_entry_time;
-               rmb();
-               *res = *state;
-               rmb();
-       } while (state->state_entry_time != state_time);
-}
-
-#define NS_PER_TICK (1000000000LL/HZ)
-
-static unsigned long
-consider_steal_time(unsigned long new_itm)
-{
-       unsigned long stolen, blocked;
-       unsigned long delta_itm = 0, stolentick = 0;
-       int cpu = smp_processor_id();
-       struct vcpu_runstate_info runstate;
-       struct task_struct *p = current;
-
-       get_runstate_snapshot(&runstate);
-
-       /*
-        * Check for vcpu migration effect
-        * In this case, itc value is reversed.
-        * This causes huge stolen value.
-        * This function just checks and reject this effect.
-        */
-       if (!time_after_eq(runstate.time[RUNSTATE_blocked],
-                          per_cpu(xen_blocked_time, cpu)))
-               blocked = 0;
-
-       if (!time_after_eq(runstate.time[RUNSTATE_runnable] +
-                          runstate.time[RUNSTATE_offline],
-                          per_cpu(xen_stolen_time, cpu)))
-               stolen = 0;
-
-       if (!time_after(delta_itm + new_itm, ia64_get_itc()))
-               stolentick = ia64_get_itc() - new_itm;
-
-       do_div(stolentick, NS_PER_TICK);
-       stolentick++;
-
-       do_div(stolen, NS_PER_TICK);
-
-       if (stolen > stolentick)
-               stolen = stolentick;
-
-       stolentick -= stolen;
-       do_div(blocked, NS_PER_TICK);
-
-       if (blocked > stolentick)
-               blocked = stolentick;
-
-       if (stolen > 0 || blocked > 0) {
-               account_steal_ticks(stolen);
-               account_idle_ticks(blocked);
-               run_local_timers();
-
-               rcu_check_callbacks(cpu, user_mode(get_irq_regs()));
-
-               scheduler_tick();
-               run_posix_cpu_timers(p);
-               delta_itm += local_cpu_data->itm_delta * (stolen + blocked);
-
-               if (cpu == time_keeper_id)
-                       xtime_update(stolen + blocked);
-
-               local_cpu_data->itm_next = delta_itm + new_itm;
-
-               per_cpu(xen_stolen_time, cpu) += NS_PER_TICK * stolen;
-               per_cpu(xen_blocked_time, cpu) += NS_PER_TICK * blocked;
-       }
-       return delta_itm;
-}
-
-static int xen_do_steal_accounting(unsigned long *new_itm)
-{
-       unsigned long delta_itm;
-       delta_itm = consider_steal_time(*new_itm);
-       *new_itm += delta_itm;
-       if (time_after(*new_itm, ia64_get_itc()) && delta_itm)
-               return 1;
-
-       return 0;
-}
-
-static void xen_itc_jitter_data_reset(void)
-{
-       u64 lcycle, ret;
-
-       do {
-               lcycle = itc_jitter_data.itc_lastcycle;
-               ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, 0);
-       } while (unlikely(ret != lcycle));
-}
-
-/* based on xen_sched_clock() in arch/x86/xen/time.c. */
-/*
- * This relies on HAVE_UNSTABLE_SCHED_CLOCK. If it can't be defined,
- * something similar logic should be implemented here.
- */
-/*
- * Xen sched_clock implementation.  Returns the number of unstolen
- * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED
- * states.
- */
-static unsigned long long xen_sched_clock(void)
-{
-       struct vcpu_runstate_info runstate;
-
-       unsigned long long now;
-       unsigned long long offset;
-       unsigned long long ret;
-
-       /*
-        * Ideally sched_clock should be called on a per-cpu basis
-        * anyway, so preempt should already be disabled, but that's
-        * not current practice at the moment.
-        */
-       preempt_disable();
-
-       /*
-        * both ia64_native_sched_clock() and xen's runstate are
-        * based on mAR.ITC. So difference of them makes sense.
-        */
-       now = ia64_native_sched_clock();
-
-       get_runstate_snapshot(&runstate);
-
-       WARN_ON(runstate.state != RUNSTATE_running);
-
-       offset = 0;
-       if (now > runstate.state_entry_time)
-               offset = now - runstate.state_entry_time;
-       ret = runstate.time[RUNSTATE_blocked] +
-               runstate.time[RUNSTATE_running] +
-               offset;
-
-       preempt_enable();
-
-       return ret;
-}
-
-struct pv_time_ops xen_time_ops __initdata = {
-       .init_missing_ticks_accounting  = xen_init_missing_ticks_accounting,
-       .do_steal_accounting            = xen_do_steal_accounting,
-       .clocksource_resume             = xen_itc_jitter_data_reset,
-       .sched_clock                    = xen_sched_clock,
-};
-
-/* Called after suspend, to resume time.  */
-static void xen_local_tick_resume(void)
-{
-       /* Just trigger a tick.  */
-       ia64_cpu_local_tick();
-       touch_softlockup_watchdog();
-}
-
-void
-xen_timer_resume(void)
-{
-       unsigned int cpu;
-
-       xen_local_tick_resume();
-
-       for_each_online_cpu(cpu)
-               xen_init_missing_ticks_accounting(cpu);
-}
-
-static void ia64_cpu_local_tick_fn(void *unused)
-{
-       xen_local_tick_resume();
-       xen_init_missing_ticks_accounting(smp_processor_id());
-}
-
-void
-xen_timer_resume_on_aps(void)
-{
-       smp_call_function(&ia64_cpu_local_tick_fn, NULL, 1);
-}
diff --git a/arch/ia64/xen/time.h b/arch/ia64/xen/time.h
deleted file mode 100644 (file)
index f98d7e1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/time.h
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This 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
- *
- */
-
-extern struct pv_time_ops xen_time_ops __initdata;
-void xen_timer_resume_on_aps(void);
diff --git a/arch/ia64/xen/xcom_hcall.c b/arch/ia64/xen/xcom_hcall.c
deleted file mode 100644 (file)
index ccaf743..0000000
+++ /dev/null
@@ -1,441 +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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- *          Tristan Gingold <tristan.gingold@bull.net>
- *
- *          Copyright (c) 2007
- *          Isaku Yamahata <yamahata at valinux co jp>
- *                          VA Linux Systems Japan K.K.
- *          consolidate mini and inline version.
- */
-
-#include <linux/module.h>
-#include <xen/interface/xen.h>
-#include <xen/interface/memory.h>
-#include <xen/interface/grant_table.h>
-#include <xen/interface/callback.h>
-#include <xen/interface/vcpu.h>
-#include <asm/xen/hypervisor.h>
-#include <asm/xen/xencomm.h>
-
-/* Xencomm notes:
- * This file defines hypercalls to be used by xencomm.  The hypercalls simply
- * create inlines or mini descriptors for pointers and then call the raw arch
- * hypercall xencomm_arch_hypercall_XXX
- *
- * If the arch wants to directly use these hypercalls, simply define macros
- * in asm/xen/hypercall.h, eg:
- *  #define HYPERVISOR_sched_op xencomm_hypercall_sched_op
- *
- * The arch may also define HYPERVISOR_xxx as a function and do more operations
- * before/after doing the hypercall.
- *
- * Note: because only inline or mini descriptors are created these functions
- * must only be called with in kernel memory parameters.
- */
-
-int
-xencomm_hypercall_console_io(int cmd, int count, char *str)
-{
-       /* xen early printk uses console io hypercall before
-        * xencomm initialization. In that case, we just ignore it.
-        */
-       if (!xencomm_is_initialized())
-               return 0;
-
-       return xencomm_arch_hypercall_console_io
-               (cmd, count, xencomm_map_no_alloc(str, count));
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io);
-
-int
-xencomm_hypercall_event_channel_op(int cmd, void *op)
-{
-       struct xencomm_handle *desc;
-       desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op));
-       if (desc == NULL)
-               return -EINVAL;
-
-       return xencomm_arch_hypercall_event_channel_op(cmd, desc);
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op);
-
-int
-xencomm_hypercall_xen_version(int cmd, void *arg)
-{
-       struct xencomm_handle *desc;
-       unsigned int argsize;
-
-       switch (cmd) {
-       case XENVER_version:
-               /* do not actually pass an argument */
-               return xencomm_arch_hypercall_xen_version(cmd, 0);
-       case XENVER_extraversion:
-               argsize = sizeof(struct xen_extraversion);
-               break;
-       case XENVER_compile_info:
-               argsize = sizeof(struct xen_compile_info);
-               break;
-       case XENVER_capabilities:
-               argsize = sizeof(struct xen_capabilities_info);
-               break;
-       case XENVER_changeset:
-               argsize = sizeof(struct xen_changeset_info);
-               break;
-       case XENVER_platform_parameters:
-               argsize = sizeof(struct xen_platform_parameters);
-               break;
-       case XENVER_get_features:
-               argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info);
-               break;
-
-       default:
-               printk(KERN_DEBUG
-                      "%s: unknown version op %d\n", __func__, cmd);
-               return -ENOSYS;
-       }
-
-       desc = xencomm_map_no_alloc(arg, argsize);
-       if (desc == NULL)
-               return -EINVAL;
-
-       return xencomm_arch_hypercall_xen_version(cmd, desc);
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version);
-
-int
-xencomm_hypercall_physdev_op(int cmd, void *op)
-{
-       unsigned int argsize;
-
-       switch (cmd) {
-       case PHYSDEVOP_apic_read:
-       case PHYSDEVOP_apic_write:
-               argsize = sizeof(struct physdev_apic);
-               break;
-       case PHYSDEVOP_alloc_irq_vector:
-       case PHYSDEVOP_free_irq_vector:
-               argsize = sizeof(struct physdev_irq);
-               break;
-       case PHYSDEVOP_irq_status_query:
-               argsize = sizeof(struct physdev_irq_status_query);
-               break;
-
-       default:
-               printk(KERN_DEBUG
-                      "%s: unknown physdev op %d\n", __func__, cmd);
-               return -ENOSYS;
-       }
-
-       return xencomm_arch_hypercall_physdev_op
-               (cmd, xencomm_map_no_alloc(op, argsize));
-}
-
-static int
-xencommize_grant_table_op(struct xencomm_mini **xc_area,
-                         unsigned int cmd, void *op, unsigned int count,
-                         struct xencomm_handle **desc)
-{
-       struct xencomm_handle *desc1;
-       unsigned int argsize;
-
-       switch (cmd) {
-       case GNTTABOP_map_grant_ref:
-               argsize = sizeof(struct gnttab_map_grant_ref);
-               break;
-       case GNTTABOP_unmap_grant_ref:
-               argsize = sizeof(struct gnttab_unmap_grant_ref);
-               break;
-       case GNTTABOP_setup_table:
-       {
-               struct gnttab_setup_table *setup = op;
-
-               argsize = sizeof(*setup);
-
-               if (count != 1)
-                       return -EINVAL;
-               desc1 = __xencomm_map_no_alloc
-                       (xen_guest_handle(setup->frame_list),
-                        setup->nr_frames *
-                        sizeof(*xen_guest_handle(setup->frame_list)),
-                        *xc_area);
-               if (desc1 == NULL)
-                       return -EINVAL;
-               (*xc_area)++;
-               set_xen_guest_handle(setup->frame_list, (void *)desc1);
-               break;
-       }
-       case GNTTABOP_dump_table:
-               argsize = sizeof(struct gnttab_dump_table);
-               break;
-       case GNTTABOP_transfer:
-               argsize = sizeof(struct gnttab_transfer);
-               break;
-       case GNTTABOP_copy:
-               argsize = sizeof(struct gnttab_copy);
-               break;
-       case GNTTABOP_query_size:
-               argsize = sizeof(struct gnttab_query_size);
-               break;
-       default:
-               printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n",
-                      __func__, cmd);
-               BUG();
-       }
-
-       *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area);
-       if (*desc == NULL)
-               return -EINVAL;
-       (*xc_area)++;
-
-       return 0;
-}
-
-int
-xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
-                                unsigned int count)
-{
-       int rc;
-       struct xencomm_handle *desc;
-       XENCOMM_MINI_ALIGNED(xc_area, 2);
-
-       rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc);
-       if (rc)
-               return rc;
-
-       return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op);
-
-int
-xencomm_hypercall_sched_op(int cmd, void *arg)
-{
-       struct xencomm_handle *desc;
-       unsigned int argsize;
-
-       switch (cmd) {
-       case SCHEDOP_yield:
-       case SCHEDOP_block:
-               argsize = 0;
-               break;
-       case SCHEDOP_shutdown:
-               argsize = sizeof(struct sched_shutdown);
-               break;
-       case SCHEDOP_poll:
-       {
-               struct sched_poll *poll = arg;
-               struct xencomm_handle *ports;
-
-               argsize = sizeof(struct sched_poll);
-               ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports),
-                                    sizeof(*xen_guest_handle(poll->ports)));
-
-               set_xen_guest_handle(poll->ports, (void *)ports);
-               break;
-       }
-       default:
-               printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd);
-               return -ENOSYS;
-       }
-
-       desc = xencomm_map_no_alloc(arg, argsize);
-       if (desc == NULL)
-               return -EINVAL;
-
-       return xencomm_arch_hypercall_sched_op(cmd, desc);
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op);
-
-int
-xencomm_hypercall_multicall(void *call_list, int nr_calls)
-{
-       int rc;
-       int i;
-       struct multicall_entry *mce;
-       struct xencomm_handle *desc;
-       XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2);
-
-       for (i = 0; i < nr_calls; i++) {
-               mce = (struct multicall_entry *)call_list + i;
-
-               switch (mce->op) {
-               case __HYPERVISOR_update_va_mapping:
-               case __HYPERVISOR_mmu_update:
-                       /* No-op on ia64.  */
-                       break;
-               case __HYPERVISOR_grant_table_op:
-                       rc = xencommize_grant_table_op
-                               (&xc_area,
-                                mce->args[0], (void *)mce->args[1],
-                                mce->args[2], &desc);
-                       if (rc)
-                               return rc;
-                       mce->args[1] = (unsigned long)desc;
-                       break;
-               case __HYPERVISOR_memory_op:
-               default:
-                       printk(KERN_DEBUG
-                              "%s: unhandled multicall op entry op %lu\n",
-                              __func__, mce->op);
-                       return -ENOSYS;
-               }
-       }
-
-       desc = xencomm_map_no_alloc(call_list,
-                                   nr_calls * sizeof(struct multicall_entry));
-       if (desc == NULL)
-               return -EINVAL;
-
-       return xencomm_arch_hypercall_multicall(desc, nr_calls);
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall);
-
-int
-xencomm_hypercall_callback_op(int cmd, void *arg)
-{
-       unsigned int argsize;
-       switch (cmd) {
-       case CALLBACKOP_register:
-               argsize = sizeof(struct callback_register);
-               break;
-       case CALLBACKOP_unregister:
-               argsize = sizeof(struct callback_unregister);
-               break;
-       default:
-               printk(KERN_DEBUG
-                      "%s: unknown callback op %d\n", __func__, cmd);
-               return -ENOSYS;
-       }
-
-       return xencomm_arch_hypercall_callback_op
-               (cmd, xencomm_map_no_alloc(arg, argsize));
-}
-
-static int
-xencommize_memory_reservation(struct xencomm_mini *xc_area,
-                             struct xen_memory_reservation *mop)
-{
-       struct xencomm_handle *desc;
-
-       desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start),
-                       mop->nr_extents *
-                       sizeof(*xen_guest_handle(mop->extent_start)),
-                       xc_area);
-       if (desc == NULL)
-               return -EINVAL;
-
-       set_xen_guest_handle(mop->extent_start, (void *)desc);
-       return 0;
-}
-
-int
-xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
-{
-       GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
-       struct xen_memory_reservation *xmr = NULL;
-       int rc;
-       struct xencomm_handle *desc;
-       unsigned int argsize;
-       XENCOMM_MINI_ALIGNED(xc_area, 2);
-
-       switch (cmd) {
-       case XENMEM_increase_reservation:
-       case XENMEM_decrease_reservation:
-       case XENMEM_populate_physmap:
-               xmr = (struct xen_memory_reservation *)arg;
-               set_xen_guest_handle(extent_start_va[0],
-                                    xen_guest_handle(xmr->extent_start));
-
-               argsize = sizeof(*xmr);
-               rc = xencommize_memory_reservation(xc_area, xmr);
-               if (rc)
-                       return rc;
-               xc_area++;
-               break;
-
-       case XENMEM_maximum_ram_page:
-               argsize = 0;
-               break;
-
-       case XENMEM_add_to_physmap:
-               argsize = sizeof(struct xen_add_to_physmap);
-               break;
-
-       default:
-               printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd);
-               return -ENOSYS;
-       }
-
-       desc = xencomm_map_no_alloc(arg, argsize);
-       if (desc == NULL)
-               return -EINVAL;
-
-       rc = xencomm_arch_hypercall_memory_op(cmd, desc);
-
-       switch (cmd) {
-       case XENMEM_increase_reservation:
-       case XENMEM_decrease_reservation:
-       case XENMEM_populate_physmap:
-               set_xen_guest_handle(xmr->extent_start,
-                                    xen_guest_handle(extent_start_va[0]));
-               break;
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op);
-
-int
-xencomm_hypercall_suspend(unsigned long srec)
-{
-       struct sched_shutdown arg;
-
-       arg.reason = SHUTDOWN_suspend;
-
-       return xencomm_arch_hypercall_sched_op(
-               SCHEDOP_shutdown, xencomm_map_no_alloc(&arg, sizeof(arg)));
-}
-
-long
-xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg)
-{
-       unsigned int argsize;
-       switch (cmd) {
-       case VCPUOP_register_runstate_memory_area: {
-               struct vcpu_register_runstate_memory_area *area =
-                       (struct vcpu_register_runstate_memory_area *)arg;
-               argsize = sizeof(*arg);
-               set_xen_guest_handle(area->addr.h,
-                    (void *)xencomm_map_no_alloc(area->addr.v,
-                                                 sizeof(area->addr.v)));
-               break;
-       }
-
-       default:
-               printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd);
-               return -ENOSYS;
-       }
-
-       return xencomm_arch_hypercall_vcpu_op(cmd, cpu,
-                                       xencomm_map_no_alloc(arg, argsize));
-}
-
-long
-xencomm_hypercall_opt_feature(void *arg)
-{
-       return xencomm_arch_hypercall_opt_feature(
-               xencomm_map_no_alloc(arg,
-                                    sizeof(struct xen_ia64_opt_feature)));
-}
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c
deleted file mode 100644 (file)
index 3e8d350..0000000
+++ /dev/null
@@ -1,1141 +0,0 @@
-/******************************************************************************
- * arch/ia64/xen/xen_pv_ops.c
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/console.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/pm.h>
-#include <linux/unistd.h>
-
-#include <asm/xen/hypervisor.h>
-#include <asm/xen/xencomm.h>
-#include <asm/xen/privop.h>
-
-#include "irq_xen.h"
-#include "time.h"
-
-/***************************************************************************
- * general info
- */
-static struct pv_info xen_info __initdata = {
-       .kernel_rpl = 2,        /* or 1: determin at runtime */
-       .paravirt_enabled = 1,
-       .name = "Xen/ia64",
-};
-
-#define IA64_RSC_PL_SHIFT      2
-#define IA64_RSC_PL_BIT_SIZE   2
-#define IA64_RSC_PL_MASK       \
-       (((1UL << IA64_RSC_PL_BIT_SIZE) - 1) << IA64_RSC_PL_SHIFT)
-
-static void __init
-xen_info_init(void)
-{
-       /* Xenified Linux/ia64 may run on pl = 1 or 2.
-        * determin at run time. */
-       unsigned long rsc = ia64_getreg(_IA64_REG_AR_RSC);
-       unsigned int rpl = (rsc & IA64_RSC_PL_MASK) >> IA64_RSC_PL_SHIFT;
-       xen_info.kernel_rpl = rpl;
-}
-
-/***************************************************************************
- * pv_init_ops
- * initialization hooks.
- */
-
-static void
-xen_panic_hypercall(struct unw_frame_info *info, void *arg)
-{
-       current->thread.ksp = (__u64)info->sw - 16;
-       HYPERVISOR_shutdown(SHUTDOWN_crash);
-       /* we're never actually going to get here... */
-}
-
-static int
-xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
-       unw_init_running(xen_panic_hypercall, NULL);
-       /* we're never actually going to get here... */
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block xen_panic_block = {
-       xen_panic_event, NULL, 0 /* try to go last */
-};
-
-static void xen_pm_power_off(void)
-{
-       local_irq_disable();
-       HYPERVISOR_shutdown(SHUTDOWN_poweroff);
-}
-
-static void __init
-xen_banner(void)
-{
-       printk(KERN_INFO
-              "Running on Xen! pl = %d start_info_pfn=0x%lx nr_pages=%ld "
-              "flags=0x%x\n",
-              xen_info.kernel_rpl,
-              HYPERVISOR_shared_info->arch.start_info_pfn,
-              xen_start_info->nr_pages, xen_start_info->flags);
-}
-
-static int __init
-xen_reserve_memory(struct rsvd_region *region)
-{
-       region->start = (unsigned long)__va(
-               (HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT));
-       region->end   = region->start + PAGE_SIZE;
-       return 1;
-}
-
-static void __init
-xen_arch_setup_early(void)
-{
-       struct shared_info *s;
-       BUG_ON(!xen_pv_domain());
-
-       s = HYPERVISOR_shared_info;
-       xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
-
-       /* Must be done before any hypercall.  */
-       xencomm_initialize();
-
-       xen_setup_features();
-       /* Register a call for panic conditions. */
-       atomic_notifier_chain_register(&panic_notifier_list,
-                                      &xen_panic_block);
-       pm_power_off = xen_pm_power_off;
-
-       xen_ia64_enable_opt_feature();
-}
-
-static void __init
-xen_arch_setup_console(char **cmdline_p)
-{
-       add_preferred_console("xenboot", 0, NULL);
-       add_preferred_console("tty", 0, NULL);
-       /* use hvc_xen */
-       add_preferred_console("hvc", 0, NULL);
-
-#if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE)
-       conswitchp = NULL;
-#endif
-}
-
-static int __init
-xen_arch_setup_nomca(void)
-{
-       return 1;
-}
-
-static void __init
-xen_post_smp_prepare_boot_cpu(void)
-{
-       xen_setup_vcpu_info_placement();
-}
-
-#ifdef ASM_SUPPORTED
-static unsigned long __init_or_module
-xen_patch_bundle(void *sbundle, void *ebundle, unsigned long type);
-#endif
-static void __init
-xen_patch_branch(unsigned long tag, unsigned long type);
-
-static const struct pv_init_ops xen_init_ops __initconst = {
-       .banner = xen_banner,
-
-       .reserve_memory = xen_reserve_memory,
-
-       .arch_setup_early = xen_arch_setup_early,
-       .arch_setup_console = xen_arch_setup_console,
-       .arch_setup_nomca = xen_arch_setup_nomca,
-
-       .post_smp_prepare_boot_cpu = xen_post_smp_prepare_boot_cpu,
-#ifdef ASM_SUPPORTED
-       .patch_bundle = xen_patch_bundle,
-#endif
-       .patch_branch = xen_patch_branch,
-};
-
-/***************************************************************************
- * pv_fsys_data
- * addresses for fsys
- */
-
-extern unsigned long xen_fsyscall_table[NR_syscalls];
-extern char xen_fsys_bubble_down[];
-struct pv_fsys_data xen_fsys_data __initdata = {
-       .fsyscall_table = (unsigned long *)xen_fsyscall_table,
-       .fsys_bubble_down = (void *)xen_fsys_bubble_down,
-};
-
-/***************************************************************************
- * pv_patchdata
- * patchdata addresses
- */
-
-#define DECLARE(name)                                                  \
-       extern unsigned long __xen_start_gate_##name##_patchlist[];     \
-       extern unsigned long __xen_end_gate_##name##_patchlist[]
-
-DECLARE(fsyscall);
-DECLARE(brl_fsys_bubble_down);
-DECLARE(vtop);
-DECLARE(mckinley_e9);
-
-extern unsigned long __xen_start_gate_section[];
-
-#define ASSIGN(name)                                                   \
-       .start_##name##_patchlist =                                     \
-               (unsigned long)__xen_start_gate_##name##_patchlist,     \
-       .end_##name##_patchlist =                                       \
-               (unsigned long)__xen_end_gate_##name##_patchlist
-
-static struct pv_patchdata xen_patchdata __initdata = {
-       ASSIGN(fsyscall),
-       ASSIGN(brl_fsys_bubble_down),
-       ASSIGN(vtop),
-       ASSIGN(mckinley_e9),
-
-       .gate_section = (void*)__xen_start_gate_section,
-};
-
-/***************************************************************************
- * pv_cpu_ops
- * intrinsics hooks.
- */
-
-#ifndef ASM_SUPPORTED
-static void
-xen_set_itm_with_offset(unsigned long val)
-{
-       /* ia64_cpu_local_tick() calls this with interrupt enabled. */
-       /* WARN_ON(!irqs_disabled()); */
-       xen_set_itm(val - XEN_MAPPEDREGS->itc_offset);
-}
-
-static unsigned long
-xen_get_itm_with_offset(void)
-{
-       /* unused at this moment */
-       printk(KERN_DEBUG "%s is called.\n", __func__);
-
-       WARN_ON(!irqs_disabled());
-       return ia64_native_getreg(_IA64_REG_CR_ITM) +
-               XEN_MAPPEDREGS->itc_offset;
-}
-
-/* ia64_set_itc() is only called by
- * cpu_init() with ia64_set_itc(0) and ia64_sync_itc().
- * So XEN_MAPPEDRESG->itc_offset cal be considered as almost constant.
- */
-static void
-xen_set_itc(unsigned long val)
-{
-       unsigned long mitc;
-
-       WARN_ON(!irqs_disabled());
-       mitc = ia64_native_getreg(_IA64_REG_AR_ITC);
-       XEN_MAPPEDREGS->itc_offset = val - mitc;
-       XEN_MAPPEDREGS->itc_last = val;
-}
-
-static unsigned long
-xen_get_itc(void)
-{
-       unsigned long res;
-       unsigned long itc_offset;
-       unsigned long itc_last;
-       unsigned long ret_itc_last;
-
-       itc_offset = XEN_MAPPEDREGS->itc_offset;
-       do {
-               itc_last = XEN_MAPPEDREGS->itc_last;
-               res = ia64_native_getreg(_IA64_REG_AR_ITC);
-               res += itc_offset;
-               if (itc_last >= res)
-                       res = itc_last + 1;
-               ret_itc_last = cmpxchg(&XEN_MAPPEDREGS->itc_last,
-                                      itc_last, res);
-       } while (unlikely(ret_itc_last != itc_last));
-       return res;
-
-#if 0
-       /* ia64_itc_udelay() calls ia64_get_itc() with interrupt enabled.
-          Should it be paravirtualized instead? */
-       WARN_ON(!irqs_disabled());
-       itc_offset = XEN_MAPPEDREGS->itc_offset;
-       itc_last = XEN_MAPPEDREGS->itc_last;
-       res = ia64_native_getreg(_IA64_REG_AR_ITC);
-       res += itc_offset;
-       if (itc_last >= res)
-               res = itc_last + 1;
-       XEN_MAPPEDREGS->itc_last = res;
-       return res;
-#endif
-}
-
-static void xen_setreg(int regnum, unsigned long val)
-{
-       switch (regnum) {
-       case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7:
-               xen_set_kr(regnum - _IA64_REG_AR_KR0, val);
-               break;
-       case _IA64_REG_AR_ITC:
-               xen_set_itc(val);
-               break;
-       case _IA64_REG_CR_TPR:
-               xen_set_tpr(val);
-               break;
-       case _IA64_REG_CR_ITM:
-               xen_set_itm_with_offset(val);
-               break;
-       case _IA64_REG_CR_EOI:
-               xen_eoi(val);
-               break;
-       default:
-               ia64_native_setreg_func(regnum, val);
-               break;
-       }
-}
-
-static unsigned long xen_getreg(int regnum)
-{
-       unsigned long res;
-
-       switch (regnum) {
-       case _IA64_REG_PSR:
-               res = xen_get_psr();
-               break;
-       case _IA64_REG_AR_ITC:
-               res = xen_get_itc();
-               break;
-       case _IA64_REG_CR_ITM:
-               res = xen_get_itm_with_offset();
-               break;
-       case _IA64_REG_CR_IVR:
-               res = xen_get_ivr();
-               break;
-       case _IA64_REG_CR_TPR:
-               res = xen_get_tpr();
-               break;
-       default:
-               res = ia64_native_getreg_func(regnum);
-               break;
-       }
-       return res;
-}
-
-/* turning on interrupts is a bit more complicated.. write to the
- * memory-mapped virtual psr.i bit first (to avoid race condition),
- * then if any interrupts were pending, we have to execute a hyperprivop
- * to ensure the pending interrupt gets delivered; else we're done! */
-static void
-xen_ssm_i(void)
-{
-       int old = xen_get_virtual_psr_i();
-       xen_set_virtual_psr_i(1);
-       barrier();
-       if (!old && xen_get_virtual_pend())
-               xen_hyper_ssm_i();
-}
-
-/* turning off interrupts can be paravirtualized simply by writing
- * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */
-static void
-xen_rsm_i(void)
-{
-       xen_set_virtual_psr_i(0);
-       barrier();
-}
-
-static unsigned long
-xen_get_psr_i(void)
-{
-       return xen_get_virtual_psr_i() ? IA64_PSR_I : 0;
-}
-
-static void
-xen_intrin_local_irq_restore(unsigned long mask)
-{
-       if (mask & IA64_PSR_I)
-               xen_ssm_i();
-       else
-               xen_rsm_i();
-}
-#else
-#define __DEFINE_FUNC(name, code)                                      \
-       extern const char xen_ ## name ## _direct_start[];              \
-       extern const char xen_ ## name ## _direct_end[];                \
-       asm (".align 32\n"                                              \
-            ".proc xen_" #name "\n"                                    \
-            "xen_" #name ":\n"                                         \
-            "xen_" #name "_direct_start:\n"                            \
-            code                                                       \
-            "xen_" #name "_direct_end:\n"                              \
-            "br.cond.sptk.many b6\n"                                   \
-            ".endp xen_" #name "\n")
-
-#define DEFINE_VOID_FUNC0(name, code)          \
-       extern void                             \
-       xen_ ## name (void);                    \
-       __DEFINE_FUNC(name, code)
-
-#define DEFINE_VOID_FUNC1(name, code)          \
-       extern void                             \
-       xen_ ## name (unsigned long arg);       \
-       __DEFINE_FUNC(name, code)
-
-#define DEFINE_VOID_FUNC1_VOID(name, code)     \
-       extern void                             \
-       xen_ ## name (void *arg);               \
-       __DEFINE_FUNC(name, code)
-
-#define DEFINE_VOID_FUNC2(name, code)          \
-       extern void                             \
-       xen_ ## name (unsigned long arg0,       \
-                     unsigned long arg1);      \
-       __DEFINE_FUNC(name, code)
-
-#define DEFINE_FUNC0(name, code)               \
-       extern unsigned long                    \
-       xen_ ## name (void);                    \
-       __DEFINE_FUNC(name, code)
-
-#define DEFINE_FUNC1(name, type, code)         \
-       extern unsigned long                    \
-       xen_ ## name (type arg);                \
-       __DEFINE_FUNC(name, code)
-
-#define XEN_PSR_I_ADDR_ADDR     (XSI_BASE + XSI_PSR_I_ADDR_OFS)
-
-/*
- * static void xen_set_itm_with_offset(unsigned long val)
- *        xen_set_itm(val - XEN_MAPPEDREGS->itc_offset);
- */
-/* 2 bundles */
-DEFINE_VOID_FUNC1(set_itm_with_offset,
-                 "mov r2 = " __stringify(XSI_BASE) " + "
-                 __stringify(XSI_ITC_OFFSET_OFS) "\n"
-                 ";;\n"
-                 "ld8 r3 = [r2]\n"
-                 ";;\n"
-                 "sub r8 = r8, r3\n"
-                 "break " __stringify(HYPERPRIVOP_SET_ITM) "\n");
-
-/*
- * static unsigned long xen_get_itm_with_offset(void)
- *    return ia64_native_getreg(_IA64_REG_CR_ITM) + XEN_MAPPEDREGS->itc_offset;
- */
-/* 2 bundles */
-DEFINE_FUNC0(get_itm_with_offset,
-            "mov r2 = " __stringify(XSI_BASE) " + "
-            __stringify(XSI_ITC_OFFSET_OFS) "\n"
-            ";;\n"
-            "ld8 r3 = [r2]\n"
-            "mov r8 = cr.itm\n"
-            ";;\n"
-            "add r8 = r8, r2\n");
-
-/*
- * static void xen_set_itc(unsigned long val)
- *     unsigned long mitc;
- *
- *     WARN_ON(!irqs_disabled());
- *     mitc = ia64_native_getreg(_IA64_REG_AR_ITC);
- *     XEN_MAPPEDREGS->itc_offset = val - mitc;
- *     XEN_MAPPEDREGS->itc_last = val;
- */
-/* 2 bundles */
-DEFINE_VOID_FUNC1(set_itc,
-                 "mov r2 = " __stringify(XSI_BASE) " + "
-                 __stringify(XSI_ITC_LAST_OFS) "\n"
-                 "mov r3 = ar.itc\n"
-                 ";;\n"
-                 "sub r3 = r8, r3\n"
-                 "st8 [r2] = r8, "
-                 __stringify(XSI_ITC_LAST_OFS) " - "
-                 __stringify(XSI_ITC_OFFSET_OFS) "\n"
-                 ";;\n"
-                 "st8 [r2] = r3\n");
-
-/*
- * static unsigned long xen_get_itc(void)
- *     unsigned long res;
- *     unsigned long itc_offset;
- *     unsigned long itc_last;
- *     unsigned long ret_itc_last;
- *
- *     itc_offset = XEN_MAPPEDREGS->itc_offset;
- *     do {
- *             itc_last = XEN_MAPPEDREGS->itc_last;
- *             res = ia64_native_getreg(_IA64_REG_AR_ITC);
- *             res += itc_offset;
- *             if (itc_last >= res)
- *                     res = itc_last + 1;
- *             ret_itc_last = cmpxchg(&XEN_MAPPEDREGS->itc_last,
- *                                    itc_last, res);
- *     } while (unlikely(ret_itc_last != itc_last));
- *     return res;
- */
-/* 5 bundles */
-DEFINE_FUNC0(get_itc,
-            "mov r2 = " __stringify(XSI_BASE) " + "
-            __stringify(XSI_ITC_OFFSET_OFS) "\n"
-            ";;\n"
-            "ld8 r9 = [r2], " __stringify(XSI_ITC_LAST_OFS) " - "
-            __stringify(XSI_ITC_OFFSET_OFS) "\n"
-                                       /* r9 = itc_offset */
-                                       /* r2 = XSI_ITC_OFFSET */
-            "888:\n"
-            "mov r8 = ar.itc\n"        /* res = ar.itc */
-            ";;\n"
-            "ld8 r3 = [r2]\n"          /* r3 = itc_last */
-            "add r8 = r8, r9\n"        /* res = ar.itc + itc_offset */
-            ";;\n"
-            "cmp.gtu p6, p0 = r3, r8\n"
-            ";;\n"
-            "(p6) add r8 = 1, r3\n"    /* if (itc_last > res) itc_last + 1 */
-            ";;\n"
-            "mov ar.ccv = r8\n"
-            ";;\n"
-            "cmpxchg8.acq r10 = [r2], r8, ar.ccv\n"
-            ";;\n"
-            "cmp.ne p6, p0 = r10, r3\n"
-            "(p6) hint @pause\n"
-            "(p6) br.cond.spnt 888b\n");
-
-DEFINE_VOID_FUNC1_VOID(fc,
-                      "break " __stringify(HYPERPRIVOP_FC) "\n");
-
-/*
- * psr_i_addr_addr = XEN_PSR_I_ADDR_ADDR
- * masked_addr = *psr_i_addr_addr
- * pending_intr_addr = masked_addr - 1
- * if (val & IA64_PSR_I) {
- *   masked = *masked_addr
- *   *masked_addr = 0:xen_set_virtual_psr_i(1)
- *   compiler barrier
- *   if (masked) {
- *      uint8_t pending = *pending_intr_addr;
- *      if (pending)
- *              XEN_HYPER_SSM_I
- *   }
- * } else {
- *   *masked_addr = 1:xen_set_virtual_psr_i(0)
- * }
- */
-/* 6 bundles */
-DEFINE_VOID_FUNC1(intrin_local_irq_restore,
-                 /* r8 = input value: 0 or IA64_PSR_I
-                  * p6 =  (flags & IA64_PSR_I)
-                  *    = if clause
-                  * p7 = !(flags & IA64_PSR_I)
-                  *    = else clause
-                  */
-                 "cmp.ne p6, p7 = r8, r0\n"
-                 "mov r9 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n"
-                 ";;\n"
-                 /* r9 = XEN_PSR_I_ADDR */
-                 "ld8 r9 = [r9]\n"
-                 ";;\n"
-
-                 /* r10 = masked previous value */
-                 "(p6) ld1.acq r10 = [r9]\n"
-                 ";;\n"
-
-                 /* p8 = !masked interrupt masked previously? */
-                 "(p6) cmp.ne.unc p8, p0 = r10, r0\n"
-
-                 /* p7 = else clause */
-                 "(p7) mov r11 = 1\n"
-                 ";;\n"
-                 /* masked = 1 */
-                 "(p7) st1.rel [r9] = r11\n"
-
-                 /* p6 = if clause */
-                 /* masked = 0
-                  * r9 = masked_addr - 1
-                  *    = pending_intr_addr
-                  */
-                 "(p8) st1.rel [r9] = r0, -1\n"
-                 ";;\n"
-                 /* r8 = pending_intr */
-                 "(p8) ld1.acq r11 = [r9]\n"
-                 ";;\n"
-                 /* p9 = interrupt pending? */
-                 "(p8) cmp.ne.unc p9, p10 = r11, r0\n"
-                 ";;\n"
-                 "(p10) mf\n"
-                 /* issue hypercall to trigger interrupt */
-                 "(p9) break " __stringify(HYPERPRIVOP_SSM_I) "\n");
-
-DEFINE_VOID_FUNC2(ptcga,
-                 "break " __stringify(HYPERPRIVOP_PTC_GA) "\n");
-DEFINE_VOID_FUNC2(set_rr,
-                 "break " __stringify(HYPERPRIVOP_SET_RR) "\n");
-
-/*
- * tmp = XEN_MAPPEDREGS->interrupt_mask_addr = XEN_PSR_I_ADDR_ADDR;
- * tmp = *tmp
- * tmp = *tmp;
- * psr_i = tmp? 0: IA64_PSR_I;
- */
-/* 4 bundles */
-DEFINE_FUNC0(get_psr_i,
-            "mov r9 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n"
-            ";;\n"
-            "ld8 r9 = [r9]\n"                  /* r9 = XEN_PSR_I_ADDR */
-            "mov r8 = 0\n"                     /* psr_i = 0 */
-            ";;\n"
-            "ld1.acq r9 = [r9]\n"              /* r9 = XEN_PSR_I */
-            ";;\n"
-            "cmp.eq.unc p6, p0 = r9, r0\n"     /* p6 = (XEN_PSR_I != 0) */
-            ";;\n"
-            "(p6) mov r8 = " __stringify(1 << IA64_PSR_I_BIT) "\n");
-
-DEFINE_FUNC1(thash, unsigned long,
-            "break " __stringify(HYPERPRIVOP_THASH) "\n");
-DEFINE_FUNC1(get_cpuid, int,
-            "break " __stringify(HYPERPRIVOP_GET_CPUID) "\n");
-DEFINE_FUNC1(get_pmd, int,
-            "break " __stringify(HYPERPRIVOP_GET_PMD) "\n");
-DEFINE_FUNC1(get_rr, unsigned long,
-            "break " __stringify(HYPERPRIVOP_GET_RR) "\n");
-
-/*
- * void xen_privop_ssm_i(void)
- *
- * int masked = !xen_get_virtual_psr_i();
- *     // masked = *(*XEN_MAPPEDREGS->interrupt_mask_addr)
- * xen_set_virtual_psr_i(1)
- *     // *(*XEN_MAPPEDREGS->interrupt_mask_addr) = 0
- * // compiler barrier
- * if (masked) {
- *     uint8_t* pend_int_addr =
- *             (uint8_t*)(*XEN_MAPPEDREGS->interrupt_mask_addr) - 1;
- *     uint8_t pending = *pend_int_addr;
- *     if (pending)
- *             XEN_HYPER_SSM_I
- * }
- */
-/* 4 bundles */
-DEFINE_VOID_FUNC0(ssm_i,
-                 "mov r8 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n"
-                 ";;\n"
-                 "ld8 r8 = [r8]\n"             /* r8 = XEN_PSR_I_ADDR */
-                 ";;\n"
-                 "ld1.acq r9 = [r8]\n"         /* r9 = XEN_PSR_I */
-                 ";;\n"
-                 "st1.rel [r8] = r0, -1\n"     /* psr_i = 0. enable interrupt
-                                                * r8 = XEN_PSR_I_ADDR - 1
-                                                *    = pend_int_addr
-                                                */
-                 "cmp.eq.unc p0, p6 = r9, r0\n"/* p6 = !XEN_PSR_I
-                                                * previously interrupt
-                                                * masked?
-                                                */
-                 ";;\n"
-                 "(p6) ld1.acq r8 = [r8]\n"    /* r8 = xen_pend_int */
-                 ";;\n"
-                 "(p6) cmp.eq.unc p6, p7 = r8, r0\n"   /*interrupt pending?*/
-                 ";;\n"
-                 /* issue hypercall to get interrupt */
-                 "(p7) break " __stringify(HYPERPRIVOP_SSM_I) "\n"
-                 ";;\n");
-
-/*
- * psr_i_addr_addr = XEN_MAPPEDREGS->interrupt_mask_addr
- *                = XEN_PSR_I_ADDR_ADDR;
- * psr_i_addr = *psr_i_addr_addr;
- * *psr_i_addr = 1;
- */
-/* 2 bundles */
-DEFINE_VOID_FUNC0(rsm_i,
-                 "mov r8 = " __stringify(XEN_PSR_I_ADDR_ADDR) "\n"
-                                               /* r8 = XEN_PSR_I_ADDR */
-                 "mov r9 = 1\n"
-                 ";;\n"
-                 "ld8 r8 = [r8]\n"             /* r8 = XEN_PSR_I */
-                 ";;\n"
-                 "st1.rel [r8] = r9\n");       /* XEN_PSR_I = 1 */
-
-extern void
-xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1,
-                  unsigned long val2, unsigned long val3,
-                  unsigned long val4);
-__DEFINE_FUNC(set_rr0_to_rr4,
-             "break " __stringify(HYPERPRIVOP_SET_RR0_TO_RR4) "\n");
-
-
-extern unsigned long xen_getreg(int regnum);
-#define __DEFINE_GET_REG(id, privop)                                   \
-       "mov r2 = " __stringify(_IA64_REG_ ## id) "\n"                  \
-       ";;\n"                                                          \
-       "cmp.eq p6, p0 = r2, r8\n"                                      \
-       ";;\n"                                                          \
-       "(p6) break " __stringify(HYPERPRIVOP_GET_ ## privop) "\n"      \
-       "(p6) br.cond.sptk.many b6\n"                                   \
-       ";;\n"
-
-__DEFINE_FUNC(getreg,
-             __DEFINE_GET_REG(PSR, PSR)
-
-             /* get_itc */
-             "mov r2 = " __stringify(_IA64_REG_AR_ITC) "\n"
-             ";;\n"
-             "cmp.eq p6, p0 = r2, r8\n"
-             ";;\n"
-             "(p6) br.cond.spnt xen_get_itc\n"
-             ";;\n"
-
-             /* get itm */
-             "mov r2 = " __stringify(_IA64_REG_CR_ITM) "\n"
-             ";;\n"
-             "cmp.eq p6, p0 = r2, r8\n"
-             ";;\n"
-             "(p6) br.cond.spnt xen_get_itm_with_offset\n"
-             ";;\n"
-
-             __DEFINE_GET_REG(CR_IVR, IVR)
-             __DEFINE_GET_REG(CR_TPR, TPR)
-
-             /* fall back */
-             "movl r2 = ia64_native_getreg_func\n"
-             ";;\n"
-             "mov b7 = r2\n"
-             ";;\n"
-             "br.cond.sptk.many b7\n");
-
-extern void xen_setreg(int regnum, unsigned long val);
-#define __DEFINE_SET_REG(id, privop)                                   \
-       "mov r2 = " __stringify(_IA64_REG_ ## id) "\n"                  \
-       ";;\n"                                                          \
-       "cmp.eq p6, p0 = r2, r9\n"                                      \
-       ";;\n"                                                          \
-       "(p6) break " __stringify(HYPERPRIVOP_ ## privop) "\n"          \
-       "(p6) br.cond.sptk.many b6\n"                                   \
-       ";;\n"
-
-__DEFINE_FUNC(setreg,
-             /* kr0 .. kr 7*/
-             /*
-              * if (_IA64_REG_AR_KR0 <= regnum &&
-              *     regnum <= _IA64_REG_AR_KR7) {
-              *     register __index asm ("r8") = regnum - _IA64_REG_AR_KR0
-              *     register __val asm ("r9") = val
-              *    "break HYPERPRIVOP_SET_KR"
-              * }
-              */
-             "mov r17 = r9\n"
-             "mov r2 = " __stringify(_IA64_REG_AR_KR0) "\n"
-             ";;\n"
-             "cmp.ge p6, p0 = r9, r2\n"
-             "sub r17 = r17, r2\n"
-             ";;\n"
-             "(p6) cmp.ge.unc p7, p0 = "
-             __stringify(_IA64_REG_AR_KR7) " - " __stringify(_IA64_REG_AR_KR0)
-             ", r17\n"
-             ";;\n"
-             "(p7) mov r9 = r8\n"
-             ";;\n"
-             "(p7) mov r8 = r17\n"
-             "(p7) break " __stringify(HYPERPRIVOP_SET_KR) "\n"
-
-             /* set itm */
-             "mov r2 = " __stringify(_IA64_REG_CR_ITM) "\n"
-             ";;\n"
-             "cmp.eq p6, p0 = r2, r8\n"
-             ";;\n"
-             "(p6) br.cond.spnt xen_set_itm_with_offset\n"
-
-             /* set itc */
-             "mov r2 = " __stringify(_IA64_REG_AR_ITC) "\n"
-             ";;\n"
-             "cmp.eq p6, p0 = r2, r8\n"
-             ";;\n"
-             "(p6) br.cond.spnt xen_set_itc\n"
-
-             __DEFINE_SET_REG(CR_TPR, SET_TPR)
-             __DEFINE_SET_REG(CR_EOI, EOI)
-
-             /* fall back */
-             "movl r2 = ia64_native_setreg_func\n"
-             ";;\n"
-             "mov b7 = r2\n"
-             ";;\n"
-             "br.cond.sptk.many b7\n");
-#endif
-
-static const struct pv_cpu_ops xen_cpu_ops __initconst = {
-       .fc             = xen_fc,
-       .thash          = xen_thash,
-       .get_cpuid      = xen_get_cpuid,
-       .get_pmd        = xen_get_pmd,
-       .getreg         = xen_getreg,
-       .setreg         = xen_setreg,
-       .ptcga          = xen_ptcga,
-       .get_rr         = xen_get_rr,
-       .set_rr         = xen_set_rr,
-       .set_rr0_to_rr4 = xen_set_rr0_to_rr4,
-       .ssm_i          = xen_ssm_i,
-       .rsm_i          = xen_rsm_i,
-       .get_psr_i      = xen_get_psr_i,
-       .intrin_local_irq_restore
-                       = xen_intrin_local_irq_restore,
-};
-
-/******************************************************************************
- * replacement of hand written assembly codes.
- */
-
-extern char xen_switch_to;
-extern char xen_leave_syscall;
-extern char xen_work_processed_syscall;
-extern char xen_leave_kernel;
-
-const struct pv_cpu_asm_switch xen_cpu_asm_switch = {
-       .switch_to              = (unsigned long)&xen_switch_to,
-       .leave_syscall          = (unsigned long)&xen_leave_syscall,
-       .work_processed_syscall = (unsigned long)&xen_work_processed_syscall,
-       .leave_kernel           = (unsigned long)&xen_leave_kernel,
-};
-
-/***************************************************************************
- * pv_iosapic_ops
- * iosapic read/write hooks.
- */
-static void
-xen_pcat_compat_init(void)
-{
-       /* nothing */
-}
-
-static struct irq_chip*
-xen_iosapic_get_irq_chip(unsigned long trigger)
-{
-       return NULL;
-}
-
-static unsigned int
-xen_iosapic_read(char __iomem *iosapic, unsigned int reg)
-{
-       struct physdev_apic apic_op;
-       int ret;
-
-       apic_op.apic_physbase = (unsigned long)iosapic -
-                                       __IA64_UNCACHED_OFFSET;
-       apic_op.reg = reg;
-       ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
-       if (ret)
-               return ret;
-       return apic_op.value;
-}
-
-static void
-xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
-{
-       struct physdev_apic apic_op;
-
-       apic_op.apic_physbase = (unsigned long)iosapic -
-                                       __IA64_UNCACHED_OFFSET;
-       apic_op.reg = reg;
-       apic_op.value = val;
-       HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op);
-}
-
-static struct pv_iosapic_ops xen_iosapic_ops __initdata = {
-       .pcat_compat_init = xen_pcat_compat_init,
-       .__get_irq_chip = xen_iosapic_get_irq_chip,
-
-       .__read = xen_iosapic_read,
-       .__write = xen_iosapic_write,
-};
-
-/***************************************************************************
- * pv_ops initialization
- */
-
-void __init
-xen_setup_pv_ops(void)
-{
-       xen_info_init();
-       pv_info = xen_info;
-       pv_init_ops = xen_init_ops;
-       pv_fsys_data = xen_fsys_data;
-       pv_patchdata = xen_patchdata;
-       pv_cpu_ops = xen_cpu_ops;
-       pv_iosapic_ops = xen_iosapic_ops;
-       pv_irq_ops = xen_irq_ops;
-       pv_time_ops = xen_time_ops;
-
-       paravirt_cpu_asm_init(&xen_cpu_asm_switch);
-}
-
-#ifdef ASM_SUPPORTED
-/***************************************************************************
- * binary pacthing
- * pv_init_ops.patch_bundle
- */
-
-#define DEFINE_FUNC_GETREG(name, privop)                               \
-       DEFINE_FUNC0(get_ ## name,                                      \
-                    "break "__stringify(HYPERPRIVOP_GET_ ## privop) "\n")
-
-DEFINE_FUNC_GETREG(psr, PSR);
-DEFINE_FUNC_GETREG(eflag, EFLAG);
-DEFINE_FUNC_GETREG(ivr, IVR);
-DEFINE_FUNC_GETREG(tpr, TPR);
-
-#define DEFINE_FUNC_SET_KR(n)                                          \
-       DEFINE_VOID_FUNC0(set_kr ## n,                                  \
-                         ";;\n"                                        \
-                         "mov r9 = r8\n"                               \
-                         "mov r8 = " #n "\n"                           \
-                         "break " __stringify(HYPERPRIVOP_SET_KR) "\n")
-
-DEFINE_FUNC_SET_KR(0);
-DEFINE_FUNC_SET_KR(1);
-DEFINE_FUNC_SET_KR(2);
-DEFINE_FUNC_SET_KR(3);
-DEFINE_FUNC_SET_KR(4);
-DEFINE_FUNC_SET_KR(5);
-DEFINE_FUNC_SET_KR(6);
-DEFINE_FUNC_SET_KR(7);
-
-#define __DEFINE_FUNC_SETREG(name, privop)                             \
-       DEFINE_VOID_FUNC0(name,                                         \
-                         "break "__stringify(HYPERPRIVOP_ ## privop) "\n")
-
-#define DEFINE_FUNC_SETREG(name, privop)                       \
-       __DEFINE_FUNC_SETREG(set_ ## name, SET_ ## privop)
-
-DEFINE_FUNC_SETREG(eflag, EFLAG);
-DEFINE_FUNC_SETREG(tpr, TPR);
-__DEFINE_FUNC_SETREG(eoi, EOI);
-
-extern const char xen_check_events[];
-extern const char __xen_intrin_local_irq_restore_direct_start[];
-extern const char __xen_intrin_local_irq_restore_direct_end[];
-extern const unsigned long __xen_intrin_local_irq_restore_direct_reloc;
-
-asm (
-       ".align 32\n"
-       ".proc xen_check_events\n"
-       "xen_check_events:\n"
-       /* masked = 0
-        * r9 = masked_addr - 1
-        *    = pending_intr_addr
-        */
-       "st1.rel [r9] = r0, -1\n"
-       ";;\n"
-       /* r8 = pending_intr */
-       "ld1.acq r11 = [r9]\n"
-       ";;\n"
-       /* p9 = interrupt pending? */
-       "cmp.ne p9, p10 = r11, r0\n"
-       ";;\n"
-       "(p10) mf\n"
-       /* issue hypercall to trigger interrupt */
-       "(p9) break " __stringify(HYPERPRIVOP_SSM_I) "\n"
-       "br.cond.sptk.many b6\n"
-       ".endp xen_check_events\n"
-       "\n"
-       ".align 32\n"
-       ".proc __xen_intrin_local_irq_restore_direct\n"
-       "__xen_intrin_local_irq_restore_direct:\n"
-       "__xen_intrin_local_irq_restore_direct_start:\n"
-       "1:\n"
-       "{\n"
-       "cmp.ne p6, p7 = r8, r0\n"
-       "mov r17 = ip\n" /* get ip to calc return address */
-       "mov r9 = "__stringify(XEN_PSR_I_ADDR_ADDR) "\n"
-       ";;\n"
-       "}\n"
-       "{\n"
-       /* r9 = XEN_PSR_I_ADDR */
-       "ld8 r9 = [r9]\n"
-       ";;\n"
-       /* r10 = masked previous value */
-       "(p6) ld1.acq r10 = [r9]\n"
-       "adds r17 =  1f - 1b, r17\n" /* calculate return address */
-       ";;\n"
-       "}\n"
-       "{\n"
-       /* p8 = !masked interrupt masked previously? */
-       "(p6) cmp.ne.unc p8, p0 = r10, r0\n"
-       "\n"
-       /* p7 = else clause */
-       "(p7) mov r11 = 1\n"
-       ";;\n"
-       "(p8) mov b6 = r17\n" /* set return address */
-       "}\n"
-       "{\n"
-       /* masked = 1 */
-       "(p7) st1.rel [r9] = r11\n"
-       "\n"
-       "[99:]\n"
-       "(p8) brl.cond.dptk.few xen_check_events\n"
-       "}\n"
-       /* pv calling stub is 5 bundles. fill nop to adjust return address */
-       "{\n"
-       "nop 0\n"
-       "nop 0\n"
-       "nop 0\n"
-       "}\n"
-       "1:\n"
-       "__xen_intrin_local_irq_restore_direct_end:\n"
-       ".endp __xen_intrin_local_irq_restore_direct\n"
-       "\n"
-       ".align 8\n"
-       "__xen_intrin_local_irq_restore_direct_reloc:\n"
-       "data8 99b\n"
-);
-
-static struct paravirt_patch_bundle_elem xen_patch_bundle_elems[]
-__initdata_or_module =
-{
-#define XEN_PATCH_BUNDLE_ELEM(name, type)              \
-       {                                               \
-               (void*)xen_ ## name ## _direct_start,   \
-               (void*)xen_ ## name ## _direct_end,     \
-               PARAVIRT_PATCH_TYPE_ ## type,           \
-       }
-
-       XEN_PATCH_BUNDLE_ELEM(fc, FC),
-       XEN_PATCH_BUNDLE_ELEM(thash, THASH),
-       XEN_PATCH_BUNDLE_ELEM(get_cpuid, GET_CPUID),
-       XEN_PATCH_BUNDLE_ELEM(get_pmd, GET_PMD),
-       XEN_PATCH_BUNDLE_ELEM(ptcga, PTCGA),
-       XEN_PATCH_BUNDLE_ELEM(get_rr, GET_RR),
-       XEN_PATCH_BUNDLE_ELEM(set_rr, SET_RR),
-       XEN_PATCH_BUNDLE_ELEM(set_rr0_to_rr4, SET_RR0_TO_RR4),
-       XEN_PATCH_BUNDLE_ELEM(ssm_i, SSM_I),
-       XEN_PATCH_BUNDLE_ELEM(rsm_i, RSM_I),
-       XEN_PATCH_BUNDLE_ELEM(get_psr_i, GET_PSR_I),
-       {
-               (void*)__xen_intrin_local_irq_restore_direct_start,
-               (void*)__xen_intrin_local_irq_restore_direct_end,
-               PARAVIRT_PATCH_TYPE_INTRIN_LOCAL_IRQ_RESTORE,
-       },
-
-#define XEN_PATCH_BUNDLE_ELEM_GETREG(name, reg)                        \
-       {                                                       \
-               xen_get_ ## name ## _direct_start,              \
-               xen_get_ ## name ## _direct_end,                \
-               PARAVIRT_PATCH_TYPE_GETREG + _IA64_REG_ ## reg, \
-       }
-
-       XEN_PATCH_BUNDLE_ELEM_GETREG(psr, PSR),
-       XEN_PATCH_BUNDLE_ELEM_GETREG(eflag, AR_EFLAG),
-
-       XEN_PATCH_BUNDLE_ELEM_GETREG(ivr, CR_IVR),
-       XEN_PATCH_BUNDLE_ELEM_GETREG(tpr, CR_TPR),
-
-       XEN_PATCH_BUNDLE_ELEM_GETREG(itc, AR_ITC),
-       XEN_PATCH_BUNDLE_ELEM_GETREG(itm_with_offset, CR_ITM),
-
-
-#define __XEN_PATCH_BUNDLE_ELEM_SETREG(name, reg)              \
-       {                                                       \
-               xen_ ## name ## _direct_start,                  \
-               xen_ ## name ## _direct_end,                    \
-               PARAVIRT_PATCH_TYPE_SETREG + _IA64_REG_ ## reg, \
-       }
-
-#define XEN_PATCH_BUNDLE_ELEM_SETREG(name, reg)                        \
-       __XEN_PATCH_BUNDLE_ELEM_SETREG(set_ ## name, reg)
-
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr0, AR_KR0),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr1, AR_KR1),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr2, AR_KR2),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr3, AR_KR3),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr4, AR_KR4),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr5, AR_KR5),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr6, AR_KR6),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(kr7, AR_KR7),
-
-       XEN_PATCH_BUNDLE_ELEM_SETREG(eflag, AR_EFLAG),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(tpr, CR_TPR),
-       __XEN_PATCH_BUNDLE_ELEM_SETREG(eoi, CR_EOI),
-
-       XEN_PATCH_BUNDLE_ELEM_SETREG(itc, AR_ITC),
-       XEN_PATCH_BUNDLE_ELEM_SETREG(itm_with_offset, CR_ITM),
-};
-
-static unsigned long __init_or_module
-xen_patch_bundle(void *sbundle, void *ebundle, unsigned long type)
-{
-       const unsigned long nelems = sizeof(xen_patch_bundle_elems) /
-               sizeof(xen_patch_bundle_elems[0]);
-       unsigned long used;
-       const struct paravirt_patch_bundle_elem *found;
-
-       used = __paravirt_patch_apply_bundle(sbundle, ebundle, type,
-                                            xen_patch_bundle_elems, nelems,
-                                            &found);
-
-       if (found == NULL)
-               /* fallback */
-               return ia64_native_patch_bundle(sbundle, ebundle, type);
-       if (used == 0)
-               return used;
-
-       /* relocation */
-       switch (type) {
-       case PARAVIRT_PATCH_TYPE_INTRIN_LOCAL_IRQ_RESTORE: {
-               unsigned long reloc =
-                       __xen_intrin_local_irq_restore_direct_reloc;
-               unsigned long reloc_offset = reloc - (unsigned long)
-                       __xen_intrin_local_irq_restore_direct_start;
-               unsigned long tag = (unsigned long)sbundle + reloc_offset;
-               paravirt_patch_reloc_brl(tag, xen_check_events);
-               break;
-       }
-       default:
-               /* nothing */
-               break;
-       }
-       return used;
-}
-#endif /* ASM_SUPPOTED */
-
-const struct paravirt_patch_branch_target xen_branch_target[]
-__initconst = {
-#define PARAVIRT_BR_TARGET(name, type)                 \
-       {                                               \
-               &xen_ ## name,                          \
-               PARAVIRT_PATCH_TYPE_BR_ ## type,        \
-       }
-       PARAVIRT_BR_TARGET(switch_to, SWITCH_TO),
-       PARAVIRT_BR_TARGET(leave_syscall, LEAVE_SYSCALL),
-       PARAVIRT_BR_TARGET(work_processed_syscall, WORK_PROCESSED_SYSCALL),
-       PARAVIRT_BR_TARGET(leave_kernel, LEAVE_KERNEL),
-};
-
-static void __init
-xen_patch_branch(unsigned long tag, unsigned long type)
-{
-       __paravirt_patch_apply_branch(tag, type, xen_branch_target,
-                                       ARRAY_SIZE(xen_branch_target));
-}
diff --git a/arch/ia64/xen/xencomm.c b/arch/ia64/xen/xencomm.c
deleted file mode 100644 (file)
index 73d903c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/mm.h>
-#include <linux/err.h>
-
-static unsigned long kernel_virtual_offset;
-static int is_xencomm_initialized;
-
-/* for xen early printk. It uses console io hypercall which uses xencomm.
- * However early printk may use it before xencomm initialization.
- */
-int
-xencomm_is_initialized(void)
-{
-       return is_xencomm_initialized;
-}
-
-void
-xencomm_initialize(void)
-{
-       kernel_virtual_offset = KERNEL_START - ia64_tpa(KERNEL_START);
-       is_xencomm_initialized = 1;
-}
-
-/* Translate virtual address to physical address.  */
-unsigned long
-xencomm_vtop(unsigned long vaddr)
-{
-       struct page *page;
-       struct vm_area_struct *vma;
-
-       if (vaddr == 0)
-               return 0UL;
-
-       if (REGION_NUMBER(vaddr) == 5) {
-               pgd_t *pgd;
-               pud_t *pud;
-               pmd_t *pmd;
-               pte_t *ptep;
-
-               /* On ia64, TASK_SIZE refers to current.  It is not initialized
-                  during boot.
-                  Furthermore the kernel is relocatable and __pa() doesn't
-                  work on  addresses.  */
-               if (vaddr >= KERNEL_START
-                   && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE))
-                       return vaddr - kernel_virtual_offset;
-
-               /* In kernel area -- virtually mapped.  */
-               pgd = pgd_offset_k(vaddr);
-               if (pgd_none(*pgd) || pgd_bad(*pgd))
-                       return ~0UL;
-
-               pud = pud_offset(pgd, vaddr);
-               if (pud_none(*pud) || pud_bad(*pud))
-                       return ~0UL;
-
-               pmd = pmd_offset(pud, vaddr);
-               if (pmd_none(*pmd) || pmd_bad(*pmd))
-                       return ~0UL;
-
-               ptep = pte_offset_kernel(pmd, vaddr);
-               if (!ptep)
-                       return ~0UL;
-
-               return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK);
-       }
-
-       if (vaddr > TASK_SIZE) {
-               /* percpu variables */
-               if (REGION_NUMBER(vaddr) == 7 &&
-                   REGION_OFFSET(vaddr) >= (1ULL << IA64_MAX_PHYS_BITS))
-                       ia64_tpa(vaddr);
-
-               /* kernel address */
-               return __pa(vaddr);
-       }
-
-       /* XXX double-check (lack of) locking */
-       vma = find_extend_vma(current->mm, vaddr);
-       if (!vma)
-               return ~0UL;
-
-       /* We assume the page is modified.  */
-       page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH);
-       if (IS_ERR_OR_NULL(page))
-               return ~0UL;
-
-       return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
-}
diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S
deleted file mode 100644 (file)
index 3e71d50..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * arch/ia64/xen/ivt.S
- *
- * Copyright (C) 2005 Hewlett-Packard Co
- *     Dan Magenheimer <dan.magenheimer@hp.com>
- *
- * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
- *                    VA Linux Systems Japan K.K.
- *                    pv_ops.
- */
-
-#include <asm/asmmacro.h>
-#include <asm/kregs.h>
-#include <asm/pgtable.h>
-
-#include "../kernel/minstate.h"
-
-       .section .text,"ax"
-GLOBAL_ENTRY(xen_event_callback)
-       mov r31=pr              // prepare to save predicates
-       ;;
-       SAVE_MIN_WITH_COVER     // uses r31; defines r2 and r3
-       ;;
-       movl r3=XSI_PSR_IC
-       mov r14=1
-       ;;
-       st4 [r3]=r14
-       ;;
-       adds r3=8,r2            // set up second base pointer for SAVE_REST
-       srlz.i                  // ensure everybody knows psr.ic is back on
-       ;;
-       SAVE_REST
-       ;;
-1:
-       alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
-       add out0=16,sp          // pass pointer to pt_regs as first arg
-       ;;
-       br.call.sptk.many b0=xen_evtchn_do_upcall
-       ;;
-       movl r20=XSI_PSR_I_ADDR
-       ;;
-       ld8 r20=[r20]
-       ;;
-       adds r20=-1,r20         // vcpu_info->evtchn_upcall_pending
-       ;;
-       ld1 r20=[r20]
-       ;;
-       cmp.ne p6,p0=r20,r0     // if there are pending events,
-       (p6) br.spnt.few 1b     // call evtchn_do_upcall again.
-       br.sptk.many xen_leave_kernel   // we know ia64_leave_kernel is
-                                       // paravirtualized as xen_leave_kernel
-END(xen_event_callback)
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S
deleted file mode 100644 (file)
index e29519e..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Support routines for Xen
- *
- * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
- */
-
-#include <asm/processor.h>
-#include <asm/asmmacro.h>
-#include <asm/pgtable.h>
-#include <asm/paravirt.h>
-#include <asm/xen/privop.h>
-#include <linux/elfnote.h>
-#include <linux/init.h>
-#include <xen/interface/elfnote.h>
-
-       .section .data..read_mostly
-       .align 8
-       .global xen_domain_type
-xen_domain_type:
-       data4 XEN_NATIVE_ASM
-       .previous
-
-       __INIT
-ENTRY(startup_xen)
-       // Calculate load offset.
-       // The constant, LOAD_OFFSET, can't be used because the boot
-       // loader doesn't always load to the LMA specified by the vmlinux.lds.
-       mov r9=ip       // must be the first instruction to make sure
-                       // that r9 = the physical address of startup_xen.
-                       // Usually r9 = startup_xen - LOAD_OFFSET
-       movl r8=startup_xen
-       ;;
-       sub r9=r9,r8    // Usually r9 = -LOAD_OFFSET.
-
-       mov r10=PARAVIRT_HYPERVISOR_TYPE_XEN
-       movl r11=_start
-       ;;
-       add r11=r11,r9
-       movl r8=hypervisor_type
-       ;;
-       add r8=r8,r9
-       mov b0=r11
-       ;;
-       st8 [r8]=r10
-       br.cond.sptk.many b0
-       ;;
-END(startup_xen)
-
-       ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,      .asciz "linux")
-       ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6")
-       ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,   .asciz "xen-3.0")
-       ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,         data8.ua startup_xen - LOAD_OFFSET)
-
-#define isBP   p3      // are we the Bootstrap Processor?
-
-GLOBAL_ENTRY(xen_setup_hook)
-       mov r8=XEN_PV_DOMAIN_ASM
-(isBP) movl r9=xen_domain_type;;
-(isBP) st4 [r9]=r8
-       movl r10=xen_ivt;;
-
-       mov cr.iva=r10
-
-       /* Set xsi base.  */
-#define FW_HYPERCALL_SET_SHARED_INFO_VA                        0x600
-(isBP) mov r2=FW_HYPERCALL_SET_SHARED_INFO_VA
-(isBP) movl r28=XSI_BASE;;
-(isBP) break 0x1000;;
-
-       /* setup pv_ops */
-(isBP) mov r4=rp
-       ;;
-(isBP) br.call.sptk.many rp=xen_setup_pv_ops
-       ;;
-(isBP) mov rp=r4
-       ;;
-
-       br.ret.sptk.many rp
-       ;;
-END(xen_setup_hook)
index 6976621efd3f5d1c313498535827cc93dcd142e4..1a40265e8d883fb494e1045bb3dcf992390c8c70 100644 (file)
 
 #define nop()  __asm__ __volatile__ ("nop" : : )
 
-/*
- * Memory barrier.
- *
- * mb() prevents loads and stores being reordered across this point.
- * rmb() prevents loads being reordered across this point.
- * wmb() prevents stores being reordered across this point.
- */
-#define mb()   barrier()
-#define rmb()  mb()
-#define wmb()  mb()
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *      CPU 0                           CPU 1
- *
- *      b = 2;
- *      memory_barrier();
- *      p = &b;                         q = p;
- *                                      read_barrier_depends();
- *                                      d = *q;
- * </programlisting>
- *
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *      CPU 0                           CPU 1
- *
- *      a = 2;
- *      memory_barrier();
- *      b = 3;                          y = b;
- *                                      read_barrier_depends();
- *                                      x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
+#include <asm-generic/barrier.h>
 
 #endif /* _ASM_M32R_BARRIER_H */
index 75f25a8e300170ce85130da8fd2f739faa983059..dbdd2231c75ddc9fab61fd1b2dca7c1cc60a3e3e 100644 (file)
@@ -87,6 +87,30 @@ config MMU_SUN3
        bool
        depends on MMU && !MMU_MOTOROLA && !MMU_COLDFIRE
 
+config KEXEC
+       bool "kexec system call"
+       depends on M68KCLASSIC
+       help
+         kexec is a system call that implements the ability to shutdown your
+         current kernel, and to start another kernel.  It is like a reboot
+         but it is independent of the system firmware.   And like a reboot
+         you can start any kernel with it, not just Linux.
+
+         The name comes from the similarity to the exec system call.
+
+         It is an ongoing process to be certain the hardware in a machine
+         is properly shutdown, so do not be surprised if this code does not
+         initially work for you.  As of this writing the exact hardware
+         interface is strongly in flux, so no good recommendation can be
+         made.
+
+config BOOTINFO_PROC
+       bool "Export bootinfo in procfs"
+       depends on KEXEC && M68KCLASSIC
+       help
+         Say Y to export the bootinfo used to boot the kernel in a
+         "bootinfo" file in procfs.  This is useful with kexec.
+
 menu "Platform setup"
 
 source arch/m68k/Kconfig.cpu
index 99449fbf9a726834ec2b2c268956a13f0ab0b99d..ba03cec3f711e024422fe916a407b4cf56556f76 100644 (file)
@@ -87,7 +87,7 @@ void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
 
        atomic_sub(size, &chipavail);
        pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
-       return (void *)ZTWO_VADDR(res->start);
+       return ZTWO_VADDR(res->start);
 }
 
 void amiga_chip_free(void *ptr)
index b819390e29cdb7e901e926a9190b30ebadb8916c..9625b71322275ea942da3bc1b3a6616e205bdc7a 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/keyboard.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-amiga.h>
+#include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
@@ -140,46 +142,46 @@ static struct resource ram_resource[NUM_MEMINFO];
      *  Parse an Amiga-specific record in the bootinfo
      */
 
-int amiga_parse_bootinfo(const struct bi_record *record)
+int __init amiga_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const unsigned long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_AMIGA_MODEL:
-               amiga_model = *data;
+               amiga_model = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_ECLOCK:
-               amiga_eclock = *data;
+               amiga_eclock = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_CHIPSET:
-               amiga_chipset = *data;
+               amiga_chipset = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_CHIP_SIZE:
-               amiga_chip_size = *(const int *)data;
+               amiga_chip_size = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_VBLANK:
-               amiga_vblank = *(const unsigned char *)data;
+               amiga_vblank = *(const __u8 *)data;
                break;
 
        case BI_AMIGA_PSFREQ:
-               amiga_psfreq = *(const unsigned char *)data;
+               amiga_psfreq = *(const __u8 *)data;
                break;
 
        case BI_AMIGA_AUTOCON:
 #ifdef CONFIG_ZORRO
                if (zorro_num_autocon < ZORRO_NUM_AUTO) {
-                       const struct ConfigDev *cd = (struct ConfigDev *)data;
-                       struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+                       const struct ConfigDev *cd = data;
+                       struct zorro_dev_init *dev = &zorro_autocon_init[zorro_num_autocon++];
                        dev->rom = cd->cd_Rom;
-                       dev->slotaddr = cd->cd_SlotAddr;
-                       dev->slotsize = cd->cd_SlotSize;
-                       dev->resource.start = (unsigned long)cd->cd_BoardAddr;
-                       dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1;
+                       dev->slotaddr = be16_to_cpu(cd->cd_SlotAddr);
+                       dev->slotsize = be16_to_cpu(cd->cd_SlotSize);
+                       dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
+                       dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
                } else
                        printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
 #endif /* CONFIG_ZORRO */
@@ -358,6 +360,14 @@ static void __init amiga_identify(void)
 #undef AMIGAHW_ANNOUNCE
 }
 
+
+static unsigned long amiga_random_get_entropy(void)
+{
+       /* VPOSR/VHPOSR provide at least 17 bits of data changing at 1.79 MHz */
+       return *(unsigned long *)&amiga_custom.vposr;
+}
+
+
     /*
      *  Setup the Amiga configuration info
      */
@@ -395,6 +405,8 @@ void __init config_amiga(void)
        mach_heartbeat = amiga_heartbeat;
 #endif
 
+       mach_random_get_entropy = amiga_random_get_entropy;
+
        /* Fill in the clock value (based on the 700 kHz E-Clock) */
        amiga_colorclock = 5*amiga_eclock;      /* 3.5 MHz */
 
@@ -608,6 +620,8 @@ static void amiga_mem_console_write(struct console *co, const char *s,
 
 static int __init amiga_savekmsg_setup(char *arg)
 {
+       bool registered;
+
        if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
                return 0;
 
@@ -618,14 +632,16 @@ static int __init amiga_savekmsg_setup(char *arg)
 
        /* Just steal the block, the chipram allocator isn't functional yet */
        amiga_chip_size -= SAVEKMSG_MAXMEM;
-       savekmsg = (void *)ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size);
+       savekmsg = ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size);
        savekmsg->magic1 = SAVEKMSG_MAGIC1;
        savekmsg->magic2 = SAVEKMSG_MAGIC2;
        savekmsg->magicptr = ZTWO_PADDR(savekmsg);
        savekmsg->size = 0;
 
+       registered = !!amiga_console_driver.write;
        amiga_console_driver.write = amiga_mem_console_write;
-       register_console(&amiga_console_driver);
+       if (!registered)
+               register_console(&amiga_console_driver);
        return 0;
 }
 
@@ -707,11 +723,16 @@ void amiga_serial_gets(struct console *co, char *s, int len)
 
 static int __init amiga_debug_setup(char *arg)
 {
-       if (MACH_IS_AMIGA && !strcmp(arg, "ser")) {
-               /* no initialization required (?) */
-               amiga_console_driver.write = amiga_serial_console_write;
+       bool registered;
+
+       if (!MACH_IS_AMIGA || strcmp(arg, "ser"))
+               return 0;
+
+       /* no initialization required (?) */
+       registered = !!amiga_console_driver.write;
+       amiga_console_driver.write = amiga_serial_console_write;
+       if (!registered)
                register_console(&amiga_console_driver);
-       }
        return 0;
 }
 
index dacd9f911f7171f847fc0087faf20a34092f0e1c..d34029d7b05892a5c0d2e646129a89407402b368 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <asm/amigahw.h>
 #include <asm/amigayle.h>
+#include <asm/byteorder.h>
 
 
 #ifdef CONFIG_ZORRO
@@ -66,10 +67,12 @@ static int __init z_dev_present(zorro_id id)
 {
        unsigned int i;
 
-       for (i = 0; i < zorro_num_autocon; i++)
-               if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) &&
-                   zorro_autocon[i].rom.er_Product == ZORRO_PROD(id))
+       for (i = 0; i < zorro_num_autocon; i++) {
+               const struct ExpansionRom *rom = &zorro_autocon_init[i].rom;
+               if (be16_to_cpu(rom->er_Manufacturer) == ZORRO_MANUF(id) &&
+                   rom->er_Product == ZORRO_PROD(id))
                        return 1;
+       }
 
        return 0;
 }
index 3ea56b90e7188df2c758bce798fc46c2d96df461..9268c0f96376b30eee39caba6d023d3fd0488cab 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -9,6 +10,8 @@
 
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-apollo.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/apollohw.h>
 #include <asm/irq.h>
@@ -43,26 +46,25 @@ static const char *apollo_models[] = {
        [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)"
 };
 
-int apollo_parse_bootinfo(const struct bi_record *record) {
-
+int __init apollo_parse_bootinfo(const struct bi_record *record)
+{
        int unknown = 0;
-       const unsigned long *data = record->data;
+       const void *data = record->data;
 
-       switch(record->tag) {
-               case BI_APOLLO_MODEL:
-                       apollo_model=*data;
-                       break;
+       switch (be16_to_cpu(record->tag)) {
+       case BI_APOLLO_MODEL:
+               apollo_model = be32_to_cpup(data);
+               break;
 
-               default:
-                        unknown=1;
+       default:
+                unknown=1;
        }
 
        return unknown;
 }
 
-void dn_setup_model(void) {
-
-
+static void __init dn_setup_model(void)
+{
        printk("Apollo hardware found: ");
        printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]);
 
index 20cde4e9fc772ed2aef86c0da2edc2facb9e1e38..3e73a63c066f8a480ae543035c26cd5265f797ae 100644 (file)
@@ -333,6 +333,9 @@ void __init atari_init_IRQ(void)
        m68k_setup_irq_controller(&atari_mfptimer_chip, handle_simple_irq,
                                  IRQ_MFP_TIMER1, 8);
 
+       irq_set_status_flags(IRQ_MFP_TIMER1, IRQ_IS_POLLED);
+       irq_set_status_flags(IRQ_MFP_TIMER2, IRQ_IS_POLLED);
+
        /* prepare timer D data for use as poll interrupt */
        /* set Timer D data Register - needs to be > 0 */
        st_mfp.tim_dt_d = 254;  /* < 100 Hz */
index fb2d0bd9b3adab5304dc160a3bcf192aa0568a53..01a62161b08a1a69a74635de7004e4e65c73bf20 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-atari.h>
+#include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
@@ -129,14 +131,14 @@ static int __init scc_test(volatile char *ctla)
 int __init atari_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const u_long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_ATARI_MCH_COOKIE:
-               atari_mch_cookie = *data;
+               atari_mch_cookie = be32_to_cpup(data);
                break;
        case BI_ATARI_MCH_TYPE:
-               atari_mch_type = *data;
+               atari_mch_type = be32_to_cpup(data);
                break;
        default:
                unknown = 1;
index a547ba9683d14a551c9d4a18632d3c3a5d7a1bed..03cb5e08d7cf9f4995a8e24c613e48c03c11b6f1 100644 (file)
@@ -287,6 +287,8 @@ static void __init atari_init_midi_port(int cflag)
 
 static int __init atari_debug_setup(char *arg)
 {
+       bool registered;
+
        if (!MACH_IS_ATARI)
                return 0;
 
@@ -294,6 +296,7 @@ static int __init atari_debug_setup(char *arg)
                /* defaults to ser2 for a Falcon and ser1 otherwise */
                arg = MACH_IS_FALCON ? "ser2" : "ser1";
 
+       registered = !!atari_console_driver.write;
        if (!strcmp(arg, "ser1")) {
                /* ST-MFP Modem1 serial port */
                atari_init_mfp_port(B9600|CS8);
@@ -317,7 +320,7 @@ static int __init atari_debug_setup(char *arg)
                sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
                atari_console_driver.write = atari_par_console_write;
        }
-       if (atari_console_driver.write)
+       if (atari_console_driver.write && !registered)
                register_console(&atari_console_driver);
 
        return 0;
index 8943aa4c18e63cd3b0719b3a8d9f50e6bec40671..478623dbb2092b357a1f355d382ad3cc272f8e95 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/bcd.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-vme.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -50,9 +52,9 @@ void bvme6000_set_vectors (void);
 static irq_handler_t tick_handler;
 
 
-int bvme6000_parse_bootinfo(const struct bi_record *bi)
+int __init bvme6000_parse_bootinfo(const struct bi_record *bi)
 {
-       if (bi->tag == BI_VME_TYPE)
+       if (be16_to_cpu(bi->tag) == BI_VME_TYPE)
                return 0;
        else
                return 1;
index 19325e117eeaaec7b844e1e50d328719077e3261..559ff3af8ff7b1e8dd4a738eebe6321f1dc3ddd9 100644 (file)
@@ -52,7 +52,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -63,11 +62,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -85,6 +84,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -98,6 +108,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -130,6 +141,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -144,11 +156,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -156,6 +175,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -170,6 +190,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
@@ -183,11 +206,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -195,10 +220,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -216,6 +244,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_IDE=y
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
@@ -262,6 +291,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -271,10 +301,10 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_3COM is not set
 CONFIG_A2065=y
 CONFIG_ARIADNE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FUJITSU is not set
 # CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -285,6 +315,7 @@ CONFIG_ZORRO8390=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -311,7 +342,6 @@ CONFIG_JOYSTICK_AMIGA=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 # CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_PRINTER=m
@@ -345,10 +375,6 @@ CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=y
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_SERIAL_CONSOLE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -385,7 +411,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -444,10 +470,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -480,6 +506,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 14dc6ccda7f45349c82c0dd1f0d113831b3ac07b..cb1f55df69b6c87b03dc2c1598b43fdbfd3fcfa0 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -61,11 +60,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -83,6 +82,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -96,6 +106,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -128,6 +139,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -142,11 +154,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -154,6 +173,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -168,6 +188,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
@@ -181,11 +204,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -193,10 +218,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -208,6 +236,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -244,12 +273,14 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -258,6 +289,7 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -279,7 +311,6 @@ CONFIG_INPUT_EVDEV=m
 # CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
 CONFIG_SERIO=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
@@ -302,10 +333,6 @@ CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -342,7 +369,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -401,10 +428,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -437,6 +464,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 6d5370c914b265123b6963df409ca3b82d17f8cf..e880cfbb62d9e419bcbf4a4d006ffd420939b4f1 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -60,11 +59,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -82,6 +81,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -95,6 +105,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -127,6 +138,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -141,11 +153,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -153,6 +172,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -167,6 +187,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
@@ -180,11 +203,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -192,10 +217,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -211,6 +239,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_IDE=y
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
@@ -249,10 +278,10 @@ CONFIG_TCM_PSCSI=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_EQUALIZER=m
-CONFIG_MII=y
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -260,6 +289,7 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_ATARILANCE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -267,6 +297,7 @@ CONFIG_ATARILANCE=y
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -291,7 +322,6 @@ CONFIG_MOUSE_ATARI=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 # CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_PRINTER=m
@@ -320,10 +350,6 @@ CONFIG_NFBLOCK=y
 CONFIG_NFCON=y
 CONFIG_NFETH=y
 CONFIG_ATARI_DSP56K=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -360,7 +386,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -419,10 +445,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -455,6 +481,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index c015ddb6fd80635c81affec06369ced3f62185f8..4aa4f45e52a8708853925fb678a19d4889f632f3 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -59,11 +58,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -81,6 +80,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -94,6 +104,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -126,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -140,11 +152,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -152,6 +171,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -166,6 +186,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
@@ -179,11 +202,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -191,10 +216,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -206,6 +234,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -243,12 +272,14 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_BVME6000_NET=y
@@ -257,6 +288,7 @@ CONFIG_BVME6000_NET=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -294,10 +326,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -334,7 +362,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -393,10 +421,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -429,6 +457,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index ec7382d8afff5390a4210a45ba348637605c4f59..7cd9d9f456fb61ab3619641b81ee8dbfbd975acf 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -61,11 +60,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -83,6 +82,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -96,6 +106,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -128,6 +139,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -142,11 +154,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -154,6 +173,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -168,6 +188,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
@@ -181,11 +204,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -193,10 +218,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -208,6 +236,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -244,6 +273,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -251,6 +281,7 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_HPLANCE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -259,6 +290,7 @@ CONFIG_HPLANCE=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -282,7 +314,6 @@ CONFIG_MOUSE_SERIAL=m
 CONFIG_INPUT_MISC=y
 CONFIG_HP_SDC_RTC=m
 CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
@@ -304,10 +335,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -344,7 +371,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -403,10 +430,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -439,6 +466,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 7d46fbec70424dc84fbe07a9ab1e77c7d1f2bec2..31f5bd061d1466f5367fa0b0dafc1ecaa8f4d521 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -60,11 +59,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -82,6 +81,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -95,6 +105,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -127,6 +138,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -141,11 +153,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -153,6 +172,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -167,6 +187,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
@@ -180,11 +203,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -195,11 +220,13 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -212,6 +239,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_IDE=y
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
@@ -261,6 +289,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -268,6 +297,7 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_MACMACE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MAC89x0=y
@@ -279,6 +309,7 @@ CONFIG_MAC8390=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -302,7 +333,6 @@ CONFIG_MOUSE_SERIAL=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 CONFIG_SERIO=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_PMACZILOG=y
@@ -327,10 +357,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -367,7 +393,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -426,10 +452,11 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
+CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -462,6 +489,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index b17a8837f0e1016b273e5f74c6f75803a1e372b8..4e5adff326eec88bccff93bf83933f518b94328b 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -69,11 +68,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -91,6 +90,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -104,6 +114,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -136,6 +147,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -150,11 +162,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -162,6 +181,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -176,6 +196,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
@@ -189,11 +212,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -204,11 +229,13 @@ CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
 CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -230,6 +257,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_IDE=y
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
@@ -290,10 +318,10 @@ CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_EQUALIZER=m
-CONFIG_MII=y
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -308,10 +336,10 @@ CONFIG_HPLANCE=y
 CONFIG_MVME147_NET=y
 CONFIG_SUN3LANCE=y
 CONFIG_MACMACE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MAC89x0=y
-# CONFIG_NET_VENDOR_FUJITSU is not set
 # CONFIG_NET_VENDOR_HP is not set
 CONFIG_BVME6000_NET=y
 CONFIG_MVME16x_NET=y
@@ -325,6 +353,7 @@ CONFIG_APNE=y
 CONFIG_ZORRO8390=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PLIP=m
 CONFIG_PPP=m
@@ -357,7 +386,6 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 CONFIG_HP_SDC_RTC=m
 CONFIG_SERIO_Q40KBD=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_PMACZILOG=y
@@ -405,10 +433,6 @@ CONFIG_NFETH=y
 CONFIG_ATARI_DSP56K=m
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_SERIAL_CONSOLE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -445,7 +469,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -504,10 +528,11 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
+CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -540,6 +565,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 5586c6529fce367fb22061b87c708b9ba10a1f61..02cdbac5565e5153f0970409e8247535bf818fd7 100644 (file)
@@ -47,7 +47,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -58,11 +57,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -80,6 +79,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -93,6 +103,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -125,6 +136,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -139,11 +151,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -151,6 +170,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -165,6 +185,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
@@ -178,11 +201,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -190,10 +215,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -205,6 +233,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -242,6 +271,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -249,6 +279,7 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_MVME147_NET=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -257,6 +288,7 @@ CONFIG_MVME147_NET=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -294,10 +326,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -334,7 +362,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -393,10 +421,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -429,6 +457,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index e5e8262bbacdd0a94c4f0b1e0e89c06166ddd8ec..05a990a9dbd46994c60488c6eefeb807aa19f287 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -59,11 +58,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -81,6 +80,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -94,6 +104,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -126,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -140,11 +152,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -152,6 +171,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -166,6 +186,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
@@ -179,11 +202,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -191,10 +216,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -206,6 +234,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -243,12 +272,14 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MVME16x_NET=y
@@ -257,6 +288,7 @@ CONFIG_MVME16x_NET=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -294,10 +326,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -334,7 +362,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -393,10 +421,11 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
+CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -429,6 +458,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index be1496ed9b66028655205c48a36b69a365ed203b..568e2a98f976ee3c91900734df88e5d675c83811 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -59,11 +58,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -81,6 +80,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -94,6 +104,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -126,6 +137,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -140,11 +152,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -152,6 +171,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -166,6 +186,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
@@ -179,11 +202,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -191,10 +216,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -209,6 +237,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_IDE=y
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=y
@@ -249,6 +278,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -257,10 +287,10 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FUJITSU is not set
 # CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -269,6 +299,7 @@ CONFIG_NE2000=m
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PLIP=m
 CONFIG_PPP=m
@@ -293,7 +324,6 @@ CONFIG_MOUSE_SERIAL=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_M68K_BEEP=m
 CONFIG_SERIO_Q40KBD=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_PRINTER=m
@@ -318,10 +348,6 @@ CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -358,7 +384,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -417,10 +443,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -453,6 +479,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 54674d61e00141069e1fb5113e22e19784fc5c01..60b0aeac5742e80f28c8345a856070638252897b 100644 (file)
@@ -45,7 +45,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -56,11 +55,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -78,6 +77,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -91,6 +101,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -123,6 +134,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -137,11 +149,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -149,6 +168,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -163,6 +183,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
@@ -176,11 +199,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -188,10 +213,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -203,6 +231,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -240,6 +269,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -247,6 +277,7 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_SUN3LANCE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 CONFIG_SUN3_82586=y
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -255,6 +286,7 @@ CONFIG_SUN3_82586=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -276,7 +308,6 @@ CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_SUNKBD=y
 # CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
@@ -296,10 +327,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -336,7 +363,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -395,10 +422,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -431,6 +458,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 832d9539f44194faff9d4e6940223f1d938850fc..21bda331eebb04cfae90c5b94d869b18c9097d95 100644 (file)
@@ -45,7 +45,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
-CONFIG_SYN_COOKIES=y
 CONFIG_NET_IPVTI=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
@@ -56,11 +55,11 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
@@ -78,6 +77,17 @@ CONFIG_NF_CONNTRACK_PPTP=m
 CONFIG_NF_CONNTRACK_SANE=m
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=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_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
@@ -91,6 +101,7 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
@@ -123,6 +134,7 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -137,11 +149,18 @@ 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
 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
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -149,6 +168,7 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
 CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -163,6 +183,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
@@ -176,11 +199,13 @@ CONFIG_IP6_NF_MATCH_RT=m
 CONFIG_IP6_NF_TARGET_HL=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
 CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_IP_DCCP=m
 # CONFIG_IP_DCCP_CCID3 is not set
 CONFIG_SCTP_COOKIE_HMAC_SHA1=y
@@ -188,10 +213,13 @@ CONFIG_RDS=m
 CONFIG_RDS_TCP=m
 CONFIG_L2TP=m
 CONFIG_ATALK=m
+CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_FW_LOADER_USER_HELPER is not set
@@ -203,6 +231,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
+CONFIG_DUMMY_IRQ=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=m
@@ -240,6 +269,7 @@ CONFIG_EQUALIZER=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_BROADCAST=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
 CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_VXLAN=m
@@ -247,6 +277,7 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_SUN3LANCE=y
+# CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -255,6 +286,7 @@ CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -276,7 +308,6 @@ CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_SUNKBD=y
 # CONFIG_MOUSE_PS2 is not set
 CONFIG_MOUSE_SERIAL=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_HW_RANDOM is not set
@@ -296,10 +327,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -336,7 +363,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
@@ -395,10 +422,10 @@ CONFIG_NLS_MAC_TURKISH=m
 CONFIG_DLM=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_ASYNC_RAID6_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_USER=m
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
@@ -431,6 +458,8 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
index 121a6660ad4e5c40db157c25385507f4f51a674f..71b78ecee75c64773921bb9aed81aefbf24dae73 100644 (file)
@@ -9,6 +9,7 @@
  * the GNU General Public License (GPL), incorporated herein by reference.
  */
 
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/console.h>
 #include <linux/string.h>
@@ -70,7 +71,7 @@ static void nf_poweroff(void)
                nf_call(id);
 }
 
-void nf_init(void)
+void __init nf_init(void)
 {
        unsigned long id, version;
        char buf[256];
index b7609f791522a45f12170799cdae4f89bc8ab80f..2e5a787ea11b8f987ef3994292c7d57832bfc266 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/console.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-hp300.h>
+#include <asm/byteorder.h>
 #include <asm/machdep.h>
 #include <asm/blinken.h>
 #include <asm/io.h>                               /* readb() and writeb() */
@@ -70,15 +72,15 @@ extern int hp300_setup_serial_console(void) __init;
 int __init hp300_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const unsigned long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_HP300_MODEL:
-               hp300_model = *data;
+               hp300_model = be32_to_cpup(data);
                break;
 
        case BI_HP300_UART_SCODE:
-               hp300_uart_scode = *data;
+               hp300_uart_scode = be32_to_cpup(data);
                break;
 
        case BI_HP300_UART_ADDR:
index 7a19b5686a4a69255f94c96aab86c382d461e482..5ad568110f1728701bab85c80c783910740cb069 100644 (file)
 
 #include <linux/ioport.h>
 
-    /*
-     *  Different Amiga models
-     */
-
-#define AMI_UNKNOWN    (0)
-#define AMI_500                (1)
-#define AMI_500PLUS    (2)
-#define AMI_600                (3)
-#define AMI_1000       (4)
-#define AMI_1200       (5)
-#define AMI_2000       (6)
-#define AMI_2500       (7)
-#define AMI_3000       (8)
-#define AMI_3000T      (9)
-#define AMI_3000PLUS   (10)
-#define AMI_4000       (11)
-#define AMI_4000T      (12)
-#define AMI_CDTV       (13)
-#define AMI_CD32       (14)
-#define AMI_DRACO      (15)
+#include <asm/bootinfo-amiga.h>
 
 
     /*
 
 extern unsigned long amiga_chipset;
 
-#define CS_STONEAGE    (0)
-#define CS_OCS         (1)
-#define CS_ECS         (2)
-#define CS_AGA         (3)
-
 
     /*
      *  Miscellaneous
@@ -266,7 +242,7 @@ struct CIA {
 
 #define zTwoBase (0x80000000)
 #define ZTWO_PADDR(x) (((unsigned long)(x))-zTwoBase)
-#define ZTWO_VADDR(x) (((unsigned long)(x))+zTwoBase)
+#define ZTWO_VADDR(x) ((void __iomem *)(((unsigned long)(x))+zTwoBase))
 
 #define CUSTOM_PHYSADDR     (0xdff000)
 #define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR)))
index 6c19e0c22411a2bd4f7b76c2daf228e462f1eb27..87fc899d32eeba4fa057d52ce172e25fa8bb0664 100644 (file)
@@ -5,18 +5,11 @@
 
 #include <linux/types.h>
 
-/*
-   apollo models
-*/
+#include <asm/bootinfo-apollo.h>
+
 
 extern u_long apollo_model;
 
-#define APOLLO_UNKNOWN (0)
-#define APOLLO_DN3000 (1)
-#define APOLLO_DN3010 (2)
-#define APOLLO_DN3500 (3)
-#define APOLLO_DN4000 (4)
-#define APOLLO_DN4500 (5)
 
 /*
    see scn2681 data sheet for more info.
index d887050e6da6438516f0884c78ed9eb9889e2eda..972c8f33f05532c5bb6576471ca0ff4466f8b81d 100644 (file)
@@ -21,7 +21,7 @@
 #define _LINUX_ATARIHW_H_
 
 #include <linux/types.h>
-#include <asm/bootinfo.h>
+#include <asm/bootinfo-atari.h>
 #include <asm/raw_io.h>
 
 extern u_long atari_mch_cookie;
index 445ce22c23cb0528bf2855c36502b1c3bedecd7f..15c5f77c16142b1b42c15cdfc646e9d97bb8de11 100644 (file)
@@ -1,20 +1,8 @@
 #ifndef _M68K_BARRIER_H
 #define _M68K_BARRIER_H
 
-/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
 #define nop()          do { asm volatile ("nop"); barrier(); } while (0)
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define read_barrier_depends() ((void)0)
-#define set_mb(var, value)     ({ (var) = (value); wmb(); })
 
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     ((void)0)
+#include <asm-generic/barrier.h>
 
 #endif /* _M68K_BARRIER_H */
index 67e7a78ad96be0c0a6c069fc2dbb399729f20eba..8e213267f8e7165054c35f9d81dab22481467fa4 100644 (file)
 ** This file is subject to the terms and conditions of the GNU General Public
 ** License.  See the file COPYING in the main directory of this archive
 ** for more details.
-**
-** Created 09/29/92 by Greg Harp
-**
-** 5/2/94 Roman Hodek:
-**   Added bi_atari part of the machine dependent union bi_un; for now it
-**   contains just a model field to distinguish between TT and Falcon.
-** 26/7/96 Roman Zippel:
-**   Renamed to setup.h; added some useful macros to allow gcc some
-**   optimizations if possible.
-** 5/10/96 Geert Uytterhoeven:
-**   Redesign of the boot information structure; renamed to bootinfo.h again
-** 27/11/96 Geert Uytterhoeven:
-**   Backwards compatibility with bootinfo interface version 1.0
 */
 
 #ifndef _M68K_BOOTINFO_H
 #define _M68K_BOOTINFO_H
 
+#include <uapi/asm/bootinfo.h>
 
-    /*
-     *  Bootinfo definitions
-     *
-     *  This is an easily parsable and extendable structure containing all
-     *  information to be passed from the bootstrap to the kernel.
-     *
-     *  This way I hope to keep all future changes back/forewards compatible.
-     *  Thus, keep your fingers crossed...
-     *
-     *  This structure is copied right after the kernel bss by the bootstrap
-     *  routine.
-     */
 
 #ifndef __ASSEMBLY__
 
-struct bi_record {
-    unsigned short tag;                        /* tag ID */
-    unsigned short size;               /* size of record (in bytes) */
-    unsigned long data[0];             /* data */
-};
-
-#endif /* __ASSEMBLY__ */
-
-
-    /*
-     *  Tag Definitions
-     *
-     *  Machine independent tags start counting from 0x0000
-     *  Machine dependent tags start counting from 0x8000
-     */
-
-#define BI_LAST                        0x0000  /* last record (sentinel) */
-#define BI_MACHTYPE            0x0001  /* machine type (u_long) */
-#define BI_CPUTYPE             0x0002  /* cpu type (u_long) */
-#define BI_FPUTYPE             0x0003  /* fpu type (u_long) */
-#define BI_MMUTYPE             0x0004  /* mmu type (u_long) */
-#define BI_MEMCHUNK            0x0005  /* memory chunk address and size */
-                                       /* (struct mem_info) */
-#define BI_RAMDISK             0x0006  /* ramdisk address and size */
-                                       /* (struct mem_info) */
-#define BI_COMMAND_LINE                0x0007  /* kernel command line parameters */
-                                       /* (string) */
-
-    /*
-     *  Amiga-specific tags
-     */
-
-#define BI_AMIGA_MODEL         0x8000  /* model (u_long) */
-#define BI_AMIGA_AUTOCON       0x8001  /* AutoConfig device */
-                                       /* (struct ConfigDev) */
-#define BI_AMIGA_CHIP_SIZE     0x8002  /* size of Chip RAM (u_long) */
-#define BI_AMIGA_VBLANK                0x8003  /* VBLANK frequency (u_char) */
-#define BI_AMIGA_PSFREQ                0x8004  /* power supply frequency (u_char) */
-#define BI_AMIGA_ECLOCK                0x8005  /* EClock frequency (u_long) */
-#define BI_AMIGA_CHIPSET       0x8006  /* native chipset present (u_long) */
-#define BI_AMIGA_SERPER                0x8007  /* serial port period (u_short) */
-
-    /*
-     *  Atari-specific tags
-     */
-
-#define BI_ATARI_MCH_COOKIE    0x8000  /* _MCH cookie from TOS (u_long) */
-#define BI_ATARI_MCH_TYPE      0x8001  /* special machine type (u_long) */
-                                       /* (values are ATARI_MACH_* defines */
-
-/* mch_cookie values (upper word) */
-#define ATARI_MCH_ST           0
-#define ATARI_MCH_STE          1
-#define ATARI_MCH_TT           2
-#define ATARI_MCH_FALCON       3
-
-/* mch_type values */
-#define ATARI_MACH_NORMAL      0       /* no special machine type */
-#define ATARI_MACH_MEDUSA      1       /* Medusa 040 */
-#define ATARI_MACH_HADES       2       /* Hades 040 or 060 */
-#define ATARI_MACH_AB40                3       /* Afterburner040 on Falcon */
-
-    /*
-     *  VME-specific tags
-     */
-
-#define BI_VME_TYPE            0x8000  /* VME sub-architecture (u_long) */
-#define BI_VME_BRDINFO         0x8001  /* VME board information (struct) */
-
-/* BI_VME_TYPE codes */
-#define        VME_TYPE_TP34V          0x0034  /* Tadpole TP34V */
-#define VME_TYPE_MVME147       0x0147  /* Motorola MVME147 */
-#define VME_TYPE_MVME162       0x0162  /* Motorola MVME162 */
-#define VME_TYPE_MVME166       0x0166  /* Motorola MVME166 */
-#define VME_TYPE_MVME167       0x0167  /* Motorola MVME167 */
-#define VME_TYPE_MVME172       0x0172  /* Motorola MVME172 */
-#define VME_TYPE_MVME177       0x0177  /* Motorola MVME177 */
-#define VME_TYPE_BVME4000      0x4000  /* BVM Ltd. BVME4000 */
-#define VME_TYPE_BVME6000      0x6000  /* BVM Ltd. BVME6000 */
-
-/* BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on
- * Motorola VME boards.  Contains board number, Bug version, board
- * configuration options, etc.  See include/asm/mvme16xhw.h for details.
- */
-
-
-    /*
-     *  Macintosh-specific tags (all u_long)
-     */
-
-#define BI_MAC_MODEL           0x8000  /* Mac Gestalt ID (model type) */
-#define BI_MAC_VADDR           0x8001  /* Mac video base address */
-#define BI_MAC_VDEPTH          0x8002  /* Mac video depth */
-#define BI_MAC_VROW            0x8003  /* Mac video rowbytes */
-#define BI_MAC_VDIM            0x8004  /* Mac video dimensions */
-#define BI_MAC_VLOGICAL                0x8005  /* Mac video logical base */
-#define BI_MAC_SCCBASE         0x8006  /* Mac SCC base address */
-#define BI_MAC_BTIME           0x8007  /* Mac boot time */
-#define BI_MAC_GMTBIAS         0x8008  /* Mac GMT timezone offset */
-#define BI_MAC_MEMSIZE         0x8009  /* Mac RAM size (sanity check) */
-#define BI_MAC_CPUID           0x800a  /* Mac CPU type (sanity check) */
-#define BI_MAC_ROMBASE         0x800b  /* Mac system ROM base address */
-
-    /*
-     *  Macintosh hardware profile data - unused, see macintosh.h for
-     *  reasonable type values
-     */
-
-#define BI_MAC_VIA1BASE                0x8010  /* Mac VIA1 base address (always present) */
-#define BI_MAC_VIA2BASE                0x8011  /* Mac VIA2 base address (type varies) */
-#define BI_MAC_VIA2TYPE                0x8012  /* Mac VIA2 type (VIA, RBV, OSS) */
-#define BI_MAC_ADBTYPE         0x8013  /* Mac ADB interface type */
-#define BI_MAC_ASCBASE         0x8014  /* Mac Apple Sound Chip base address */
-#define BI_MAC_SCSI5380                0x8015  /* Mac NCR 5380 SCSI (base address, multi) */
-#define BI_MAC_SCSIDMA         0x8016  /* Mac SCSI DMA (base address) */
-#define BI_MAC_SCSI5396                0x8017  /* Mac NCR 53C96 SCSI (base address, multi) */
-#define BI_MAC_IDETYPE         0x8018  /* Mac IDE interface type */
-#define BI_MAC_IDEBASE         0x8019  /* Mac IDE interface base address */
-#define BI_MAC_NUBUS           0x801a  /* Mac Nubus type (none, regular, pseudo) */
-#define BI_MAC_SLOTMASK                0x801b  /* Mac Nubus slots present */
-#define BI_MAC_SCCTYPE         0x801c  /* Mac SCC serial type (normal, IOP) */
-#define BI_MAC_ETHTYPE         0x801d  /* Mac builtin ethernet type (Sonic, MACE */
-#define BI_MAC_ETHBASE         0x801e  /* Mac builtin ethernet base address */
-#define BI_MAC_PMU             0x801f  /* Mac power management / poweroff hardware */
-#define BI_MAC_IOP_SWIM                0x8020  /* Mac SWIM floppy IOP */
-#define BI_MAC_IOP_ADB         0x8021  /* Mac ADB IOP */
-
-    /*
-     * Mac: compatibility with old booter data format (temporarily)
-     * Fields unused with the new bootinfo can be deleted now; instead of
-     * adding new fields the struct might be splitted into a hardware address
-     * part and a hardware type part
-     */
-
-#ifndef __ASSEMBLY__
-
-struct mac_booter_data
-{
-       unsigned long videoaddr;
-       unsigned long videorow;
-       unsigned long videodepth;
-       unsigned long dimensions;
-       unsigned long args;
-       unsigned long boottime;
-       unsigned long gmtbias;
-       unsigned long bootver;
-       unsigned long videological;
-       unsigned long sccbase;
-       unsigned long id;
-       unsigned long memsize;
-       unsigned long serialmf;
-       unsigned long serialhsk;
-       unsigned long serialgpi;
-       unsigned long printmf;
-       unsigned long printhsk;
-       unsigned long printgpi;
-       unsigned long cpuid;
-       unsigned long rombase;
-       unsigned long adbdelay;
-       unsigned long timedbra;
-};
-
-extern struct mac_booter_data
-       mac_bi_data;
-
+#ifdef CONFIG_BOOTINFO_PROC
+extern void save_bootinfo(const struct bi_record *bi);
+#else
+static inline void save_bootinfo(const struct bi_record *bi) {}
 #endif
 
-    /*
-     *  Apollo-specific tags
-     */
-
-#define BI_APOLLO_MODEL         0x8000  /* model (u_long) */
-
-    /*
-     *  HP300-specific tags
-     */
-
-#define BI_HP300_MODEL         0x8000  /* model (u_long) */
-#define BI_HP300_UART_SCODE    0x8001  /* UART select code (u_long) */
-#define BI_HP300_UART_ADDR     0x8002  /* phys. addr of UART (u_long) */
-
-    /*
-     * Stuff for bootinfo interface versioning
-     *
-     * At the start of kernel code, a 'struct bootversion' is located.
-     * bootstrap checks for a matching version of the interface before booting
-     * a kernel, to avoid user confusion if kernel and bootstrap don't work
-     * together :-)
-     *
-     * If incompatible changes are made to the bootinfo interface, the major
-     * number below should be stepped (and the minor reset to 0) for the
-     * appropriate machine. If a change is backward-compatible, the minor
-     * should be stepped. "Backwards-compatible" means that booting will work,
-     * but certain features may not.
-     */
-
-#define BOOTINFOV_MAGIC                        0x4249561A      /* 'BIV^Z' */
-#define MK_BI_VERSION(major,minor)     (((major)<<16)+(minor))
-#define BI_VERSION_MAJOR(v)            (((v) >> 16) & 0xffff)
-#define BI_VERSION_MINOR(v)            ((v) & 0xffff)
-
-#ifndef __ASSEMBLY__
-
-struct bootversion {
-    unsigned short branch;
-    unsigned long magic;
-    struct {
-       unsigned long machtype;
-       unsigned long version;
-    } machversions[0];
-};
-
 #endif /* __ASSEMBLY__ */
 
-#define AMIGA_BOOTI_VERSION    MK_BI_VERSION( 2, 0 )
-#define ATARI_BOOTI_VERSION    MK_BI_VERSION( 2, 1 )
-#define MAC_BOOTI_VERSION      MK_BI_VERSION( 2, 0 )
-#define MVME147_BOOTI_VERSION  MK_BI_VERSION( 2, 0 )
-#define MVME16x_BOOTI_VERSION  MK_BI_VERSION( 2, 0 )
-#define BVME6000_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
-#define Q40_BOOTI_VERSION      MK_BI_VERSION( 2, 0 )
-#define HP300_BOOTI_VERSION    MK_BI_VERSION( 2, 0 )
-
-#ifdef BOOTINFO_COMPAT_1_0
-
-    /*
-     *  Backwards compatibility with bootinfo interface version 1.0
-     */
-
-#define COMPAT_AMIGA_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
-#define COMPAT_ATARI_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
-#define COMPAT_MAC_BOOTI_VERSION      MK_BI_VERSION( 1, 0 )
-
-#include <linux/zorro.h>
-
-#define COMPAT_NUM_AUTO    16
-
-struct compat_bi_Amiga {
-    int model;
-    int num_autocon;
-    struct ConfigDev autocon[COMPAT_NUM_AUTO];
-    unsigned long chip_size;
-    unsigned char vblank;
-    unsigned char psfreq;
-    unsigned long eclock;
-    unsigned long chipset;
-    unsigned long hw_present;
-};
-
-struct compat_bi_Atari {
-    unsigned long hw_present;
-    unsigned long mch_cookie;
-};
-
-#ifndef __ASSEMBLY__
-
-struct compat_bi_Macintosh
-{
-       unsigned long videoaddr;
-       unsigned long videorow;
-       unsigned long videodepth;
-       unsigned long dimensions;
-       unsigned long args;
-       unsigned long boottime;
-       unsigned long gmtbias;
-       unsigned long bootver;
-       unsigned long videological;
-       unsigned long sccbase;
-       unsigned long id;
-       unsigned long memsize;
-       unsigned long serialmf;
-       unsigned long serialhsk;
-       unsigned long serialgpi;
-       unsigned long printmf;
-       unsigned long printhsk;
-       unsigned long printgpi;
-       unsigned long cpuid;
-       unsigned long rombase;
-       unsigned long adbdelay;
-       unsigned long timedbra;
-};
-
-#endif
-
-struct compat_mem_info {
-    unsigned long addr;
-    unsigned long size;
-};
-
-#define COMPAT_NUM_MEMINFO  4
-
-#define COMPAT_CPUB_68020 0
-#define COMPAT_CPUB_68030 1
-#define COMPAT_CPUB_68040 2
-#define COMPAT_CPUB_68060 3
-#define COMPAT_FPUB_68881 5
-#define COMPAT_FPUB_68882 6
-#define COMPAT_FPUB_68040 7
-#define COMPAT_FPUB_68060 8
-
-#define COMPAT_CPU_68020    (1<<COMPAT_CPUB_68020)
-#define COMPAT_CPU_68030    (1<<COMPAT_CPUB_68030)
-#define COMPAT_CPU_68040    (1<<COMPAT_CPUB_68040)
-#define COMPAT_CPU_68060    (1<<COMPAT_CPUB_68060)
-#define COMPAT_CPU_MASK     (31)
-#define COMPAT_FPU_68881    (1<<COMPAT_FPUB_68881)
-#define COMPAT_FPU_68882    (1<<COMPAT_FPUB_68882)
-#define COMPAT_FPU_68040    (1<<COMPAT_FPUB_68040)
-#define COMPAT_FPU_68060    (1<<COMPAT_FPUB_68060)
-#define COMPAT_FPU_MASK     (0xfe0)
-
-#define COMPAT_CL_SIZE      (256)
-
-struct compat_bootinfo {
-    unsigned long machtype;
-    unsigned long cputype;
-    struct compat_mem_info memory[COMPAT_NUM_MEMINFO];
-    int num_memory;
-    unsigned long ramdisk_size;
-    unsigned long ramdisk_addr;
-    char command_line[COMPAT_CL_SIZE];
-    union {
-       struct compat_bi_Amiga     bi_ami;
-       struct compat_bi_Atari     bi_ata;
-       struct compat_bi_Macintosh bi_mac;
-    } bi_un;
-};
-
-#define bi_amiga       bi_un.bi_ami
-#define bi_atari       bi_un.bi_ata
-#define bi_mac         bi_un.bi_mac
-
-#endif /* BOOTINFO_COMPAT_1_0 */
-
 
 #endif /* _M68K_BOOTINFO_H */
index d998ea67c19c34d8fd1c005629bffecb9771d7cb..64f5271dd7be2ec70f4503af410a7af48362dfad 100644 (file)
@@ -1,25 +1,9 @@
 #ifndef _M68K_HP300HW_H
 #define _M68K_HP300HW_H
 
-extern unsigned long hp300_model;
+#include <asm/bootinfo-hp300.h>
 
-/* This information was taken from NetBSD */
-#define        HP_320          (0)     /* 16MHz 68020+HP MMU+16K external cache */
-#define        HP_330          (1)     /* 16MHz 68020+68851 MMU */
-#define        HP_340          (2)     /* 16MHz 68030 */
-#define        HP_345          (3)     /* 50MHz 68030+32K external cache */
-#define        HP_350          (4)     /* 25MHz 68020+HP MMU+32K external cache */
-#define        HP_360          (5)     /* 25MHz 68030 */
-#define        HP_370          (6)     /* 33MHz 68030+64K external cache */
-#define        HP_375          (7)     /* 50MHz 68030+32K external cache */
-#define        HP_380          (8)     /* 25MHz 68040 */
-#define        HP_385          (9)     /* 33MHz 68040 */
 
-#define        HP_400          (10)    /* 50MHz 68030+32K external cache */
-#define        HP_425T         (11)    /* 25MHz 68040 - model 425t */
-#define        HP_425S         (12)    /* 25MHz 68040 - model 425s */
-#define HP_425E                (13)    /* 25MHz 68040 - model 425e */
-#define HP_433T                (14)    /* 33MHz 68040 - model 433t */
-#define HP_433S                (15)    /* 33MHz 68040 - model 433s */
+extern unsigned long hp300_model;
 
 #endif /* _M68K_HP300HW_H */
diff --git a/arch/m68k/include/asm/kexec.h b/arch/m68k/include/asm/kexec.h
new file mode 100644 (file)
index 0000000..3df97ab
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _ASM_M68K_KEXEC_H
+#define _ASM_M68K_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE        4096
+
+#define KEXEC_ARCH KEXEC_ARCH_68K
+
+#ifndef __ASSEMBLY__
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                   struct pt_regs *oldregs)
+{
+       /* Dummy implementation for now */
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ASM_M68K_KEXEC_H */
index aeeedf8b2d259d6f9736d4bb946252055f8138f5..fe3fc9ae1b69d0163805c0265c862c1125d53f8e 100644 (file)
 extern volatile __u8 *via1,*via2;
 extern int rbv_present,via_alt_mapping;
 
+struct irq_desc;
+
 extern void via_register_interrupts(void);
 extern void via_irq_enable(int);
 extern void via_irq_disable(int);
index 682a1a2ff55f931ceeeac2f812d5254a75d1810b..d323b2c2d07d4e9a574da7e7f97d7a21bca08b6f 100644 (file)
@@ -4,6 +4,9 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 
+#include <asm/bootinfo-mac.h>
+
+
 /*
  *     Apple Macintoshisms
  */
@@ -74,65 +77,29 @@ struct mac_model
 #define MAC_FLOPPY_SWIM_IOP    3
 #define MAC_FLOPPY_AV          4
 
-/*
- *     Gestalt numbers
- */
+extern struct mac_model *macintosh_config;
 
-#define MAC_MODEL_II           6
-#define MAC_MODEL_IIX          7
-#define MAC_MODEL_IICX         8
-#define MAC_MODEL_SE30         9
-#define MAC_MODEL_IICI         11
-#define MAC_MODEL_IIFX         13      /* And well numbered it is too */
-#define MAC_MODEL_IISI         18
-#define MAC_MODEL_LC           19
-#define MAC_MODEL_Q900         20
-#define MAC_MODEL_PB170                21
-#define MAC_MODEL_Q700         22
-#define MAC_MODEL_CLII         23      /* aka: P200 */
-#define MAC_MODEL_PB140                25
-#define MAC_MODEL_Q950         26      /* aka: WGS95 */
-#define MAC_MODEL_LCIII                27      /* aka: P450 */
-#define MAC_MODEL_PB210                29
-#define MAC_MODEL_C650         30
-#define MAC_MODEL_PB230                32
-#define MAC_MODEL_PB180                33
-#define MAC_MODEL_PB160                34
-#define MAC_MODEL_Q800         35      /* aka: WGS80 */
-#define MAC_MODEL_Q650         36
-#define MAC_MODEL_LCII         37      /* aka: P400/405/410/430 */
-#define MAC_MODEL_PB250                38
-#define MAC_MODEL_IIVI         44
-#define MAC_MODEL_P600         45      /* aka: P600CD */
-#define MAC_MODEL_IIVX         48
-#define MAC_MODEL_CCL          49      /* aka: P250 */
-#define MAC_MODEL_PB165C       50
-#define MAC_MODEL_C610         52      /* aka: WGS60 */
-#define MAC_MODEL_Q610         53
-#define MAC_MODEL_PB145                54      /* aka: PB145B */
-#define MAC_MODEL_P520         56      /* aka: LC520 */
-#define MAC_MODEL_C660         60
-#define MAC_MODEL_P460         62      /* aka: LCIII+, P466/P467 */
-#define MAC_MODEL_PB180C       71
-#define MAC_MODEL_PB520                72      /* aka: PB520C, PB540, PB540C, PB550C */
-#define MAC_MODEL_PB270C       77
-#define MAC_MODEL_Q840         78
-#define MAC_MODEL_P550         80      /* aka: LC550, P560 */
-#define MAC_MODEL_CCLII                83      /* aka: P275 */
-#define MAC_MODEL_PB165                84
-#define MAC_MODEL_PB190                85      /* aka: PB190CS */
-#define MAC_MODEL_TV           88
-#define MAC_MODEL_P475         89      /* aka: LC475, P476 */
-#define MAC_MODEL_P475F                90      /* aka: P475 w/ FPU (no LC040) */
-#define MAC_MODEL_P575         92      /* aka: LC575, P577/P578 */
-#define MAC_MODEL_Q605         94
-#define MAC_MODEL_Q605_ACC     95      /* Q605 accelerated to 33 MHz */
-#define MAC_MODEL_Q630         98      /* aka: LC630, P630/631/635/636/637/638/640 */
-#define MAC_MODEL_P588         99      /* aka: LC580, P580 */
-#define MAC_MODEL_PB280                102
-#define MAC_MODEL_PB280C       103
-#define MAC_MODEL_PB150                115
 
-extern struct mac_model *macintosh_config;
+    /*
+     * Internal representation of the Mac hardware, filled in from bootinfo
+     */
+
+struct mac_booter_data
+{
+       unsigned long videoaddr;
+       unsigned long videorow;
+       unsigned long videodepth;
+       unsigned long dimensions;
+       unsigned long boottime;
+       unsigned long gmtbias;
+       unsigned long videological;
+       unsigned long sccbase;
+       unsigned long id;
+       unsigned long memsize;
+       unsigned long cpuid;
+       unsigned long rombase;
+};
+
+extern struct mac_booter_data mac_bi_data;
 
 #endif
index 9f70a01f73dc9960e00817963aceb75b5e89db24..05b43bf5cdf3909f7ea23b2da4ed4dbb6d9dd9bb 100644 (file)
 
 #include <asm/atarihw.h>
 
-#define RTC_PORT(x)    (TT_RTC_BAS + 2*(x))
+#define ATARI_RTC_PORT(x)      (TT_RTC_BAS + 2*(x))
 #define RTC_ALWAYS_BCD 0
 
 #define CMOS_READ(addr) ({ \
-atari_outb_p((addr),RTC_PORT(0)); \
-atari_inb_p(RTC_PORT(1)); \
+atari_outb_p((addr), ATARI_RTC_PORT(0)); \
+atari_inb_p(ATARI_RTC_PORT(1)); \
 })
 #define CMOS_WRITE(val, addr) ({ \
-atari_outb_p((addr),RTC_PORT(0)); \
-atari_outb_p((val),RTC_PORT(1)); \
+atari_outb_p((addr), ATARI_RTC_PORT(0)); \
+atari_outb_p((val), ATARI_RTC_PORT(1)); \
 })
 #endif /* CONFIG_ATARI */
 
index 6117f56653d28d3c14bcbee597a552b18cf6cecd..1eb89de631e5c09d1be76d0c043d2e467906b9a6 100644 (file)
@@ -3,23 +3,6 @@
 
 #include <asm/irq.h>
 
-/* Board ID data structure - pointer to this retrieved from Bug by head.S */
-
-/* Note, bytes 12 and 13 are board no in BCD (0162,0166,0167,0177,etc) */
-
-extern long mvme_bdid_ptr;
-
-typedef struct {
-       char    bdid[4];
-       u_char  rev, mth, day, yr;
-       u_short size, reserved;
-       u_short brdno;
-       char brdsuffix[2];
-       u_long  options;
-       u_short clun, dlun, ctype, dnum;
-       u_long  option2;
-} t_bdid, *p_bdid;
-
 
 typedef struct {
        u_char  ack_icr,
index 65e78a2dad64a9840fdb96bdc898e8b848f52331..8f2023f8c1c45727a6904d0567fb070e9f8b7364 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
+#include <uapi/asm/bootinfo.h>
 #include <uapi/asm/setup.h>
 
 
@@ -297,14 +298,14 @@ extern int m68k_is040or060;
 #define NUM_MEMINFO    4
 
 #ifndef __ASSEMBLY__
-struct mem_info {
+struct m68k_mem_info {
        unsigned long addr;             /* physical address of memory chunk */
        unsigned long size;             /* length of memory chunk (in bytes) */
 };
 
 extern int m68k_num_memory;            /* # of memory blocks found (and used) */
 extern int m68k_realnum_memory;                /* real # of memory blocks found */
-extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+extern struct m68k_mem_info m68k_memory[NUM_MEMINFO];/* memory description */
 #endif
 
 #endif /* _M68K_SETUP_H */
index 6759dad954f61d9a3d40800f63cf95179c8129aa..efc1f48923573d4731806326b1e72395775fde3d 100644 (file)
@@ -28,4 +28,14 @@ static inline cycles_t get_cycles(void)
        return 0;
 }
 
+extern unsigned long (*mach_random_get_entropy)(void);
+
+static inline unsigned long random_get_entropy(void)
+{
+       if (mach_random_get_entropy)
+               return mach_random_get_entropy();
+       return 0;
+}
+#define random_get_entropy     random_get_entropy
+
 #endif
index 1fef45ada0973c7d83494f42c0c780ebc18f5ca3..6a2d257bdfb2224492f8f901575d17cc9b4f82d7 100644 (file)
@@ -11,6 +11,14 @@ generic-y += termbits.h
 generic-y += termios.h
 
 header-y += a.out.h
+header-y += bootinfo.h
+header-y += bootinfo-amiga.h
+header-y += bootinfo-apollo.h
+header-y += bootinfo-atari.h
+header-y += bootinfo-hp300.h
+header-y += bootinfo-mac.h
+header-y += bootinfo-q40.h
+header-y += bootinfo-vme.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += fcntl.h
diff --git a/arch/m68k/include/uapi/asm/bootinfo-amiga.h b/arch/m68k/include/uapi/asm/bootinfo-amiga.h
new file mode 100644 (file)
index 0000000..daad3c5
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+** asm/bootinfo-amiga.h -- Amiga-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_AMIGA_H
+#define _UAPI_ASM_M68K_BOOTINFO_AMIGA_H
+
+
+    /*
+     *  Amiga-specific tags
+     */
+
+#define BI_AMIGA_MODEL         0x8000  /* model (__be32) */
+#define BI_AMIGA_AUTOCON       0x8001  /* AutoConfig device */
+                                       /* (AmigaOS struct ConfigDev) */
+#define BI_AMIGA_CHIP_SIZE     0x8002  /* size of Chip RAM (__be32) */
+#define BI_AMIGA_VBLANK                0x8003  /* VBLANK frequency (__u8) */
+#define BI_AMIGA_PSFREQ                0x8004  /* power supply frequency (__u8) */
+#define BI_AMIGA_ECLOCK                0x8005  /* EClock frequency (__be32) */
+#define BI_AMIGA_CHIPSET       0x8006  /* native chipset present (__be32) */
+#define BI_AMIGA_SERPER                0x8007  /* serial port period (__be16) */
+
+
+    /*
+     *  Amiga models (BI_AMIGA_MODEL)
+     */
+
+#define AMI_UNKNOWN            0
+#define AMI_500                        1
+#define AMI_500PLUS            2
+#define AMI_600                        3
+#define AMI_1000               4
+#define AMI_1200               5
+#define AMI_2000               6
+#define AMI_2500               7
+#define AMI_3000               8
+#define AMI_3000T              9
+#define AMI_3000PLUS           10
+#define AMI_4000               11
+#define AMI_4000T              12
+#define AMI_CDTV               13
+#define AMI_CD32               14
+#define AMI_DRACO              15
+
+
+    /*
+     *  Amiga chipsets (BI_AMIGA_CHIPSET)
+     */
+
+#define CS_STONEAGE            0
+#define CS_OCS                 1
+#define CS_ECS                 2
+#define CS_AGA                 3
+
+
+    /*
+     *  Latest Amiga bootinfo version
+     */
+
+#define AMIGA_BOOTI_VERSION    MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_AMIGA_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-apollo.h b/arch/m68k/include/uapi/asm/bootinfo-apollo.h
new file mode 100644 (file)
index 0000000..a93e0af
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+** asm/bootinfo-apollo.h -- Apollo-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_APOLLO_H
+#define _UAPI_ASM_M68K_BOOTINFO_APOLLO_H
+
+
+    /*
+     *  Apollo-specific tags
+     */
+
+#define BI_APOLLO_MODEL                0x8000  /* model (__be32) */
+
+
+    /*
+     *  Apollo models (BI_APOLLO_MODEL)
+     */
+
+#define APOLLO_UNKNOWN         0
+#define APOLLO_DN3000          1
+#define APOLLO_DN3010          2
+#define APOLLO_DN3500          3
+#define APOLLO_DN4000          4
+#define APOLLO_DN4500          5
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_APOLLO_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-atari.h b/arch/m68k/include/uapi/asm/bootinfo-atari.h
new file mode 100644 (file)
index 0000000..a817854
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+** asm/bootinfo-atari.h -- Atari-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_ATARI_H
+#define _UAPI_ASM_M68K_BOOTINFO_ATARI_H
+
+
+    /*
+     *  Atari-specific tags
+     */
+
+#define BI_ATARI_MCH_COOKIE    0x8000  /* _MCH cookie from TOS (__be32) */
+#define BI_ATARI_MCH_TYPE      0x8001  /* special machine type (__be32) */
+
+
+    /*
+     *  mch_cookie values (upper word of BI_ATARI_MCH_COOKIE)
+     */
+
+#define ATARI_MCH_ST           0
+#define ATARI_MCH_STE          1
+#define ATARI_MCH_TT           2
+#define ATARI_MCH_FALCON       3
+
+
+    /*
+     *  Atari machine types (BI_ATARI_MCH_TYPE)
+     */
+
+#define ATARI_MACH_NORMAL      0       /* no special machine type */
+#define ATARI_MACH_MEDUSA      1       /* Medusa 040 */
+#define ATARI_MACH_HADES       2       /* Hades 040 or 060 */
+#define ATARI_MACH_AB40                3       /* Afterburner040 on Falcon */
+
+
+    /*
+     *  Latest Atari bootinfo version
+     */
+
+#define ATARI_BOOTI_VERSION    MK_BI_VERSION(2, 1)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_ATARI_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-hp300.h b/arch/m68k/include/uapi/asm/bootinfo-hp300.h
new file mode 100644 (file)
index 0000000..c90cb71
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+** asm/bootinfo-hp300.h -- HP9000/300-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_HP300_H
+#define _UAPI_ASM_M68K_BOOTINFO_HP300_H
+
+
+    /*
+     *  HP9000/300-specific tags
+     */
+
+#define BI_HP300_MODEL         0x8000  /* model (__be32) */
+#define BI_HP300_UART_SCODE    0x8001  /* UART select code (__be32) */
+#define BI_HP300_UART_ADDR     0x8002  /* phys. addr of UART (__be32) */
+
+
+    /*
+     *  HP9000/300 and /400 models (BI_HP300_MODEL)
+     *
+     * This information was taken from NetBSD
+     */
+
+#define HP_320         0       /* 16MHz 68020+HP MMU+16K external cache */
+#define HP_330         1       /* 16MHz 68020+68851 MMU */
+#define HP_340         2       /* 16MHz 68030 */
+#define HP_345         3       /* 50MHz 68030+32K external cache */
+#define HP_350         4       /* 25MHz 68020+HP MMU+32K external cache */
+#define HP_360         5       /* 25MHz 68030 */
+#define HP_370         6       /* 33MHz 68030+64K external cache */
+#define HP_375         7       /* 50MHz 68030+32K external cache */
+#define HP_380         8       /* 25MHz 68040 */
+#define HP_385         9       /* 33MHz 68040 */
+
+#define HP_400         10      /* 50MHz 68030+32K external cache */
+#define HP_425T                11      /* 25MHz 68040 - model 425t */
+#define HP_425S                12      /* 25MHz 68040 - model 425s */
+#define HP_425E                13      /* 25MHz 68040 - model 425e */
+#define HP_433T                14      /* 33MHz 68040 - model 433t */
+#define HP_433S                15      /* 33MHz 68040 - model 433s */
+
+
+    /*
+     *  Latest HP9000/300 bootinfo version
+     */
+
+#define HP300_BOOTI_VERSION    MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_HP300_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-mac.h b/arch/m68k/include/uapi/asm/bootinfo-mac.h
new file mode 100644 (file)
index 0000000..b44ff73
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+** asm/bootinfo-mac.h -- Macintosh-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_MAC_H
+#define _UAPI_ASM_M68K_BOOTINFO_MAC_H
+
+
+    /*
+     *  Macintosh-specific tags (all __be32)
+     */
+
+#define BI_MAC_MODEL           0x8000  /* Mac Gestalt ID (model type) */
+#define BI_MAC_VADDR           0x8001  /* Mac video base address */
+#define BI_MAC_VDEPTH          0x8002  /* Mac video depth */
+#define BI_MAC_VROW            0x8003  /* Mac video rowbytes */
+#define BI_MAC_VDIM            0x8004  /* Mac video dimensions */
+#define BI_MAC_VLOGICAL                0x8005  /* Mac video logical base */
+#define BI_MAC_SCCBASE         0x8006  /* Mac SCC base address */
+#define BI_MAC_BTIME           0x8007  /* Mac boot time */
+#define BI_MAC_GMTBIAS         0x8008  /* Mac GMT timezone offset */
+#define BI_MAC_MEMSIZE         0x8009  /* Mac RAM size (sanity check) */
+#define BI_MAC_CPUID           0x800a  /* Mac CPU type (sanity check) */
+#define BI_MAC_ROMBASE         0x800b  /* Mac system ROM base address */
+
+
+    /*
+     *  Macintosh hardware profile data - unused, see macintosh.h for
+     *  reasonable type values
+     */
+
+#define BI_MAC_VIA1BASE                0x8010  /* Mac VIA1 base address (always present) */
+#define BI_MAC_VIA2BASE                0x8011  /* Mac VIA2 base address (type varies) */
+#define BI_MAC_VIA2TYPE                0x8012  /* Mac VIA2 type (VIA, RBV, OSS) */
+#define BI_MAC_ADBTYPE         0x8013  /* Mac ADB interface type */
+#define BI_MAC_ASCBASE         0x8014  /* Mac Apple Sound Chip base address */
+#define BI_MAC_SCSI5380                0x8015  /* Mac NCR 5380 SCSI (base address, multi) */
+#define BI_MAC_SCSIDMA         0x8016  /* Mac SCSI DMA (base address) */
+#define BI_MAC_SCSI5396                0x8017  /* Mac NCR 53C96 SCSI (base address, multi) */
+#define BI_MAC_IDETYPE         0x8018  /* Mac IDE interface type */
+#define BI_MAC_IDEBASE         0x8019  /* Mac IDE interface base address */
+#define BI_MAC_NUBUS           0x801a  /* Mac Nubus type (none, regular, pseudo) */
+#define BI_MAC_SLOTMASK                0x801b  /* Mac Nubus slots present */
+#define BI_MAC_SCCTYPE         0x801c  /* Mac SCC serial type (normal, IOP) */
+#define BI_MAC_ETHTYPE         0x801d  /* Mac builtin ethernet type (Sonic, MACE */
+#define BI_MAC_ETHBASE         0x801e  /* Mac builtin ethernet base address */
+#define BI_MAC_PMU             0x801f  /* Mac power management / poweroff hardware */
+#define BI_MAC_IOP_SWIM                0x8020  /* Mac SWIM floppy IOP */
+#define BI_MAC_IOP_ADB         0x8021  /* Mac ADB IOP */
+
+
+    /*
+     * Macintosh Gestalt numbers (BI_MAC_MODEL)
+     */
+
+#define MAC_MODEL_II           6
+#define MAC_MODEL_IIX          7
+#define MAC_MODEL_IICX         8
+#define MAC_MODEL_SE30         9
+#define MAC_MODEL_IICI         11
+#define MAC_MODEL_IIFX         13      /* And well numbered it is too */
+#define MAC_MODEL_IISI         18
+#define MAC_MODEL_LC           19
+#define MAC_MODEL_Q900         20
+#define MAC_MODEL_PB170                21
+#define MAC_MODEL_Q700         22
+#define MAC_MODEL_CLII         23      /* aka: P200 */
+#define MAC_MODEL_PB140                25
+#define MAC_MODEL_Q950         26      /* aka: WGS95 */
+#define MAC_MODEL_LCIII                27      /* aka: P450 */
+#define MAC_MODEL_PB210                29
+#define MAC_MODEL_C650         30
+#define MAC_MODEL_PB230                32
+#define MAC_MODEL_PB180                33
+#define MAC_MODEL_PB160                34
+#define MAC_MODEL_Q800         35      /* aka: WGS80 */
+#define MAC_MODEL_Q650         36
+#define MAC_MODEL_LCII         37      /* aka: P400/405/410/430 */
+#define MAC_MODEL_PB250                38
+#define MAC_MODEL_IIVI         44
+#define MAC_MODEL_P600         45      /* aka: P600CD */
+#define MAC_MODEL_IIVX         48
+#define MAC_MODEL_CCL          49      /* aka: P250 */
+#define MAC_MODEL_PB165C       50
+#define MAC_MODEL_C610         52      /* aka: WGS60 */
+#define MAC_MODEL_Q610         53
+#define MAC_MODEL_PB145                54      /* aka: PB145B */
+#define MAC_MODEL_P520         56      /* aka: LC520 */
+#define MAC_MODEL_C660         60
+#define MAC_MODEL_P460         62      /* aka: LCIII+, P466/P467 */
+#define MAC_MODEL_PB180C       71
+#define MAC_MODEL_PB520                72      /* aka: PB520C, PB540, PB540C, PB550C */
+#define MAC_MODEL_PB270C       77
+#define MAC_MODEL_Q840         78
+#define MAC_MODEL_P550         80      /* aka: LC550, P560 */
+#define MAC_MODEL_CCLII                83      /* aka: P275 */
+#define MAC_MODEL_PB165                84
+#define MAC_MODEL_PB190                85      /* aka: PB190CS */
+#define MAC_MODEL_TV           88
+#define MAC_MODEL_P475         89      /* aka: LC475, P476 */
+#define MAC_MODEL_P475F                90      /* aka: P475 w/ FPU (no LC040) */
+#define MAC_MODEL_P575         92      /* aka: LC575, P577/P578 */
+#define MAC_MODEL_Q605         94
+#define MAC_MODEL_Q605_ACC     95      /* Q605 accelerated to 33 MHz */
+#define MAC_MODEL_Q630         98      /* aka: LC630, P630/631/635/636/637/638/640 */
+#define MAC_MODEL_P588         99      /* aka: LC580, P580 */
+#define MAC_MODEL_PB280                102
+#define MAC_MODEL_PB280C       103
+#define MAC_MODEL_PB150                115
+
+
+    /*
+     *  Latest Macintosh bootinfo version
+     */
+
+#define MAC_BOOTI_VERSION      MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-q40.h b/arch/m68k/include/uapi/asm/bootinfo-q40.h
new file mode 100644 (file)
index 0000000..c79fea7
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+** asm/bootinfo-q40.h -- Q40-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_Q40_H
+#define _UAPI_ASM_M68K_BOOTINFO_Q40_H
+
+
+    /*
+     *  Latest Q40 bootinfo version
+     */
+
+#define Q40_BOOTI_VERSION      MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_Q40_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-vme.h b/arch/m68k/include/uapi/asm/bootinfo-vme.h
new file mode 100644 (file)
index 0000000..a135eb4
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+** asm/bootinfo-vme.h -- VME-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_VME_H
+#define _UAPI_ASM_M68K_BOOTINFO_VME_H
+
+
+#include <linux/types.h>
+
+
+    /*
+     *  VME-specific tags
+     */
+
+#define BI_VME_TYPE            0x8000  /* VME sub-architecture (__be32) */
+#define BI_VME_BRDINFO         0x8001  /* VME board information (struct) */
+
+
+    /*
+     *  VME models (BI_VME_TYPE)
+     */
+
+#define VME_TYPE_TP34V         0x0034  /* Tadpole TP34V */
+#define VME_TYPE_MVME147       0x0147  /* Motorola MVME147 */
+#define VME_TYPE_MVME162       0x0162  /* Motorola MVME162 */
+#define VME_TYPE_MVME166       0x0166  /* Motorola MVME166 */
+#define VME_TYPE_MVME167       0x0167  /* Motorola MVME167 */
+#define VME_TYPE_MVME172       0x0172  /* Motorola MVME172 */
+#define VME_TYPE_MVME177       0x0177  /* Motorola MVME177 */
+#define VME_TYPE_BVME4000      0x4000  /* BVM Ltd. BVME4000 */
+#define VME_TYPE_BVME6000      0x6000  /* BVM Ltd. BVME6000 */
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Board ID data structure - pointer to this retrieved from Bug by head.S
+ *
+ * BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on
+ * Motorola VME boards.  Contains board number, Bug version, board
+ * configuration options, etc.
+ *
+ * Note, bytes 12 and 13 are board no in BCD (0162,0166,0167,0177,etc)
+ */
+
+typedef struct {
+       char    bdid[4];
+       __u8    rev, mth, day, yr;
+       __be16  size, reserved;
+       __be16  brdno;
+       char    brdsuffix[2];
+       __be32  options;
+       __be16  clun, dlun, ctype, dnum;
+       __be32  option2;
+} t_bdid, *p_bdid;
+
+#endif /* __ASSEMBLY__ */
+
+
+    /*
+     *  Latest VME bootinfo versions
+     */
+
+#define MVME147_BOOTI_VERSION  MK_BI_VERSION(2, 0)
+#define MVME16x_BOOTI_VERSION  MK_BI_VERSION(2, 0)
+#define BVME6000_BOOTI_VERSION MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_VME_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo.h b/arch/m68k/include/uapi/asm/bootinfo.h
new file mode 100644 (file)
index 0000000..cdeb26a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * asm/bootinfo.h -- Definition of the Linux/m68k boot information structure
+ *
+ * Copyright 1992 by Greg Harp
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_H
+#define _UAPI_ASM_M68K_BOOTINFO_H
+
+
+#include <linux/types.h>
+
+
+#ifndef __ASSEMBLY__
+
+    /*
+     *  Bootinfo definitions
+     *
+     *  This is an easily parsable and extendable structure containing all
+     *  information to be passed from the bootstrap to the kernel.
+     *
+     *  This way I hope to keep all future changes back/forewards compatible.
+     *  Thus, keep your fingers crossed...
+     *
+     *  This structure is copied right after the kernel by the bootstrap
+     *  routine.
+     */
+
+struct bi_record {
+       __be16 tag;                     /* tag ID */
+       __be16 size;                    /* size of record (in bytes) */
+       __be32 data[0];                 /* data */
+};
+
+
+struct mem_info {
+       __be32 addr;                    /* physical address of memory chunk */
+       __be32 size;                    /* length of memory chunk (in bytes) */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+    /*
+     *  Tag Definitions
+     *
+     *  Machine independent tags start counting from 0x0000
+     *  Machine dependent tags start counting from 0x8000
+     */
+
+#define BI_LAST                        0x0000  /* last record (sentinel) */
+#define BI_MACHTYPE            0x0001  /* machine type (__be32) */
+#define BI_CPUTYPE             0x0002  /* cpu type (__be32) */
+#define BI_FPUTYPE             0x0003  /* fpu type (__be32) */
+#define BI_MMUTYPE             0x0004  /* mmu type (__be32) */
+#define BI_MEMCHUNK            0x0005  /* memory chunk address and size */
+                                       /* (struct mem_info) */
+#define BI_RAMDISK             0x0006  /* ramdisk address and size */
+                                       /* (struct mem_info) */
+#define BI_COMMAND_LINE                0x0007  /* kernel command line parameters */
+                                       /* (string) */
+
+
+    /*
+     *  Linux/m68k Architectures (BI_MACHTYPE)
+     */
+
+#define MACH_AMIGA             1
+#define MACH_ATARI             2
+#define MACH_MAC               3
+#define MACH_APOLLO            4
+#define MACH_SUN3              5
+#define MACH_MVME147           6
+#define MACH_MVME16x           7
+#define MACH_BVME6000          8
+#define MACH_HP300             9
+#define MACH_Q40               10
+#define MACH_SUN3X             11
+#define MACH_M54XX             12
+
+
+    /*
+     *  CPU, FPU and MMU types (BI_CPUTYPE, BI_FPUTYPE, BI_MMUTYPE)
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020             0
+#define CPUB_68030             1
+#define CPUB_68040             2
+#define CPUB_68060             3
+#define CPUB_COLDFIRE          4
+
+#define CPU_68020              (1 << CPUB_68020)
+#define CPU_68030              (1 << CPUB_68030)
+#define CPU_68040              (1 << CPUB_68040)
+#define CPU_68060              (1 << CPUB_68060)
+#define CPU_COLDFIRE           (1 << CPUB_COLDFIRE)
+
+#define FPUB_68881             0
+#define FPUB_68882             1
+#define FPUB_68040             2       /* Internal FPU */
+#define FPUB_68060             3       /* Internal FPU */
+#define FPUB_SUNFPA            4       /* Sun-3 FPA */
+#define FPUB_COLDFIRE          5       /* ColdFire FPU */
+
+#define FPU_68881              (1 << FPUB_68881)
+#define FPU_68882              (1 << FPUB_68882)
+#define FPU_68040              (1 << FPUB_68040)
+#define FPU_68060              (1 << FPUB_68060)
+#define FPU_SUNFPA             (1 << FPUB_SUNFPA)
+#define FPU_COLDFIRE           (1 << FPUB_COLDFIRE)
+
+#define MMUB_68851             0
+#define MMUB_68030             1       /* Internal MMU */
+#define MMUB_68040             2       /* Internal MMU */
+#define MMUB_68060             3       /* Internal MMU */
+#define MMUB_APOLLO            4       /* Custom Apollo */
+#define MMUB_SUN3              5       /* Custom Sun-3 */
+#define MMUB_COLDFIRE          6       /* Internal MMU */
+
+#define MMU_68851              (1 << MMUB_68851)
+#define MMU_68030              (1 << MMUB_68030)
+#define MMU_68040              (1 << MMUB_68040)
+#define MMU_68060              (1 << MMUB_68060)
+#define MMU_SUN3               (1 << MMUB_SUN3)
+#define MMU_APOLLO             (1 << MMUB_APOLLO)
+#define MMU_COLDFIRE           (1 << MMUB_COLDFIRE)
+
+
+    /*
+     * Stuff for bootinfo interface versioning
+     *
+     * At the start of kernel code, a 'struct bootversion' is located.
+     * bootstrap checks for a matching version of the interface before booting
+     * a kernel, to avoid user confusion if kernel and bootstrap don't work
+     * together :-)
+     *
+     * If incompatible changes are made to the bootinfo interface, the major
+     * number below should be stepped (and the minor reset to 0) for the
+     * appropriate machine. If a change is backward-compatible, the minor
+     * should be stepped. "Backwards-compatible" means that booting will work,
+     * but certain features may not.
+     */
+
+#define BOOTINFOV_MAGIC                        0x4249561A      /* 'BIV^Z' */
+#define MK_BI_VERSION(major, minor)    (((major) << 16) + (minor))
+#define BI_VERSION_MAJOR(v)            (((v) >> 16) & 0xffff)
+#define BI_VERSION_MINOR(v)            ((v) & 0xffff)
+
+#ifndef __ASSEMBLY__
+
+struct bootversion {
+       __be16 branch;
+       __be32 magic;
+       struct {
+               __be32 machtype;
+               __be32 version;
+       } machversions[0];
+} __packed;
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_H */
index 85579bff455ccb32fc7f9e805d0f78383c053245..6a6dc636761eaa210844f10614ad1633cff41bc3 100644 (file)
@@ -6,98 +6,11 @@
 ** This file is subject to the terms and conditions of the GNU General Public
 ** License.  See the file COPYING in the main directory of this archive
 ** for more details.
-**
-** Created 09/29/92 by Greg Harp
-**
-** 5/2/94 Roman Hodek:
-**   Added bi_atari part of the machine dependent union bi_un; for now it
-**   contains just a model field to distinguish between TT and Falcon.
-** 26/7/96 Roman Zippel:
-**   Renamed to setup.h; added some useful macros to allow gcc some
-**   optimizations if possible.
-** 5/10/96 Geert Uytterhoeven:
-**   Redesign of the boot information structure; moved boot information
-**   structure to bootinfo.h
 */
 
 #ifndef _UAPI_M68K_SETUP_H
 #define _UAPI_M68K_SETUP_H
 
-
-
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-#define MACH_M54XX   12
-
 #define COMMAND_LINE_SIZE 256
 
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-#define CPUB_COLDFIRE  4
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-#define MMUB_COLDFIRE  6                       /* Internal MMU */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
-
-
 #endif /* _UAPI_M68K_SETUP_H */
index 655347d807801e3543412c5aaedc550f3ebdef80..2d5d9be162732dae6ae603622e3572e1d0349523 100644 (file)
@@ -22,3 +22,6 @@ obj-$(CONFIG_PCI) += pcibios.o
 
 obj-$(CONFIG_HAS_DMA)  += dma.o
 
+obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_BOOTINFO_PROC)    += bootinfo_proc.o
+
index 8b7b228463667da0145f9d7e821172553822d20d..3a386341aa6e282336a5ceea41b248fc45943191 100644 (file)
@@ -98,6 +98,9 @@ int main(void)
        DEFINE(CIABBASE, &ciab);
        DEFINE(C_PRA, offsetof(struct CIA, pra));
        DEFINE(ZTWOBASE, zTwoBase);
+
+       /* enum m68k_fixup_type */
+       DEFINE(M68K_FIXUP_MEMOFFSET, m68k_fixup_memoffset);
 #endif
 
        return 0;
diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c
new file mode 100644 (file)
index 0000000..7ee853e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Based on arch/arm/kernel/atags_proc.c
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/printk.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/byteorder.h>
+
+
+static char bootinfo_tmp[1536] __initdata;
+
+static void *bootinfo_copy;
+static size_t bootinfo_size;
+
+static ssize_t bootinfo_read(struct file *file, char __user *buf,
+                         size_t count, loff_t *ppos)
+{
+       return simple_read_from_buffer(buf, count, ppos, bootinfo_copy,
+                                      bootinfo_size);
+}
+
+static const struct file_operations bootinfo_fops = {
+       .read = bootinfo_read,
+       .llseek = default_llseek,
+};
+
+void __init save_bootinfo(const struct bi_record *bi)
+{
+       const void *start = bi;
+       size_t size = sizeof(bi->tag);
+
+       while (be16_to_cpu(bi->tag) != BI_LAST) {
+               uint16_t n = be16_to_cpu(bi->size);
+               size += n;
+               bi = (struct bi_record *)((unsigned long)bi + n);
+       }
+
+       if (size > sizeof(bootinfo_tmp)) {
+               pr_err("Cannot save %zu bytes of bootinfo\n", size);
+               return;
+       }
+
+       pr_info("Saving %zu bytes of bootinfo\n", size);
+       memcpy(bootinfo_tmp, start, size);
+       bootinfo_size = size;
+}
+
+static int __init init_bootinfo_procfs(void)
+{
+       /*
+        * This cannot go into save_bootinfo() because kmalloc and proc don't
+        * work yet when it is called.
+        */
+       struct proc_dir_entry *pde;
+
+       if (!bootinfo_size)
+               return -EINVAL;
+
+       bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL);
+       if (!bootinfo_copy)
+               return -ENOMEM;
+
+       memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size);
+
+       pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
+       if (!pde) {
+               kfree(bootinfo_copy);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+arch_initcall(init_bootinfo_procfs);
index ac85f16534af929c33d0f1daf1f3a565488b6af4..4c99bab7e6647c0709ebacbff38b42f01ab24449 100644 (file)
@@ -23,7 +23,7 @@
 ** 98/04/25 Phil Blundell: added HP300 support
 ** 1998/08/30 David Kilzer: Added support for font_desc structures
 **            for linux-2.1.115
-** 9/02/11  Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
+** 1999/02/11  Richard Zidlicky: added Q40 support (initial version 99/01/01)
 ** 2004/05/13 Kars de Jong: Finalised HP300 support
 **
 ** This file is subject to the terms and conditions of the GNU General Public
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-amiga.h>
+#include <asm/bootinfo-atari.h>
+#include <asm/bootinfo-hp300.h>
+#include <asm/bootinfo-mac.h>
+#include <asm/bootinfo-q40.h>
+#include <asm/bootinfo-vme.h>
 #include <asm/setup.h>
 #include <asm/entry.h>
 #include <asm/pgtable.h>
@@ -1532,7 +1538,7 @@ L(cache_done):
 
 /*
  * Find a tag record in the bootinfo structure
- * The bootinfo structure is located right after the kernel bss
+ * The bootinfo structure is located right after the kernel
  * Returns: d0: size (-1 if not found)
  *          a0: data pointer (end-of-records if not found)
  */
@@ -2909,7 +2915,9 @@ func_start        serial_init,%d0/%d1/%a0/%a1
 
 #if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
        movel   %pc@(L(mac_sccbase)),%a0
-       /* Reset SCC device */
+       /* Reset SCC register pointer */
+       moveb   %a0@(mac_scc_cha_a_ctrl_offset),%d0
+       /* Reset SCC device: write register pointer then register value */
        moveb   #9,%a0@(mac_scc_cha_a_ctrl_offset)
        moveb   #0xc0,%a0@(mac_scc_cha_a_ctrl_offset)
        /* Wait for 5 PCLK cycles, which is about 68 CPU cycles */
@@ -3896,8 +3904,6 @@ BVME_SCC_DATA_A   = 0xffb0000f
 #endif
 
 #if defined(CONFIG_MAC)
-L(mac_booter_data):
-       .long   0
 L(mac_videobase):
        .long   0
 L(mac_videodepth):
diff --git a/arch/m68k/kernel/machine_kexec.c b/arch/m68k/kernel/machine_kexec.c
new file mode 100644 (file)
index 0000000..d4affc9
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ */
+#include <linux/compiler.h>
+#include <linux/kexec.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+extern const unsigned char relocate_new_kernel[];
+extern const size_t relocate_new_kernel_size;
+
+int machine_kexec_prepare(struct kimage *kimage)
+{
+       return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *kimage)
+{
+}
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+typedef void (*relocate_kernel_t)(unsigned long ptr,
+                                 unsigned long start,
+                                 unsigned long cpu_mmu_flags) __noreturn;
+
+void machine_kexec(struct kimage *image)
+{
+       void *reboot_code_buffer;
+       unsigned long cpu_mmu_flags;
+
+       reboot_code_buffer = page_address(image->control_code_page);
+
+       memcpy(reboot_code_buffer, relocate_new_kernel,
+              relocate_new_kernel_size);
+
+       /*
+        * we do not want to be bothered.
+        */
+       local_irq_disable();
+
+       pr_info("Will call new kernel at 0x%08lx. Bye...\n", image->start);
+       __flush_cache_all();
+       cpu_mmu_flags = m68k_cputype | m68k_mmutype << 8;
+       ((relocate_kernel_t) reboot_code_buffer)(image->head & PAGE_MASK,
+                                                image->start,
+                                                cpu_mmu_flags);
+}
diff --git a/arch/m68k/kernel/relocate_kernel.S b/arch/m68k/kernel/relocate_kernel.S
new file mode 100644 (file)
index 0000000..3e09a89
--- /dev/null
@@ -0,0 +1,159 @@
+#include <linux/linkage.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+
+#define MMU_BASE       8               /* MMU flags base in cpu_mmu_flags */
+
+.text
+
+ENTRY(relocate_new_kernel)
+       movel %sp@(4),%a0               /* a0 = ptr */
+       movel %sp@(8),%a1               /* a1 = start */
+       movel %sp@(12),%d1              /* d1 = cpu_mmu_flags */
+       movew #PAGE_MASK,%d2            /* d2 = PAGE_MASK */
+
+       /* Disable MMU */
+
+       btst #MMU_BASE + MMUB_68851,%d1
+       jeq 3f
+
+1:     /* 68851 or 68030 */
+
+       lea %pc@(.Lcopy),%a4
+2:     addl #0x00000000,%a4            /* virt_to_phys() */
+
+       .section ".m68k_fixup","aw"
+       .long M68K_FIXUP_MEMOFFSET, 2b+2
+       .previous
+
+       .chip 68030
+       pmove %tc,%d0                   /* Disable MMU */
+       bclr #7,%d0
+       pmove %d0,%tc
+       jmp %a4@                        /* Jump to physical .Lcopy */
+       .chip 68k
+
+3:
+       btst #MMU_BASE + MMUB_68030,%d1
+       jne 1b
+
+       btst #MMU_BASE + MMUB_68040,%d1
+       jeq 6f
+
+4:     /* 68040 or 68060 */
+
+       lea %pc@(.Lcont040),%a4
+5:     addl #0x00000000,%a4            /* virt_to_phys() */
+
+       .section ".m68k_fixup","aw"
+       .long M68K_FIXUP_MEMOFFSET, 5b+2
+       .previous
+
+       movel %a4,%d0
+       andl #0xff000000,%d0
+       orw #0xe020,%d0                 /* Map 16 MiB, enable, cacheable */
+       .chip 68040
+       movec %d0,%itt0
+       movec %d0,%dtt0
+       .chip 68k
+       jmp %a4@                        /* Jump to physical .Lcont040 */
+
+.Lcont040:
+       moveq #0,%d0
+       .chip 68040
+       movec %d0,%tc                   /* Disable MMU */
+       movec %d0,%itt0
+       movec %d0,%itt1
+       movec %d0,%dtt0
+       movec %d0,%dtt1
+       .chip 68k
+       jra .Lcopy
+
+6:
+       btst #MMU_BASE + MMUB_68060,%d1
+       jne 4b
+
+.Lcopy:
+       movel %a0@+,%d0                 /* d0 = entry = *ptr */
+       jeq .Lflush
+
+       btst #2,%d0                     /* entry & IND_DONE? */
+       jne .Lflush
+
+       btst #1,%d0                     /* entry & IND_INDIRECTION? */
+       jeq 1f
+       andw %d2,%d0
+       movel %d0,%a0                   /* ptr = entry & PAGE_MASK */
+       jra .Lcopy
+
+1:
+       btst #0,%d0                     /* entry & IND_DESTINATION? */
+       jeq 2f
+       andw %d2,%d0
+       movel %d0,%a2                   /* a2 = dst = entry & PAGE_MASK */
+       jra .Lcopy
+
+2:
+       btst #3,%d0                     /* entry & IND_SOURCE? */
+       jeq .Lcopy
+
+       andw %d2,%d0
+       movel %d0,%a3                   /* a3 = src = entry & PAGE_MASK */
+       movew #PAGE_SIZE/32 - 1,%d0     /* d0 = PAGE_SIZE/32 - 1 */
+3:
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       dbf %d0, 3b
+       jra .Lcopy
+
+.Lflush:
+       /* Flush all caches */
+
+       btst #CPUB_68020,%d1
+       jeq 2f
+
+1:     /* 68020 or 68030 */
+       .chip 68030
+       movec %cacr,%d0
+       orw #0x808,%d0
+       movec %d0,%cacr
+       .chip 68k
+       jra .Lreincarnate
+
+2:
+       btst #CPUB_68030,%d1
+       jne 1b
+
+       btst #CPUB_68040,%d1
+       jeq 4f
+
+3:     /* 68040 or 68060 */
+       .chip 68040
+       nop
+       cpusha %bc
+       nop
+       cinva %bc
+       nop
+       .chip 68k
+       jra .Lreincarnate
+
+4:
+       btst #CPUB_68060,%d1
+       jne 3b
+
+.Lreincarnate:
+       jmp %a1@
+
+relocate_new_kernel_end:
+
+ENTRY(relocate_new_kernel_size)
+       .long relocate_new_kernel_end - relocate_new_kernel
index e67e53159573a81d0db7da0d93464766e47ab264..5b8ec4d5f8e8d79d1becaa48d489d0117374daa8 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/initrd.h>
 
 #include <asm/bootinfo.h>
+#include <asm/byteorder.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
@@ -71,12 +72,12 @@ EXPORT_SYMBOL(m68k_num_memory);
 int m68k_realnum_memory;
 EXPORT_SYMBOL(m68k_realnum_memory);
 unsigned long m68k_memoffset;
-struct mem_info m68k_memory[NUM_MEMINFO];
+struct m68k_mem_info m68k_memory[NUM_MEMINFO];
 EXPORT_SYMBOL(m68k_memory);
 
-struct mem_info m68k_ramdisk;
+static struct m68k_mem_info m68k_ramdisk __initdata;
 
-static char m68k_command_line[CL_SIZE];
+static char m68k_command_line[CL_SIZE] __initdata;
 
 void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
 /* machine dependent irq functions */
@@ -143,11 +144,16 @@ extern void paging_init(void);
 
 static void __init m68k_parse_bootinfo(const struct bi_record *record)
 {
-       while (record->tag != BI_LAST) {
+       uint16_t tag;
+
+       save_bootinfo(record);
+
+       while ((tag = be16_to_cpu(record->tag)) != BI_LAST) {
                int unknown = 0;
-               const unsigned long *data = record->data;
+               const void *data = record->data;
+               uint16_t size = be16_to_cpu(record->size);
 
-               switch (record->tag) {
+               switch (tag) {
                case BI_MACHTYPE:
                case BI_CPUTYPE:
                case BI_FPUTYPE:
@@ -157,20 +163,27 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 
                case BI_MEMCHUNK:
                        if (m68k_num_memory < NUM_MEMINFO) {
-                               m68k_memory[m68k_num_memory].addr = data[0];
-                               m68k_memory[m68k_num_memory].size = data[1];
+                               const struct mem_info *m = data;
+                               m68k_memory[m68k_num_memory].addr =
+                                       be32_to_cpu(m->addr);
+                               m68k_memory[m68k_num_memory].size =
+                                       be32_to_cpu(m->size);
                                m68k_num_memory++;
                        } else
-                               printk("m68k_parse_bootinfo: too many memory chunks\n");
+                               pr_warn("%s: too many memory chunks\n",
+                                       __func__);
                        break;
 
                case BI_RAMDISK:
-                       m68k_ramdisk.addr = data[0];
-                       m68k_ramdisk.size = data[1];
+                       {
+                               const struct mem_info *m = data;
+                               m68k_ramdisk.addr = be32_to_cpu(m->addr);
+                               m68k_ramdisk.size = be32_to_cpu(m->size);
+                       }
                        break;
 
                case BI_COMMAND_LINE:
-                       strlcpy(m68k_command_line, (const char *)data,
+                       strlcpy(m68k_command_line, data,
                                sizeof(m68k_command_line));
                        break;
 
@@ -197,17 +210,16 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
                                unknown = 1;
                }
                if (unknown)
-                       printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
-                              record->tag);
-               record = (struct bi_record *)((unsigned long)record +
-                                             record->size);
+                       pr_warn("%s: unknown tag 0x%04x ignored\n", __func__,
+                               tag);
+               record = (struct bi_record *)((unsigned long)record + size);
        }
 
        m68k_realnum_memory = m68k_num_memory;
 #ifdef CONFIG_SINGLE_MEMORY_CHUNK
        if (m68k_num_memory > 1) {
-               printk("Ignoring last %i chunks of physical memory\n",
-                      (m68k_num_memory - 1));
+               pr_warn("%s: ignoring last %i chunks of physical memory\n",
+                       __func__, (m68k_num_memory - 1));
                m68k_num_memory = 1;
        }
 #endif
@@ -219,7 +231,7 @@ void __init setup_arch(char **cmdline_p)
        int i;
 #endif
 
-       /* The bootinfo is located right after the kernel bss */
+       /* The bootinfo is located right after the kernel */
        if (!CPU_IS_COLDFIRE)
                m68k_parse_bootinfo((const struct bi_record *)_end);
 
@@ -247,7 +259,7 @@ void __init setup_arch(char **cmdline_p)
                asm (".chip 68060; movec %%pcr,%0; .chip 68k"
                     : "=d" (pcr));
                if (((pcr >> 8) & 0xff) <= 5) {
-                       printk("Enabling workaround for errata I14\n");
+                       pr_warn("Enabling workaround for errata I14\n");
                        asm (".chip 68060; movec %0,%%pcr; .chip 68k"
                             : : "d" (pcr | 0x20));
                }
@@ -336,12 +348,12 @@ void __init setup_arch(char **cmdline_p)
                panic("No configuration setup");
        }
 
+       paging_init();
+
 #ifdef CONFIG_NATFEAT
        nf_init();
 #endif
 
-       paging_init();
-
 #ifndef CONFIG_SUN3
        for (i = 1; i < m68k_num_memory; i++)
                free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
@@ -353,7 +365,7 @@ void __init setup_arch(char **cmdline_p)
                                     BOOTMEM_DEFAULT);
                initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
                initrd_end = initrd_start + m68k_ramdisk.size;
-               printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+               pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
        }
 #endif
 
@@ -538,9 +550,9 @@ void check_bugs(void)
 {
 #ifndef CONFIG_M68KFPU_EMU
        if (m68k_fputype == 0) {
-               printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
+               pr_emerg("*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
                        "WHICH IS REQUIRED BY LINUX/M68K ***\n");
-               printk(KERN_EMERG "Upgrade your hardware or join the FPU "
+               pr_emerg("Upgrade your hardware or join the FPU "
                        "emulation project\n");
                panic("no FPU");
        }
index 7eb9792009f8994d4bddd0566b6da18649318cb1..958f1adb9d0c421eeec89d1cdbdf62361a866326 100644 (file)
 #include <linux/timex.h>
 #include <linux/profile.h>
 
+
+unsigned long (*mach_random_get_entropy)(void);
+
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "xtime_update()" routine every clocktick
index 88fcd8c70e7bed8ac311a718aa9c643a2f3370a9..6c9ca24830e9829d7be7761bdd528a765e8b7d2f 100644 (file)
@@ -133,9 +133,7 @@ static inline void access_error060 (struct frame *fp)
 {
        unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
 
-#ifdef DEBUG
-       printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
-#endif
+       pr_debug("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
 
        if (fslw & MMU060_BPE) {
                /* branch prediction error -> clear branch cache */
@@ -162,9 +160,7 @@ static inline void access_error060 (struct frame *fp)
                }
                if (fslw & MMU060_W)
                        errorcode |= 2;
-#ifdef DEBUG
-               printk("errorcode = %d\n", errorcode );
-#endif
+               pr_debug("errorcode = %ld\n", errorcode);
                do_page_fault(&fp->ptregs, addr, errorcode);
        } else if (fslw & (MMU060_SEE)){
                /* Software Emulation Error.
@@ -173,8 +169,9 @@ static inline void access_error060 (struct frame *fp)
                send_fault_sig(&fp->ptregs);
        } else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
                   send_fault_sig(&fp->ptregs) > 0) {
-               printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
-               printk( "68060 access error, fslw=%lx\n", fslw );
+               pr_err("pc=%#lx, fa=%#lx\n", fp->ptregs.pc,
+                      fp->un.fmt4.effaddr);
+               pr_err("68060 access error, fslw=%lx\n", fslw);
                trap_c( fp );
        }
 }
@@ -225,9 +222,7 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
        set_fs(old_fs);
 
 
-#ifdef DEBUG
-       printk("do_040writeback1, res=%d\n",res);
-#endif
+       pr_debug("do_040writeback1, res=%d\n", res);
 
        return res;
 }
@@ -249,7 +244,7 @@ static inline void do_040writebacks(struct frame *fp)
        int res = 0;
 #if 0
        if (fp->un.fmt7.wb1s & WBV_040)
-               printk("access_error040: cannot handle 1st writeback. oops.\n");
+               pr_err("access_error040: cannot handle 1st writeback. oops.\n");
 #endif
 
        if ((fp->un.fmt7.wb2s & WBV_040) &&
@@ -302,14 +297,12 @@ static inline void access_error040(struct frame *fp)
        unsigned short ssw = fp->un.fmt7.ssw;
        unsigned long mmusr;
 
-#ifdef DEBUG
-       printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
-        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
+       pr_debug("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
+       pr_debug("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
                fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
-       printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
+       pr_debug("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
                fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
                fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
-#endif
 
        if (ssw & ATC_040) {
                unsigned long addr = fp->un.fmt7.faddr;
@@ -324,9 +317,7 @@ static inline void access_error040(struct frame *fp)
 
                /* MMU error, get the MMUSR info for this access */
                mmusr = probe040(!(ssw & RW_040), addr, ssw);
-#ifdef DEBUG
-               printk("mmusr = %lx\n", mmusr);
-#endif
+               pr_debug("mmusr = %lx\n", mmusr);
                errorcode = 1;
                if (!(mmusr & MMU_R_040)) {
                        /* clear the invalid atc entry */
@@ -340,14 +331,10 @@ static inline void access_error040(struct frame *fp)
                        errorcode |= 2;
 
                if (do_page_fault(&fp->ptregs, addr, errorcode)) {
-#ifdef DEBUG
-                       printk("do_page_fault() !=0\n");
-#endif
+                       pr_debug("do_page_fault() !=0\n");
                        if (user_mode(&fp->ptregs)){
                                /* delay writebacks after signal delivery */
-#ifdef DEBUG
-                               printk(".. was usermode - return\n");
-#endif
+                               pr_debug(".. was usermode - return\n");
                                return;
                        }
                        /* disable writeback into user space from kernel
@@ -355,9 +342,7 @@ static inline void access_error040(struct frame *fp)
                          * the writeback won't do good)
                         */
 disable_wb:
-#ifdef DEBUG
-                       printk(".. disabling wb2\n");
-#endif
+                       pr_debug(".. disabling wb2\n");
                        if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
                                fp->un.fmt7.wb2s &= ~WBV_040;
                        if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
@@ -371,7 +356,7 @@ disable_wb:
                current->thread.signo = SIGBUS;
                current->thread.faddr = fp->un.fmt7.faddr;
                if (send_fault_sig(&fp->ptregs) >= 0)
-                       printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
+                       pr_err("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
                               fp->un.fmt7.faddr);
                goto disable_wb;
        }
@@ -394,19 +379,17 @@ static inline void bus_error030 (struct frame *fp)
        unsigned short ssw = fp->un.fmtb.ssw;
        extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
 
-#ifdef DEBUG
        if (ssw & (FC | FB))
-               printk ("Instruction fault at %#010lx\n",
+               pr_debug("Instruction fault at %#010lx\n",
                        ssw & FC ?
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
                        :
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
        if (ssw & DF)
-               printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+               pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n",
                        ssw & RW ? "read" : "write",
                        fp->un.fmtb.daddr,
                        space_names[ssw & DFC], fp->ptregs.pc);
-#endif
 
        /*
         * Check if this page should be demand-mapped. This needs to go before
@@ -429,7 +412,7 @@ static inline void bus_error030 (struct frame *fp)
                          return;
                        /* instruction fault or kernel data fault! */
                        if (ssw & (FC | FB))
-                               printk ("Instruction fault at %#010lx\n",
+                               pr_err("Instruction fault at %#010lx\n",
                                        fp->ptregs.pc);
                        if (ssw & DF) {
                                /* was this fault incurred testing bus mappings? */
@@ -439,12 +422,12 @@ static inline void bus_error030 (struct frame *fp)
                                        return;
                                }
 
-                               printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+                               pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
                                        ssw & RW ? "read" : "write",
                                        fp->un.fmtb.daddr,
                                        space_names[ssw & DFC], fp->ptregs.pc);
                        }
-                       printk ("BAD KERNEL BUSERR\n");
+                       pr_err("BAD KERNEL BUSERR\n");
 
                        die_if_kernel("Oops", &fp->ptregs,0);
                        force_sig(SIGKILL, current);
@@ -473,12 +456,11 @@ static inline void bus_error030 (struct frame *fp)
                else if (buserr_type & SUN3_BUSERR_INVALID)
                        errorcode = 0x00;
                else {
-#ifdef DEBUG
-                       printk ("*** unexpected busfault type=%#04x\n", buserr_type);
-                       printk ("invalid %s access at %#lx from pc %#lx\n",
-                               !(ssw & RW) ? "write" : "read", addr,
-                               fp->ptregs.pc);
-#endif
+                       pr_debug("*** unexpected busfault type=%#04x\n",
+                                buserr_type);
+                       pr_debug("invalid %s access at %#lx from pc %#lx\n",
+                                !(ssw & RW) ? "write" : "read", addr,
+                                fp->ptregs.pc);
                        die_if_kernel ("Oops", &fp->ptregs, buserr_type);
                        force_sig (SIGBUS, current);
                        return;
@@ -509,9 +491,7 @@ static inline void bus_error030 (struct frame *fp)
                if (!mmu_emu_handle_fault(addr, 1, 0))
                        do_page_fault (&fp->ptregs, addr, 0);
        } else {
-#ifdef DEBUG
-               printk ("protection fault on insn access (segv).\n");
-#endif
+               pr_debug("protection fault on insn access (segv).\n");
                force_sig (SIGSEGV, current);
        }
 }
@@ -525,22 +505,22 @@ static inline void bus_error030 (struct frame *fp)
        unsigned short ssw = fp->un.fmtb.ssw;
 #ifdef DEBUG
        unsigned long desc;
+#endif
 
-       printk ("pid = %x  ", current->pid);
-       printk ("SSW=%#06x  ", ssw);
+       pr_debug("pid = %x  ", current->pid);
+       pr_debug("SSW=%#06x  ", ssw);
 
        if (ssw & (FC | FB))
-               printk ("Instruction fault at %#010lx\n",
+               pr_debug("Instruction fault at %#010lx\n",
                        ssw & FC ?
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
                        :
                        fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
        if (ssw & DF)
-               printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+               pr_debug("Data %s fault at %#010lx in %s (pc=%#lx)\n",
                        ssw & RW ? "read" : "write",
                        fp->un.fmtb.daddr,
                        space_names[ssw & DFC], fp->ptregs.pc);
-#endif
 
        /* ++andreas: If a data fault and an instruction fault happen
           at the same time map in both pages.  */
@@ -554,27 +534,23 @@ static inline void bus_error030 (struct frame *fp)
                              "pmove %%psr,%1"
                              : "=a&" (desc), "=m" (temp)
                              : "a" (addr), "d" (ssw));
+               pr_debug("mmusr is %#x for addr %#lx in task %p\n",
+                        temp, addr, current);
+               pr_debug("descriptor address is 0x%p, contents %#lx\n",
+                        __va(desc), *(unsigned long *)__va(desc));
 #else
                asm volatile ("ptestr %2,%1@,#7\n\t"
                              "pmove %%psr,%0"
                              : "=m" (temp) : "a" (addr), "d" (ssw));
 #endif
                mmusr = temp;
-
-#ifdef DEBUG
-               printk("mmusr is %#x for addr %#lx in task %p\n",
-                      mmusr, addr, current);
-               printk("descriptor address is %#lx, contents %#lx\n",
-                      __va(desc), *(unsigned long *)__va(desc));
-#endif
-
                errorcode = (mmusr & MMU_I) ? 0 : 1;
                if (!(ssw & RW) || (ssw & RM))
                        errorcode |= 2;
 
                if (mmusr & (MMU_I | MMU_WP)) {
                        if (ssw & 4) {
-                               printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+                               pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
                                       ssw & RW ? "read" : "write",
                                       fp->un.fmtb.daddr,
                                       space_names[ssw & DFC], fp->ptregs.pc);
@@ -587,9 +563,10 @@ static inline void bus_error030 (struct frame *fp)
                } else if (!(mmusr & MMU_I)) {
                        /* probably a 020 cas fault */
                        if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
-                               printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
+                               pr_err("unexpected bus error (%#x,%#x)\n", ssw,
+                                      mmusr);
                } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
-                       printk("invalid %s access at %#lx from pc %#lx\n",
+                       pr_err("invalid %s access at %#lx from pc %#lx\n",
                               !(ssw & RW) ? "write" : "read", addr,
                               fp->ptregs.pc);
                        die_if_kernel("Oops",&fp->ptregs,mmusr);
@@ -600,7 +577,7 @@ static inline void bus_error030 (struct frame *fp)
                        static volatile long tlong;
 #endif
 
-                       printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
+                       pr_err("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
                               !(ssw & RW) ? "write" : "read", addr,
                               fp->ptregs.pc, ssw);
                        asm volatile ("ptestr #1,%1@,#0\n\t"
@@ -609,18 +586,16 @@ static inline void bus_error030 (struct frame *fp)
                                      : "a" (addr));
                        mmusr = temp;
 
-                       printk ("level 0 mmusr is %#x\n", mmusr);
+                       pr_err("level 0 mmusr is %#x\n", mmusr);
 #if 0
                        asm volatile ("pmove %%tt0,%0"
                                      : "=m" (tlong));
-                       printk("tt0 is %#lx, ", tlong);
+                       pr_debug("tt0 is %#lx, ", tlong);
                        asm volatile ("pmove %%tt1,%0"
                                      : "=m" (tlong));
-                       printk("tt1 is %#lx\n", tlong);
-#endif
-#ifdef DEBUG
-                       printk("Unknown SIGSEGV - 1\n");
+                       pr_debug("tt1 is %#lx\n", tlong);
 #endif
+                       pr_debug("Unknown SIGSEGV - 1\n");
                        die_if_kernel("Oops",&fp->ptregs,mmusr);
                        force_sig(SIGSEGV, current);
                        return;
@@ -641,10 +616,9 @@ static inline void bus_error030 (struct frame *fp)
                return;
 
        if (fp->ptregs.sr & PS_S) {
-               printk("Instruction fault at %#010lx\n",
-                       fp->ptregs.pc);
+               pr_err("Instruction fault at %#010lx\n", fp->ptregs.pc);
        buserr:
-               printk ("BAD KERNEL BUSERR\n");
+               pr_err("BAD KERNEL BUSERR\n");
                die_if_kernel("Oops",&fp->ptregs,0);
                force_sig(SIGKILL, current);
                return;
@@ -668,28 +642,22 @@ static inline void bus_error030 (struct frame *fp)
                      "pmove %%psr,%1"
                      : "=a&" (desc), "=m" (temp)
                      : "a" (addr));
+       pr_debug("mmusr is %#x for addr %#lx in task %p\n",
+               temp, addr, current);
+       pr_debug("descriptor address is 0x%p, contents %#lx\n",
+               __va(desc), *(unsigned long *)__va(desc));
 #else
        asm volatile ("ptestr #1,%1@,#7\n\t"
                      "pmove %%psr,%0"
                      : "=m" (temp) : "a" (addr));
 #endif
        mmusr = temp;
-
-#ifdef DEBUG
-       printk ("mmusr is %#x for addr %#lx in task %p\n",
-               mmusr, addr, current);
-       printk ("descriptor address is %#lx, contents %#lx\n",
-               __va(desc), *(unsigned long *)__va(desc));
-#endif
-
        if (mmusr & MMU_I)
                do_page_fault (&fp->ptregs, addr, 0);
        else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
-               printk ("invalid insn access at %#lx from pc %#lx\n",
+               pr_err("invalid insn access at %#lx from pc %#lx\n",
                        addr, fp->ptregs.pc);
-#ifdef DEBUG
-               printk("Unknown SIGSEGV - 2\n");
-#endif
+               pr_debug("Unknown SIGSEGV - 2\n");
                die_if_kernel("Oops",&fp->ptregs,mmusr);
                force_sig(SIGSEGV, current);
                return;
@@ -791,9 +759,7 @@ asmlinkage void buserr_c(struct frame *fp)
        if (user_mode(&fp->ptregs))
                current->thread.esp0 = (unsigned long) fp;
 
-#ifdef DEBUG
-       printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
+       pr_debug("*** Bus Error *** Format is %x\n", fp->ptregs.format);
 
 #if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU)
        if (CPU_IS_COLDFIRE) {
@@ -836,9 +802,7 @@ asmlinkage void buserr_c(struct frame *fp)
 #endif
        default:
          die_if_kernel("bad frame format",&fp->ptregs,0);
-#ifdef DEBUG
-         printk("Unknown SIGSEGV - 4\n");
-#endif
+         pr_debug("Unknown SIGSEGV - 4\n");
          force_sig(SIGSEGV, current);
        }
 }
@@ -852,7 +816,7 @@ void show_trace(unsigned long *stack)
        unsigned long addr;
        int i;
 
-       printk("Call Trace:");
+       pr_info("Call Trace:");
        addr = (unsigned long)stack + THREAD_SIZE - 1;
        endstack = (unsigned long *)(addr & -THREAD_SIZE);
        i = 0;
@@ -869,13 +833,13 @@ void show_trace(unsigned long *stack)
                if (__kernel_text_address(addr)) {
 #ifndef CONFIG_KALLSYMS
                        if (i % 5 == 0)
-                               printk("\n       ");
+                               pr_cont("\n       ");
 #endif
-                       printk(" [<%08lx>] %pS\n", addr, (void *)addr);
+                       pr_cont(" [<%08lx>] %pS\n", addr, (void *)addr);
                        i++;
                }
        }
-       printk("\n");
+       pr_cont("\n");
 }
 
 void show_registers(struct pt_regs *regs)
@@ -887,81 +851,87 @@ void show_registers(struct pt_regs *regs)
        int i;
 
        print_modules();
-       printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
-       printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
-       printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
+       pr_info("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
+       pr_info("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
+       pr_info("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
               regs->d0, regs->d1, regs->d2, regs->d3);
-       printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
+       pr_info("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
               regs->d4, regs->d5, regs->a0, regs->a1);
 
-       printk("Process %s (pid: %d, task=%p)\n",
+       pr_info("Process %s (pid: %d, task=%p)\n",
                current->comm, task_pid_nr(current), current);
        addr = (unsigned long)&fp->un;
-       printk("Frame format=%X ", regs->format);
+       pr_info("Frame format=%X ", regs->format);
        switch (regs->format) {
        case 0x2:
-               printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
+               pr_cont("instr addr=%08lx\n", fp->un.fmt2.iaddr);
                addr += sizeof(fp->un.fmt2);
                break;
        case 0x3:
-               printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
+               pr_cont("eff addr=%08lx\n", fp->un.fmt3.effaddr);
                addr += sizeof(fp->un.fmt3);
                break;
        case 0x4:
-               printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
-                       : "eff addr=%08lx pc=%08lx\n"),
-                       fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+               if (CPU_IS_060)
+                       pr_cont("fault addr=%08lx fslw=%08lx\n",
+                               fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+               else
+                       pr_cont("eff addr=%08lx pc=%08lx\n",
+                               fp->un.fmt4.effaddr, fp->un.fmt4.pc);
                addr += sizeof(fp->un.fmt4);
                break;
        case 0x7:
-               printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
+               pr_cont("eff addr=%08lx ssw=%04x faddr=%08lx\n",
                        fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
-               printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
+               pr_info("wb 1 stat/addr/data: %04x %08lx %08lx\n",
                        fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
-               printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
+               pr_info("wb 2 stat/addr/data: %04x %08lx %08lx\n",
                        fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
-               printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
+               pr_info("wb 3 stat/addr/data: %04x %08lx %08lx\n",
                        fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
-               printk("push data: %08lx %08lx %08lx %08lx\n",
+               pr_info("push data: %08lx %08lx %08lx %08lx\n",
                        fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
                        fp->un.fmt7.pd3);
                addr += sizeof(fp->un.fmt7);
                break;
        case 0x9:
-               printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
+               pr_cont("instr addr=%08lx\n", fp->un.fmt9.iaddr);
                addr += sizeof(fp->un.fmt9);
                break;
        case 0xa:
-               printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+               pr_cont("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
                        fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
                        fp->un.fmta.daddr, fp->un.fmta.dobuf);
                addr += sizeof(fp->un.fmta);
                break;
        case 0xb:
-               printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+               pr_cont("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
                        fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
                        fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
-               printk("baddr=%08lx dibuf=%08lx ver=%x\n",
+               pr_info("baddr=%08lx dibuf=%08lx ver=%x\n",
                        fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
                addr += sizeof(fp->un.fmtb);
                break;
        default:
-               printk("\n");
+               pr_cont("\n");
        }
        show_stack(NULL, (unsigned long *)addr);
 
-       printk("Code:");
+       pr_info("Code:");
        set_fs(KERNEL_DS);
        cp = (u16 *)regs->pc;
        for (i = -8; i < 16; i++) {
                if (get_user(c, cp + i) && i >= 0) {
-                       printk(" Bad PC value.");
+                       pr_cont(" Bad PC value.");
                        break;
                }
-               printk(i ? " %04x" : " <%04x>", c);
+               if (i)
+                       pr_cont(" %04x", c);
+               else
+                       pr_cont(" <%04x>", c);
        }
        set_fs(old_fs);
-       printk ("\n");
+       pr_cont("\n");
 }
 
 void show_stack(struct task_struct *task, unsigned long *stack)
@@ -978,16 +948,16 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        }
        endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
 
-       printk("Stack from %08lx:", (unsigned long)stack);
+       pr_info("Stack from %08lx:", (unsigned long)stack);
        p = stack;
        for (i = 0; i < kstack_depth_to_print; i++) {
                if (p + 1 > endstack)
                        break;
                if (i % 8 == 0)
-                       printk("\n       ");
-               printk(" %08lx", *p++);
+                       pr_cont("\n       ");
+               pr_cont(" %08lx", *p++);
        }
-       printk("\n");
+       pr_cont("\n");
        show_trace(stack);
 }
 
@@ -1005,32 +975,32 @@ void bad_super_trap (struct frame *fp)
 
        console_verbose();
        if (vector < ARRAY_SIZE(vec_names))
-               printk ("*** %s ***   FORMAT=%X\n",
+               pr_err("*** %s ***   FORMAT=%X\n",
                        vec_names[vector],
                        fp->ptregs.format);
        else
-               printk ("*** Exception %d ***   FORMAT=%X\n",
+               pr_err("*** Exception %d ***   FORMAT=%X\n",
                        vector, fp->ptregs.format);
        if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) {
                unsigned short ssw = fp->un.fmtb.ssw;
 
-               printk ("SSW=%#06x  ", ssw);
+               pr_err("SSW=%#06x  ", ssw);
 
                if (ssw & RC)
-                       printk ("Pipe stage C instruction fault at %#010lx\n",
+                       pr_err("Pipe stage C instruction fault at %#010lx\n",
                                (fp->ptregs.format) == 0xA ?
                                fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
                if (ssw & RB)
-                       printk ("Pipe stage B instruction fault at %#010lx\n",
+                       pr_err("Pipe stage B instruction fault at %#010lx\n",
                                (fp->ptregs.format) == 0xA ?
                                fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
                if (ssw & DF)
-                       printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+                       pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
                                ssw & RW ? "read" : "write",
                                fp->un.fmtb.daddr, space_names[ssw & DFC],
                                fp->ptregs.pc);
        }
-       printk ("Current process id is %d\n", task_pid_nr(current));
+       pr_err("Current process id is %d\n", task_pid_nr(current));
        die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
 }
 
@@ -1162,7 +1132,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
                return;
 
        console_verbose();
-       printk("%s: %08x\n",str,nr);
+       pr_crit("%s: %08x\n", str, nr);
        show_registers(fp);
        add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
        do_exit(SIGSEGV);
index afb95d5fb26b3b29b172d730d8b5bacc4c3c664a..982c3fe73c4a45b45eeeff08e8d8446a47151c16 100644 (file)
 #include <linux/adb.h>
 #include <linux/cuda.h>
 
-#define BOOTINFO_COMPAT_1_0
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-mac.h>
+#include <asm/byteorder.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -107,45 +108,46 @@ static void __init mac_sched_init(irq_handler_t vector)
 int __init mac_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const u_long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_MAC_MODEL:
-               mac_bi_data.id = *data;
+               mac_bi_data.id = be32_to_cpup(data);
                break;
        case BI_MAC_VADDR:
-               mac_bi_data.videoaddr = *data;
+               mac_bi_data.videoaddr = be32_to_cpup(data);
                break;
        case BI_MAC_VDEPTH:
-               mac_bi_data.videodepth = *data;
+               mac_bi_data.videodepth = be32_to_cpup(data);
                break;
        case BI_MAC_VROW:
-               mac_bi_data.videorow = *data;
+               mac_bi_data.videorow = be32_to_cpup(data);
                break;
        case BI_MAC_VDIM:
-               mac_bi_data.dimensions = *data;
+               mac_bi_data.dimensions = be32_to_cpup(data);
                break;
        case BI_MAC_VLOGICAL:
-               mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
-               mac_orig_videoaddr = *data;
+               mac_orig_videoaddr = be32_to_cpup(data);
+               mac_bi_data.videological =
+                       VIDEOMEMBASE + (mac_orig_videoaddr & ~VIDEOMEMMASK);
                break;
        case BI_MAC_SCCBASE:
-               mac_bi_data.sccbase = *data;
+               mac_bi_data.sccbase = be32_to_cpup(data);
                break;
        case BI_MAC_BTIME:
-               mac_bi_data.boottime = *data;
+               mac_bi_data.boottime = be32_to_cpup(data);
                break;
        case BI_MAC_GMTBIAS:
-               mac_bi_data.gmtbias = *data;
+               mac_bi_data.gmtbias = be32_to_cpup(data);
                break;
        case BI_MAC_MEMSIZE:
-               mac_bi_data.memsize = *data;
+               mac_bi_data.memsize = be32_to_cpup(data);
                break;
        case BI_MAC_CPUID:
-               mac_bi_data.cpuid = *data;
+               mac_bi_data.cpuid = be32_to_cpup(data);
                break;
        case BI_MAC_ROMBASE:
-               mac_bi_data.rombase = *data;
+               mac_bi_data.rombase = be32_to_cpup(data);
                break;
        default:
                unknown = 1;
index 7d8d46127ad9fc91717dcb660ac9647d0b9708e4..4d2adfb32a2ab4f61951357114a8d053bf74de82 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_iop.h>
 
 /*#define DEBUG_IOP*/
 
-/* Set to non-zero if the IOPs are present. Set by iop_init() */
+/* Non-zero if the IOPs are present */
 
-int iop_scc_present,iop_ism_present;
+int iop_scc_present, iop_ism_present;
 
 /* structure for tracking channel listeners */
 
index 5e085554ac7f2bb9f0c3a964a30f001049804f8a..707b61aea2030c8f7de9058a2546a8eb85ce1639 100644 (file)
@@ -25,8 +25,6 @@
 #include <asm/mac_via.h>
 #include <asm/mac_oss.h>
 
-#define BOOTINFO_COMPAT_1_0
-#include <asm/bootinfo.h>
 #include <asm/machdep.h>
 
 /* Offset between Unix time (1970-based) and Mac time (1904-based) */
index 6c4c882c126e826e2d1b114f39acaf3e8b9ddc15..54037125ebf8c0e05c82cb937cb2560a7575244d 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
index 6f026fc302fab3ca70f6e05386a732ac52e1d985..835fa04511c85ad0d6e71ba8ee1f3a2dc26fcc1b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/irq.h>
 
 #include <asm/traps.h>
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_psc.h>
@@ -54,7 +53,7 @@ static void psc_debug_dump(void)
  * expanded to cover what I think are the other 7 channels.
  */
 
-static void psc_dma_die_die_die(void)
+static __init void psc_dma_die_die_die(void)
 {
        int i;
 
index 5d1458bb871b8bd5e55eb25c5501067adef4810b..e198dec868e472e802768c5a9459e498e7623b00 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/irq.h>
 
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
index eb1d61f6872549991dae7d5e491a74627d8456d0..2bd7487440c455802dac6470ec05ac138148bfcb 100644 (file)
@@ -25,9 +25,8 @@ int send_fault_sig(struct pt_regs *regs)
        siginfo.si_signo = current->thread.signo;
        siginfo.si_code = current->thread.code;
        siginfo.si_addr = (void *)current->thread.faddr;
-#ifdef DEBUG
-       printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code);
-#endif
+       pr_debug("send_fault_sig: %p,%d,%d\n", siginfo.si_addr,
+                siginfo.si_signo, siginfo.si_code);
 
        if (user_mode(regs)) {
                force_sig_info(siginfo.si_signo,
@@ -45,10 +44,10 @@ int send_fault_sig(struct pt_regs *regs)
                 * terminate things with extreme prejudice.
                 */
                if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
-                       printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+                       pr_alert("Unable to handle kernel NULL pointer dereference");
                else
-                       printk(KERN_ALERT "Unable to handle kernel access");
-               printk(" at virtual address %p\n", siginfo.si_addr);
+                       pr_alert("Unable to handle kernel access");
+               pr_cont(" at virtual address %p\n", siginfo.si_addr);
                die_if_kernel("Oops", regs, 0 /*error_code*/);
                do_exit(SIGKILL);
        }
@@ -75,11 +74,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
        int fault;
        unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
-#ifdef DEBUG
-       printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
-               regs->sr, regs->pc, address, error_code,
-               current->mm->pgd);
-#endif
+       pr_debug("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
+               regs->sr, regs->pc, address, error_code, mm ? mm->pgd : NULL);
 
        /*
         * If we're in an interrupt or have no user
@@ -118,9 +114,7 @@ retry:
  * we can handle it..
  */
 good_area:
-#ifdef DEBUG
-       printk("do_page_fault: good_area\n");
-#endif
+       pr_debug("do_page_fault: good_area\n");
        switch (error_code & 3) {
                default:        /* 3: write, present */
                        /* fall through */
@@ -143,9 +137,7 @@ good_area:
         */
 
        fault = handle_mm_fault(mm, vma, address, flags);
-#ifdef DEBUG
-       printk("handle_mm_fault returns %d\n",fault);
-#endif
+       pr_debug("handle_mm_fault returns %d\n", fault);
 
        if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
                return 0;
index 6b4baa6e4d31d8f24e09950d581f6ae9ab1cc6dd..acaff6a49e357e89154651f6ec57db9ab53f0459 100644 (file)
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(pg_data_table);
 void __init m68k_setup_node(int node)
 {
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
-       struct mem_info *info = m68k_memory + node;
+       struct m68k_mem_info *info = m68k_memory + node;
        int i, end;
 
        i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
index 568cfad3ceb8daf59034282cd8e9bf776fab1f29..6e4955bc542bfc591721aa23fdac1fdbaf66b586 100644 (file)
@@ -27,9 +27,9 @@
 
 /*
  * For 040/060 we can use the virtual memory area like other architectures,
- * but for 020/030 we want to use early termination page descriptor and we
+ * but for 020/030 we want to use early termination page descriptors and we
  * can't mix this with normal page descriptors, so we have to copy that code
- * (mm/vmalloc.c) and return appriorate aligned addresses.
+ * (mm/vmalloc.c) and return appropriately aligned addresses.
  */
 
 #ifdef CPU_M68040_OR_M68060_ONLY
@@ -224,7 +224,7 @@ void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cachefla
 EXPORT_SYMBOL(__ioremap);
 
 /*
- * Unmap a ioremap()ed region again
+ * Unmap an ioremap()ed region again
  */
 void iounmap(void __iomem *addr)
 {
@@ -241,8 +241,8 @@ EXPORT_SYMBOL(iounmap);
 
 /*
  * __iounmap unmaps nearly everything, so be careful
- * it doesn't free currently pointer/page tables anymore but it
- * wans't used anyway and might be added later.
+ * Currently it doesn't free pointer/page tables anymore but this
+ * wasn't used anyway and might be added later.
  */
 void __iounmap(void *addr, unsigned long size)
 {
index 251c5437787be6054086b4d5586adfc0887e0472..7d4024432163ffa534665582fcf522ed4e9ea51f 100644 (file)
@@ -233,7 +233,7 @@ void __init paging_init(void)
                        printk("Fix your bootloader or use a memfile to make use of this area!\n");
                        m68k_num_memory--;
                        memmove(m68k_memory + i, m68k_memory + i + 1,
-                               (m68k_num_memory - i) * sizeof(struct mem_info));
+                               (m68k_num_memory - i) * sizeof(struct m68k_mem_info));
                        continue;
                }
                addr = m68k_memory[i].addr + m68k_memory[i].size;
index 1c6262803b9455d46fbde9b05587fc910b1687f5..1bb3ce6634d36630d4ad82e34e91cc45de83da97 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-vme.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -51,9 +53,10 @@ static int bcd2int (unsigned char b);
 irq_handler_t tick_handler;
 
 
-int mvme147_parse_bootinfo(const struct bi_record *bi)
+int __init mvme147_parse_bootinfo(const struct bi_record *bi)
 {
-       if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO)
+       uint16_t tag = be16_to_cpu(bi->tag);
+       if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO)
                return 0;
        else
                return 1;
index 080a342458a1934162aa61f44d72d59dfc1afbd9..eab7d342757ef6abdf01e13ff1a199209381c81d 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-vme.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -60,9 +62,10 @@ unsigned short mvme16x_config;
 EXPORT_SYMBOL(mvme16x_config);
 
 
-int mvme16x_parse_bootinfo(const struct bi_record *bi)
+int __init mvme16x_parse_bootinfo(const struct bi_record *bi)
 {
-       if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO)
+       uint16_t tag = be16_to_cpu(bi->tag);
+       if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO)
                return 0;
        else
                return 1;
@@ -87,15 +90,15 @@ static void mvme16x_get_model(char *model)
     suf[3] = '\0';
     suf[0] = suf[1] ? '-' : '\0';
 
-    sprintf(model, "Motorola MVME%x%s", p->brdno, suf);
+    sprintf(model, "Motorola MVME%x%s", be16_to_cpu(p->brdno), suf);
 }
 
 
 static void mvme16x_get_hardware_list(struct seq_file *m)
 {
-    p_bdid p = &mvme_bdid;
+    uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
 
-    if (p->brdno == 0x0162 || p->brdno == 0x0172)
+    if (brdno == 0x0162 || brdno == 0x0172)
     {
        unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
 
@@ -285,6 +288,7 @@ void __init config_mvme16x(void)
 {
     p_bdid p = &mvme_bdid;
     char id[40];
+    uint16_t brdno = be16_to_cpu(p->brdno);
 
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = mvme16x_sched_init;
@@ -306,18 +310,18 @@ void __init config_mvme16x(void)
     }
     /* Board type is only set by newer versions of vmelilo/tftplilo */
     if (vme_brdtype == 0)
-       vme_brdtype = p->brdno;
+       vme_brdtype = brdno;
 
     mvme16x_get_model(id);
     printk ("\nBRD_ID: %s   BUG %x.%x %02x/%02x/%02x\n", id, p->rev>>4,
                                        p->rev&0xf, p->yr, p->mth, p->day);
-    if (p->brdno == 0x0162 || p->brdno == 0x172)
+    if (brdno == 0x0162 || brdno == 0x172)
     {
        unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
 
        mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA;
 
-       printk ("MVME%x Hardware status:\n", p->brdno);
+       printk ("MVME%x Hardware status:\n", brdno);
        printk ("    CPU Type           68%s040\n",
                        rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC");
        printk ("    CPU clock          %dMHz\n",
@@ -347,12 +351,12 @@ void __init config_mvme16x(void)
 
 static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
 {
-       p_bdid p = &mvme_bdid;
        unsigned long *new = (unsigned long *)vectors;
        unsigned long *old = (unsigned long *)0xffe00000;
        volatile unsigned char uc, *ucp;
+       uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
 
-       if (p->brdno == 0x0162 || p->brdno == 0x172)
+       if (brdno == 0x0162 || brdno == 0x172)
        {
                ucp = (volatile unsigned char *)0xfff42043;
                uc = *ucp | 8;
@@ -366,7 +370,7 @@ static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
        *(new+9) = *(old+9);            /* Trace */
        *(new+47) = *(old+47);          /* Trap #15 */
 
-       if (p->brdno == 0x0162 || p->brdno == 0x172)
+       if (brdno == 0x0162 || brdno == 0x172)
                *(new+0x5e) = *(old+0x5e);      /* ABORT switch */
        else
                *(new+0x6e) = *(old+0x6e);      /* ABORT switch */
@@ -381,7 +385,7 @@ static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 
 void mvme16x_sched_init (irq_handler_t timer_routine)
 {
-    p_bdid p = &mvme_bdid;
+    uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
     int irq;
 
     tick_handler = timer_routine;
@@ -394,7 +398,7 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
                                "timer", mvme16x_timer_int))
        panic ("Couldn't register timer int");
 
-    if (p->brdno == 0x0162 || p->brdno == 0x172)
+    if (brdno == 0x0162 || brdno == 0x172)
        irq = MVME162_IRQ_ABORT;
     else
         irq = MVME167_IRQ_ABORT;
index 078bb744b5fe1193232a96999eb85c92b798c04a..e90fe903613ead8ad480797d138f7d566f738f48 100644 (file)
@@ -154,7 +154,7 @@ static unsigned int serports[] =
        0x3f8,0x2f8,0x3e8,0x2e8,0
 };
 
-static void q40_disable_irqs(void)
+static void __init q40_disable_irqs(void)
 {
        unsigned i, j;
 
@@ -198,7 +198,7 @@ void __init config_q40(void)
 }
 
 
-int q40_parse_bootinfo(const struct bi_record *rec)
+int __init q40_parse_bootinfo(const struct bi_record *rec)
 {
        return 1;
 }
index d522eaab45510aacd13b7cdf6e11ff14f88659a0..d95506e06c2ac42b67f9ce634413da8efc50082f 100644 (file)
@@ -7,6 +7,7 @@
  *
  */
 
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
@@ -62,10 +63,7 @@ int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
 
 }
 
-void sun3_dvma_init(void)
+void __init sun3_dvma_init(void)
 {
-
        memset(ptelist, 0, sizeof(ptelist));
-
-
 }
index 8edc510a21be663122fc285df8f624cf818d6b7b..3f258e230ba5d0c95806848ef96c64ce1160d479 100644 (file)
@@ -6,6 +6,7 @@
 ** Started 1/16/98 @ 2:22 am
 */
 
+#include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
@@ -122,7 +123,7 @@ void print_pte_vaddr (unsigned long vaddr)
 /*
  * Initialise the MMU emulator.
  */
-void mmu_emu_init(unsigned long bootmem_end)
+void __init mmu_emu_init(unsigned long bootmem_end)
 {
        unsigned long seg, num;
        int i,j;
index cab54482ca34b97fa4412eaaaa4a0ee31d173833..b37521a5259ddb7a040d6606fdd24f324f657e8f 100644 (file)
@@ -6,6 +6,8 @@
  * Contains common routines for sun3/sun3x DVMA management.
  */
 
+#include <linux/bootmem.h>
+#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/gfp.h>
@@ -30,7 +32,7 @@ static inline void dvma_unmap_iommu(unsigned long a, int b)
 extern void sun3_dvma_init(void);
 #endif
 
-static unsigned long iommu_use[IOMMU_TOTAL_ENTRIES];
+static unsigned long *iommu_use;
 
 #define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT)
 
@@ -245,7 +247,7 @@ static inline int free_baddr(unsigned long baddr)
 
 }
 
-void dvma_init(void)
+void __init dvma_init(void)
 {
 
        struct hole *hole;
@@ -265,7 +267,7 @@ void dvma_init(void)
 
        list_add(&(hole->list), &hole_list);
 
-       memset(iommu_use, 0, sizeof(iommu_use));
+       iommu_use = alloc_bootmem(IOMMU_TOTAL_ENTRIES * sizeof(unsigned long));
 
        dvma_unmap_iommu(DVMA_START, DVMA_SIZE);
 
index a7b7e818d6279450119f4a8da5e76cf1c6746466..0898c3f8150851a34e8c4f54fe8c3d7760497cd4 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/bootinfo.h>
 #include <asm/setup.h>
 #include <asm/traps.h>
 #include <asm/sun3xprom.h>
index c90bfc6bf64892c76867fc2540183c02684afc3e..5d6b4b407ddab29b677a7aa5328715127dfdad56 100644 (file)
@@ -82,4 +82,19 @@ static inline void fence(void)
 #define smp_read_barrier_depends()     do { } while (0)
 #define set_mb(var, value) do { var = value; smp_mb(); } while (0)
 
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ___p1;                                                          \
+})
+
 #endif /* _ASM_METAG_BARRIER_H */
index e0373f81a1172fdabc23afc174302a89b2f8814a..1d7e770f7a54bfca3c9382b5fe5b657885037612 100644 (file)
@@ -7,13 +7,11 @@
 
 enum ipi_msg_type {
        IPI_CALL_FUNC,
-       IPI_CALL_FUNC_SINGLE,
        IPI_RESCHEDULE,
 };
 
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
 
 asmlinkage void secondary_start_kernel(void);
 
index db589ad5dbc41e5bb1cb0bc52dfc4faefc9c1820..c700d625067a96cb725064e0c19ceadad078cd6a 100644 (file)
@@ -399,11 +399,6 @@ static int __init dma_alloc_init(void)
                pgd = pgd_offset(&init_mm, CONSISTENT_START);
                pud = pud_alloc(&init_mm, pgd, CONSISTENT_START);
                pmd = pmd_alloc(&init_mm, pud, CONSISTENT_START);
-               if (!pmd) {
-                       pr_err("%s: no pmd tables\n", __func__);
-                       ret = -ENOMEM;
-                       break;
-               }
                WARN_ON(!pmd_none(*pmd));
 
                pte = pte_alloc_kernel(pmd, CONSISTENT_START);
index 7c01131429817ab58ce63490cc97e5dba4f4b4c9..f006d2276f40abb67d6aeb2356a2f00aebcdb9fb 100644 (file)
@@ -68,7 +68,7 @@ static DECLARE_COMPLETION(cpu_running);
 /*
  * "thread" is assumed to be a valid Meta hardware thread ID.
  */
-int boot_secondary(unsigned int thread, struct task_struct *idle)
+static int boot_secondary(unsigned int thread, struct task_struct *idle)
 {
        u32 val;
 
@@ -491,7 +491,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
 void show_ipi_list(struct seq_file *p)
@@ -517,11 +517,10 @@ static DEFINE_SPINLOCK(stop_lock);
  *
  *  Bit 0 - Inter-processor function call
  */
-static int do_IPI(struct pt_regs *regs)
+static int do_IPI(void)
 {
        unsigned int cpu = smp_processor_id();
        struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-       struct pt_regs *old_regs = set_irq_regs(regs);
        unsigned long msgs, nextmsg;
        int handled = 0;
 
@@ -546,10 +545,6 @@ static int do_IPI(struct pt_regs *regs)
                        generic_smp_call_function_interrupt();
                        break;
 
-               case IPI_CALL_FUNC_SINGLE:
-                       generic_smp_call_function_single_interrupt();
-                       break;
-
                default:
                        pr_crit("CPU%u: Unknown IPI message 0x%lx\n",
                                cpu, nextmsg);
@@ -557,8 +552,6 @@ static int do_IPI(struct pt_regs *regs)
                }
        }
 
-       set_irq_regs(old_regs);
-
        return handled;
 }
 
@@ -624,7 +617,7 @@ static void kick_raise_softirq(cpumask_t callmap, unsigned int irq)
 static TBIRES ipi_handler(TBIRES State, int SigNum, int Triggers,
                   int Inst, PTBI pTBI, int *handled)
 {
-       *handled = do_IPI((struct pt_regs *)State.Sig.pCtx);
+       *handled = do_IPI();
 
        return State;
 }
index bec3dec4922e689d307cd9092a41aa5308c13ad1..4ba595701f7d8cd98a9584579bebc919f00a405d 100644 (file)
@@ -19,6 +19,7 @@
 DEFINE_PER_CPU(struct cpuinfo_metag, cpu_data);
 
 cpumask_t cpu_core_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_core_map);
 
 static cpumask_t cpu_coregroup_map(unsigned int cpu)
 {
index ce0bbf8f5640e78127f89616188a59be1bb5ba8b..a82426589fffb2cb9bf440b1d44ad73eab8002f9 100644 (file)
@@ -1,4 +1,5 @@
 
+generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
diff --git a/arch/microblaze/include/asm/barrier.h b/arch/microblaze/include/asm/barrier.h
deleted file mode 100644 (file)
index df5be3e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_BARRIER_H
-#define _ASM_MICROBLAZE_BARRIER_H
-
-#define nop()                  asm volatile ("nop")
-
-#define smp_read_barrier_depends()     do {} while (0)
-#define read_barrier_depends()         do {} while (0)
-
-#define mb()                   barrier()
-#define rmb()                  mb()
-#define wmb()                  mb()
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
-#define set_wmb(var, value)    do { var = value; wmb(); } while (0)
-
-#define smp_mb()               mb()
-#define smp_rmb()              rmb()
-#define smp_wmb()              wmb()
-
-#endif /* _ASM_MICROBLAZE_BARRIER_H */
index 650de3976e7a5a337ab60dcc6ee5f0dd04fe22c0..c93d92beb3d62c264adaded9c69d9f26b48afd6a 100644 (file)
@@ -47,6 +47,7 @@ config MIPS
        select MODULES_USE_ELF_RELA if MODULES && 64BIT
        select CLONE_BACKWARDS
        select HAVE_DEBUG_STACKOVERFLOW
+       select HAVE_CC_STACKPROTECTOR
 
 menu "Machine selection"
 
@@ -2322,19 +2323,6 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
-config CC_STACKPROTECTOR
-       bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
-       help
-         This option turns on the -fstack-protector GCC feature. This
-         feature puts, at the beginning of functions, a canary value on
-         the stack just before the return address, and validates
-         the value just before actually returning.  Stack based buffer
-         overflows (that need to overwrite this return address) now also
-         overwrite the canary, which gets detected and the attack is then
-         neutralized via a kernel panic.
-
-         This feature requires gcc version 4.2 or above.
-
 config USE_OF
        bool
        select OF
index de300b9936076faad63463c884687d9e19ea914f..efe50787cd897c4391575cefcef73ecb40ff3385 100644 (file)
@@ -232,10 +232,6 @@ bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \
 
 LDFLAGS                        += -m $(ld-emul)
 
-ifdef CONFIG_CC_STACKPROTECTOR
-  KBUILD_CFLAGS += -fstack-protector
-endif
-
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
        egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
index 9a357fffcfbe0a0c6767e5b12d70d22f23e5b1b7..820b7a313d9bfd593cdaa63e6374f0cf4bd15d6a 100644 (file)
@@ -92,7 +92,6 @@ void __init plat_mem_setup(void)
        _machine_restart = ar7_machine_restart;
        _machine_halt = ar7_machine_halt;
        pm_power_off = ar7_machine_power_off;
-       panic_timeout = 3;
 
        io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
        if (!io_base)
index d71005835c007aeb8df0f8b288fbfb1f3045457d..9100122e5cef891c18767fee89c98858df661f11 100644 (file)
@@ -111,9 +111,6 @@ void __init plat_mem_setup(void)
        iomem_resource.start = EMMA2RH_IO_BASE;
        iomem_resource.end = EMMA2RH_ROM_BASE - 1;
 
-       /* Reboot on panic */
-       panic_timeout = 180;
-
        markeins_sio_setup();
 }
 
index f26d8e1bf3c37575b4b42144282587caaa1c6a3f..e1aa4e4c2984230e2353760a4b9863387d90ad24 100644 (file)
 #define nudge_writes() mb()
 #endif
 
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ___p1;                                                          \
+})
+
 #endif /* __ASM_BARRIER_H */
index c75025f27c201f02a9b85f65c2fdbbc529768325..06b9bc7ea14b1da802dc29090174230cc2e1d613 100644 (file)
@@ -83,6 +83,6 @@
 /*
  * Loongson2-specific cacheops
  */
-#define Hit_Invalidate_I_Loongson23    0x00
+#define Hit_Invalidate_I_Loongson2     0x00
 
 #endif /* __ASM_CACHEOPS_H */
index 34d1a19171257ff8d8e602988615b8b8e2878ff9..c84caddb8bdedea260acac25a71c0d5a9c59ef19 100644 (file)
@@ -165,7 +165,7 @@ static inline void flush_icache_line(unsigned long addr)
        __iflush_prologue
        switch (boot_cpu_type()) {
        case CPU_LOONGSON2:
-               cache_op(Hit_Invalidate_I_Loongson23, addr);
+               cache_op(Hit_Invalidate_I_Loongson2, addr);
                break;
 
        default:
@@ -219,7 +219,7 @@ static inline void protected_flush_icache_line(unsigned long addr)
 {
        switch (boot_cpu_type()) {
        case CPU_LOONGSON2:
-               protected_cache_op(Hit_Invalidate_I_Loongson23, addr);
+               protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
                break;
 
        default:
@@ -357,8 +357,8 @@ static inline void invalidate_tcache_page(unsigned long addr)
                  "i" (op));
 
 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
-static inline void blast_##pfx##cache##lsize(void)                     \
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra)   \
+static inline void extra##blast_##pfx##cache##lsize(void)              \
 {                                                                      \
        unsigned long start = INDEX_BASE;                               \
        unsigned long end = start + current_cpu_data.desc.waysize;      \
@@ -376,7 +376,7 @@ static inline void blast_##pfx##cache##lsize(void)                  \
        __##pfx##flush_epilogue                                         \
 }                                                                      \
                                                                        \
-static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
 {                                                                      \
        unsigned long start = page;                                     \
        unsigned long end = page + PAGE_SIZE;                           \
@@ -391,7 +391,7 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
        __##pfx##flush_epilogue                                         \
 }                                                                      \
                                                                        \
-static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
+static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
 {                                                                      \
        unsigned long indexmask = current_cpu_data.desc.waysize - 1;    \
        unsigned long start = INDEX_BASE + (page & indexmask);          \
@@ -410,23 +410,24 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
        __##pfx##flush_epilogue                                         \
 }
 
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
-
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
+
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
 
 /* build blast_xxx_range, protected_blast_xxx_range */
 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra)       \
@@ -452,8 +453,8 @@ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start,
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson23, \
-       protected_, loongson23_)
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \
+       protected_, loongson2_)
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 /* blast_inv_dcache_range */
index 62ffd20ea86909be81906691dd1531a35733c410..49e572d879e1348234bc1413f2e9f25e593d9318 100644 (file)
@@ -237,6 +237,8 @@ static void r4k_blast_icache_page_setup(void)
                r4k_blast_icache_page = (void *)cache_noop;
        else if (ic_lsize == 16)
                r4k_blast_icache_page = blast_icache16_page;
+       else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2)
+               r4k_blast_icache_page = loongson2_blast_icache32_page;
        else if (ic_lsize == 32)
                r4k_blast_icache_page = blast_icache32_page;
        else if (ic_lsize == 64)
@@ -261,6 +263,9 @@ static void r4k_blast_icache_page_indexed_setup(void)
                else if (TX49XX_ICACHE_INDEX_INV_WAR)
                        r4k_blast_icache_page_indexed =
                                tx49_blast_icache32_page_indexed;
+               else if (current_cpu_type() == CPU_LOONGSON2)
+                       r4k_blast_icache_page_indexed =
+                               loongson2_blast_icache32_page_indexed;
                else
                        r4k_blast_icache_page_indexed =
                                blast_icache32_page_indexed;
@@ -284,6 +289,8 @@ static void r4k_blast_icache_setup(void)
                        r4k_blast_icache = blast_r4600_v1_icache32;
                else if (TX49XX_ICACHE_INDEX_INV_WAR)
                        r4k_blast_icache = tx49_blast_icache32;
+               else if (current_cpu_type() == CPU_LOONGSON2)
+                       r4k_blast_icache = loongson2_blast_icache32;
                else
                        r4k_blast_icache = blast_icache32;
        } else if (ic_lsize == 64)
@@ -580,11 +587,11 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
        else {
                switch (boot_cpu_type()) {
                case CPU_LOONGSON2:
-                       protected_blast_icache_range(start, end);
+                       protected_loongson2_blast_icache_range(start, end);
                        break;
 
                default:
-                       protected_loongson23_blast_icache_range(start, end);
+                       protected_blast_icache_range(start, end);
                        break;
                }
        }
index 6d981bb337ecd8abf96324d1e0f2a006caa942de..54e75c77184b883fdbec601e1b2e97e49b1aa8c9 100644 (file)
@@ -92,7 +92,6 @@ static void __init xlp_init_mem_from_bars(void)
 
 void __init plat_mem_setup(void)
 {
-       panic_timeout   = 5;
        _machine_restart = (void (*)(char *))nlm_linux_exit;
        _machine_halt   = nlm_linux_exit;
        pm_power_off    = nlm_linux_exit;
index 214d123b79faf7f6659ae4127ffe938257fb26ae..921be5f77797706279d61c1c79f897a206546d07 100644 (file)
@@ -92,7 +92,6 @@ static void nlm_linux_exit(void)
 
 void __init plat_mem_setup(void)
 {
-       panic_timeout   = 5;
        _machine_restart = (void (*)(char *))nlm_linux_exit;
        _machine_halt   = nlm_linux_exit;
        pm_power_off    = nlm_linux_exit;
index 41707a245dea61c1cabd467f2bc3d2ec2ca28cd8..3462c831d0ea5f1b307fcd002645d7b328bc816f 100644 (file)
@@ -134,8 +134,6 @@ void __init plat_mem_setup(void)
 #error invalid SiByte board configuration
 #endif
 
-       panic_timeout = 5;  /* For debug.  */
-
        board_be_handler = swarm_be_handler;
 
        if (xicor_probe())
index 74742dc6a3daabd3ec3a4b2c9c5af03f90d7685c..032143ec23245113fd0394c8a5d26dfc134ea29e 100644 (file)
@@ -1,4 +1,5 @@
 
+generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
diff --git a/arch/mn10300/include/asm/barrier.h b/arch/mn10300/include/asm/barrier.h
deleted file mode 100644 (file)
index 2bd97a5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* MN10300 memory barrier definitions
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_BARRIER_H
-#define _ASM_BARRIER_H
-
-#define nop()  asm volatile ("nop")
-
-#define mb()   asm volatile ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define set_mb(var, value)  do { xchg(&var, value); } while (0)
-#else  /* CONFIG_SMP */
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#endif /* CONFIG_SMP */
-
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-#endif /* _ASM_BARRIER_H */
index ec1b014952b6601458f4c3b2901d8e86670b96fc..acacd348df89bb2f817855e5247e82f731539c6f 100644 (file)
@@ -50,7 +50,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_NS87415=y
-CONFIG_BLK_DEV_SIIMAGE=m
+CONFIG_PATA_SIL680=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
index e1c8d2015c8938ac0a3440d38af427b4ac8eec7a..8249ac9d9cfcc2a2e74d1111ac4b16ac54e67493 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_PA8X00=y
-CONFIG_MLONGCALLS=y
 CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
@@ -81,8 +80,6 @@ CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_PLATFORM=y
 CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
@@ -94,6 +91,8 @@ CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_ISCSI_TCP=m
 CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=y
 CONFIG_FUSION_SAS=y
@@ -114,9 +113,8 @@ CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_CM109=m
 CONFIG_SERIO_SERPORT=m
 CONFIG_SERIO_PARKBD=m
 CONFIG_SERIO_GSCPS2=m
@@ -167,34 +165,6 @@ CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_AD1889=m
 # CONFIG_SND_USB is not set
 # CONFIG_SND_GSC is not set
-CONFIG_HID_A4TECH=m
-CONFIG_HID_APPLE=m
-CONFIG_HID_BELKIN=m
-CONFIG_HID_CHERRY=m
-CONFIG_HID_CHICONY=m
-CONFIG_HID_CYPRESS=m
-CONFIG_HID_DRAGONRISE=m
-CONFIG_HID_EZKEY=m
-CONFIG_HID_KYE=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_TWINHAN=m
-CONFIG_HID_KENSINGTON=m
-CONFIG_HID_LOGITECH=m
-CONFIG_HID_LOGITECH_DJ=m
-CONFIG_HID_MICROSOFT=m
-CONFIG_HID_MONTEREY=m
-CONFIG_HID_NTRIG=m
-CONFIG_HID_ORTEK=m
-CONFIG_HID_PANTHERLORD=m
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_HID_GREENASIA=m
-CONFIG_HID_SMARTJOYPLUS=m
-CONFIG_HID_TOPSEED=m
-CONFIG_HID_THRUSTMASTER=m
-CONFIG_HID_ZEROPLUS=m
-CONFIG_USB_HID=m
 CONFIG_USB=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 5874cebee07701725f3ab9939acb6cd11f1e46f2..28c1b5de044e827d128f3165ea15d807f39ff0b6 100644 (file)
@@ -24,7 +24,6 @@ CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_PA8X00=y
-CONFIG_MLONGCALLS=y
 CONFIG_64BIT=y
 CONFIG_SMP=y
 # CONFIG_COMPACTION is not set
@@ -68,7 +67,6 @@ CONFIG_IDE_GD=m
 CONFIG_IDE_GD_ATAPI=y
 CONFIG_BLK_DEV_IDECD=m
 CONFIG_BLK_DEV_NS87415=y
-CONFIG_BLK_DEV_SIIMAGE=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
@@ -82,6 +80,7 @@ CONFIG_SCSI_ZALON=y
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_DH=y
 CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
 CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_MD_LINEAR=m
@@ -162,7 +161,7 @@ CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
-# CONFIG_INPUT_MOUSE is not set
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_INPUT_MISC=y
 CONFIG_SERIO_SERPORT=m
 # CONFIG_HP_SDC is not set
@@ -216,32 +215,7 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
-CONFIG_HID=m
 CONFIG_HIDRAW=y
-CONFIG_HID_DRAGONRISE=m
-CONFIG_DRAGONRISE_FF=y
-CONFIG_HID_KYE=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_TWINHAN=m
-CONFIG_LOGITECH_FF=y
-CONFIG_LOGIRUMBLEPAD2_FF=y
-CONFIG_HID_NTRIG=m
-CONFIG_HID_PANTHERLORD=m
-CONFIG_PANTHERLORD_FF=y
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SONY=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_HID_GREENASIA=m
-CONFIG_GREENASIA_FF=y
-CONFIG_HID_SMARTJOYPLUS=m
-CONFIG_SMARTJOYPLUS_FF=y
-CONFIG_HID_TOPSEED=m
-CONFIG_HID_THRUSTMASTER=m
-CONFIG_THRUSTMASTER_FF=y
-CONFIG_HID_ZEROPLUS=m
-CONFIG_ZEROPLUS_FF=y
-CONFIG_USB_HID=m
 CONFIG_HID_PID=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
@@ -251,13 +225,8 @@ CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_MON=m
 CONFIG_USB_WUSB_CBAF=m
 CONFIG_USB_XHCI_HCD=m
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_R8A66597_HCD=m
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_WDM=m
-CONFIG_USB_TMC=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGERS=y
index a603b9ebe54ce38c19328ac936059618771a07c0..34b0be4ca52d7728137b4651a55b35b12420c344 100644 (file)
@@ -1,4 +1,5 @@
 
+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 \
diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h
deleted file mode 100644 (file)
index e77d834..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __PARISC_BARRIER_H
-#define __PARISC_BARRIER_H
-
-/*
-** This is simply the barrier() macro from linux/kernel.h but when serial.c
-** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
-** hasn't yet been included yet so it fails, thus repeating the macro here.
-**
-** PA-RISC architecture allows for weakly ordered memory accesses although
-** none of the processors use it. There is a strong ordered bit that is
-** set in the O-bit of the page directory entry. Operating systems that
-** can not tolerate out of order accesses should set this bit when mapping
-** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
-** of the processor implemented the PSW O-bit). The PCX-W ERS states that
-** the TLB O-bit is not implemented so the page directory does not need to
-** have the O-bit set when mapping pages (section 3.1). This section also
-** states that the PSW Y, Z, G, and O bits are not implemented.
-** So it looks like nothing needs to be done for parisc-linux (yet).
-** (thanks to chada for the above comment -ggg)
-**
-** The __asm__ op below simple prevents gcc/ld from reordering
-** instructions across the mb() "call".
-*/
-#define mb()           __asm__ __volatile__("":::"memory")     /* barrier() */
-#define rmb()          mb()
-#define wmb()          mb()
-#define smp_mb()       mb()
-#define smp_rmb()      mb()
-#define smp_wmb()      mb()
-#define smp_read_barrier_depends()     do { } while(0)
-#define read_barrier_depends()         do { } while(0)
-
-#define set_mb(var, value)             do { var = value; mb(); } while (0)
-
-#endif /* __PARISC_BARRIER_H */
index f0e2784e7ccacd6c6d0856ce87d1f1d26e81c083..2f9b751878ba86bf6cc32cfdadd9b7847ad158d5 100644 (file)
@@ -125,42 +125,38 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma
 void mark_rodata_ro(void);
 #endif
 
-#ifdef CONFIG_PA8X00
-/* Only pa8800, pa8900 needs this */
-
 #include <asm/kmap_types.h>
 
 #define ARCH_HAS_KMAP
 
-void kunmap_parisc(void *addr);
-
 static inline void *kmap(struct page *page)
 {
        might_sleep();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void kunmap(struct page *page)
 {
-       kunmap_parisc(page_address(page));
+       flush_kernel_dcache_page_addr(page_address(page));
 }
 
 static inline void *kmap_atomic(struct page *page)
 {
        pagefault_disable();
+       flush_dcache_page(page);
        return page_address(page);
 }
 
 static inline void __kunmap_atomic(void *addr)
 {
-       kunmap_parisc(addr);
+       flush_kernel_dcache_page_addr(addr);
        pagefault_enable();
 }
 
 #define kmap_atomic_prot(page, prot)   kmap_atomic(page)
 #define kmap_atomic_pfn(pfn)   kmap_atomic(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
-#endif
 
 #endif /* _PARISC_CACHEFLUSH_H */
 
index b7adb2ac049c0e6b72817dee3df92d124c612e42..c53fc63149e8312437fe4109e8070495ba39d90a 100644 (file)
@@ -28,9 +28,8 @@ struct page;
 
 void clear_page_asm(void *page);
 void copy_page_asm(void *to, void *from);
-void clear_user_page(void *vto, unsigned long vaddr, struct page *pg);
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-                          struct page *pg);
+#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
+#define copy_user_page(vto, vfrom, vaddr, page) copy_page_asm(vto, vfrom)
 
 /* #define CONFIG_PARISC_TMPALIAS */
 
index d7e3cc60dbc3693a3b8ce475fbd128bb9563a284..77e9b67c87ee1ed382670ec604b067f5b3a99b25 100644 (file)
@@ -6,5 +6,3 @@
  * This is used for 16550-compatible UARTs
  */
 #define BASE_BAUD ( 1843200 / 16 )
-
-#define SERIAL_PORT_DFNS
index f33113a6141e7540da2195cc72469152edfbecf2..70b3674dac4e39c1048b1844dc53dee85f907296 100644 (file)
@@ -75,6 +75,6 @@
 
 #define SO_BUSY_POLL           0x4027
 
-#define SO_MAX_PACING_RATE     0x4048
+#define SO_MAX_PACING_RATE     0x4028
 
 #endif /* _UAPI_ASM_SOCKET_H */
index c035673209f732f0850aaa4dc98d2d49eee3b74c..a72545554a3154c254eace0648a769d4df645b25 100644 (file)
@@ -388,41 +388,6 @@ void flush_kernel_dcache_page_addr(void *addr)
 }
 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
 
-void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
-{
-       clear_page_asm(vto);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(clear_user_page);
-
-void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
-       struct page *pg)
-{
-       /* Copy using kernel mapping.  No coherency is needed
-          (all in kmap/kunmap) on machines that don't support
-          non-equivalent aliasing.  However, the `from' page
-          needs to be flushed before it can be accessed through
-          the kernel mapping. */
-       preempt_disable();
-       flush_dcache_page_asm(__pa(vfrom), vaddr);
-       preempt_enable();
-       copy_page_asm(vto, vfrom);
-       if (!parisc_requires_coherency())
-               flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(copy_user_page);
-
-#ifdef CONFIG_PA8X00
-
-void kunmap_parisc(void *addr)
-{
-       if (parisc_requires_coherency())
-               flush_kernel_dcache_page_addr(addr);
-}
-EXPORT_SYMBOL(kunmap_parisc);
-#endif
-
 void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 {
        unsigned long flags;
index 06cb3992907e67e9847b84259e5a61f3e42c2b71..608716f8496bf8dfe0acc08a71a15807ce20c557 100644 (file)
@@ -36,6 +36,9 @@
  *     HP PARISC Hardware Database
  *     Access to this database is only possible during bootup
  *     so don't reference this table after starting the init process
+ *
+ *     NOTE: Product names which are listed here and ends with a '?'
+ *     are guessed. If you know the correct name, please let us know.
  */
  
 static struct hp_hardware hp_hardware_list[] = {
@@ -222,7 +225,7 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
        {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
        {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
-       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+? (rp5470)"},
+       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+ (rp5470)?"},
        {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
        {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
        {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
@@ -276,9 +279,11 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"},
        {HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"},
        {HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak Slow"},
+       {HPHW_NPROC,0x88B,0x4,0x91,"Crestone Peak Fast?"},
        {HPHW_NPROC,0x88C,0x4,0x91,"Orca Mako+"},
        {HPHW_NPROC,0x88D,0x4,0x91,"Rainier/Medel Mako+ Slow"},
        {HPHW_NPROC,0x88E,0x4,0x91,"Rainier/Medel Mako+ Fast"},
+       {HPHW_NPROC,0x892,0x4,0x91,"Mt. Hamilton Slow Mako+?"},
        {HPHW_NPROC,0x894,0x4,0x91,"Mt. Hamilton Fast Mako+"},
        {HPHW_NPROC,0x895,0x4,0x91,"Storm Peak Slow Mako+"},
        {HPHW_NPROC,0x896,0x4,0x91,"Storm Peak Fast Mako+"},
index d2d58258aea68084c4f09cc6012a741b838b22d5..d4dc588c0dc1f6963f99e6545de14031192d4543 100644 (file)
@@ -41,9 +41,7 @@ END(boot_args)
         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
        .import $global$                /* forward declaration */
 #endif /*!CONFIG_64BIT*/
-       .export _stext,data             /* Kernel want it this way! */
-_stext:
-ENTRY(stext)
+ENTRY(parisc_kernel_start)
        .proc
        .callinfo
 
@@ -347,7 +345,7 @@ smp_slave_stext:
        .procend
 #endif /* CONFIG_SMP */
 
-ENDPROC(stext)
+ENDPROC(parisc_kernel_start)
 
 #ifndef CONFIG_64BIT
        .section .data..read_mostly
index 5dfd248e3f1a84fd6dbd961bf278002338cba4b0..0d3a9d4927b58009bfe0c4dc4114585409ddd2f5 100644 (file)
@@ -61,8 +61,15 @@ static int get_offset(struct address_space *mapping)
        return (unsigned long) mapping >> 8;
 }
 
-static unsigned long get_shared_area(struct address_space *mapping,
-               unsigned long addr, unsigned long len, unsigned long pgoff)
+static unsigned long shared_align_offset(struct file *filp, unsigned long pgoff)
+{
+       struct address_space *mapping = filp ? filp->f_mapping : NULL;
+
+       return (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+}
+
+static unsigned long get_shared_area(struct file *filp, unsigned long addr,
+               unsigned long len, unsigned long pgoff)
 {
        struct vm_unmapped_area_info info;
 
@@ -71,7 +78,7 @@ static unsigned long get_shared_area(struct address_space *mapping,
        info.low_limit = PAGE_ALIGN(addr);
        info.high_limit = TASK_SIZE;
        info.align_mask = PAGE_MASK & (SHMLBA - 1);
-       info.align_offset = (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+       info.align_offset = shared_align_offset(filp, pgoff);
        return vm_unmapped_area(&info);
 }
 
@@ -82,20 +89,18 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                return -ENOMEM;
        if (flags & MAP_FIXED) {
                if ((flags & MAP_SHARED) &&
-                   (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+                   (addr - shared_align_offset(filp, pgoff)) & (SHMLBA - 1))
                        return -EINVAL;
                return addr;
        }
        if (!addr)
                addr = TASK_UNMAPPED_BASE;
 
-       if (filp) {
-               addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
-       } else if(flags & MAP_SHARED) {
-               addr = get_shared_area(NULL, addr, len, pgoff);
-       } else {
+       if (filp || (flags & MAP_SHARED))
+               addr = get_shared_area(filp, addr, len, pgoff);
+       else
                addr = get_unshared_area(addr, len);
-       }
+
        return addr;
 }
 
index 76ed62ed785b6f4be9c1a6e663101ff3daeb6aa7..ddd988b267a9ddde0e9d2433f87e036f41e9d2a1 100644 (file)
@@ -168,7 +168,7 @@ void unwind_table_remove(struct unwind_table *table)
 }
 
 /* Called from setup_arch to import the kernel unwind info */
-int unwind_init(void)
+int __init unwind_init(void)
 {
        long start, stop;
        register unsigned long gp __asm__ ("r27");
@@ -233,7 +233,6 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
        e = find_unwind_entry(info->ip);
        if (e == NULL) {
                unsigned long sp;
-               extern char _stext[], _etext[];
 
                dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
 
@@ -281,8 +280,7 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
                                break;
                        info->prev_ip = tmp;
                        sp = info->prev_sp;
-               } while (info->prev_ip < (unsigned long)_stext ||
-                        info->prev_ip > (unsigned long)_etext);
+               } while (!kernel_text_address(info->prev_ip));
 
                info->rp = 0;
 
@@ -435,9 +433,8 @@ unsigned long return_address(unsigned int level)
        do {
                if (unwind_once(&info) < 0 || info.ip == 0)
                        return 0;
-               if (!__kernel_text_address(info.ip)) {
+               if (!kernel_text_address(info.ip))
                        return 0;
-               }
        } while (info.ip && level--);
 
        return info.ip;
index 4bb095a2f6fc2266388723cbb2634518a9570e44..0dacc5ca555afe7643da970bf9f3ae75ebc88790 100644 (file)
@@ -6,24 +6,19 @@
  *    Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *    Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
- *    Copyright (C) 2006 Helge Deller <deller@gmx.de>
- *
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *    Copyright (C) 2006-2013 Helge Deller <deller@gmx.de>
+ */
+
+/*
+ * Put page table entries (swapper_pg_dir) as the first thing in .bss. This
+ * will ensure that it has .bss alignment (PAGE_SIZE).
  */
+#define BSS_FIRST_SECTIONS     *(.data..vm0.pmd) \
+                               *(.data..vm0.pgd) \
+                               *(.data..vm0.pte)
+
 #include <asm-generic/vmlinux.lds.h>
+
 /* needed for the processor specific cache alignment size */   
 #include <asm/cache.h>
 #include <asm/page.h>
@@ -39,7 +34,7 @@ OUTPUT_FORMAT("elf64-hppa-linux")
 OUTPUT_ARCH(hppa:hppa2.0w)
 #endif
 
-ENTRY(_stext)
+ENTRY(parisc_kernel_start)
 #ifndef CONFIG_64BIT
 jiffies = jiffies_64 + 4;
 #else
@@ -49,11 +44,29 @@ SECTIONS
 {
        . = KERNEL_BINARY_TEXT_START;
 
+       __init_begin = .;
+       HEAD_TEXT_SECTION
+       INIT_TEXT_SECTION(8)
+
+       . = ALIGN(PAGE_SIZE);
+       INIT_DATA_SECTION(PAGE_SIZE)
+       /* we have to discard exit text and such at runtime, not link time */
+       .exit.text :
+       {
+               EXIT_TEXT
+       }
+       .exit.data :
+       {
+               EXIT_DATA
+       }
+       PERCPU_SECTION(8)
+       . = ALIGN(PAGE_SIZE);
+       __init_end = .;
+       /* freed after init ends here */
+
        _text = .;              /* Text and read-only data */
-       .head ALIGN(16) : {
-               HEAD_TEXT
-       } = 0
-       .text ALIGN(16) : {
+       _stext = .;
+       .text ALIGN(PAGE_SIZE) : {
                TEXT_TEXT
                SCHED_TEXT
                LOCK_TEXT
@@ -68,21 +81,28 @@ SECTIONS
                *(.lock.text)           /* out-of-line lock text */
                *(.gnu.warning)
        }
-       /* End of text section */
+       . = ALIGN(PAGE_SIZE);
        _etext = .;
+       /* End of text section */
 
        /* Start of data section */
        _sdata = .;
 
-       RODATA
+       RO_DATA_SECTION(8)
 
-       /* writeable */
-       /* Make sure this is page aligned so
-        * that we can properly leave these
-        * as writable
-        */
-       . = ALIGN(PAGE_SIZE);
-       data_start = .;
+#ifdef CONFIG_64BIT
+       . = ALIGN(16);
+       /* Linkage tables */
+       .opd : {
+               *(.opd)
+       } PROVIDE (__gp = .);
+       .plt : {
+               *(.plt)
+       }
+       .dlt : {
+               *(.dlt)
+       }
+#endif
 
        /* unwind info */
        .PARISC.unwind : {
@@ -91,7 +111,15 @@ SECTIONS
                __stop___unwind = .;
        }
 
-       EXCEPTION_TABLE(16)
+       /* writeable */
+       /* Make sure this is page aligned so
+        * that we can properly leave these
+        * as writable
+        */
+       . = ALIGN(PAGE_SIZE);
+       data_start = .;
+
+       EXCEPTION_TABLE(8)
        NOTES
 
        /* Data */
@@ -107,54 +135,8 @@ SECTIONS
        _edata = .;
 
        /* BSS */
-       __bss_start = .;
-       /* page table entries need to be PAGE_SIZE aligned */
-       . = ALIGN(PAGE_SIZE);
-       .data..vmpages : {
-               *(.data..vm0.pmd)
-               *(.data..vm0.pgd)
-               *(.data..vm0.pte)
-       }
-       .bss : {
-               *(.bss)
-               *(COMMON)
-       }
-       __bss_stop = .;
-
-#ifdef CONFIG_64BIT
-       . = ALIGN(16);
-       /* Linkage tables */
-       .opd : {
-               *(.opd)
-       } PROVIDE (__gp = .); 
-       .plt : {
-               *(.plt)
-       } 
-       .dlt : {
-               *(.dlt)
-       }
-#endif
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 8)
 
-       /* reserve space for interrupt stack by aligning __init* to 16k */
-       . = ALIGN(16384);
-       __init_begin = .;
-       INIT_TEXT_SECTION(16384)
-       . = ALIGN(PAGE_SIZE);
-       INIT_DATA_SECTION(16)
-       /* we have to discard exit text and such at runtime, not link time */
-       .exit.text :
-       {
-               EXIT_TEXT
-       }
-       .exit.data :
-       {
-               EXIT_DATA
-       }
-
-       PERCPU_SECTION(L1_CACHE_BYTES)
-       . = ALIGN(PAGE_SIZE);
-       __init_end = .;
-       /* freed after init ends here */
        _end = . ;
 
        STABS_DEBUG
index b0f96c0e6316f15531afb2a5a2a0e4684d1892a8..96f8168cf4ec1d9d50aad70ae17f54110a2c1527 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/sections.h>
 
 extern int  data_start;
+extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
 
 #if PT_NLEVELS == 3
 /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
@@ -324,8 +325,9 @@ static void __init setup_bootmem(void)
        reserve_bootmem_node(NODE_DATA(0), 0UL,
                        (unsigned long)(PAGE0->mem_free +
                                PDC_CONSOLE_IO_IODC_SIZE), BOOTMEM_DEFAULT);
-       reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
-                       (unsigned long)(_end - _text), BOOTMEM_DEFAULT);
+       reserve_bootmem_node(NODE_DATA(0), __pa(KERNEL_BINARY_TEXT_START),
+                       (unsigned long)(_end - KERNEL_BINARY_TEXT_START),
+                       BOOTMEM_DEFAULT);
        reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
                        ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT),
                        BOOTMEM_DEFAULT);
@@ -378,6 +380,17 @@ static void __init setup_bootmem(void)
        request_resource(&sysram_resources[0], &pdcdata_resource);
 }
 
+static int __init parisc_text_address(unsigned long vaddr)
+{
+       static unsigned long head_ptr __initdata;
+
+       if (!head_ptr)
+               head_ptr = PAGE_MASK & (unsigned long)
+                       dereference_function_descriptor(&parisc_kernel_start);
+
+       return core_kernel_text(vaddr) || vaddr == head_ptr;
+}
+
 static void __init map_pages(unsigned long start_vaddr,
                             unsigned long start_paddr, unsigned long size,
                             pgprot_t pgprot, int force)
@@ -466,7 +479,7 @@ static void __init map_pages(unsigned long start_vaddr,
                                 */
                                if (force)
                                        pte =  __mk_pte(address, pgprot);
-                               else if (core_kernel_text(vaddr) &&
+                               else if (parisc_text_address(vaddr) &&
                                         address != fv_addr)
                                        pte = __mk_pte(address, PAGE_KERNEL_EXEC);
                                else
index b44b52c0a8f07d2854d5a21ca6fb2ecf409409c1..b2be8e8cb5c71471864e9fafebf6a475cab67bec 100644 (file)
@@ -147,6 +147,10 @@ config EARLY_PRINTK
        bool
        default y
 
+config PANIC_TIMEOUT
+       int
+       default 180
+
 config COMPAT
        bool
        default y if PPC64
index bd14c00e5146b31a90c8913e2b605c06d40184f1..2d7cb04ac962ba3cfed781f408646d7669e50d7d 100644 (file)
@@ -77,7 +77,6 @@
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     /* 66 MHz ips bus */
index 4177b62240c2440ff19f6089cb84cd5b9e0d27a0..a618dfc13e4c8f88a5ff70b88325fd39675c9e8a 100644 (file)
@@ -58,7 +58,6 @@
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     // 66 MHz ips bus
                        reg = <0xA000 0x1000>;
                };
 
+               // disable USB1 port
+               // TODO:
+               // correct pinmux config and fix USB3320 ulpi dependency
+               // before re-enabling it
                usb@3000 {
                        compatible = "fsl,mpc5121-usb2-dr";
                        reg = <0x3000 0x400>;
                        interrupts = <43 0x8>;
                        dr_mode = "host";
                        phy_type = "ulpi";
+                       status = "disabled";
                };
 
                // 5125 PSCs are not 52xx or 5121 PSC compatible
index 69b57daf402e056d0739e4ec50303f8349b78c0d..0b88c7b30bb9a4a5697cc87fe8fd6486bfca6bf4 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_EXPERT=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
@@ -71,6 +70,8 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index f3638ae0a627ceb6c481dae4bbc588616864548c..104a332e79ab961f2881776ea0ca80539b4444b7 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_LITE5200=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SPARSE_IRQ=y
@@ -59,6 +58,8 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 0c7de9620ea64a1715a836866c244dc1317e38d4..0d13ad7e44782fdf9adafa6f3a82231920048c98 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_EXPERT=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
@@ -84,6 +83,8 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 22e719575c60b33cb64cee5fcb840c2507f942c8..430aa182fa1ceab8f53ca6af410ca39772095f3b 100644 (file)
@@ -21,7 +21,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_HZ_100=y
@@ -87,6 +86,8 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 716a37be16e33b5d071416592ca8eb39fc7cca2f..7af4c5bb7c63b30d23a058d885a26cbe40b179ee 100644 (file)
@@ -17,7 +17,6 @@ CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -86,6 +85,8 @@ CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_DS1374=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 6640a35bebb7ac74d88d63f5c4420510088e088a..8b682d1cf4d6c49e90f83182db293fc6f1db6264 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_PPC_MEDIA5200=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 CONFIG_PPC_MPC5200_LPBFIFO=m
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SIMPLE_GPIO=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -125,6 +124,8 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index bd8a6f71944f153367df2312fa121ed97977ce27..cec044a3ff69dd6c05dcfec122fcb53653b412f8 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_PPC64=y
 CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -45,8 +44,9 @@ CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_SLRAM=y
 CONFIG_MTD_PHRAM=y
@@ -88,7 +88,6 @@ CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_MII=y
 CONFIG_TIGON3=y
 CONFIG_E1000=y
 CONFIG_PASEMI_MAC=y
@@ -174,8 +173,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_CRC_CCITT=y
 CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
index ae782254e731bbcd03c8152379b4adf6ddea01a7..f89da808ce310e1f373da55e96fc52d58bd4ccc9 100644 (file)
 #    define SMPWMB      eieio
 #endif
 
+#define __lwsync()     __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+
 #define smp_mb()       mb()
-#define smp_rmb()      __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+#define smp_rmb()      __lwsync()
 #define smp_wmb()      __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
 #define smp_read_barrier_depends()     read_barrier_depends()
 #else
+#define __lwsync()     barrier()
+
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
 #define smp_wmb()      barrier()
 #define data_barrier(x)        \
        asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
 
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       __lwsync();                                                     \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       __lwsync();                                                     \
+       ___p1;                                                          \
+})
+
 #endif /* _ASM_POWERPC_BARRIER_H */
index 894662a5d4d5c5aa25f43e30653609d80d901774..243ce69ad685ffd335041537e6f0b33b0aafe3df 100644 (file)
@@ -284,7 +284,7 @@ do_kvm_##n:                                                         \
        subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
        beq-    1f;                                                        \
        ld      r1,PACAKSAVE(r13);      /* kernel stack to use          */ \
-1:     cmpdi   cr1,r1,0;               /* check if r1 is in userspace  */ \
+1:     cmpdi   cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace  */ \
        blt+    cr1,3f;                 /* abort if it is               */ \
        li      r1,(n);                 /* will be reloaded later       */ \
        sth     r1,PACA_TRAP_SAVE(r13);                                    \
index 4a594b76674d4e536ce714b40c183f598bf380d6..bc23b1ba798068b1c5a1f21e93da8bd47018ff55 100644 (file)
@@ -192,6 +192,10 @@ extern void kvmppc_load_up_vsx(void);
 extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst);
 extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst);
 extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd);
+extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
+                                struct kvm_vcpu *vcpu);
+extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
+                                  struct kvmppc_book3s_shadow_vcpu *svcpu);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
index 0bd9348a4db91264d5e8a104f17ed77afcd5f815..192917d2239c4ed5a0eafd36b1206d176f0dddaa 100644 (file)
@@ -79,6 +79,7 @@ struct kvmppc_host_state {
        ulong vmhandler;
        ulong scratch0;
        ulong scratch1;
+       ulong scratch2;
        u8 in_guest;
        u8 restore_hid5;
        u8 napping;
@@ -106,6 +107,7 @@ struct kvmppc_host_state {
 };
 
 struct kvmppc_book3s_shadow_vcpu {
+       bool in_use;
        ulong gpr[14];
        u32 cr;
        u32 xer;
index 033c06be1d840da02423d596121940d0aa11adb5..7bdcf340016c412285df77ac56162aaa94982416 100644 (file)
@@ -720,13 +720,13 @@ 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, uint64_t *val);
+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_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
                       uint32_t addr, uint32_t data, uint32_t sz);
 int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type,
-                     uint32_t addr, uint32_t *data, uint32_t sz);
+                     uint32_t addr, __be32 *data, uint32_t sz);
 int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
index 27b2386f738a681fbea5a305b958e3681374df35..842846c1b71185b1a5e086e8521ed65342ae9cb0 100644 (file)
@@ -84,10 +84,8 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       struct page *page = page_address(table);
-
        tlb_flush_pgtable(tlb, address);
-       pgtable_page_dtor(page);
-       pgtable_free_tlb(tlb, page, 0);
+       pgtable_page_dtor(table);
+       pgtable_free_tlb(tlb, page_address(table), 0);
 }
 #endif /* _ASM_POWERPC_PGALLOC_32_H */
index 694012877bf7f1cfd1e1ea067b448f7e7c449e87..4b0be20fcbfdeee22498ea67f7a6b2adb3b55213 100644 (file)
@@ -148,11 +148,9 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       struct page *page = page_address(table);
-
        tlb_flush_pgtable(tlb, address);
-       pgtable_page_dtor(page);
-       pgtable_free_tlb(tlb, page, 0);
+       pgtable_page_dtor(table);
+       pgtable_free_tlb(tlb, page_address(table), 0);
 }
 
 #else /* if CONFIG_PPC_64K_PAGES */
index 703a8412dac28e2a567b4d1b4da5586ae890c34a..11ba86e176315e4ef260c8eb740ba52ca347c192 100644 (file)
@@ -26,6 +26,7 @@ extern void reloc_got2(unsigned long);
 void check_for_initrd(void);
 void do_init_bootmem(void);
 void setup_panic(void);
+#define ARCH_PANIC_TIMEOUT 180
 
 #endif /* !__ASSEMBLY__ */
 
index 5f54a744dcc5e26921ddafe1d267985f71dd8540..f6e78d63fb6accd584e71cd5ebe7b26c5dae2916 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
 
+#define smp_mb__after_unlock_lock()    smp_mb()  /* Full ordering for lock. */
+
 #define arch_spin_is_locked(x)         ((x)->slock != 0)
 
 #ifdef CONFIG_PPC64
index 9ee12610af02bdca7fd61b9b7f6b16f2c74d36d0..aace90547614db30ea638945d30d143fbdfb336e 100644 (file)
@@ -35,7 +35,7 @@ extern void giveup_vsx(struct task_struct *);
 extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
-extern void switch_booke_debug_regs(struct thread_struct *new_thread);
+extern void switch_booke_debug_regs(struct debug_reg *new_debug);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
index 5f1b1e3c21374d5a1833ed00c9af9d5c06a35123..8296381ae43294e679976f6a82d3bb936d64921f 100644 (file)
@@ -4,13 +4,18 @@
 #ifdef __KERNEL__
 
 /*
- * The PowerPC can do unaligned accesses itself in big endian mode.
+ * The PowerPC can do unaligned accesses itself based on its endian mode.
  */
 #include <linux/unaligned/access_ok.h>
 #include <linux/unaligned/generic.h>
 
+#ifdef __LITTLE_ENDIAN__
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
+#else
 #define get_unaligned  __get_unaligned_be
 #define put_unaligned  __put_unaligned_be
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UNALIGNED_H */
index 75c6ecdb8f3728a175bd61808cad34a9689fd47e..7422a999a39a5bfd8edbd674905417951a792a25 100644 (file)
@@ -36,9 +36,8 @@ typedef ppc_opcode_t uprobe_opcode_t;
 
 struct arch_uprobe {
        union {
-               u8      insn[MAX_UINSN_BYTES];
-               u8      ixol[MAX_UINSN_BYTES];
-               u32     ainsn;
+               u32     insn;
+               u32     ixol;
        };
 };
 
index 2ea5cc033ec8b633febb50071c43cfd31958f4f3..d3de01066f7dd786cd531614046b801ff7ebb18f 100644 (file)
@@ -576,6 +576,7 @@ int main(void)
        HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
        HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
        HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+       HSTATE_FIELD(HSTATE_SCRATCH2, scratch2);
        HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
        HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
        HSTATE_FIELD(HSTATE_NAPPING, napping);
index 779a78c2643502a4414af7d646f4dce810deba72..11c1d069d920a1fc97ec601ab0542c41708d7cc1 100644 (file)
@@ -124,15 +124,15 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
 void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
 {
        unsigned long addr;
-       const u32 *basep, *sizep;
+       const __be32 *basep, *sizep;
        unsigned int rtas_start = 0, rtas_end = 0;
 
        basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
        sizep = of_get_property(rtas.dev, "rtas-size", NULL);
 
        if (basep && sizep) {
-               rtas_start = *basep;
-               rtas_end = *basep + *sizep;
+               rtas_start = be32_to_cpup(basep);
+               rtas_end = rtas_start + be32_to_cpup(sizep);
        }
 
        for (addr = begin; addr < end; addr += PAGE_SIZE) {
index 2ae41aba40530f7facf916f6ce101ad3196a7363..4f0946de2d5c917540f6f51a50c13640011fea8c 100644 (file)
@@ -80,6 +80,7 @@ END_FTR_SECTION(0, 1)
         * of the function that the cpu should jump to to continue
         * initialization.
         */
+       .balign 8
        .globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
        .llong  0x0
@@ -470,6 +471,7 @@ _STATIC(__after_prom_start)
        mtctr   r8
        bctr
 
+.balign 8
 p_end: .llong  _end - _stext
 
 4:     /* Now copy the rest of the kernel up to _end */
index 88a7fb458dfd50f0201d269d8177007cc382c62d..75d4f7340da893bc2825f97dda750409d8963323 100644 (file)
@@ -148,7 +148,7 @@ void __init reserve_crashkernel(void)
                 * a small SLB (128MB) since the crash kernel needs to place
                 * itself and some stacks to be in the first segment.
                 */
-               crashk_res.start = min(0x80000000ULL, (ppc64_rma_size / 2));
+               crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
 #else
                crashk_res.start = KDUMP_KERNELBASE;
 #endif
index e59caf874d05ed60e500579b06bfcdf38bd85125..64bf8db12b15be3e8dbc903b6c8bb27173940fc1 100644 (file)
@@ -246,8 +246,8 @@ _GLOBAL(__bswapdi2)
        or      r3,r7,r9
        blr
 
-#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
 _GLOBAL(rmci_on)
        sync
        isync
@@ -277,6 +277,9 @@ _GLOBAL(rmci_off)
        isync
        sync
        blr
+#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
+
+#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 
 /*
  * Do an IO access in real mode
index 3386d8ab7eb0607b3c9d6f03e68824d4abe4bd88..4a96556fd2d49e484c143ed3643db6c8a24962df 100644 (file)
@@ -339,7 +339,7 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 #endif
 }
 
-static void prime_debug_regs(struct thread_struct *thread)
+static void prime_debug_regs(struct debug_reg *debug)
 {
        /*
         * We could have inherited MSR_DE from userspace, since
@@ -348,22 +348,22 @@ static void prime_debug_regs(struct thread_struct *thread)
         */
        mtmsr(mfmsr() & ~MSR_DE);
 
-       mtspr(SPRN_IAC1, thread->debug.iac1);
-       mtspr(SPRN_IAC2, thread->debug.iac2);
+       mtspr(SPRN_IAC1, debug->iac1);
+       mtspr(SPRN_IAC2, debug->iac2);
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
-       mtspr(SPRN_IAC3, thread->debug.iac3);
-       mtspr(SPRN_IAC4, thread->debug.iac4);
+       mtspr(SPRN_IAC3, debug->iac3);
+       mtspr(SPRN_IAC4, debug->iac4);
 #endif
-       mtspr(SPRN_DAC1, thread->debug.dac1);
-       mtspr(SPRN_DAC2, thread->debug.dac2);
+       mtspr(SPRN_DAC1, debug->dac1);
+       mtspr(SPRN_DAC2, debug->dac2);
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-       mtspr(SPRN_DVC1, thread->debug.dvc1);
-       mtspr(SPRN_DVC2, thread->debug.dvc2);
+       mtspr(SPRN_DVC1, debug->dvc1);
+       mtspr(SPRN_DVC2, debug->dvc2);
 #endif
-       mtspr(SPRN_DBCR0, thread->debug.dbcr0);
-       mtspr(SPRN_DBCR1, thread->debug.dbcr1);
+       mtspr(SPRN_DBCR0, debug->dbcr0);
+       mtspr(SPRN_DBCR1, debug->dbcr1);
 #ifdef CONFIG_BOOKE
-       mtspr(SPRN_DBCR2, thread->debug.dbcr2);
+       mtspr(SPRN_DBCR2, debug->dbcr2);
 #endif
 }
 /*
@@ -371,11 +371,11 @@ static void prime_debug_regs(struct thread_struct *thread)
  * debug registers, set the debug registers from the values
  * stored in the new thread.
  */
-void switch_booke_debug_regs(struct thread_struct *new_thread)
+void switch_booke_debug_regs(struct debug_reg *new_debug)
 {
        if ((current->thread.debug.dbcr0 & DBCR0_IDM)
-               || (new_thread->debug.dbcr0 & DBCR0_IDM))
-                       prime_debug_regs(new_thread);
+               || (new_debug->dbcr0 & DBCR0_IDM))
+                       prime_debug_regs(new_debug);
 }
 EXPORT_SYMBOL_GPL(switch_booke_debug_regs);
 #else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
@@ -683,7 +683,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-       switch_booke_debug_regs(&new->thread);
+       switch_booke_debug_regs(&new->thread.debug);
 #else
 /*
  * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would
index cb64a6e1dc5186918b4d2052e52e961cfb14eedb..078145acf7fb867dca6278f776a935ba0b2ecf25 100644 (file)
@@ -1986,19 +1986,23 @@ static void __init prom_init_stdout(void)
        /* Get the full OF pathname of the stdout device */
        memset(path, 0, 256);
        call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
-       stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
-       val = cpu_to_be32(stdout_node);
-       prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
-                    &val, sizeof(val));
        prom_printf("OF stdout device is: %s\n", of_stdout_device);
        prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
                     path, strlen(path) + 1);
 
-       /* If it's a display, note it */
-       memset(type, 0, sizeof(type));
-       prom_getprop(stdout_node, "device_type", type, sizeof(type));
-       if (strcmp(type, "display") == 0)
-               prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
+       /* instance-to-package fails on PA-Semi */
+       stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
+       if (stdout_node != PROM_ERROR) {
+               val = cpu_to_be32(stdout_node);
+               prom_setprop(prom.chosen, "/chosen", "linux,stdout-package",
+                            &val, sizeof(val));
+
+               /* If it's a display, note it */
+               memset(type, 0, sizeof(type));
+               prom_getprop(stdout_node, "device_type", type, sizeof(type));
+               if (strcmp(type, "display") == 0)
+                       prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
+       }
 }
 
 static int __init prom_find_machine_type(void)
index 75fb40498b419c3e8c1f2c639acfaa4f61f419d2..2e3d2bf536c5662c00f02e07cf36cd1e4b111825 100644 (file)
@@ -1555,7 +1555,7 @@ long arch_ptrace(struct task_struct *child, long request,
 
                        flush_fp_to_thread(child);
                        if (fpidx < (PT_FPSCR - PT_FPR0))
-                               memcpy(&tmp, &child->thread.fp_state.fpr,
+                               memcpy(&tmp, &child->thread.TS_FPR(fpidx),
                                       sizeof(long));
                        else
                                tmp = child->thread.fp_state.fpscr;
@@ -1588,7 +1588,7 @@ long arch_ptrace(struct task_struct *child, long request,
 
                        flush_fp_to_thread(child);
                        if (fpidx < (PT_FPSCR - PT_FPR0))
-                               memcpy(&child->thread.fp_state.fpr, &data,
+                               memcpy(&child->thread.TS_FPR(fpidx), &data,
                                       sizeof(long));
                        else
                                child->thread.fp_state.fpscr = data;
index febc80445d25850acf2578943c60357d8436b1c2..bc76cc6b419c2a8d0b5491637afadfe046278142 100644 (file)
@@ -479,7 +479,7 @@ void __init smp_setup_cpu_maps(void)
        if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
            (dn = of_find_node_by_path("/rtas"))) {
                int num_addr_cell, num_size_cell, maxcpus;
-               const unsigned int *ireg;
+               const __be32 *ireg;
 
                num_addr_cell = of_n_addr_cells(dn);
                num_size_cell = of_n_size_cells(dn);
@@ -489,7 +489,7 @@ void __init smp_setup_cpu_maps(void)
                if (!ireg)
                        goto out;
 
-               maxcpus = ireg[num_addr_cell + num_size_cell];
+               maxcpus = be32_to_cpup(ireg + num_addr_cell + num_size_cell);
 
                /* Double maxcpus for processors which have SMT capability */
                if (cpu_has_feature(CPU_FTR_SMT))
index b903dc5cf944aee99fc36629fdb974f3e26b6888..2b0da27eaee4242f156d37bfbb4efa06bad334df 100644 (file)
@@ -296,9 +296,6 @@ void __init setup_arch(char **cmdline_p)
        if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
                ucache_bsize = icache_bsize = dcache_bsize;
 
-       /* reboot on panic */
-       panic_timeout = 180;
-
        if (ppc_md.panic)
                setup_panic();
 
index 4085aaa9478fd90eff1f1ce149d661bc7488284f..856dd4e99bfe459cdb430f5cba6fbc0b3229be89 100644 (file)
@@ -588,9 +588,6 @@ void __init setup_arch(char **cmdline_p)
        dcache_bsize = ppc64_caches.dline_size;
        icache_bsize = ppc64_caches.iline_size;
 
-       /* reboot on panic */
-       panic_timeout = 180;
-
        if (ppc_md.panic)
                setup_panic();
 
index a3b64f3bf9a298b057cfdc57b008ea01eebecf63..c1cf4a1522d9940bf3bb97a3e995a2642dee41ca 100644 (file)
@@ -580,7 +580,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 int cpu_to_core_id(int cpu)
 {
        struct device_node *np;
-       const int *reg;
+       const __be32 *reg;
        int id = -1;
 
        np = of_get_cpu_node(cpu, NULL);
@@ -591,7 +591,7 @@ int cpu_to_core_id(int cpu)
        if (!reg)
                goto out;
 
-       id = *reg;
+       id = be32_to_cpup(reg);
 out:
        of_node_put(np);
        return id;
index 59f419b935f2501653379fd099b2b1b731a4e7d9..003b20964ea0dfa435af8e1aac8fadde534f1fc2 100644 (file)
@@ -186,7 +186,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
         * emulate_step() returns 1 if the insn was successfully emulated.
         * For all other cases, we need to single-step in hardware.
         */
-       ret = emulate_step(regs, auprobe->ainsn);
+       ret = emulate_step(regs, auprobe->insn);
        if (ret > 0)
                return true;
 
index f3ff587a8b7d58e064e6364606e98a0e6473f106..c5d148434c08197034eba8ababd951176adb6a1f 100644 (file)
@@ -469,11 +469,14 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
                slb_v = vcpu->kvm->arch.vrma_slb_v;
        }
 
+       preempt_disable();
        /* Find the HPTE in the hash table */
        index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
                                         HPTE_V_VALID | HPTE_V_ABSENT);
-       if (index < 0)
+       if (index < 0) {
+               preempt_enable();
                return -ENOENT;
+       }
        hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
        v = hptep[0] & ~HPTE_V_HVLOCK;
        gr = kvm->arch.revmap[index].guest_rpte;
@@ -481,6 +484,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        /* Unlock the HPTE */
        asm volatile("lwsync" : : : "memory");
        hptep[0] = v;
+       preempt_enable();
 
        gpte->eaddr = eaddr;
        gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
@@ -665,6 +669,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        return -EFAULT;
        } else {
                page = pages[0];
+               pfn = page_to_pfn(page);
                if (PageHuge(page)) {
                        page = compound_head(page);
                        pte_size <<= compound_order(page);
@@ -689,7 +694,6 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        }
                        rcu_read_unlock_sched();
                }
-               pfn = page_to_pfn(page);
        }
 
        ret = -EFAULT;
@@ -707,8 +711,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                r = (r & ~(HPTE_R_W|HPTE_R_I|HPTE_R_G)) | HPTE_R_M;
        }
 
-       /* Set the HPTE to point to pfn */
-       r = (r & ~(HPTE_R_PP0 - pte_size)) | (pfn << PAGE_SHIFT);
+       /*
+        * Set the HPTE to point to pfn.
+        * Since the pfn is at PAGE_SIZE granularity, make sure we
+        * don't mask out lower-order bits if psize < PAGE_SIZE.
+        */
+       if (psize < PAGE_SIZE)
+               psize = PAGE_SIZE;
+       r = (r & ~(HPTE_R_PP0 - psize)) | ((pfn << PAGE_SHIFT) & ~(psize - 1));
        if (hpte_is_writable(r) && !write_ok)
                r = hpte_make_readonly(r);
        ret = RESUME_GUEST;
index 072287f1c3bc7347b6ff4f959843c97053fa4aa1..b51d5db780684ea5dcb3b6dae5c5bc70224dca43 100644 (file)
@@ -131,8 +131,9 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
 static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE &&
            vc->preempt_tb != TB_NIL) {
                vc->stolen_tb += mftb() - vc->preempt_tb;
@@ -143,19 +144,20 @@ static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
                vcpu->arch.busy_stolen += mftb() - vcpu->arch.busy_preempt;
                vcpu->arch.busy_preempt = TB_NIL;
        }
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       unsigned long flags;
 
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE)
                vc->preempt_tb = mftb();
        if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
                vcpu->arch.busy_preempt = mftb();
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irqrestore(&vcpu->arch.tbacct_lock, flags);
 }
 
 static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
@@ -486,11 +488,11 @@ static u64 vcore_stolen_time(struct kvmppc_vcore *vc, u64 now)
         */
        if (vc->vcore_state != VCORE_INACTIVE &&
            vc->runner->arch.run_task != current) {
-               spin_lock(&vc->runner->arch.tbacct_lock);
+               spin_lock_irq(&vc->runner->arch.tbacct_lock);
                p = vc->stolen_tb;
                if (vc->preempt_tb != TB_NIL)
                        p += now - vc->preempt_tb;
-               spin_unlock(&vc->runner->arch.tbacct_lock);
+               spin_unlock_irq(&vc->runner->arch.tbacct_lock);
        } else {
                p = vc->stolen_tb;
        }
@@ -512,10 +514,10 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
        core_stolen = vcore_stolen_time(vc, now);
        stolen = core_stolen - vcpu->arch.stolen_logged;
        vcpu->arch.stolen_logged = core_stolen;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        stolen += vcpu->arch.busy_stolen;
        vcpu->arch.busy_stolen = 0;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        if (!dt || !vpa)
                return;
        memset(dt, 0, sizeof(struct dtl_entry));
@@ -589,7 +591,9 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                if (list_empty(&vcpu->kvm->arch.rtas_tokens))
                        return RESUME_HOST;
 
+               idx = srcu_read_lock(&vcpu->kvm->srcu);
                rc = kvmppc_rtas_hcall(vcpu);
+               srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
                if (rc == -ENOENT)
                        return RESUME_HOST;
@@ -1115,13 +1119,13 @@ static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 
        if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                return;
-       spin_lock(&vcpu->arch.tbacct_lock);
+       spin_lock_irq(&vcpu->arch.tbacct_lock);
        now = mftb();
        vcpu->arch.busy_stolen += vcore_stolen_time(vc, now) -
                vcpu->arch.stolen_logged;
        vcpu->arch.busy_preempt = now;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
-       spin_unlock(&vcpu->arch.tbacct_lock);
+       spin_unlock_irq(&vcpu->arch.tbacct_lock);
        --vc->n_runnable;
        list_del(&vcpu->arch.run_list);
 }
index 9c515440ad1ae7e0451d3b3b67dd029ab06a0ebb..8689e2e308573b0df26996e2ebfed77e235df59c 100644 (file)
@@ -225,6 +225,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                is_io = pa & (HPTE_R_I | HPTE_R_W);
                pte_size = PAGE_SIZE << (pa & KVMPPC_PAGE_ORDER_MASK);
                pa &= PAGE_MASK;
+               pa |= gpa & ~PAGE_MASK;
        } else {
                /* Translate to host virtual address */
                hva = __gfn_to_hva_memslot(memslot, gfn);
@@ -238,13 +239,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                                ptel = hpte_make_readonly(ptel);
                        is_io = hpte_cache_bits(pte_val(pte));
                        pa = pte_pfn(pte) << PAGE_SHIFT;
+                       pa |= hva & (pte_size - 1);
+                       pa |= gpa & ~PAGE_MASK;
                }
        }
 
        if (pte_size < psize)
                return H_PARAMETER;
-       if (pa && pte_size > psize)
-               pa |= gpa & (pte_size - 1);
 
        ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
@@ -749,6 +750,10 @@ static int slb_base_page_shift[4] = {
        20,     /* 1M, unsupported */
 };
 
+/* When called from virtmode, this func should be protected by
+ * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
+ * can trigger deadlock issue.
+ */
 long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
                              unsigned long valid)
 {
index bc8de75b1925cd34ad1d11379fee8c09f1d275e5..be4fa04a37c96d56d5f07d241395afe22e1627dd 100644 (file)
@@ -153,7 +153,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
 13:    b       machine_check_fwnmi
 
-
 /*
  * We come in here when wakened from nap mode on a secondary hw thread.
  * Relocation is off and most register values are lost.
@@ -224,6 +223,11 @@ kvm_start_guest:
        /* Clear our vcpu pointer so we don't come back in early */
        li      r0, 0
        std     r0, HSTATE_KVM_VCPU(r13)
+       /*
+        * Make sure we clear HSTATE_KVM_VCPU(r13) before incrementing
+        * the nap_count, because once the increment to nap_count is
+        * visible we could be given another vcpu.
+        */
        lwsync
        /* Clear any pending IPI - we're an offline thread */
        ld      r5, HSTATE_XICS_PHYS(r13)
@@ -241,7 +245,6 @@ kvm_start_guest:
        /* increment the nap count and then go to nap mode */
        ld      r4, HSTATE_KVM_VCORE(r13)
        addi    r4, r4, VCORE_NAP_COUNT
-       lwsync                          /* make previous updates visible */
 51:    lwarx   r3, 0, r4
        addi    r3, r3, 1
        stwcx.  r3, 0, r4
@@ -751,15 +754,14 @@ kvmppc_interrupt_hv:
         * guest CR, R12 saved in shadow VCPU SCRATCH1/0
         * guest R13 saved in SPRN_SCRATCH0
         */
-       /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */
-       std     r9, HSTATE_HOST_R2(r13)
+       std     r9, HSTATE_SCRATCH2(r13)
 
        lbz     r9, HSTATE_IN_GUEST(r13)
        cmpwi   r9, KVM_GUEST_MODE_HOST_HV
        beq     kvmppc_bad_host_intr
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        cmpwi   r9, KVM_GUEST_MODE_GUEST
-       ld      r9, HSTATE_HOST_R2(r13)
+       ld      r9, HSTATE_SCRATCH2(r13)
        beq     kvmppc_interrupt_pr
 #endif
        /* We're now back in the host but in guest MMU context */
@@ -779,7 +781,7 @@ kvmppc_interrupt_hv:
        std     r6, VCPU_GPR(R6)(r9)
        std     r7, VCPU_GPR(R7)(r9)
        std     r8, VCPU_GPR(R8)(r9)
-       ld      r0, HSTATE_HOST_R2(r13)
+       ld      r0, HSTATE_SCRATCH2(r13)
        std     r0, VCPU_GPR(R9)(r9)
        std     r10, VCPU_GPR(R10)(r9)
        std     r11, VCPU_GPR(R11)(r9)
@@ -990,14 +992,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
         */
        /* Increment the threads-exiting-guest count in the 0xff00
           bits of vcore->entry_exit_count */
-       lwsync
        ld      r5,HSTATE_KVM_VCORE(r13)
        addi    r6,r5,VCORE_ENTRY_EXIT
 41:    lwarx   r3,0,r6
        addi    r0,r3,0x100
        stwcx.  r0,0,r6
        bne     41b
-       lwsync
+       isync           /* order stwcx. vs. reading napping_threads */
 
        /*
         * At this point we have an interrupt that we have to pass
@@ -1030,6 +1031,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        sld     r0,r0,r4
        andc.   r3,r3,r0                /* no sense IPI'ing ourselves */
        beq     43f
+       /* Order entry/exit update vs. IPIs */
+       sync
        mulli   r4,r4,PACA_SIZE         /* get paca for thread 0 */
        subf    r6,r4,r13
 42:    andi.   r0,r3,1
@@ -1638,10 +1641,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        bge     kvm_cede_exit
        stwcx.  r4,0,r6
        bne     31b
+       /* order napping_threads update vs testing entry_exit_count */
+       isync
        li      r0,1
        stb     r0,HSTATE_NAPPING(r13)
-       /* order napping_threads update vs testing entry_exit_count */
-       lwsync
        mr      r4,r3
        lwz     r7,VCORE_ENTRY_EXIT(r5)
        cmpwi   r7,0x100
index f4dd041c14eac9400fb012beae92792fe9c9cfd1..f779450cb07c728681ede6d566ef85920117337e 100644 (file)
@@ -129,29 +129,32 @@ kvm_start_lightweight:
         * R12      = exit handler id
         * R13      = PACA
         * SVCPU.*  = guest *
+        * MSR.EE   = 1
         *
         */
 
+       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
+       /*
+        * kvmppc_copy_from_svcpu can clobber volatile registers, save
+        * the exit handler id to the vcpu and restore it from there later.
+        */
+       stw     r12, VCPU_TRAP(r3)
+
        /* Transfer reg values from shadow vcpu back to vcpu struct */
        /* On 64-bit, interrupts are still off at this point */
-       PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
+
        GET_SHADOW_VCPU(r4)
        bl      FUNC(kvmppc_copy_from_svcpu)
        nop
 
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Re-enable interrupts */
-       ld      r3, HSTATE_HOST_MSR(r13)
-       ori     r3, r3, MSR_EE
-       MTMSR_EERI(r3)
-
        /*
         * Reload kernel SPRG3 value.
         * No need to save guest value as usermode can't modify SPRG3.
         */
        ld      r3, PACA_SPRG3(r13)
        mtspr   SPRN_SPRG3, r3
-
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
        /* R7 = vcpu */
@@ -177,7 +180,7 @@ kvm_start_lightweight:
        PPC_STL r31, VCPU_GPR(R31)(r7)
 
        /* Pass the exit number as 3rd argument to kvmppc_handle_exit */
-       mr      r5, r12
+       lwz     r5, VCPU_TRAP(r7)
 
        /* Restore r3 (kvm_run) and r4 (vcpu) */
        REST_2GPRS(3, r1)
index fe14ca3dd171cd60b3c07191fa3bdd78a141e2a6..5b9e9063cfaf0c407be267a67ab26d35fcc84a93 100644 (file)
@@ -66,6 +66,7 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
        memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb));
        svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
+       svcpu->in_use = 0;
        svcpu_put(svcpu);
 #endif
        vcpu->cpu = smp_processor_id();
@@ -78,6 +79,9 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
        struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+       if (svcpu->in_use) {
+               kvmppc_copy_from_svcpu(vcpu, svcpu);
+       }
        memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb));
        to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max;
        svcpu_put(svcpu);
@@ -110,12 +114,26 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
        svcpu->ctr = vcpu->arch.ctr;
        svcpu->lr  = vcpu->arch.lr;
        svcpu->pc  = vcpu->arch.pc;
+       svcpu->in_use = true;
 }
 
 /* Copy data touched by real-mode code from shadow vcpu back to vcpu */
 void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
                            struct kvmppc_book3s_shadow_vcpu *svcpu)
 {
+       /*
+        * vcpu_put would just call us again because in_use hasn't
+        * been updated yet.
+        */
+       preempt_disable();
+
+       /*
+        * Maybe we were already preempted and synced the svcpu from
+        * our preempt notifiers. Don't bother touching this svcpu then.
+        */
+       if (!svcpu->in_use)
+               goto out;
+
        vcpu->arch.gpr[0] = svcpu->gpr[0];
        vcpu->arch.gpr[1] = svcpu->gpr[1];
        vcpu->arch.gpr[2] = svcpu->gpr[2];
@@ -139,6 +157,10 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
        vcpu->arch.fault_dar   = svcpu->fault_dar;
        vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
        vcpu->arch.last_inst   = svcpu->last_inst;
+       svcpu->in_use = false;
+
+out:
+       preempt_enable();
 }
 
 static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)
index a38c4c9edab87aca16929b5e96377368b5016fbd..c3c5231adade6f3871709a318fed1abc752040fe 100644 (file)
@@ -153,15 +153,11 @@ _GLOBAL(kvmppc_entry_trampoline)
 
        li      r6, MSR_IR | MSR_DR
        andc    r6, r5, r6      /* Clear DR and IR in MSR value */
-#ifdef CONFIG_PPC_BOOK3S_32
        /*
         * Set EE in HOST_MSR so that it's enabled when we get into our
-        * C exit handler function.  On 64-bit we delay enabling
-        * interrupts until we have finished transferring stuff
-        * to or from the PACA.
+        * C exit handler function.
         */
        ori     r5, r5, MSR_EE
-#endif
        mtsrr0  r7
        mtsrr1  r6
        RFI
index 53e65a210b9a451ab1089bfe788277ddda071cf3..0591e05db74b1a1a1f906af6a2a67cf9770320fa 100644 (file)
@@ -681,7 +681,7 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
        int ret, s;
-       struct thread_struct thread;
+       struct debug_reg debug;
 #ifdef CONFIG_PPC_FPU
        struct thread_fp_state fp;
        int fpexc_mode;
@@ -723,9 +723,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
        /* Switch to guest debug context */
-       thread.debug = vcpu->arch.shadow_dbg_reg;
-       switch_booke_debug_regs(&thread);
-       thread.debug = current->thread.debug;
+       debug = vcpu->arch.shadow_dbg_reg;
+       switch_booke_debug_regs(&debug);
+       debug = current->thread.debug;
        current->thread.debug = vcpu->arch.shadow_dbg_reg;
 
        kvmppc_fix_ee_before_entry();
@@ -736,8 +736,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
           We also get here with interrupts enabled. */
 
        /* Switch back to user space debug context */
-       switch_booke_debug_regs(&thread);
-       current->thread.debug = thread.debug;
+       switch_booke_debug_regs(&debug);
+       current->thread.debug = debug;
 
 #ifdef CONFIG_PPC_FPU
        kvmppc_save_guest_fp(vcpu);
index d73a5901490018486fed19115fce46d88084f701..596a285c07554d65dfd561367a52ffed47aba55d 100644 (file)
@@ -9,6 +9,14 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 
+#ifdef __BIG_ENDIAN__
+#define sLd sld                /* Shift towards low-numbered address. */
+#define sHd srd                /* Shift towards high-numbered address. */
+#else
+#define sLd srd                /* Shift towards low-numbered address. */
+#define sHd sld                /* Shift towards high-numbered address. */
+#endif
+
        .align  7
 _GLOBAL(__copy_tofrom_user)
 BEGIN_FTR_SECTION
@@ -118,10 +126,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 24:    ld      r9,0(r4)        /* 3+2n loads, 2+2n stores */
 25:    ld      r0,8(r4)
-       sld     r6,r9,r10
+       sLd     r6,r9,r10
 26:    ldu     r9,16(r4)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        or      r7,r7,r6
        blt     cr6,79f
 27:    ld      r0,8(r4)
@@ -129,35 +137,35 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
 
 28:    ld      r0,0(r4)        /* 4+2n loads, 3+2n stores */
 29:    ldu     r9,8(r4)
-       sld     r8,r0,r10
+       sLd     r8,r0,r10
        addi    r3,r3,-8
        blt     cr6,5f
 30:    ld      r0,8(r4)
-       srd     r12,r9,r11
-       sld     r6,r9,r10
+       sHd     r12,r9,r11
+       sLd     r6,r9,r10
 31:    ldu     r9,16(r4)
        or      r12,r8,r12
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        addi    r3,r3,16
        beq     cr6,78f
 
 1:     or      r7,r7,r6
 32:    ld      r0,8(r4)
 76:    std     r12,8(r3)
-2:     srd     r12,r9,r11
-       sld     r6,r9,r10
+2:     sHd     r12,r9,r11
+       sLd     r6,r9,r10
 33:    ldu     r9,16(r4)
        or      r12,r8,r12
 77:    stdu    r7,16(r3)
-       srd     r7,r0,r11
-       sld     r8,r0,r10
+       sHd     r7,r0,r11
+       sLd     r8,r0,r10
        bdnz    1b
 
 78:    std     r12,8(r3)
        or      r7,r7,r6
 79:    std     r7,16(r3)
-5:     srd     r12,r9,r11
+5:     sHd     r12,r9,r11
        or      r12,r8,r12
 80:    std     r12,24(r3)
        bne     6f
@@ -165,23 +173,38 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        blr
 6:     cmpwi   cr1,r5,8
        addi    r3,r3,32
-       sld     r9,r9,r10
+       sLd     r9,r9,r10
        ble     cr1,7f
 34:    ld      r0,8(r4)
-       srd     r7,r0,r11
+       sHd     r7,r0,r11
        or      r9,r7,r9
 7:
        bf      cr7*4+1,1f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,32
+#endif
 94:    stw     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,32
+#endif
        addi    r3,r3,4
 1:     bf      cr7*4+2,2f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,16
+#endif
 95:    sth     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,16
+#endif
        addi    r3,r3,2
 2:     bf      cr7*4+3,3f
+#ifdef __BIG_ENDIAN__
        rotldi  r9,r9,8
+#endif
 96:    stb     r9,0(r3)
+#ifdef __LITTLE_ENDIAN__
+       rotrdi  r9,r9,8
+#endif
 3:     li      r3,0
        blr
 
index ac3c2a10dafda9e73145dabfbc7181548f288fd5..555034f8505e8d1d83bfeef3480a9bc058499754 100644 (file)
@@ -223,10 +223,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                        }
                        PPC_DIVWU(r_A, r_A, r_X);
                        break;
-               case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+               case BPF_S_ALU_DIV_K: /* A /= K */
+                       if (K == 1)
+                               break;
                        PPC_LI32(r_scratch1, K);
-                       /* Top 32 bits of 64bit result -> A */
-                       PPC_MULHWU(r_A, r_A, r_scratch1);
+                       PPC_DIVWU(r_A, r_A, r_scratch1);
                        break;
                case BPF_S_ALU_AND_X:
                        ctx->seen |= SEEN_XREG;
index 02245cee78183852d52f3a907023dcd9a63529bf..d7ddcee7feb8bc8084d18be32f348263c8de6e0e 100644 (file)
@@ -36,7 +36,6 @@
 #include "powernv.h"
 #include "pci.h"
 
-static char *hub_diag = NULL;
 static int ioda_eeh_nb_init = 0;
 
 static int ioda_eeh_event(struct notifier_block *nb,
@@ -140,15 +139,6 @@ static int ioda_eeh_post_init(struct pci_controller *hose)
                ioda_eeh_nb_init = 1;
        }
 
-       /* We needn't HUB diag-data on PHB3 */
-       if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
-               hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-               if (!hub_diag) {
-                       pr_err("%s: Out of memory !\n", __func__);
-                       return -ENOMEM;
-               }
-       }
-
 #ifdef CONFIG_DEBUG_FS
        if (phb->dbgfs) {
                debugfs_create_file("err_injct_outbound", 0600,
@@ -633,11 +623,10 @@ static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data)
 static void ioda_eeh_hub_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoP7IOCErrorData *data;
+       struct OpalIoP7IOCErrorData *data = &phb->diag.hub_diag;
        long rc;
 
-       data = (struct OpalIoP7IOCErrorData *)ioda_eeh_hub_diag;
-       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, PAGE_SIZE);
+       rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data));
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n",
                           __func__, phb->hub_id, rc);
@@ -820,14 +809,15 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose)
        struct OpalIoPhbErrorCommon *common;
        long rc;
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, common, PAGE_SIZE);
+       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;
        }
 
+       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
        switch (common->ioType) {
        case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
                ioda_eeh_p7ioc_phb_diag(hose, common);
index e7e59e4f9892deb85b8ff96b502a6c14fe989d19..79d83cad3d6709c543dad5bb96eafba2ff8756a7 100644 (file)
@@ -24,25 +24,25 @@ static int opal_lpc_chip_id = -1;
 static u8 opal_lpc_inb(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xffff)
                return 0xff;
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 1);
-       return rc ? 0xff : data;
+       return rc ? 0xff : be32_to_cpu(data);
 }
 
 static __le16 __opal_lpc_inw(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xfffe)
                return 0xffff;
        if (port & 1)
                return (__le16)opal_lpc_inb(port) << 8 | opal_lpc_inb(port + 1);
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 2);
-       return rc ? 0xffff : data;
+       return rc ? 0xffff : be32_to_cpu(data);
 }
 static u16 opal_lpc_inw(unsigned long port)
 {
@@ -52,7 +52,7 @@ static u16 opal_lpc_inw(unsigned long port)
 static __le32 __opal_lpc_inl(unsigned long port)
 {
        int64_t rc;
-       uint32_t data;
+       __be32 data;
 
        if (opal_lpc_chip_id < 0 || port > 0xfffc)
                return 0xffffffff;
@@ -62,7 +62,7 @@ static __le32 __opal_lpc_inl(unsigned long port)
                       (__le32)opal_lpc_inb(port + 2) <<  8 |
                               opal_lpc_inb(port + 3);
        rc = opal_lpc_read(opal_lpc_chip_id, OPAL_LPC_IO, port, &data, 4);
-       return rc ? 0xffffffff : data;
+       return rc ? 0xffffffff : be32_to_cpu(data);
 }
 
 static u32 opal_lpc_inl(unsigned long port)
index 4d99a8fd55acf2a286e8f7877cd919d2150355bf..4fbf276ac99eeb4e2900196e3905a3343bedc988 100644 (file)
@@ -96,9 +96,11 @@ static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
 {
        struct opal_scom_map *m = map;
        int64_t rc;
+       __be64 v;
 
        reg = opal_scom_unmangle(reg);
-       rc = opal_xscom_read(m->chip, m->addr + reg, (uint64_t *)__pa(value));
+       rc = opal_xscom_read(m->chip, m->addr + reg, (__be64 *)__pa(&v));
+       *value = be64_to_cpu(v);
        return opal_xscom_err_xlate(rc);
 }
 
index 084cdfa40682b2be9f35fde51eb2e4e201accfe9..2c6d173842b2f1056d3702826b3c2a1d84d614ad 100644 (file)
@@ -720,6 +720,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
                tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
        }
        iommu_init_table(tbl, phb->hose->node);
+       iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
 
        if (pe->pdev)
                set_iommu_table_base(&pe->pdev->dev, tbl);
index 911c24ef033e0ae207036e5d5cab8bceaf07e14a..1ed8d5f40f5ad1423f78c9ae7fdac42abac4376d 100644 (file)
@@ -172,11 +172,13 @@ struct pnv_phb {
                } ioda;
        };
 
-       /* PHB status structure */
+       /* PHB and hub status structure */
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoP7IOCErrorData     hub_diag;
        } diag;
+
 };
 
 extern struct pci_ops pnv_pci_ops;
index e738007eae643262d72942c599a6418b252b4849..c9fecf09b8fada71dec94e9833c35be524b498e4 100644 (file)
@@ -157,7 +157,7 @@ static void parse_ppp_data(struct seq_file *m)
 {
        struct hvcall_ppp_data ppp_data;
        struct device_node *root;
-       const int *perf_level;
+       const __be32 *perf_level;
        int rc;
 
        rc = h_get_ppp(&ppp_data);
@@ -201,7 +201,7 @@ static void parse_ppp_data(struct seq_file *m)
                perf_level = of_get_property(root,
                                "ibm,partition-performance-parameters-level",
                                             NULL);
-               if (perf_level && (*perf_level >= 1)) {
+               if (perf_level && (be32_to_cpup(perf_level) >= 1)) {
                        seq_printf(m,
                            "physical_procs_allocated_to_virtualization=%d\n",
                                   ppp_data.phys_platform_procs);
@@ -435,7 +435,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        int partition_potential_processors;
        int partition_active_processors;
        struct device_node *rtas_node;
-       const int *lrdrp = NULL;
+       const __be32 *lrdrp = NULL;
 
        rtas_node = of_find_node_by_path("/rtas");
        if (rtas_node)
@@ -444,7 +444,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
        if (lrdrp == NULL) {
                partition_potential_processors = vdso_data->processorCount;
        } else {
-               partition_potential_processors = *(lrdrp + 4);
+               partition_potential_processors = be32_to_cpup(lrdrp + 4);
        }
        of_node_put(rtas_node);
 
@@ -654,7 +654,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
        const char *model = "";
        const char *system_id = "";
        const char *tmp;
-       const unsigned int *lp_index_ptr;
+       const __be32 *lp_index_ptr;
        unsigned int lp_index = 0;
 
        seq_printf(m, "%s %s\n", MODULE_NAME, MODULE_VERS);
@@ -670,7 +670,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
                lp_index_ptr = of_get_property(rootdn, "ibm,partition-no",
                                        NULL);
                if (lp_index_ptr)
-                       lp_index = *lp_index_ptr;
+                       lp_index = be32_to_cpup(lp_index_ptr);
                of_node_put(rootdn);
        }
        seq_printf(m, "serial_number=%s\n", system_id);
index 6d2f0abce6fae652d207b499ac99a47e20a500f2..0c882e83c4ce29373f6d3957b7de34979d9fae98 100644 (file)
@@ -130,7 +130,8 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 {
        struct device_node *dn;
        struct pci_dn *pdn;
-       const u32 *req_msi;
+       const __be32 *p;
+       u32 req_msi;
 
        pdn = pci_get_pdn(pdev);
        if (!pdn)
@@ -138,19 +139,20 @@ static int check_req(struct pci_dev *pdev, int nvec, char *prop_name)
 
        dn = pdn->node;
 
-       req_msi = of_get_property(dn, prop_name, NULL);
-       if (!req_msi) {
+       p = of_get_property(dn, prop_name, NULL);
+       if (!p) {
                pr_debug("rtas_msi: No %s on %s\n", prop_name, dn->full_name);
                return -ENOENT;
        }
 
-       if (*req_msi < nvec) {
+       req_msi = be32_to_cpup(p);
+       if (req_msi < nvec) {
                pr_debug("rtas_msi: %s requests < %d MSIs\n", prop_name, nvec);
 
-               if (*req_msi == 0) /* Be paranoid */
+               if (req_msi == 0) /* Be paranoid */
                        return -ENOSPC;
 
-               return *req_msi;
+               return req_msi;
        }
 
        return 0;
@@ -171,7 +173,7 @@ static int check_req_msix(struct pci_dev *pdev, int nvec)
 static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
 {
        struct device_node *dn;
-       const u32 *p;
+       const __be32 *p;
 
        dn = of_node_get(pci_device_to_OF_node(dev));
        while (dn) {
@@ -179,7 +181,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
                if (p) {
                        pr_debug("rtas_msi: found prop on dn %s\n",
                                dn->full_name);
-                       *total = *p;
+                       *total = be32_to_cpup(p);
                        return dn;
                }
 
@@ -232,13 +234,13 @@ struct msi_counts {
 static void *count_non_bridge_devices(struct device_node *dn, void *data)
 {
        struct msi_counts *counts = data;
-       const u32 *p;
+       const __be32 *p;
        u32 class;
 
        pr_debug("rtas_msi: counting %s\n", dn->full_name);
 
        p = of_get_property(dn, "class-code", NULL);
-       class = p ? *p : 0;
+       class = p ? be32_to_cpup(p) : 0;
 
        if ((class >> 8) != PCI_CLASS_BRIDGE_PCI)
                counts->num_devices++;
@@ -249,7 +251,7 @@ static void *count_non_bridge_devices(struct device_node *dn, void *data)
 static void *count_spare_msis(struct device_node *dn, void *data)
 {
        struct msi_counts *counts = data;
-       const u32 *p;
+       const __be32 *p;
        int req;
 
        if (dn == counts->requestor)
@@ -260,11 +262,11 @@ static void *count_spare_msis(struct device_node *dn, void *data)
                req = 0;
                p = of_get_property(dn, "ibm,req#msi", NULL);
                if (p)
-                       req = *p;
+                       req = be32_to_cpup(p);
 
                p = of_get_property(dn, "ibm,req#msi-x", NULL);
                if (p)
-                       req = max(req, (int)*p);
+                       req = max(req, (int)be32_to_cpup(p));
        }
 
        if (req < counts->quota)
index 7bfaf58d4664460db12c94499fc151e251f47f68..d7096f2f7751a5a0e41cb30ee48fef3242901f09 100644 (file)
@@ -43,8 +43,8 @@ static char nvram_buf[NVRW_CNT];      /* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
 struct err_log_info {
-       int error_type;
-       unsigned int seq_num;
+       __be32 error_type;
+       __be32 seq_num;
 };
 
 struct nvram_os_partition {
@@ -79,9 +79,9 @@ static const char *pseries_nvram_os_partitions[] = {
 };
 
 struct oops_log_info {
-       u16 version;
-       u16 report_length;
-       u64 timestamp;
+       __be16 version;
+       __be16 report_length;
+       __be64 timestamp;
 } __attribute__((packed));
 
 static void oops_to_nvram(struct kmsg_dumper *dumper,
@@ -291,8 +291,8 @@ int nvram_write_os_partition(struct nvram_os_partition *part, char * buff,
                length = part->size;
        }
 
-       info.error_type = err_type;
-       info.seq_num = error_log_cnt;
+       info.error_type = cpu_to_be32(err_type);
+       info.seq_num = cpu_to_be32(error_log_cnt);
 
        tmp_index = part->index;
 
@@ -364,8 +364,8 @@ int nvram_read_partition(struct nvram_os_partition *part, char *buff,
        }
 
        if (part->os_partition) {
-               *error_log_cnt = info.seq_num;
-               *err_type = info.error_type;
+               *error_log_cnt = be32_to_cpu(info.seq_num);
+               *err_type = be32_to_cpu(info.error_type);
        }
 
        return 0;
@@ -529,9 +529,9 @@ static int zip_oops(size_t text_len)
                pr_err("nvram: logging uncompressed oops/panic report\n");
                return -1;
        }
-       oops_hdr->version = OOPS_HDR_VERSION;
-       oops_hdr->report_length = (u16) zipped_len;
-       oops_hdr->timestamp = get_seconds();
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(zipped_len);
+       oops_hdr->timestamp = cpu_to_be64(get_seconds());
        return 0;
 }
 
@@ -574,9 +574,9 @@ static int nvram_pstore_write(enum pstore_type_id type,
                                clobbering_unread_rtas_event())
                return -1;
 
-       oops_hdr->version = OOPS_HDR_VERSION;
-       oops_hdr->report_length = (u16) size;
-       oops_hdr->timestamp = get_seconds();
+       oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+       oops_hdr->report_length = cpu_to_be16(size);
+       oops_hdr->timestamp = cpu_to_be64(get_seconds());
 
        if (compressed)
                err_type = ERR_TYPE_KERNEL_PANIC_GZ;
@@ -670,16 +670,16 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
                size_t length, hdr_size;
 
                oops_hdr = (struct oops_log_info *)buff;
-               if (oops_hdr->version < OOPS_HDR_VERSION) {
+               if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
                        /* Old format oops header had 2-byte record size */
                        hdr_size = sizeof(u16);
-                       length = oops_hdr->version;
+                       length = be16_to_cpu(oops_hdr->version);
                        time->tv_sec = 0;
                        time->tv_nsec = 0;
                } else {
                        hdr_size = sizeof(*oops_hdr);
-                       length = oops_hdr->report_length;
-                       time->tv_sec = oops_hdr->timestamp;
+                       length = be16_to_cpu(oops_hdr->report_length);
+                       time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
                        time->tv_nsec = 0;
                }
                *buf = kmalloc(length, GFP_KERNEL);
@@ -889,13 +889,13 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
                kmsg_dump_get_buffer(dumper, false,
                                     oops_data, oops_data_sz, &text_len);
                err_type = ERR_TYPE_KERNEL_PANIC;
-               oops_hdr->version = OOPS_HDR_VERSION;
-               oops_hdr->report_length = (u16) text_len;
-               oops_hdr->timestamp = get_seconds();
+               oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
+               oops_hdr->report_length = cpu_to_be16(text_len);
+               oops_hdr->timestamp = cpu_to_be64(get_seconds());
        }
 
        (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-               (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
+               (int) (sizeof(*oops_hdr) + text_len), err_type,
                ++oops_count);
 
        spin_unlock_irqrestore(&lock, flags);
index 5f93856cdf479a3950cd053288174e1a85db4cad..70670a2d9cf2ddd691a936dbe489d8e338ed4029 100644 (file)
@@ -113,7 +113,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
        struct device_node *dn, *pdn;
        struct pci_bus *bus;
-       const uint32_t *pcie_link_speed_stats;
+       const __be32 *pcie_link_speed_stats;
 
        bus = bridge->bus;
 
@@ -122,7 +122,7 @@ 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 = (const uint32_t *) of_get_property(pdn,
+               pcie_link_speed_stats = of_get_property(pdn,
                        "ibm,pcie-link-speed-stats", NULL);
                if (pcie_link_speed_stats)
                        break;
@@ -135,7 +135,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                return 0;
        }
 
-       switch (pcie_link_speed_stats[0]) {
+       switch (be32_to_cpup(pcie_link_speed_stats)) {
        case 0x01:
                bus->max_bus_speed = PCIE_SPEED_2_5GT;
                break;
@@ -147,7 +147,7 @@ int pseries_root_bridge_prepare(struct pci_host_bridge *bridge)
                break;
        }
 
-       switch (pcie_link_speed_stats[1]) {
+       switch (be32_to_cpup(pcie_link_speed_stats)) {
        case 0x01:
                bus->cur_bus_speed = PCIE_SPEED_2_5GT;
                break;
index c1f1908587011d6d131dd56bdf2e1cb283c41128..6f76ae417f47e561bbf7e8b01c588a8e73f6374d 100644 (file)
@@ -470,7 +470,7 @@ static long pseries_little_endian_exceptions(void)
 
 static void __init pSeries_setup_arch(void)
 {
-       panic_timeout = 10;
+       set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
 
        /* Discover PIC type and setup ppc_md accordingly */
        pseries_discover_pic();
index b7c43453236dfac7d001b583e554d8938b0ba426..85d9e37f5ccbf76c93c2cf71c1d70677d7a14366 100644 (file)
@@ -339,7 +339,7 @@ void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
                if (IS_ERR_VALUE(offset))
                        continue;
 
-               ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
+               ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
                if (!ocm_blk) {
                        printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
                        rh_free(ocm_reg->rh, offset);
index 5877e71901b345ef191a911f9ad0ba537abd9c8c..e9f3125325266ff8b93f13c009003d3d4aa335de 100644 (file)
@@ -135,7 +135,6 @@ config S390
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16 if 32BIT
        select HAVE_VIRT_CPU_ACCOUNTING
-       select INIT_ALL_POSSIBLE
        select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
        select OLD_SIGACTION
@@ -347,14 +346,14 @@ config SMP
          Even if you don't know what to do here, say Y.
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-64)"
-       range 2 64
+       int "Maximum number of CPUs (2-256)"
+       range 2 256
        depends on SMP
        default "32" if !64BIT
        default "64" if 64BIT
        help
          This allows you to specify the maximum number of CPUs which this
-         kernel will support.  The maximum supported value is 64 and the
+         kernel will support. The maximum supported value is 256 and the
          minimum value which makes sense is 2.
 
          This is purely to save memory - each supported CPU adds
index 4363528dc8fd013492b2165f6978b5e5226657b1..b3feabd39f31f8eead0a69f4340a8abc0ea17da6 100644 (file)
@@ -55,8 +55,7 @@ struct pcc_param {
 
 struct s390_xts_ctx {
        u8 key[32];
-       u8 xts_param[16];
-       struct pcc_param pcc;
+       u8 pcc_key[32];
        long enc;
        long dec;
        int key_len;
@@ -591,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                xts_ctx->enc = KM_XTS_128_ENCRYPT;
                xts_ctx->dec = KM_XTS_128_DECRYPT;
                memcpy(xts_ctx->key + 16, in_key, 16);
-               memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16);
+               memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
                break;
        case 48:
                xts_ctx->enc = 0;
@@ -602,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                xts_ctx->enc = KM_XTS_256_ENCRYPT;
                xts_ctx->dec = KM_XTS_256_DECRYPT;
                memcpy(xts_ctx->key, in_key, 32);
-               memcpy(xts_ctx->pcc.key, in_key + 32, 32);
+               memcpy(xts_ctx->pcc_key, in_key + 32, 32);
                break;
        default:
                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -621,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
        unsigned int nbytes = walk->nbytes;
        unsigned int n;
        u8 *in, *out;
-       void *param;
+       struct pcc_param pcc_param;
+       struct {
+               u8 key[32];
+               u8 init[16];
+       } xts_param;
 
        if (!nbytes)
                goto out;
 
-       memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block));
-       memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit));
-       memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts));
-       memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
-       param = xts_ctx->pcc.key + offset;
-       ret = crypt_s390_pcc(func, param);
+       memset(pcc_param.block, 0, sizeof(pcc_param.block));
+       memset(pcc_param.bit, 0, sizeof(pcc_param.bit));
+       memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
+       memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
+       memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
+       ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
        if (ret < 0)
                return -EIO;
 
-       memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
-       param = xts_ctx->key + offset;
+       memcpy(xts_param.key, xts_ctx->key, 32);
+       memcpy(xts_param.init, pcc_param.xts, 16);
        do {
                /* only use complete blocks */
                n = nbytes & ~(AES_BLOCK_SIZE - 1);
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
 
-               ret = crypt_s390_km(func, param, out, in, n);
+               ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
                if (ret < 0 || ret != n)
                        return -EIO;
 
index 16760eeb79b09ec5ea6da10274157491bb5a5d0f..578680f6207acb62ccc8f52c321c349f510f73a6 100644 (file)
 
 #define set_mb(var, value)             do { var = value; mb(); } while (0)
 
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ___p1;                                                          \
+})
+
 #endif /* __ASM_BARRIER_H */
index 4bf9da03591e7abda64ab4632f511c16b7734d16..5d7e8cf83bd6c7d53b5f2a34fc2120add4cfa2d8 100644 (file)
@@ -38,7 +38,8 @@
 
 #define PSW32_USER_BITS (PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT | \
                         PSW32_DEFAULT_KEY | PSW32_MASK_BASE | \
-                        PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | PSW32_ASC_HOME)
+                        PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | \
+                        PSW32_ASC_PRIMARY)
 
 #define COMPAT_USER_HZ         100
 #define COMPAT_UTS_MACHINE     "s390\0\0\0\0"
index c879fad404c8d36d73aff75ea1174df65374061b..cb700d54bd832a91256803b35bbff06adc3a95d3 100644 (file)
@@ -56,6 +56,96 @@ struct cpumf_ctr_info {
        u32   reserved2[12];
 } __packed;
 
+/* QUERY SAMPLING INFORMATION block */
+struct hws_qsi_info_block {        /* Bit(s) */
+       unsigned int b0_13:14;      /* 0-13: zeros                       */
+       unsigned int as:1;          /* 14: basic-sampling authorization  */
+       unsigned int ad:1;          /* 15: diag-sampling authorization   */
+       unsigned int b16_21:6;      /* 16-21: zeros                      */
+       unsigned int es:1;          /* 22: basic-sampling enable control */
+       unsigned int ed:1;          /* 23: diag-sampling enable control  */
+       unsigned int b24_29:6;      /* 24-29: zeros                      */
+       unsigned int cs:1;          /* 30: basic-sampling activation control */
+       unsigned int cd:1;          /* 31: diag-sampling activation control */
+       unsigned int bsdes:16;      /* 4-5: size of basic sampling entry */
+       unsigned int dsdes:16;      /* 6-7: size of diagnostic sampling entry */
+       unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
+       unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
+       unsigned long tear;         /* 24-31: TEAR contents              */
+       unsigned long dear;         /* 32-39: DEAR contents              */
+       unsigned int rsvrd0;        /* 40-43: reserved                   */
+       unsigned int cpu_speed;     /* 44-47: CPU speed                  */
+       unsigned long long rsvrd1;  /* 48-55: reserved                   */
+       unsigned long long rsvrd2;  /* 56-63: reserved                   */
+} __packed;
+
+/* SET SAMPLING CONTROLS request block */
+struct hws_lsctl_request_block {
+       unsigned int s:1;           /* 0: maximum buffer indicator       */
+       unsigned int h:1;           /* 1: part. level reserved for VM use*/
+       unsigned long long b2_53:52;/* 2-53: zeros                       */
+       unsigned int es:1;          /* 54: basic-sampling enable control */
+       unsigned int ed:1;          /* 55: diag-sampling enable control  */
+       unsigned int b56_61:6;      /* 56-61: - zeros                    */
+       unsigned int cs:1;          /* 62: basic-sampling activation control */
+       unsigned int cd:1;          /* 63: diag-sampling activation control  */
+       unsigned long interval;     /* 8-15: sampling interval           */
+       unsigned long tear;         /* 16-23: TEAR contents              */
+       unsigned long dear;         /* 24-31: DEAR contents              */
+       /* 32-63:                                                        */
+       unsigned long rsvrd1;       /* reserved                          */
+       unsigned long rsvrd2;       /* reserved                          */
+       unsigned long rsvrd3;       /* reserved                          */
+       unsigned long rsvrd4;       /* reserved                          */
+} __packed;
+
+struct hws_basic_entry {
+       unsigned int def:16;        /* 0-15  Data Entry Format           */
+       unsigned int R:4;           /* 16-19 reserved                    */
+       unsigned int U:4;           /* 20-23 Number of unique instruct.  */
+       unsigned int z:2;           /* zeros                             */
+       unsigned int T:1;           /* 26 PSW DAT mode                   */
+       unsigned int W:1;           /* 27 PSW wait state                 */
+       unsigned int P:1;           /* 28 PSW Problem state              */
+       unsigned int AS:2;          /* 29-30 PSW address-space control   */
+       unsigned int I:1;           /* 31 entry valid or invalid         */
+       unsigned int:16;
+       unsigned int prim_asn:16;   /* primary ASN                       */
+       unsigned long long ia;      /* Instruction Address               */
+       unsigned long long gpp;     /* Guest Program Parameter           */
+       unsigned long long hpp;     /* Host Program Parameter            */
+} __packed;
+
+struct hws_diag_entry {
+       unsigned int def:16;        /* 0-15  Data Entry Format           */
+       unsigned int R:14;          /* 16-19 and 20-30 reserved          */
+       unsigned int I:1;           /* 31 entry valid or invalid         */
+       u8           data[];        /* Machine-dependent sample data     */
+} __packed;
+
+struct hws_combined_entry {
+       struct hws_basic_entry  basic;  /* Basic-sampling data entry */
+       struct hws_diag_entry   diag;   /* Diagnostic-sampling data entry */
+} __packed;
+
+struct hws_trailer_entry {
+       union {
+               struct {
+                       unsigned int f:1;       /* 0 - Block Full Indicator   */
+                       unsigned int a:1;       /* 1 - Alert request control  */
+                       unsigned int t:1;       /* 2 - Timestamp format       */
+                       unsigned long long:61;  /* 3 - 63: Reserved           */
+               };
+               unsigned long long flags;       /* 0 - 63: All indicators     */
+       };
+       unsigned long long overflow;     /* 64 - sample Overflow count        */
+       unsigned char timestamp[16];     /* 16 - 31 timestamp                 */
+       unsigned long long reserved1;    /* 32 -Reserved                      */
+       unsigned long long reserved2;    /*                                   */
+       unsigned long long progusage1;   /* 48 - reserved for programming use */
+       unsigned long long progusage2;   /*                                   */
+} __packed;
+
 /* Query counter information */
 static inline int qctri(struct cpumf_ctr_info *info)
 {
@@ -99,4 +189,95 @@ static inline int ecctr(u64 ctr, u64 *val)
        return cc;
 }
 
+/* Query sampling information */
+static inline int qsi(struct hws_qsi_info_block *info)
+{
+       int cc;
+       cc = 1;
+
+       asm volatile(
+               "0:     .insn   s,0xb2860000,0(%1)\n"
+               "1:     lhi     %0,0\n"
+               "2:\n"
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+               : "=d" (cc), "+a" (info)
+               : "m" (*info)
+               : "cc", "memory");
+
+       return cc ? -EINVAL : 0;
+}
+
+/* Load sampling controls */
+static inline int lsctl(struct hws_lsctl_request_block *req)
+{
+       int cc;
+
+       cc = 1;
+       asm volatile(
+               "0:     .insn   s,0xb2870000,0(%1)\n"
+               "1:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "2:\n"
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+               : "+d" (cc), "+a" (req)
+               : "m" (*req)
+               : "cc", "memory");
+
+       return cc ? -EINVAL : 0;
+}
+
+/* Sampling control helper functions */
+
+#include <linux/time.h>
+
+static inline unsigned long freq_to_sample_rate(struct hws_qsi_info_block *qsi,
+                                               unsigned long freq)
+{
+       return (USEC_PER_SEC / freq) * qsi->cpu_speed;
+}
+
+static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi,
+                                               unsigned long rate)
+{
+       return USEC_PER_SEC * qsi->cpu_speed / rate;
+}
+
+#define SDB_TE_ALERT_REQ_MASK  0x4000000000000000UL
+#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL
+
+/* Return TOD timestamp contained in an trailer entry */
+static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
+{
+       /* TOD in STCKE format */
+       if (te->t)
+               return *((unsigned long long *) &te->timestamp[1]);
+
+       /* TOD in STCK format */
+       return *((unsigned long long *) &te->timestamp[0]);
+}
+
+/* Return pointer to trailer entry of an sample data block */
+static inline unsigned long *trailer_entry_ptr(unsigned long v)
+{
+       void *ret;
+
+       ret = (void *) v;
+       ret += PAGE_SIZE;
+       ret -= sizeof(struct hws_trailer_entry);
+
+       return (unsigned long *) ret;
+}
+
+/* Return if the entry in the sample data block table (sdbt)
+ * is a link to the next sdbt */
+static inline int is_link_entry(unsigned long *s)
+{
+       return *s & 0x1ul ? 1 : 0;
+}
+
+/* Return pointer to the linked sdbt */
+static inline unsigned long *get_next_sdbt(unsigned long *s)
+{
+       return (unsigned long *) (*s & ~0x1ul);
+}
 #endif /* _ASM_S390_CPU_MF_H */
index 7e1c917bbba2ace4f6b5785f67db518ba7c2cfc1..09d1dd46bd5777e7af01f6e194b0e2c2eb066532 100644 (file)
@@ -29,6 +29,8 @@ struct css_general_char {
        u32 fcx : 1;     /* bit 88 */
        u32 : 19;
        u32 alt_ssi : 1; /* bit 108 */
+       u32:1;
+       u32 narf:1;      /* bit 110 */
 } __packed;
 
 extern struct css_general_char css_general_characteristics;
index c129ab2ac731c989503e0b61ee338332105a85f9..2583466f576b617181ed8b39f1db6c32106bd999 100644 (file)
@@ -144,6 +144,7 @@ int clp_disable_fh(struct zpci_dev *);
 void zpci_event_error(void *);
 void zpci_event_availability(void *);
 void zpci_rescan(void);
+bool zpci_is_enabled(void);
 #else /* CONFIG_PCI */
 static inline void zpci_event_error(void *e) {}
 static inline void zpci_event_availability(void *e) {}
index 1141fb3e7b21e6ad2e915835eb571301982cf29e..159a8ec6da9afc30e26a3fe1ffe10ec5f7c26745 100644 (file)
@@ -1,21 +1,40 @@
 /*
  * Performance event support - s390 specific definitions.
  *
- * Copyright IBM Corp. 2009, 2012
+ * Copyright IBM Corp. 2009, 2013
  * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  *           Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
  */
 
-#include <asm/cpu_mf.h>
+#ifndef _ASM_S390_PERF_EVENT_H
+#define _ASM_S390_PERF_EVENT_H
 
-/* CPU-measurement counter facility */
-#define PERF_CPUM_CF_MAX_CTR           256
+#ifdef CONFIG_64BIT
+
+#include <linux/perf_event.h>
+#include <linux/device.h>
+#include <asm/cpu_mf.h>
 
 /* Per-CPU flags for PMU states */
 #define PMU_F_RESERVED                 0x1000
 #define PMU_F_ENABLED                  0x2000
+#define PMU_F_IN_USE                   0x4000
+#define PMU_F_ERR_IBE                  0x0100
+#define PMU_F_ERR_LSDA                 0x0200
+#define PMU_F_ERR_MASK                 (PMU_F_ERR_IBE|PMU_F_ERR_LSDA)
+
+/* Perf defintions for PMU event attributes in sysfs */
+extern __init const struct attribute_group **cpumf_cf_event_group(void);
+extern ssize_t cpumf_events_sysfs_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *page);
+#define EVENT_VAR(_cat, _name)         event_attr_##_cat##_##_name
+#define EVENT_PTR(_cat, _name)         (&EVENT_VAR(_cat, _name).attr.attr)
+
+#define CPUMF_EVENT_ATTR(cat, name, id)                        \
+       PMU_EVENT_ATTR(name, EVENT_VAR(cat, name), id, cpumf_events_sysfs_show)
+#define CPUMF_EVENT_PTR(cat, name)     EVENT_PTR(cat, name)
 
-#ifdef CONFIG_64BIT
 
 /* Perf callbacks */
 struct pt_regs;
@@ -23,4 +42,55 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
 extern unsigned long perf_misc_flags(struct pt_regs *regs);
 #define perf_misc_flags(regs) perf_misc_flags(regs)
 
+/* Perf pt_regs extension for sample-data-entry indicators */
+struct perf_sf_sde_regs {
+       unsigned char in_guest:1;         /* guest sample */
+       unsigned long reserved:63;        /* reserved */
+};
+
+/* Perf PMU definitions for the counter facility */
+#define PERF_CPUM_CF_MAX_CTR           256
+
+/* Perf PMU definitions for the sampling facility */
+#define PERF_CPUM_SF_MAX_CTR           2
+#define PERF_EVENT_CPUM_SF             0xB0000UL /* Event: Basic-sampling */
+#define PERF_EVENT_CPUM_SF_DIAG                0xBD000UL /* Event: Combined-sampling */
+#define PERF_CPUM_SF_BASIC_MODE                0x0001    /* Basic-sampling flag */
+#define PERF_CPUM_SF_DIAG_MODE         0x0002    /* Diagnostic-sampling flag */
+#define PERF_CPUM_SF_MODE_MASK         (PERF_CPUM_SF_BASIC_MODE| \
+                                        PERF_CPUM_SF_DIAG_MODE)
+#define PERF_CPUM_SF_FULL_BLOCKS       0x0004    /* Process full SDBs only */
+
+#define REG_NONE               0
+#define REG_OVERFLOW           1
+#define OVERFLOW_REG(hwc)      ((hwc)->extra_reg.config)
+#define SFB_ALLOC_REG(hwc)     ((hwc)->extra_reg.alloc)
+#define RAWSAMPLE_REG(hwc)     ((hwc)->config)
+#define TEAR_REG(hwc)          ((hwc)->last_tag)
+#define SAMPL_RATE(hwc)                ((hwc)->event_base)
+#define SAMPL_FLAGS(hwc)       ((hwc)->config_base)
+#define SAMPL_DIAG_MODE(hwc)   (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_DIAG_MODE)
+#define SDB_FULL_BLOCKS(hwc)   (SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FULL_BLOCKS)
+
+/* Structure for sampling data entries to be passed as perf raw sample data
+ * to user space.  Note that raw sample data must be aligned and, thus, might
+ * be padded with zeros.
+ */
+struct sf_raw_sample {
+#define SF_RAW_SAMPLE_BASIC    PERF_CPUM_SF_BASIC_MODE
+#define SF_RAW_SAMPLE_DIAG     PERF_CPUM_SF_DIAG_MODE
+       u64                     format;
+       u32                      size;    /* Size of sf_raw_sample */
+       u16                     bsdes;    /* Basic-sampling data entry size */
+       u16                     dsdes;    /* Diagnostic-sampling data entry size */
+       struct hws_basic_entry  basic;    /* Basic-sampling data entry */
+       struct hws_diag_entry    diag;    /* Diagnostic-sampling data entry */
+       u8                  padding[];    /* Padding to next multiple of 8 */
+} __packed;
+
+/* Perf hardware reserve and release functions */
+int perf_reserve_sampling(void);
+void perf_release_sampling(void);
+
 #endif /* CONFIG_64BIT */
+#endif /* _ASM_S390_PERF_EVENT_H */
index 57d0d7e794b18a1976b2b5901d0409e53a69d9a8..d786c634e05206ee47271882a6030fac5d3f29b5 100644 (file)
@@ -336,7 +336,7 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
 #define QDIO_FLAG_CLEANUP_USING_HALT           0x02
 
 /**
- * struct qdio_initialize - qdio initalization data
+ * struct qdio_initialize - qdio initialization data
  * @cdev: associated ccw device
  * @q_format: queue format
  * @adapter_name: name for the adapter
@@ -378,6 +378,34 @@ struct qdio_initialize {
        struct qdio_outbuf_state *output_sbal_state_array;
 };
 
+/**
+ * enum qdio_brinfo_entry_type - type of address entry for qdio_brinfo_desc()
+ * @l3_ipv6_addr: entry contains IPv6 address
+ * @l3_ipv4_addr: entry contains IPv4 address
+ * @l2_addr_lnid: entry contains MAC address and VLAN ID
+ */
+enum qdio_brinfo_entry_type {l3_ipv6_addr, l3_ipv4_addr, l2_addr_lnid};
+
+/**
+ * struct qdio_brinfo_entry_XXX - Address entry for qdio_brinfo_desc()
+ * @nit:  Network interface token
+ * @addr: Address of one of the three types
+ *
+ * The struct is passed to the callback function by qdio_brinfo_desc()
+ */
+struct qdio_brinfo_entry_l3_ipv6 {
+       u64 nit;
+       struct { unsigned char _s6_addr[16]; } addr;
+} __packed;
+struct qdio_brinfo_entry_l3_ipv4 {
+       u64 nit;
+       struct { uint32_t _s_addr; } addr;
+} __packed;
+struct qdio_brinfo_entry_l2 {
+       u64 nit;
+       struct { u8 mac[6]; u16 lnid; } addr_lnid;
+} __packed;
+
 #define QDIO_STATE_INACTIVE            0x00000002 /* after qdio_cleanup */
 #define QDIO_STATE_ESTABLISHED         0x00000004 /* after qdio_establish */
 #define QDIO_STATE_ACTIVE              0x00000008 /* after qdio_activate */
@@ -399,5 +427,10 @@ extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *);
 extern int qdio_shutdown(struct ccw_device *, int);
 extern int qdio_free(struct ccw_device *);
 extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *);
+extern int qdio_pnso_brinfo(struct subchannel_id schid,
+               int cnc, u16 *response,
+               void (*cb)(void *priv, enum qdio_brinfo_entry_type type,
+                               void *entry),
+               void *priv);
 
 #endif /* __QDIO_H__ */
index 30ef748bc161eb3a7f52084ea763d54fe6ed09fc..220e171413f857210012d7a09f07dfb904c21a10 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <asm/chpid.h>
+#include <asm/cpu.h>
 
 #define SCLP_CHP_INFO_MASK_SIZE                32
 
@@ -37,7 +38,7 @@ struct sclp_cpu_info {
        unsigned int standby;
        unsigned int combined;
        int has_cpu_type;
-       struct sclp_cpu_entry cpu[255];
+       struct sclp_cpu_entry cpu[MAX_CPU_ADDRESS + 1];
 };
 
 int sclp_get_cpu_info(struct sclp_cpu_info *info);
@@ -51,8 +52,8 @@ int sclp_chp_configure(struct chp_id chpid);
 int sclp_chp_deconfigure(struct chp_id chpid);
 int sclp_chp_read_info(struct sclp_chp_info *info);
 void sclp_get_ipl_info(struct sclp_ipl_info *info);
-bool sclp_has_linemode(void);
-bool sclp_has_vt220(void);
+bool __init sclp_has_linemode(void);
+bool __init sclp_has_vt220(void);
 int sclp_pci_configure(u32 fid);
 int sclp_pci_deconfigure(u32 fid);
 int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
index ac9bed8e103fa741f85b3aecc64fcc9a18511c82..16077939409622fc946b943f4556d91cc272211c 100644 (file)
@@ -31,6 +31,7 @@ extern void smp_yield(void);
 extern void smp_stop_cpu(void);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
+extern void smp_fill_possible_mask(void);
 
 #else /* CONFIG_SMP */
 
@@ -50,6 +51,7 @@ static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_yield(void) { }
 static inline void smp_stop_cpu(void) { }
+static inline void smp_fill_possible_mask(void) { }
 
 #endif /* CONFIG_SMP */
 
index e83fc116f5bf2c24ceb4f4b9aa663d7d1c291b8f..f2b18eacaca80c969e79aed515d017fa8e061522 100644 (file)
@@ -154,6 +154,67 @@ struct ica_xcRB {
        unsigned short  priority_window;
        unsigned int    status;
 } __attribute__((packed));
+
+/**
+ * struct ep11_cprb - EP11 connectivity programming request block
+ * @cprb_len:          CPRB header length [0x0020]
+ * @cprb_ver_id:       CPRB version id.   [0x04]
+ * @pad_000:           Alignment pad bytes
+ * @flags:             Admin cmd [0x80] or functional cmd [0x00]
+ * @func_id:           Function id / subtype [0x5434]
+ * @source_id:         Source id [originator id]
+ * @target_id:         Target id [usage/ctrl domain id]
+ * @ret_code:          Return code
+ * @reserved1:         Reserved
+ * @reserved2:         Reserved
+ * @payload_len:       Payload length
+ */
+struct ep11_cprb {
+       uint16_t        cprb_len;
+       unsigned char   cprb_ver_id;
+       unsigned char   pad_000[2];
+       unsigned char   flags;
+       unsigned char   func_id[2];
+       uint32_t        source_id;
+       uint32_t        target_id;
+       uint32_t        ret_code;
+       uint32_t        reserved1;
+       uint32_t        reserved2;
+       uint32_t        payload_len;
+} __attribute__((packed));
+
+/**
+ * struct ep11_target_dev - EP11 target device list
+ * @ap_id:     AP device id
+ * @dom_id:    Usage domain id
+ */
+struct ep11_target_dev {
+       uint16_t ap_id;
+       uint16_t dom_id;
+};
+
+/**
+ * struct ep11_urb - EP11 user request block
+ * @targets_num:       Number of target adapters
+ * @targets:           Addr to target adapter list
+ * @weight:            Level of request priority
+ * @req_no:            Request id/number
+ * @req_len:           Request length
+ * @req:               Addr to request block
+ * @resp_len:          Response length
+ * @resp:              Addr to response block
+ */
+struct ep11_urb {
+       uint16_t                targets_num;
+       uint64_t                targets;
+       uint64_t                weight;
+       uint64_t                req_no;
+       uint64_t                req_len;
+       uint64_t                req;
+       uint64_t                resp_len;
+       uint64_t                resp;
+} __attribute__((packed));
+
 #define AUTOSELECT ((unsigned int)0xFFFFFFFF)
 
 #define ZCRYPT_IOCTL_MAGIC 'z'
@@ -183,6 +244,9 @@ struct ica_xcRB {
  *   ZSECSENDCPRB
  *     Send an arbitrary CPRB to a crypto card.
  *
+ *   ZSENDEP11CPRB
+ *     Send an arbitrary EP11 CPRB to an EP11 coprocessor crypto card.
+ *
  *   Z90STAT_STATUS_MASK
  *     Return an 64 element array of unsigned chars for the status of
  *     all devices.
@@ -256,6 +320,7 @@ struct ica_xcRB {
 #define ICARSAMODEXPO  _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x05, 0)
 #define ICARSACRT      _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0)
 #define ZSECSENDCPRB   _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0)
+#define ZSENDEP11CPRB  _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x04, 0)
 
 /* New status calls */
 #define Z90STAT_TOTALCOUNT     _IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int)
index 2403303cfed708d3ae73a0b0091cab67c21f6f9f..1b3ac09c11b6df2981ca3dbde3cc6df3fba5d2e9 100644 (file)
@@ -60,7 +60,8 @@ obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 
 ifdef CONFIG_64BIT
-obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_cpum_cf.o
+obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_cpum_cf.o perf_cpum_sf.o \
+                                               perf_cpum_cf_events.o
 obj-y                          += runtime_instr.o cache.o
 endif
 
index 496116cd65ec8ef3a1b566ac8c1c0641dfcad5f4..e4c99a1836511b16b90de5b4591bea5dc9fc8e69 100644 (file)
@@ -72,6 +72,7 @@ int main(void)
        /* constants used by the vdso */
        DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
        DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+       DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
        DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
        BLANK();
        /* idle data offsets */
index 95e7ba0fbb7eb1323b45300c4f6afcae04103dc8..8b84bc373e945bbb2edaba876addbbf5a850fcdd 100644 (file)
@@ -412,8 +412,9 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
                regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
        } else {
                regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
-               err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
-                                 (u16 __force __user *)(frame->retcode));
+               if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+                              (u16 __force __user *)(frame->retcode)))
+                       goto give_sigsegv;
        }
 
        /* Set up backchain. */
index e5b43c97a8340a807671ace329a4fa87a573709a..384e609b47110dc59c7a96cfa419e864cca86b2a 100644 (file)
@@ -74,7 +74,7 @@ _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
        .endm
 
        .macro LPP newpp
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+#if IS_ENABLED(CONFIG_KVM)
        tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_LPP
        jz      .+8
        .insn   s,0xb2800000,\newpp
@@ -82,7 +82,7 @@ _TIF_TRACE    = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
        .endm
 
        .macro  HANDLE_SIE_INTERCEPT scratch,reason
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+#if IS_ENABLED(CONFIG_KVM)
        tmhh    %r8,0x0001              # interrupting from user ?
        jnz     .+62
        lgr     \scratch,%r9
@@ -946,7 +946,7 @@ cleanup_idle_insn:
        .quad   __critical_end - __critical_start
 
 
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+#if IS_ENABLED(CONFIG_KVM)
 /*
  * sie64a calling convention:
  * %r2 pointer to sie control block
@@ -975,7 +975,7 @@ sie_done:
        lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
 # some program checks are suppressing. C code (e.g. do_protection_exception)
 # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
-# instructions beween sie64a and sie_done should not cause program
+# instructions between sie64a and sie_done should not cause program
 # interrupts. So lets use a nop (47 00 00 00) as a landing pad.
 # See also HANDLE_SIE_INTERCEPT
 rewind_pad:
index 1105502bf6e976c98bb63dbac703939dacab9677..f51214c0485884556151bfc63ecf0bdf88faafc7 100644 (file)
@@ -680,6 +680,7 @@ static int __init cpumf_pmu_init(void)
                goto out;
        }
 
+       cpumf_pmu.attr_groups = cpumf_cf_event_group();
        rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
        if (rc) {
                pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc);
diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c
new file mode 100644 (file)
index 0000000..4554a4b
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Perf PMU sysfs events attributes for available CPU-measurement counters
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+
+
+/* BEGIN: CPUM_CF COUNTER DEFINITIONS =================================== */
+
+CPUMF_EVENT_ATTR(cf, CPU_CYCLES, 0x0000);
+CPUMF_EVENT_ATTR(cf, INSTRUCTIONS, 0x0001);
+CPUMF_EVENT_ATTR(cf, L1I_DIR_WRITES, 0x0002);
+CPUMF_EVENT_ATTR(cf, L1I_PENALTY_CYCLES, 0x0003);
+CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_CPU_CYCLES, 0x0020);
+CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_INSTRUCTIONS, 0x0021);
+CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1I_DIR_WRITES, 0x0022);
+CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1I_PENALTY_CYCLES, 0x0023);
+CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1D_DIR_WRITES, 0x0024);
+CPUMF_EVENT_ATTR(cf, PROBLEM_STATE_L1D_PENALTY_CYCLES, 0x0025);
+CPUMF_EVENT_ATTR(cf, L1D_DIR_WRITES, 0x0004);
+CPUMF_EVENT_ATTR(cf, L1D_PENALTY_CYCLES, 0x0005);
+CPUMF_EVENT_ATTR(cf, PRNG_FUNCTIONS, 0x0040);
+CPUMF_EVENT_ATTR(cf, PRNG_CYCLES, 0x0041);
+CPUMF_EVENT_ATTR(cf, PRNG_BLOCKED_FUNCTIONS, 0x0042);
+CPUMF_EVENT_ATTR(cf, PRNG_BLOCKED_CYCLES, 0x0043);
+CPUMF_EVENT_ATTR(cf, SHA_FUNCTIONS, 0x0044);
+CPUMF_EVENT_ATTR(cf, SHA_CYCLES, 0x0045);
+CPUMF_EVENT_ATTR(cf, SHA_BLOCKED_FUNCTIONS, 0x0046);
+CPUMF_EVENT_ATTR(cf, SHA_BLOCKED_CYCLES, 0x0047);
+CPUMF_EVENT_ATTR(cf, DEA_FUNCTIONS, 0x0048);
+CPUMF_EVENT_ATTR(cf, DEA_CYCLES, 0x0049);
+CPUMF_EVENT_ATTR(cf, DEA_BLOCKED_FUNCTIONS, 0x004a);
+CPUMF_EVENT_ATTR(cf, DEA_BLOCKED_CYCLES, 0x004b);
+CPUMF_EVENT_ATTR(cf, AES_FUNCTIONS, 0x004c);
+CPUMF_EVENT_ATTR(cf, AES_CYCLES, 0x004d);
+CPUMF_EVENT_ATTR(cf, AES_BLOCKED_FUNCTIONS, 0x004e);
+CPUMF_EVENT_ATTR(cf, AES_BLOCKED_CYCLES, 0x004f);
+CPUMF_EVENT_ATTR(cf_z10, L1I_L2_SOURCED_WRITES, 0x0080);
+CPUMF_EVENT_ATTR(cf_z10, L1D_L2_SOURCED_WRITES, 0x0081);
+CPUMF_EVENT_ATTR(cf_z10, L1I_L3_LOCAL_WRITES, 0x0082);
+CPUMF_EVENT_ATTR(cf_z10, L1D_L3_LOCAL_WRITES, 0x0083);
+CPUMF_EVENT_ATTR(cf_z10, L1I_L3_REMOTE_WRITES, 0x0084);
+CPUMF_EVENT_ATTR(cf_z10, L1D_L3_REMOTE_WRITES, 0x0085);
+CPUMF_EVENT_ATTR(cf_z10, L1D_LMEM_SOURCED_WRITES, 0x0086);
+CPUMF_EVENT_ATTR(cf_z10, L1I_LMEM_SOURCED_WRITES, 0x0087);
+CPUMF_EVENT_ATTR(cf_z10, L1D_RO_EXCL_WRITES, 0x0088);
+CPUMF_EVENT_ATTR(cf_z10, L1I_CACHELINE_INVALIDATES, 0x0089);
+CPUMF_EVENT_ATTR(cf_z10, ITLB1_WRITES, 0x008a);
+CPUMF_EVENT_ATTR(cf_z10, DTLB1_WRITES, 0x008b);
+CPUMF_EVENT_ATTR(cf_z10, TLB2_PTE_WRITES, 0x008c);
+CPUMF_EVENT_ATTR(cf_z10, TLB2_CRSTE_WRITES, 0x008d);
+CPUMF_EVENT_ATTR(cf_z10, TLB2_CRSTE_HPAGE_WRITES, 0x008e);
+CPUMF_EVENT_ATTR(cf_z10, ITLB1_MISSES, 0x0091);
+CPUMF_EVENT_ATTR(cf_z10, DTLB1_MISSES, 0x0092);
+CPUMF_EVENT_ATTR(cf_z10, L2C_STORES_SENT, 0x0093);
+CPUMF_EVENT_ATTR(cf_z196, L1D_L2_SOURCED_WRITES, 0x0080);
+CPUMF_EVENT_ATTR(cf_z196, L1I_L2_SOURCED_WRITES, 0x0081);
+CPUMF_EVENT_ATTR(cf_z196, DTLB1_MISSES, 0x0082);
+CPUMF_EVENT_ATTR(cf_z196, ITLB1_MISSES, 0x0083);
+CPUMF_EVENT_ATTR(cf_z196, L2C_STORES_SENT, 0x0085);
+CPUMF_EVENT_ATTR(cf_z196, L1D_OFFBOOK_L3_SOURCED_WRITES, 0x0086);
+CPUMF_EVENT_ATTR(cf_z196, L1D_ONBOOK_L4_SOURCED_WRITES, 0x0087);
+CPUMF_EVENT_ATTR(cf_z196, L1I_ONBOOK_L4_SOURCED_WRITES, 0x0088);
+CPUMF_EVENT_ATTR(cf_z196, L1D_RO_EXCL_WRITES, 0x0089);
+CPUMF_EVENT_ATTR(cf_z196, L1D_OFFBOOK_L4_SOURCED_WRITES, 0x008a);
+CPUMF_EVENT_ATTR(cf_z196, L1I_OFFBOOK_L4_SOURCED_WRITES, 0x008b);
+CPUMF_EVENT_ATTR(cf_z196, DTLB1_HPAGE_WRITES, 0x008c);
+CPUMF_EVENT_ATTR(cf_z196, L1D_LMEM_SOURCED_WRITES, 0x008d);
+CPUMF_EVENT_ATTR(cf_z196, L1I_LMEM_SOURCED_WRITES, 0x008e);
+CPUMF_EVENT_ATTR(cf_z196, L1I_OFFBOOK_L3_SOURCED_WRITES, 0x008f);
+CPUMF_EVENT_ATTR(cf_z196, DTLB1_WRITES, 0x0090);
+CPUMF_EVENT_ATTR(cf_z196, ITLB1_WRITES, 0x0091);
+CPUMF_EVENT_ATTR(cf_z196, TLB2_PTE_WRITES, 0x0092);
+CPUMF_EVENT_ATTR(cf_z196, TLB2_CRSTE_HPAGE_WRITES, 0x0093);
+CPUMF_EVENT_ATTR(cf_z196, TLB2_CRSTE_WRITES, 0x0094);
+CPUMF_EVENT_ATTR(cf_z196, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0096);
+CPUMF_EVENT_ATTR(cf_z196, L1D_OFFCHIP_L3_SOURCED_WRITES, 0x0098);
+CPUMF_EVENT_ATTR(cf_z196, L1I_ONCHIP_L3_SOURCED_WRITES, 0x0099);
+CPUMF_EVENT_ATTR(cf_z196, L1I_OFFCHIP_L3_SOURCED_WRITES, 0x009b);
+CPUMF_EVENT_ATTR(cf_zec12, DTLB1_MISSES, 0x0080);
+CPUMF_EVENT_ATTR(cf_zec12, ITLB1_MISSES, 0x0081);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_L2I_SOURCED_WRITES, 0x0082);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_L2I_SOURCED_WRITES, 0x0083);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_L2D_SOURCED_WRITES, 0x0084);
+CPUMF_EVENT_ATTR(cf_zec12, DTLB1_WRITES, 0x0085);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_LMEM_SOURCED_WRITES, 0x0087);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_LMEM_SOURCED_WRITES, 0x0089);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_RO_EXCL_WRITES, 0x008a);
+CPUMF_EVENT_ATTR(cf_zec12, DTLB1_HPAGE_WRITES, 0x008b);
+CPUMF_EVENT_ATTR(cf_zec12, ITLB1_WRITES, 0x008c);
+CPUMF_EVENT_ATTR(cf_zec12, TLB2_PTE_WRITES, 0x008d);
+CPUMF_EVENT_ATTR(cf_zec12, TLB2_CRSTE_HPAGE_WRITES, 0x008e);
+CPUMF_EVENT_ATTR(cf_zec12, TLB2_CRSTE_WRITES, 0x008f);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0090);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES, 0x0091);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES, 0x0092);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_ONBOOK_L4_SOURCED_WRITES, 0x0093);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L4_SOURCED_WRITES, 0x0094);
+CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TEND, 0x0095);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES_IV, 0x0096);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES_IV, 0x0097);
+CPUMF_EVENT_ATTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES_IV, 0x0098);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES, 0x0099);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES, 0x009a);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES, 0x009b);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_ONBOOK_L4_SOURCED_WRITES, 0x009c);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L4_SOURCED_WRITES, 0x009d);
+CPUMF_EVENT_ATTR(cf_zec12, TX_C_TEND, 0x009e);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES_IV, 0x009f);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES_IV, 0x00a0);
+CPUMF_EVENT_ATTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV, 0x00a1);
+CPUMF_EVENT_ATTR(cf_zec12, TX_NC_TABORT, 0x00b1);
+CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_NO_SPECIAL, 0x00b2);
+CPUMF_EVENT_ATTR(cf_zec12, TX_C_TABORT_SPECIAL, 0x00b3);
+
+static struct attribute *cpumcf_pmu_event_attr[] = {
+       CPUMF_EVENT_PTR(cf, CPU_CYCLES),
+       CPUMF_EVENT_PTR(cf, INSTRUCTIONS),
+       CPUMF_EVENT_PTR(cf, L1I_DIR_WRITES),
+       CPUMF_EVENT_PTR(cf, L1I_PENALTY_CYCLES),
+       CPUMF_EVENT_PTR(cf, PROBLEM_STATE_CPU_CYCLES),
+       CPUMF_EVENT_PTR(cf, PROBLEM_STATE_INSTRUCTIONS),
+       CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1I_DIR_WRITES),
+       CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1I_PENALTY_CYCLES),
+       CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1D_DIR_WRITES),
+       CPUMF_EVENT_PTR(cf, PROBLEM_STATE_L1D_PENALTY_CYCLES),
+       CPUMF_EVENT_PTR(cf, L1D_DIR_WRITES),
+       CPUMF_EVENT_PTR(cf, L1D_PENALTY_CYCLES),
+       CPUMF_EVENT_PTR(cf, PRNG_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, PRNG_CYCLES),
+       CPUMF_EVENT_PTR(cf, PRNG_BLOCKED_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, PRNG_BLOCKED_CYCLES),
+       CPUMF_EVENT_PTR(cf, SHA_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, SHA_CYCLES),
+       CPUMF_EVENT_PTR(cf, SHA_BLOCKED_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, SHA_BLOCKED_CYCLES),
+       CPUMF_EVENT_PTR(cf, DEA_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, DEA_CYCLES),
+       CPUMF_EVENT_PTR(cf, DEA_BLOCKED_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, DEA_BLOCKED_CYCLES),
+       CPUMF_EVENT_PTR(cf, AES_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, AES_CYCLES),
+       CPUMF_EVENT_PTR(cf, AES_BLOCKED_FUNCTIONS),
+       CPUMF_EVENT_PTR(cf, AES_BLOCKED_CYCLES),
+       NULL,
+};
+
+static struct attribute *cpumcf_z10_pmu_event_attr[] __initdata = {
+       CPUMF_EVENT_PTR(cf_z10, L1I_L2_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1D_L2_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1I_L3_LOCAL_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1D_L3_LOCAL_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1I_L3_REMOTE_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1D_L3_REMOTE_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1D_LMEM_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1I_LMEM_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1D_RO_EXCL_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, L1I_CACHELINE_INVALIDATES),
+       CPUMF_EVENT_PTR(cf_z10, ITLB1_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, DTLB1_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, TLB2_PTE_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, TLB2_CRSTE_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, TLB2_CRSTE_HPAGE_WRITES),
+       CPUMF_EVENT_PTR(cf_z10, ITLB1_MISSES),
+       CPUMF_EVENT_PTR(cf_z10, DTLB1_MISSES),
+       CPUMF_EVENT_PTR(cf_z10, L2C_STORES_SENT),
+       NULL,
+};
+
+static struct attribute *cpumcf_z196_pmu_event_attr[] __initdata = {
+       CPUMF_EVENT_PTR(cf_z196, L1D_L2_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_L2_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, DTLB1_MISSES),
+       CPUMF_EVENT_PTR(cf_z196, ITLB1_MISSES),
+       CPUMF_EVENT_PTR(cf_z196, L2C_STORES_SENT),
+       CPUMF_EVENT_PTR(cf_z196, L1D_OFFBOOK_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1D_ONBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_ONBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1D_RO_EXCL_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1D_OFFBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_OFFBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, DTLB1_HPAGE_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1D_LMEM_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_LMEM_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_OFFBOOK_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, DTLB1_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, ITLB1_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, TLB2_PTE_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, TLB2_CRSTE_HPAGE_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, TLB2_CRSTE_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1D_ONCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1D_OFFCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_ONCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_z196, L1I_OFFCHIP_L3_SOURCED_WRITES),
+       NULL,
+};
+
+static struct attribute *cpumcf_zec12_pmu_event_attr[] __initdata = {
+       CPUMF_EVENT_PTR(cf_zec12, DTLB1_MISSES),
+       CPUMF_EVENT_PTR(cf_zec12, ITLB1_MISSES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_L2I_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_L2I_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_L2D_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, DTLB1_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_LMEM_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_LMEM_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_RO_EXCL_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, DTLB1_HPAGE_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, ITLB1_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, TLB2_PTE_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, TLB2_CRSTE_HPAGE_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, TLB2_CRSTE_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_ONBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, TX_NC_TEND),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_ONCHIP_L3_SOURCED_WRITES_IV),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_OFFCHIP_L3_SOURCED_WRITES_IV),
+       CPUMF_EVENT_PTR(cf_zec12, L1D_OFFBOOK_L3_SOURCED_WRITES_IV),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_ONBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L4_SOURCED_WRITES),
+       CPUMF_EVENT_PTR(cf_zec12, TX_C_TEND),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_ONCHIP_L3_SOURCED_WRITES_IV),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_OFFCHIP_L3_SOURCED_WRITES_IV),
+       CPUMF_EVENT_PTR(cf_zec12, L1I_OFFBOOK_L3_SOURCED_WRITES_IV),
+       CPUMF_EVENT_PTR(cf_zec12, TX_NC_TABORT),
+       CPUMF_EVENT_PTR(cf_zec12, TX_C_TABORT_NO_SPECIAL),
+       CPUMF_EVENT_PTR(cf_zec12, TX_C_TABORT_SPECIAL),
+       NULL,
+};
+
+/* END: CPUM_CF COUNTER DEFINITIONS ===================================== */
+
+static struct attribute_group cpumsf_pmu_events_group = {
+       .name = "events",
+       .attrs = cpumcf_pmu_event_attr,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-63");
+
+static struct attribute *cpumsf_pmu_format_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group cpumsf_pmu_format_group = {
+       .name = "format",
+       .attrs = cpumsf_pmu_format_attr,
+};
+
+static const struct attribute_group *cpumsf_pmu_attr_groups[] = {
+       &cpumsf_pmu_events_group,
+       &cpumsf_pmu_format_group,
+       NULL,
+};
+
+
+static __init struct attribute **merge_attr(struct attribute **a,
+                                           struct attribute **b)
+{
+       struct attribute **new;
+       int j, i;
+
+       for (j = 0; a[j]; j++)
+               ;
+       for (i = 0; b[i]; i++)
+               j++;
+       j++;
+
+       new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL);
+       if (!new)
+               return NULL;
+       j = 0;
+       for (i = 0; a[i]; i++)
+               new[j++] = a[i];
+       for (i = 0; b[i]; i++)
+               new[j++] = b[i];
+       new[j] = NULL;
+
+       return new;
+}
+
+__init const struct attribute_group **cpumf_cf_event_group(void)
+{
+       struct attribute **combined, **model;
+       struct cpuid cpu_id;
+
+       get_cpu_id(&cpu_id);
+       switch (cpu_id.machine) {
+       case 0x2097:
+       case 0x2098:
+               model = cpumcf_z10_pmu_event_attr;
+               break;
+       case 0x2817:
+       case 0x2818:
+               model = cpumcf_z196_pmu_event_attr;
+               break;
+       case 0x2827:
+       case 0x2828:
+               model = cpumcf_zec12_pmu_event_attr;
+               break;
+       default:
+               model = NULL;
+               break;
+       };
+
+       if (!model)
+               goto out;
+
+       combined = merge_attr(cpumcf_pmu_event_attr, model);
+       if (combined)
+               cpumsf_pmu_events_group.attrs = combined;
+out:
+       return cpumsf_pmu_attr_groups;
+}
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
new file mode 100644 (file)
index 0000000..6c0d298
--- /dev/null
@@ -0,0 +1,1641 @@
+/*
+ * Performance event support for the System z CPU-measurement Sampling Facility
+ *
+ * Copyright IBM Corp. 2013
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.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 only)
+ * as published by the Free Software Foundation.
+ */
+#define KMSG_COMPONENT "cpum_sf"
+#define pr_fmt(fmt)    KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/perf_event.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <asm/cpu_mf.h>
+#include <asm/irq.h>
+#include <asm/debug.h>
+#include <asm/timex.h>
+
+/* Minimum number of sample-data-block-tables:
+ * At least one table is required for the sampling buffer structure.
+ * A single table contains up to 511 pointers to sample-data-blocks.
+ */
+#define CPUM_SF_MIN_SDBT       1
+
+/* Number of sample-data-blocks per sample-data-block-table (SDBT):
+ * A table contains SDB pointers (8 bytes) and one table-link entry
+ * that points to the origin of the next SDBT.
+ */
+#define CPUM_SF_SDB_PER_TABLE  ((PAGE_SIZE - 8) / 8)
+
+/* Maximum page offset for an SDBT table-link entry:
+ * If this page offset is reached, a table-link entry to the next SDBT
+ * must be added.
+ */
+#define CPUM_SF_SDBT_TL_OFFSET (CPUM_SF_SDB_PER_TABLE * 8)
+static inline int require_table_link(const void *sdbt)
+{
+       return ((unsigned long) sdbt & ~PAGE_MASK) == CPUM_SF_SDBT_TL_OFFSET;
+}
+
+/* Minimum and maximum sampling buffer sizes:
+ *
+ * This number represents the maximum size of the sampling buffer taking
+ * the number of sample-data-block-tables into account.  Note that these
+ * numbers apply to the basic-sampling function only.
+ * The maximum number of SDBs is increased by CPUM_SF_SDB_DIAG_FACTOR if
+ * the diagnostic-sampling function is active.
+ *
+ * Sampling buffer size                Buffer characteristics
+ * ---------------------------------------------------
+ *      64KB               ==    16 pages (4KB per page)
+ *                                1 page  for SDB-tables
+ *                               15 pages for SDBs
+ *
+ *  32MB                   ==  8192 pages (4KB per page)
+ *                               16 pages for SDB-tables
+ *                             8176 pages for SDBs
+ */
+static unsigned long __read_mostly CPUM_SF_MIN_SDB = 15;
+static unsigned long __read_mostly CPUM_SF_MAX_SDB = 8176;
+static unsigned long __read_mostly CPUM_SF_SDB_DIAG_FACTOR = 1;
+
+struct sf_buffer {
+       unsigned long    *sdbt;     /* Sample-data-block-table origin */
+       /* buffer characteristics (required for buffer increments) */
+       unsigned long  num_sdb;     /* Number of sample-data-blocks */
+       unsigned long num_sdbt;     /* Number of sample-data-block-tables */
+       unsigned long    *tail;     /* last sample-data-block-table */
+};
+
+struct cpu_hw_sf {
+       /* CPU-measurement sampling information block */
+       struct hws_qsi_info_block qsi;
+       /* CPU-measurement sampling control block */
+       struct hws_lsctl_request_block lsctl;
+       struct sf_buffer sfb;       /* Sampling buffer */
+       unsigned int flags;         /* Status flags */
+       struct perf_event *event;   /* Scheduled perf event */
+};
+static DEFINE_PER_CPU(struct cpu_hw_sf, cpu_hw_sf);
+
+/* Debug feature */
+static debug_info_t *sfdbg;
+
+/*
+ * sf_disable() - Switch off sampling facility
+ */
+static int sf_disable(void)
+{
+       struct hws_lsctl_request_block sreq;
+
+       memset(&sreq, 0, sizeof(sreq));
+       return lsctl(&sreq);
+}
+
+/*
+ * sf_buffer_available() - Check for an allocated sampling buffer
+ */
+static int sf_buffer_available(struct cpu_hw_sf *cpuhw)
+{
+       return !!cpuhw->sfb.sdbt;
+}
+
+/*
+ * deallocate sampling facility buffer
+ */
+static void free_sampling_buffer(struct sf_buffer *sfb)
+{
+       unsigned long *sdbt, *curr;
+
+       if (!sfb->sdbt)
+               return;
+
+       sdbt = sfb->sdbt;
+       curr = sdbt;
+
+       /* Free the SDBT after all SDBs are processed... */
+       while (1) {
+               if (!*curr || !sdbt)
+                       break;
+
+               /* Process table-link entries */
+               if (is_link_entry(curr)) {
+                       curr = get_next_sdbt(curr);
+                       if (sdbt)
+                               free_page((unsigned long) sdbt);
+
+                       /* If the origin is reached, sampling buffer is freed */
+                       if (curr == sfb->sdbt)
+                               break;
+                       else
+                               sdbt = curr;
+               } else {
+                       /* Process SDB pointer */
+                       if (*curr) {
+                               free_page(*curr);
+                               curr++;
+                       }
+               }
+       }
+
+       debug_sprintf_event(sfdbg, 5,
+                           "free_sampling_buffer: freed sdbt=%p\n", sfb->sdbt);
+       memset(sfb, 0, sizeof(*sfb));
+}
+
+static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags)
+{
+       unsigned long sdb, *trailer;
+
+       /* Allocate and initialize sample-data-block */
+       sdb = get_zeroed_page(gfp_flags);
+       if (!sdb)
+               return -ENOMEM;
+       trailer = trailer_entry_ptr(sdb);
+       *trailer = SDB_TE_ALERT_REQ_MASK;
+
+       /* Link SDB into the sample-data-block-table */
+       *sdbt = sdb;
+
+       return 0;
+}
+
+/*
+ * realloc_sampling_buffer() - extend sampler memory
+ *
+ * Allocates new sample-data-blocks and adds them to the specified sampling
+ * buffer memory.
+ *
+ * Important: This modifies the sampling buffer and must be called when the
+ *           sampling facility is disabled.
+ *
+ * Returns zero on success, non-zero otherwise.
+ */
+static int realloc_sampling_buffer(struct sf_buffer *sfb,
+                                  unsigned long num_sdb, gfp_t gfp_flags)
+{
+       int i, rc;
+       unsigned long *new, *tail;
+
+       if (!sfb->sdbt || !sfb->tail)
+               return -EINVAL;
+
+       if (!is_link_entry(sfb->tail))
+               return -EINVAL;
+
+       /* Append to the existing sampling buffer, overwriting the table-link
+        * register.
+        * The tail variables always points to the "tail" (last and table-link)
+        * entry in an SDB-table.
+        */
+       tail = sfb->tail;
+
+       /* Do a sanity check whether the table-link entry points to
+        * the sampling buffer origin.
+        */
+       if (sfb->sdbt != get_next_sdbt(tail)) {
+               debug_sprintf_event(sfdbg, 3, "realloc_sampling_buffer: "
+                                   "sampling buffer is not linked: origin=%p"
+                                   "tail=%p\n",
+                                   (void *) sfb->sdbt, (void *) tail);
+               return -EINVAL;
+       }
+
+       /* Allocate remaining SDBs */
+       rc = 0;
+       for (i = 0; i < num_sdb; i++) {
+               /* Allocate a new SDB-table if it is full. */
+               if (require_table_link(tail)) {
+                       new = (unsigned long *) get_zeroed_page(gfp_flags);
+                       if (!new) {
+                               rc = -ENOMEM;
+                               break;
+                       }
+                       sfb->num_sdbt++;
+                       /* Link current page to tail of chain */
+                       *tail = (unsigned long)(void *) new + 1;
+                       tail = new;
+               }
+
+               /* Allocate a new sample-data-block.
+                * If there is not enough memory, stop the realloc process
+                * and simply use what was allocated.  If this is a temporary
+                * issue, a new realloc call (if required) might succeed.
+                */
+               rc = alloc_sample_data_block(tail, gfp_flags);
+               if (rc)
+                       break;
+               sfb->num_sdb++;
+               tail++;
+       }
+
+       /* Link sampling buffer to its origin */
+       *tail = (unsigned long) sfb->sdbt + 1;
+       sfb->tail = tail;
+
+       debug_sprintf_event(sfdbg, 4, "realloc_sampling_buffer: new buffer"
+                           " settings: sdbt=%lu sdb=%lu\n",
+                           sfb->num_sdbt, sfb->num_sdb);
+       return rc;
+}
+
+/*
+ * allocate_sampling_buffer() - allocate sampler memory
+ *
+ * Allocates and initializes a sampling buffer structure using the
+ * specified number of sample-data-blocks (SDB).  For each allocation,
+ * a 4K page is used.  The number of sample-data-block-tables (SDBT)
+ * are calculated from SDBs.
+ * Also set the ALERT_REQ mask in each SDBs trailer.
+ *
+ * Returns zero on success, non-zero otherwise.
+ */
+static int alloc_sampling_buffer(struct sf_buffer *sfb, unsigned long num_sdb)
+{
+       int rc;
+
+       if (sfb->sdbt)
+               return -EINVAL;
+
+       /* Allocate the sample-data-block-table origin */
+       sfb->sdbt = (unsigned long *) get_zeroed_page(GFP_KERNEL);
+       if (!sfb->sdbt)
+               return -ENOMEM;
+       sfb->num_sdb = 0;
+       sfb->num_sdbt = 1;
+
+       /* Link the table origin to point to itself to prepare for
+        * realloc_sampling_buffer() invocation.
+        */
+       sfb->tail = sfb->sdbt;
+       *sfb->tail = (unsigned long)(void *) sfb->sdbt + 1;
+
+       /* Allocate requested number of sample-data-blocks */
+       rc = realloc_sampling_buffer(sfb, num_sdb, GFP_KERNEL);
+       if (rc) {
+               free_sampling_buffer(sfb);
+               debug_sprintf_event(sfdbg, 4, "alloc_sampling_buffer: "
+                       "realloc_sampling_buffer failed with rc=%i\n", rc);
+       } else
+               debug_sprintf_event(sfdbg, 4,
+                       "alloc_sampling_buffer: tear=%p dear=%p\n",
+                       sfb->sdbt, (void *) *sfb->sdbt);
+       return rc;
+}
+
+static void sfb_set_limits(unsigned long min, unsigned long max)
+{
+       struct hws_qsi_info_block si;
+
+       CPUM_SF_MIN_SDB = min;
+       CPUM_SF_MAX_SDB = max;
+
+       memset(&si, 0, sizeof(si));
+       if (!qsi(&si))
+               CPUM_SF_SDB_DIAG_FACTOR = DIV_ROUND_UP(si.dsdes, si.bsdes);
+}
+
+static unsigned long sfb_max_limit(struct hw_perf_event *hwc)
+{
+       return SAMPL_DIAG_MODE(hwc) ? CPUM_SF_MAX_SDB * CPUM_SF_SDB_DIAG_FACTOR
+                                   : CPUM_SF_MAX_SDB;
+}
+
+static unsigned long sfb_pending_allocs(struct sf_buffer *sfb,
+                                       struct hw_perf_event *hwc)
+{
+       if (!sfb->sdbt)
+               return SFB_ALLOC_REG(hwc);
+       if (SFB_ALLOC_REG(hwc) > sfb->num_sdb)
+               return SFB_ALLOC_REG(hwc) - sfb->num_sdb;
+       return 0;
+}
+
+static int sfb_has_pending_allocs(struct sf_buffer *sfb,
+                                  struct hw_perf_event *hwc)
+{
+       return sfb_pending_allocs(sfb, hwc) > 0;
+}
+
+static void sfb_account_allocs(unsigned long num, struct hw_perf_event *hwc)
+{
+       /* Limit the number of SDBs to not exceed the maximum */
+       num = min_t(unsigned long, num, sfb_max_limit(hwc) - SFB_ALLOC_REG(hwc));
+       if (num)
+               SFB_ALLOC_REG(hwc) += num;
+}
+
+static void sfb_init_allocs(unsigned long num, struct hw_perf_event *hwc)
+{
+       SFB_ALLOC_REG(hwc) = 0;
+       sfb_account_allocs(num, hwc);
+}
+
+static size_t event_sample_size(struct hw_perf_event *hwc)
+{
+       struct sf_raw_sample *sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc);
+       size_t sample_size;
+
+       /* The sample size depends on the sampling function: The basic-sampling
+        * function must be always enabled, diagnostic-sampling function is
+        * optional.
+        */
+       sample_size = sfr->bsdes;
+       if (SAMPL_DIAG_MODE(hwc))
+               sample_size += sfr->dsdes;
+
+       return sample_size;
+}
+
+static void deallocate_buffers(struct cpu_hw_sf *cpuhw)
+{
+       if (cpuhw->sfb.sdbt)
+               free_sampling_buffer(&cpuhw->sfb);
+}
+
+static int allocate_buffers(struct cpu_hw_sf *cpuhw, struct hw_perf_event *hwc)
+{
+       unsigned long n_sdb, freq, factor;
+       size_t sfr_size, sample_size;
+       struct sf_raw_sample *sfr;
+
+       /* Allocate raw sample buffer
+        *
+        *    The raw sample buffer is used to temporarily store sampling data
+        *    entries for perf raw sample processing.  The buffer size mainly
+        *    depends on the size of diagnostic-sampling data entries which is
+        *    machine-specific.  The exact size calculation includes:
+        *      1. The first 4 bytes of diagnostic-sampling data entries are
+        *         already reflected in the sf_raw_sample structure.  Subtract
+        *         these bytes.
+        *      2. The perf raw sample data must be 8-byte aligned (u64) and
+        *         perf's internal data size must be considered too.  So add
+        *         an additional u32 for correct alignment and subtract before
+        *         allocating the buffer.
+        *      3. Store the raw sample buffer pointer in the perf event
+        *         hardware structure.
+        */
+       sfr_size = ALIGN((sizeof(*sfr) - sizeof(sfr->diag) + cpuhw->qsi.dsdes) +
+                        sizeof(u32), sizeof(u64));
+       sfr_size -= sizeof(u32);
+       sfr = kzalloc(sfr_size, GFP_KERNEL);
+       if (!sfr)
+               return -ENOMEM;
+       sfr->size = sfr_size;
+       sfr->bsdes = cpuhw->qsi.bsdes;
+       sfr->dsdes = cpuhw->qsi.dsdes;
+       RAWSAMPLE_REG(hwc) = (unsigned long) sfr;
+
+       /* Calculate sampling buffers using 4K pages
+        *
+        *    1. Determine the sample data size which depends on the used
+        *       sampling functions, for example, basic-sampling or
+        *       basic-sampling with diagnostic-sampling.
+        *
+        *    2. Use the sampling frequency as input.  The sampling buffer is
+        *       designed for almost one second.  This can be adjusted through
+        *       the "factor" variable.
+        *       In any case, alloc_sampling_buffer() sets the Alert Request
+        *       Control indicator to trigger a measurement-alert to harvest
+        *       sample-data-blocks (sdb).
+        *
+        *    3. Compute the number of sample-data-blocks and ensure a minimum
+        *       of CPUM_SF_MIN_SDB.  Also ensure the upper limit does not
+        *       exceed a "calculated" maximum.  The symbolic maximum is
+        *       designed for basic-sampling only and needs to be increased if
+        *       diagnostic-sampling is active.
+        *       See also the remarks for these symbolic constants.
+        *
+        *    4. Compute the number of sample-data-block-tables (SDBT) and
+        *       ensure a minimum of CPUM_SF_MIN_SDBT (one table can manage up
+        *       to 511 SDBs).
+        */
+       sample_size = event_sample_size(hwc);
+       freq = sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc));
+       factor = 1;
+       n_sdb = DIV_ROUND_UP(freq, factor * ((PAGE_SIZE-64) / sample_size));
+       if (n_sdb < CPUM_SF_MIN_SDB)
+               n_sdb = CPUM_SF_MIN_SDB;
+
+       /* If there is already a sampling buffer allocated, it is very likely
+        * that the sampling facility is enabled too.  If the event to be
+        * initialized requires a greater sampling buffer, the allocation must
+        * be postponed.  Changing the sampling buffer requires the sampling
+        * facility to be in the disabled state.  So, account the number of
+        * required SDBs and let cpumsf_pmu_enable() resize the buffer just
+        * before the event is started.
+        */
+       sfb_init_allocs(n_sdb, hwc);
+       if (sf_buffer_available(cpuhw))
+               return 0;
+
+       debug_sprintf_event(sfdbg, 3,
+                           "allocate_buffers: rate=%lu f=%lu sdb=%lu/%lu"
+                           " sample_size=%lu cpuhw=%p\n",
+                           SAMPL_RATE(hwc), freq, n_sdb, sfb_max_limit(hwc),
+                           sample_size, cpuhw);
+
+       return alloc_sampling_buffer(&cpuhw->sfb,
+                                    sfb_pending_allocs(&cpuhw->sfb, hwc));
+}
+
+static unsigned long min_percent(unsigned int percent, unsigned long base,
+                                unsigned long min)
+{
+       return min_t(unsigned long, min, DIV_ROUND_UP(percent * base, 100));
+}
+
+static unsigned long compute_sfb_extent(unsigned long ratio, unsigned long base)
+{
+       /* Use a percentage-based approach to extend the sampling facility
+        * buffer.  Accept up to 5% sample data loss.
+        * Vary the extents between 1% to 5% of the current number of
+        * sample-data-blocks.
+        */
+       if (ratio <= 5)
+               return 0;
+       if (ratio <= 25)
+               return min_percent(1, base, 1);
+       if (ratio <= 50)
+               return min_percent(1, base, 1);
+       if (ratio <= 75)
+               return min_percent(2, base, 2);
+       if (ratio <= 100)
+               return min_percent(3, base, 3);
+       if (ratio <= 250)
+               return min_percent(4, base, 4);
+
+       return min_percent(5, base, 8);
+}
+
+static void sfb_account_overflows(struct cpu_hw_sf *cpuhw,
+                                 struct hw_perf_event *hwc)
+{
+       unsigned long ratio, num;
+
+       if (!OVERFLOW_REG(hwc))
+               return;
+
+       /* The sample_overflow contains the average number of sample data
+        * that has been lost because sample-data-blocks were full.
+        *
+        * Calculate the total number of sample data entries that has been
+        * discarded.  Then calculate the ratio of lost samples to total samples
+        * per second in percent.
+        */
+       ratio = DIV_ROUND_UP(100 * OVERFLOW_REG(hwc) * cpuhw->sfb.num_sdb,
+                            sample_rate_to_freq(&cpuhw->qsi, SAMPL_RATE(hwc)));
+
+       /* Compute number of sample-data-blocks */
+       num = compute_sfb_extent(ratio, cpuhw->sfb.num_sdb);
+       if (num)
+               sfb_account_allocs(num, hwc);
+
+       debug_sprintf_event(sfdbg, 5, "sfb: overflow: overflow=%llu ratio=%lu"
+                           " num=%lu\n", OVERFLOW_REG(hwc), ratio, num);
+       OVERFLOW_REG(hwc) = 0;
+}
+
+/* extend_sampling_buffer() - Extend sampling buffer
+ * @sfb:       Sampling buffer structure (for local CPU)
+ * @hwc:       Perf event hardware structure
+ *
+ * Use this function to extend the sampling buffer based on the overflow counter
+ * and postponed allocation extents stored in the specified Perf event hardware.
+ *
+ * Important: This function disables the sampling facility in order to safely
+ *           change the sampling buffer structure.  Do not call this function
+ *           when the PMU is active.
+ */
+static void extend_sampling_buffer(struct sf_buffer *sfb,
+                                  struct hw_perf_event *hwc)
+{
+       unsigned long num, num_old;
+       int rc;
+
+       num = sfb_pending_allocs(sfb, hwc);
+       if (!num)
+               return;
+       num_old = sfb->num_sdb;
+
+       /* Disable the sampling facility to reset any states and also
+        * clear pending measurement alerts.
+        */
+       sf_disable();
+
+       /* Extend the sampling buffer.
+        * This memory allocation typically happens in an atomic context when
+        * called by perf.  Because this is a reallocation, it is fine if the
+        * new SDB-request cannot be satisfied immediately.
+        */
+       rc = realloc_sampling_buffer(sfb, num, GFP_ATOMIC);
+       if (rc)
+               debug_sprintf_event(sfdbg, 5, "sfb: extend: realloc "
+                                   "failed with rc=%i\n", rc);
+
+       if (sfb_has_pending_allocs(sfb, hwc))
+               debug_sprintf_event(sfdbg, 5, "sfb: extend: "
+                                   "req=%lu alloc=%lu remaining=%lu\n",
+                                   num, sfb->num_sdb - num_old,
+                                   sfb_pending_allocs(sfb, hwc));
+}
+
+
+/* Number of perf events counting hardware events */
+static atomic_t num_events;
+/* Used to avoid races in calling reserve/release_cpumf_hardware */
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+#define PMC_INIT      0
+#define PMC_RELEASE   1
+#define PMC_FAILURE   2
+static void setup_pmc_cpu(void *flags)
+{
+       int err;
+       struct cpu_hw_sf *cpusf = &__get_cpu_var(cpu_hw_sf);
+
+       err = 0;
+       switch (*((int *) flags)) {
+       case PMC_INIT:
+               memset(cpusf, 0, sizeof(*cpusf));
+               err = qsi(&cpusf->qsi);
+               if (err)
+                       break;
+               cpusf->flags |= PMU_F_RESERVED;
+               err = sf_disable();
+               if (err)
+                       pr_err("Switching off the sampling facility failed "
+                              "with rc=%i\n", err);
+               debug_sprintf_event(sfdbg, 5,
+                                   "setup_pmc_cpu: initialized: cpuhw=%p\n", cpusf);
+               break;
+       case PMC_RELEASE:
+               cpusf->flags &= ~PMU_F_RESERVED;
+               err = sf_disable();
+               if (err) {
+                       pr_err("Switching off the sampling facility failed "
+                              "with rc=%i\n", err);
+               } else
+                       deallocate_buffers(cpusf);
+               debug_sprintf_event(sfdbg, 5,
+                                   "setup_pmc_cpu: released: cpuhw=%p\n", cpusf);
+               break;
+       }
+       if (err)
+               *((int *) flags) |= PMC_FAILURE;
+}
+
+static void release_pmc_hardware(void)
+{
+       int flags = PMC_RELEASE;
+
+       irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
+       on_each_cpu(setup_pmc_cpu, &flags, 1);
+       perf_release_sampling();
+}
+
+static int reserve_pmc_hardware(void)
+{
+       int flags = PMC_INIT;
+       int err;
+
+       err = perf_reserve_sampling();
+       if (err)
+               return err;
+       on_each_cpu(setup_pmc_cpu, &flags, 1);
+       if (flags & PMC_FAILURE) {
+               release_pmc_hardware();
+               return -ENODEV;
+       }
+       irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT);
+
+       return 0;
+}
+
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+       /* Free raw sample buffer */
+       if (RAWSAMPLE_REG(&event->hw))
+               kfree((void *) RAWSAMPLE_REG(&event->hw));
+
+       /* Release PMC if this is the last perf event */
+       if (!atomic_add_unless(&num_events, -1, 1)) {
+               mutex_lock(&pmc_reserve_mutex);
+               if (atomic_dec_return(&num_events) == 0)
+                       release_pmc_hardware();
+               mutex_unlock(&pmc_reserve_mutex);
+       }
+}
+
+static void hw_init_period(struct hw_perf_event *hwc, u64 period)
+{
+       hwc->sample_period = period;
+       hwc->last_period = hwc->sample_period;
+       local64_set(&hwc->period_left, hwc->sample_period);
+}
+
+static void hw_reset_registers(struct hw_perf_event *hwc,
+                              unsigned long *sdbt_origin)
+{
+       struct sf_raw_sample *sfr;
+
+       /* (Re)set to first sample-data-block-table */
+       TEAR_REG(hwc) = (unsigned long) sdbt_origin;
+
+       /* (Re)set raw sampling buffer register */
+       sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(hwc);
+       memset(&sfr->basic, 0, sizeof(sfr->basic));
+       memset(&sfr->diag, 0, sfr->dsdes);
+}
+
+static unsigned long hw_limit_rate(const struct hws_qsi_info_block *si,
+                                  unsigned long rate)
+{
+       return clamp_t(unsigned long, rate,
+                      si->min_sampl_rate, si->max_sampl_rate);
+}
+
+static int __hw_perf_event_init(struct perf_event *event)
+{
+       struct cpu_hw_sf *cpuhw;
+       struct hws_qsi_info_block si;
+       struct perf_event_attr *attr = &event->attr;
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long rate;
+       int cpu, err;
+
+       /* Reserve CPU-measurement sampling facility */
+       err = 0;
+       if (!atomic_inc_not_zero(&num_events)) {
+               mutex_lock(&pmc_reserve_mutex);
+               if (atomic_read(&num_events) == 0 && reserve_pmc_hardware())
+                       err = -EBUSY;
+               else
+                       atomic_inc(&num_events);
+               mutex_unlock(&pmc_reserve_mutex);
+       }
+       event->destroy = hw_perf_event_destroy;
+
+       if (err)
+               goto out;
+
+       /* Access per-CPU sampling information (query sampling info) */
+       /*
+        * The event->cpu value can be -1 to count on every CPU, for example,
+        * when attaching to a task.  If this is specified, use the query
+        * sampling info from the current CPU, otherwise use event->cpu to
+        * retrieve the per-CPU information.
+        * Later, cpuhw indicates whether to allocate sampling buffers for a
+        * particular CPU (cpuhw!=NULL) or each online CPU (cpuw==NULL).
+        */
+       memset(&si, 0, sizeof(si));
+       cpuhw = NULL;
+       if (event->cpu == -1)
+               qsi(&si);
+       else {
+               /* Event is pinned to a particular CPU, retrieve the per-CPU
+                * sampling structure for accessing the CPU-specific QSI.
+                */
+               cpuhw = &per_cpu(cpu_hw_sf, event->cpu);
+               si = cpuhw->qsi;
+       }
+
+       /* Check sampling facility authorization and, if not authorized,
+        * fall back to other PMUs.  It is safe to check any CPU because
+        * the authorization is identical for all configured CPUs.
+        */
+       if (!si.as) {
+               err = -ENOENT;
+               goto out;
+       }
+
+       /* Always enable basic sampling */
+       SAMPL_FLAGS(hwc) = PERF_CPUM_SF_BASIC_MODE;
+
+       /* Check if diagnostic sampling is requested.  Deny if the required
+        * sampling authorization is missing.
+        */
+       if (attr->config == PERF_EVENT_CPUM_SF_DIAG) {
+               if (!si.ad) {
+                       err = -EPERM;
+                       goto out;
+               }
+               SAMPL_FLAGS(hwc) |= PERF_CPUM_SF_DIAG_MODE;
+       }
+
+       /* Check and set other sampling flags */
+       if (attr->config1 & PERF_CPUM_SF_FULL_BLOCKS)
+               SAMPL_FLAGS(hwc) |= PERF_CPUM_SF_FULL_BLOCKS;
+
+       /* The sampling information (si) contains information about the
+        * min/max sampling intervals and the CPU speed.  So calculate the
+        * correct sampling interval and avoid the whole period adjust
+        * feedback loop.
+        */
+       rate = 0;
+       if (attr->freq) {
+               rate = freq_to_sample_rate(&si, attr->sample_freq);
+               rate = hw_limit_rate(&si, rate);
+               attr->freq = 0;
+               attr->sample_period = rate;
+       } else {
+               /* The min/max sampling rates specifies the valid range
+                * of sample periods.  If the specified sample period is
+                * out of range, limit the period to the range boundary.
+                */
+               rate = hw_limit_rate(&si, hwc->sample_period);
+
+               /* The perf core maintains a maximum sample rate that is
+                * configurable through the sysctl interface.  Ensure the
+                * sampling rate does not exceed this value.  This also helps
+                * to avoid throttling when pushing samples with
+                * perf_event_overflow().
+                */
+               if (sample_rate_to_freq(&si, rate) >
+                     sysctl_perf_event_sample_rate) {
+                       err = -EINVAL;
+                       debug_sprintf_event(sfdbg, 1, "Sampling rate exceeds maximum perf sample rate\n");
+                       goto out;
+               }
+       }
+       SAMPL_RATE(hwc) = rate;
+       hw_init_period(hwc, SAMPL_RATE(hwc));
+
+       /* Initialize sample data overflow accounting */
+       hwc->extra_reg.reg = REG_OVERFLOW;
+       OVERFLOW_REG(hwc) = 0;
+
+       /* Allocate the per-CPU sampling buffer using the CPU information
+        * from the event.  If the event is not pinned to a particular
+        * CPU (event->cpu == -1; or cpuhw == NULL), allocate sampling
+        * buffers for each online CPU.
+        */
+       if (cpuhw)
+               /* Event is pinned to a particular CPU */
+               err = allocate_buffers(cpuhw, hwc);
+       else {
+               /* Event is not pinned, allocate sampling buffer on
+                * each online CPU
+                */
+               for_each_online_cpu(cpu) {
+                       cpuhw = &per_cpu(cpu_hw_sf, cpu);
+                       err = allocate_buffers(cpuhw, hwc);
+                       if (err)
+                               break;
+               }
+       }
+out:
+       return err;
+}
+
+static int cpumsf_pmu_event_init(struct perf_event *event)
+{
+       int err;
+
+       /* No support for taken branch sampling */
+       if (has_branch_stack(event))
+               return -EOPNOTSUPP;
+
+       switch (event->attr.type) {
+       case PERF_TYPE_RAW:
+               if ((event->attr.config != PERF_EVENT_CPUM_SF) &&
+                   (event->attr.config != PERF_EVENT_CPUM_SF_DIAG))
+                       return -ENOENT;
+               break;
+       case PERF_TYPE_HARDWARE:
+               /* Support sampling of CPU cycles in addition to the
+                * counter facility.  However, the counter facility
+                * is more precise and, hence, restrict this PMU to
+                * sampling events only.
+                */
+               if (event->attr.config != PERF_COUNT_HW_CPU_CYCLES)
+                       return -ENOENT;
+               if (!is_sampling_event(event))
+                       return -ENOENT;
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       /* Check online status of the CPU to which the event is pinned */
+       if (event->cpu >= nr_cpumask_bits ||
+           (event->cpu >= 0 && !cpu_online(event->cpu)))
+               return -ENODEV;
+
+       /* Force reset of idle/hv excludes regardless of what the
+        * user requested.
+        */
+       if (event->attr.exclude_hv)
+               event->attr.exclude_hv = 0;
+       if (event->attr.exclude_idle)
+               event->attr.exclude_idle = 0;
+
+       err = __hw_perf_event_init(event);
+       if (unlikely(err))
+               if (event->destroy)
+                       event->destroy(event);
+       return err;
+}
+
+static void cpumsf_pmu_enable(struct pmu *pmu)
+{
+       struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf);
+       struct hw_perf_event *hwc;
+       int err;
+
+       if (cpuhw->flags & PMU_F_ENABLED)
+               return;
+
+       if (cpuhw->flags & PMU_F_ERR_MASK)
+               return;
+
+       /* Check whether to extent the sampling buffer.
+        *
+        * Two conditions trigger an increase of the sampling buffer for a
+        * perf event:
+        *    1. Postponed buffer allocations from the event initialization.
+        *    2. Sampling overflows that contribute to pending allocations.
+        *
+        * Note that the extend_sampling_buffer() function disables the sampling
+        * facility, but it can be fully re-enabled using sampling controls that
+        * have been saved in cpumsf_pmu_disable().
+        */
+       if (cpuhw->event) {
+               hwc = &cpuhw->event->hw;
+               /* Account number of overflow-designated buffer extents */
+               sfb_account_overflows(cpuhw, hwc);
+               if (sfb_has_pending_allocs(&cpuhw->sfb, hwc))
+                       extend_sampling_buffer(&cpuhw->sfb, hwc);
+       }
+
+       /* (Re)enable the PMU and sampling facility */
+       cpuhw->flags |= PMU_F_ENABLED;
+       barrier();
+
+       err = lsctl(&cpuhw->lsctl);
+       if (err) {
+               cpuhw->flags &= ~PMU_F_ENABLED;
+               pr_err("Loading sampling controls failed: op=%i err=%i\n",
+                       1, err);
+               return;
+       }
+
+       debug_sprintf_event(sfdbg, 6, "pmu_enable: es=%i cs=%i ed=%i cd=%i "
+                           "tear=%p dear=%p\n", cpuhw->lsctl.es, cpuhw->lsctl.cs,
+                           cpuhw->lsctl.ed, cpuhw->lsctl.cd,
+                           (void *) cpuhw->lsctl.tear, (void *) cpuhw->lsctl.dear);
+}
+
+static void cpumsf_pmu_disable(struct pmu *pmu)
+{
+       struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf);
+       struct hws_lsctl_request_block inactive;
+       struct hws_qsi_info_block si;
+       int err;
+
+       if (!(cpuhw->flags & PMU_F_ENABLED))
+               return;
+
+       if (cpuhw->flags & PMU_F_ERR_MASK)
+               return;
+
+       /* Switch off sampling activation control */
+       inactive = cpuhw->lsctl;
+       inactive.cs = 0;
+       inactive.cd = 0;
+
+       err = lsctl(&inactive);
+       if (err) {
+               pr_err("Loading sampling controls failed: op=%i err=%i\n",
+                       2, err);
+               return;
+       }
+
+       /* Save state of TEAR and DEAR register contents */
+       if (!qsi(&si)) {
+               /* TEAR/DEAR values are valid only if the sampling facility is
+                * enabled.  Note that cpumsf_pmu_disable() might be called even
+                * for a disabled sampling facility because cpumsf_pmu_enable()
+                * controls the enable/disable state.
+                */
+               if (si.es) {
+                       cpuhw->lsctl.tear = si.tear;
+                       cpuhw->lsctl.dear = si.dear;
+               }
+       } else
+               debug_sprintf_event(sfdbg, 3, "cpumsf_pmu_disable: "
+                                   "qsi() failed with err=%i\n", err);
+
+       cpuhw->flags &= ~PMU_F_ENABLED;
+}
+
+/* perf_exclude_event() - Filter event
+ * @event:     The perf event
+ * @regs:      pt_regs structure
+ * @sde_regs:  Sample-data-entry (sde) regs structure
+ *
+ * Filter perf events according to their exclude specification.
+ *
+ * Return non-zero if the event shall be excluded.
+ */
+static int perf_exclude_event(struct perf_event *event, struct pt_regs *regs,
+                             struct perf_sf_sde_regs *sde_regs)
+{
+       if (event->attr.exclude_user && user_mode(regs))
+               return 1;
+       if (event->attr.exclude_kernel && !user_mode(regs))
+               return 1;
+       if (event->attr.exclude_guest && sde_regs->in_guest)
+               return 1;
+       if (event->attr.exclude_host && !sde_regs->in_guest)
+               return 1;
+       return 0;
+}
+
+/* perf_push_sample() - Push samples to perf
+ * @event:     The perf event
+ * @sample:    Hardware sample data
+ *
+ * Use the hardware sample data to create perf event sample.  The sample
+ * is the pushed to the event subsystem and the function checks for
+ * possible event overflows.  If an event overflow occurs, the PMU is
+ * stopped.
+ *
+ * Return non-zero if an event overflow occurred.
+ */
+static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
+{
+       int overflow;
+       struct pt_regs regs;
+       struct perf_sf_sde_regs *sde_regs;
+       struct perf_sample_data data;
+       struct perf_raw_record raw;
+
+       /* Setup perf sample */
+       perf_sample_data_init(&data, 0, event->hw.last_period);
+       raw.size = sfr->size;
+       raw.data = sfr;
+       data.raw = &raw;
+
+       /* Setup pt_regs to look like an CPU-measurement external interrupt
+        * using the Program Request Alert code.  The regs.int_parm_long
+        * field which is unused contains additional sample-data-entry related
+        * indicators.
+        */
+       memset(&regs, 0, sizeof(regs));
+       regs.int_code = 0x1407;
+       regs.int_parm = CPU_MF_INT_SF_PRA;
+       sde_regs = (struct perf_sf_sde_regs *) &regs.int_parm_long;
+
+       regs.psw.addr = sfr->basic.ia;
+       if (sfr->basic.T)
+               regs.psw.mask |= PSW_MASK_DAT;
+       if (sfr->basic.W)
+               regs.psw.mask |= PSW_MASK_WAIT;
+       if (sfr->basic.P)
+               regs.psw.mask |= PSW_MASK_PSTATE;
+       switch (sfr->basic.AS) {
+       case 0x0:
+               regs.psw.mask |= PSW_ASC_PRIMARY;
+               break;
+       case 0x1:
+               regs.psw.mask |= PSW_ASC_ACCREG;
+               break;
+       case 0x2:
+               regs.psw.mask |= PSW_ASC_SECONDARY;
+               break;
+       case 0x3:
+               regs.psw.mask |= PSW_ASC_HOME;
+               break;
+       }
+
+       /* The host-program-parameter (hpp) contains the sie control
+        * block that is set by sie64a() in entry64.S.  Check if hpp
+        * refers to a valid control block and set sde_regs flags
+        * accordingly.  This would allow to use hpp values for other
+        * purposes too.
+        * For now, simply use a non-zero value as guest indicator.
+        */
+       if (sfr->basic.hpp)
+               sde_regs->in_guest = 1;
+
+       overflow = 0;
+       if (perf_exclude_event(event, &regs, sde_regs))
+               goto out;
+       if (perf_event_overflow(event, &data, &regs)) {
+               overflow = 1;
+               event->pmu->stop(event, 0);
+       }
+       perf_event_update_userpage(event);
+out:
+       return overflow;
+}
+
+static void perf_event_count_update(struct perf_event *event, u64 count)
+{
+       local64_add(count, &event->count);
+}
+
+static int sample_format_is_valid(struct hws_combined_entry *sample,
+                                  unsigned int flags)
+{
+       if (likely(flags & PERF_CPUM_SF_BASIC_MODE))
+               /* Only basic-sampling data entries with data-entry-format
+                * version of 0x0001 can be processed.
+                */
+               if (sample->basic.def != 0x0001)
+                       return 0;
+       if (flags & PERF_CPUM_SF_DIAG_MODE)
+               /* The data-entry-format number of diagnostic-sampling data
+                * entries can vary.  Because diagnostic data is just passed
+                * through, do only a sanity check on the DEF.
+                */
+               if (sample->diag.def < 0x8001)
+                       return 0;
+       return 1;
+}
+
+static int sample_is_consistent(struct hws_combined_entry *sample,
+                               unsigned long flags)
+{
+       /* This check applies only to basic-sampling data entries of potentially
+        * combined-sampling data entries.  Invalid entries cannot be processed
+        * by the PMU and, thus, do not deliver an associated
+        * diagnostic-sampling data entry.
+        */
+       if (unlikely(!(flags & PERF_CPUM_SF_BASIC_MODE)))
+               return 0;
+       /*
+        * Samples are skipped, if they are invalid or for which the
+        * instruction address is not predictable, i.e., the wait-state bit is
+        * set.
+        */
+       if (sample->basic.I || sample->basic.W)
+               return 0;
+       return 1;
+}
+
+static void reset_sample_slot(struct hws_combined_entry *sample,
+                             unsigned long flags)
+{
+       if (likely(flags & PERF_CPUM_SF_BASIC_MODE))
+               sample->basic.def = 0;
+       if (flags & PERF_CPUM_SF_DIAG_MODE)
+               sample->diag.def = 0;
+}
+
+static void sfr_store_sample(struct sf_raw_sample *sfr,
+                            struct hws_combined_entry *sample)
+{
+       if (likely(sfr->format & PERF_CPUM_SF_BASIC_MODE))
+               sfr->basic = sample->basic;
+       if (sfr->format & PERF_CPUM_SF_DIAG_MODE)
+               memcpy(&sfr->diag, &sample->diag, sfr->dsdes);
+}
+
+static void debug_sample_entry(struct hws_combined_entry *sample,
+                              struct hws_trailer_entry *te,
+                              unsigned long flags)
+{
+       debug_sprintf_event(sfdbg, 4, "hw_collect_samples: Found unknown "
+                           "sampling data entry: te->f=%i basic.def=%04x (%p)"
+                           " diag.def=%04x (%p)\n", te->f,
+                           sample->basic.def, &sample->basic,
+                           (flags & PERF_CPUM_SF_DIAG_MODE)
+                                       ? sample->diag.def : 0xFFFF,
+                           (flags & PERF_CPUM_SF_DIAG_MODE)
+                                       ?  &sample->diag : NULL);
+}
+
+/* hw_collect_samples() - Walk through a sample-data-block and collect samples
+ * @event:     The perf event
+ * @sdbt:      Sample-data-block table
+ * @overflow:  Event overflow counter
+ *
+ * Walks through a sample-data-block and collects sampling data entries that are
+ * then pushed to the perf event subsystem.  Depending on the sampling function,
+ * there can be either basic-sampling or combined-sampling data entries.  A
+ * combined-sampling data entry consists of a basic- and a diagnostic-sampling
+ * data entry. The sampling function is determined by the flags in the perf
+ * event hardware structure.  The function always works with a combined-sampling
+ * data entry but ignores the the diagnostic portion if it is not available.
+ *
+ * Note that the implementation focuses on basic-sampling data entries and, if
+ * such an entry is not valid, the entire combined-sampling data entry is
+ * ignored.
+ *
+ * The overflow variables counts the number of samples that has been discarded
+ * due to a perf event overflow.
+ */
+static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
+                              unsigned long long *overflow)
+{
+       unsigned long flags = SAMPL_FLAGS(&event->hw);
+       struct hws_combined_entry *sample;
+       struct hws_trailer_entry *te;
+       struct sf_raw_sample *sfr;
+       size_t sample_size;
+
+       /* Prepare and initialize raw sample data */
+       sfr = (struct sf_raw_sample *) RAWSAMPLE_REG(&event->hw);
+       sfr->format = flags & PERF_CPUM_SF_MODE_MASK;
+
+       sample_size = event_sample_size(&event->hw);
+       te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt);
+       sample = (struct hws_combined_entry *) *sdbt;
+       while ((unsigned long *) sample < (unsigned long *) te) {
+               /* Check for an empty sample */
+               if (!sample->basic.def)
+                       break;
+
+               /* Update perf event period */
+               perf_event_count_update(event, SAMPL_RATE(&event->hw));
+
+               /* Check sampling data entry */
+               if (sample_format_is_valid(sample, flags)) {
+                       /* If an event overflow occurred, the PMU is stopped to
+                        * throttle event delivery.  Remaining sample data is
+                        * discarded.
+                        */
+                       if (!*overflow) {
+                               if (sample_is_consistent(sample, flags)) {
+                                       /* Deliver sample data to perf */
+                                       sfr_store_sample(sfr, sample);
+                                       *overflow = perf_push_sample(event, sfr);
+                               }
+                       } else
+                               /* Count discarded samples */
+                               *overflow += 1;
+               } else {
+                       debug_sample_entry(sample, te, flags);
+                       /* Sample slot is not yet written or other record.
+                        *
+                        * This condition can occur if the buffer was reused
+                        * from a combined basic- and diagnostic-sampling.
+                        * If only basic-sampling is then active, entries are
+                        * written into the larger diagnostic entries.
+                        * This is typically the case for sample-data-blocks
+                        * that are not full.  Stop processing if the first
+                        * invalid format was detected.
+                        */
+                       if (!te->f)
+                               break;
+               }
+
+               /* Reset sample slot and advance to next sample */
+               reset_sample_slot(sample, flags);
+               sample += sample_size;
+       }
+}
+
+/* hw_perf_event_update() - Process sampling buffer
+ * @event:     The perf event
+ * @flush_all: Flag to also flush partially filled sample-data-blocks
+ *
+ * Processes the sampling buffer and create perf event samples.
+ * The sampling buffer position are retrieved and saved in the TEAR_REG
+ * register of the specified perf event.
+ *
+ * Only full sample-data-blocks are processed. Specify the flash_all flag
+ * to also walk through partially filled sample-data-blocks.  It is ignored
+ * if PERF_CPUM_SF_FULL_BLOCKS is set. The PERF_CPUM_SF_FULL_BLOCKS flag
+ * enforces the processing of full sample-data-blocks only (trailer entries
+ * with the block-full-indicator bit set).
+ */
+static void hw_perf_event_update(struct perf_event *event, int flush_all)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hws_trailer_entry *te;
+       unsigned long *sdbt;
+       unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags;
+       int done;
+
+       if (flush_all && SDB_FULL_BLOCKS(hwc))
+               flush_all = 0;
+
+       sdbt = (unsigned long *) TEAR_REG(hwc);
+       done = event_overflow = sampl_overflow = num_sdb = 0;
+       while (!done) {
+               /* Get the trailer entry of the sample-data-block */
+               te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt);
+
+               /* Leave loop if no more work to do (block full indicator) */
+               if (!te->f) {
+                       done = 1;
+                       if (!flush_all)
+                               break;
+               }
+
+               /* Check the sample overflow count */
+               if (te->overflow)
+                       /* Account sample overflows and, if a particular limit
+                        * is reached, extend the sampling buffer.
+                        * For details, see sfb_account_overflows().
+                        */
+                       sampl_overflow += te->overflow;
+
+               /* Timestamps are valid for full sample-data-blocks only */
+               debug_sprintf_event(sfdbg, 6, "hw_perf_event_update: sdbt=%p "
+                                   "overflow=%llu timestamp=0x%llx\n",
+                                   sdbt, te->overflow,
+                                   (te->f) ? trailer_timestamp(te) : 0ULL);
+
+               /* Collect all samples from a single sample-data-block and
+                * flag if an (perf) event overflow happened.  If so, the PMU
+                * is stopped and remaining samples will be discarded.
+                */
+               hw_collect_samples(event, sdbt, &event_overflow);
+               num_sdb++;
+
+               /* Reset trailer (using compare-double-and-swap) */
+               do {
+                       te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK;
+                       te_flags |= SDB_TE_ALERT_REQ_MASK;
+               } while (!cmpxchg_double(&te->flags, &te->overflow,
+                                        te->flags, te->overflow,
+                                        te_flags, 0ULL));
+
+               /* Advance to next sample-data-block */
+               sdbt++;
+               if (is_link_entry(sdbt))
+                       sdbt = get_next_sdbt(sdbt);
+
+               /* Update event hardware registers */
+               TEAR_REG(hwc) = (unsigned long) sdbt;
+
+               /* Stop processing sample-data if all samples of the current
+                * sample-data-block were flushed even if it was not full.
+                */
+               if (flush_all && done)
+                       break;
+
+               /* If an event overflow happened, discard samples by
+                * processing any remaining sample-data-blocks.
+                */
+               if (event_overflow)
+                       flush_all = 1;
+       }
+
+       /* Account sample overflows in the event hardware structure */
+       if (sampl_overflow)
+               OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) +
+                                                sampl_overflow, 1 + num_sdb);
+       if (sampl_overflow || event_overflow)
+               debug_sprintf_event(sfdbg, 4, "hw_perf_event_update: "
+                                   "overflow stats: sample=%llu event=%llu\n",
+                                   sampl_overflow, event_overflow);
+}
+
+static void cpumsf_pmu_read(struct perf_event *event)
+{
+       /* Nothing to do ... updates are interrupt-driven */
+}
+
+/* Activate sampling control.
+ * Next call of pmu_enable() starts sampling.
+ */
+static void cpumsf_pmu_start(struct perf_event *event, int flags)
+{
+       struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf);
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       if (flags & PERF_EF_RELOAD)
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+       perf_pmu_disable(event->pmu);
+       event->hw.state = 0;
+       cpuhw->lsctl.cs = 1;
+       if (SAMPL_DIAG_MODE(&event->hw))
+               cpuhw->lsctl.cd = 1;
+       perf_pmu_enable(event->pmu);
+}
+
+/* Deactivate sampling control.
+ * Next call of pmu_enable() stops sampling.
+ */
+static void cpumsf_pmu_stop(struct perf_event *event, int flags)
+{
+       struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf);
+
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
+       perf_pmu_disable(event->pmu);
+       cpuhw->lsctl.cs = 0;
+       cpuhw->lsctl.cd = 0;
+       event->hw.state |= PERF_HES_STOPPED;
+
+       if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
+               hw_perf_event_update(event, 1);
+               event->hw.state |= PERF_HES_UPTODATE;
+       }
+       perf_pmu_enable(event->pmu);
+}
+
+static int cpumsf_pmu_add(struct perf_event *event, int flags)
+{
+       struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf);
+       int err;
+
+       if (cpuhw->flags & PMU_F_IN_USE)
+               return -EAGAIN;
+
+       if (!cpuhw->sfb.sdbt)
+               return -EINVAL;
+
+       err = 0;
+       perf_pmu_disable(event->pmu);
+
+       event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       /* Set up sampling controls.  Always program the sampling register
+        * using the SDB-table start.  Reset TEAR_REG event hardware register
+        * that is used by hw_perf_event_update() to store the sampling buffer
+        * position after samples have been flushed.
+        */
+       cpuhw->lsctl.s = 0;
+       cpuhw->lsctl.h = 1;
+       cpuhw->lsctl.tear = (unsigned long) cpuhw->sfb.sdbt;
+       cpuhw->lsctl.dear = *(unsigned long *) cpuhw->sfb.sdbt;
+       cpuhw->lsctl.interval = SAMPL_RATE(&event->hw);
+       hw_reset_registers(&event->hw, cpuhw->sfb.sdbt);
+
+       /* Ensure sampling functions are in the disabled state.  If disabled,
+        * switch on sampling enable control. */
+       if (WARN_ON_ONCE(cpuhw->lsctl.es == 1 || cpuhw->lsctl.ed == 1)) {
+               err = -EAGAIN;
+               goto out;
+       }
+       cpuhw->lsctl.es = 1;
+       if (SAMPL_DIAG_MODE(&event->hw))
+               cpuhw->lsctl.ed = 1;
+
+       /* Set in_use flag and store event */
+       event->hw.idx = 0;        /* only one sampling event per CPU supported */
+       cpuhw->event = event;
+       cpuhw->flags |= PMU_F_IN_USE;
+
+       if (flags & PERF_EF_START)
+               cpumsf_pmu_start(event, PERF_EF_RELOAD);
+out:
+       perf_event_update_userpage(event);
+       perf_pmu_enable(event->pmu);
+       return err;
+}
+
+static void cpumsf_pmu_del(struct perf_event *event, int flags)
+{
+       struct cpu_hw_sf *cpuhw = &__get_cpu_var(cpu_hw_sf);
+
+       perf_pmu_disable(event->pmu);
+       cpumsf_pmu_stop(event, PERF_EF_UPDATE);
+
+       cpuhw->lsctl.es = 0;
+       cpuhw->lsctl.ed = 0;
+       cpuhw->flags &= ~PMU_F_IN_USE;
+       cpuhw->event = NULL;
+
+       perf_event_update_userpage(event);
+       perf_pmu_enable(event->pmu);
+}
+
+static int cpumsf_pmu_event_idx(struct perf_event *event)
+{
+       return event->hw.idx;
+}
+
+CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC, PERF_EVENT_CPUM_SF);
+CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC_DIAG, PERF_EVENT_CPUM_SF_DIAG);
+
+static struct attribute *cpumsf_pmu_events_attr[] = {
+       CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC),
+       CPUMF_EVENT_PTR(SF, SF_CYCLES_BASIC_DIAG),
+       NULL,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-63");
+
+static struct attribute *cpumsf_pmu_format_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group cpumsf_pmu_events_group = {
+       .name = "events",
+       .attrs = cpumsf_pmu_events_attr,
+};
+static struct attribute_group cpumsf_pmu_format_group = {
+       .name = "format",
+       .attrs = cpumsf_pmu_format_attr,
+};
+static const struct attribute_group *cpumsf_pmu_attr_groups[] = {
+       &cpumsf_pmu_events_group,
+       &cpumsf_pmu_format_group,
+       NULL,
+};
+
+static struct pmu cpumf_sampling = {
+       .pmu_enable   = cpumsf_pmu_enable,
+       .pmu_disable  = cpumsf_pmu_disable,
+
+       .event_init   = cpumsf_pmu_event_init,
+       .add          = cpumsf_pmu_add,
+       .del          = cpumsf_pmu_del,
+
+       .start        = cpumsf_pmu_start,
+       .stop         = cpumsf_pmu_stop,
+       .read         = cpumsf_pmu_read,
+
+       .event_idx    = cpumsf_pmu_event_idx,
+       .attr_groups  = cpumsf_pmu_attr_groups,
+};
+
+static void cpumf_measurement_alert(struct ext_code ext_code,
+                                   unsigned int alert, unsigned long unused)
+{
+       struct cpu_hw_sf *cpuhw;
+
+       if (!(alert & CPU_MF_INT_SF_MASK))
+               return;
+       inc_irq_stat(IRQEXT_CMS);
+       cpuhw = &__get_cpu_var(cpu_hw_sf);
+
+       /* Measurement alerts are shared and might happen when the PMU
+        * is not reserved.  Ignore these alerts in this case. */
+       if (!(cpuhw->flags & PMU_F_RESERVED))
+               return;
+
+       /* The processing below must take care of multiple alert events that
+        * might be indicated concurrently. */
+
+       /* Program alert request */
+       if (alert & CPU_MF_INT_SF_PRA) {
+               if (cpuhw->flags & PMU_F_IN_USE)
+                       hw_perf_event_update(cpuhw->event, 0);
+               else
+                       WARN_ON_ONCE(!(cpuhw->flags & PMU_F_IN_USE));
+       }
+
+       /* Report measurement alerts only for non-PRA codes */
+       if (alert != CPU_MF_INT_SF_PRA)
+               debug_sprintf_event(sfdbg, 6, "measurement alert: 0x%x\n", alert);
+
+       /* Sampling authorization change request */
+       if (alert & CPU_MF_INT_SF_SACA)
+               qsi(&cpuhw->qsi);
+
+       /* Loss of sample data due to high-priority machine activities */
+       if (alert & CPU_MF_INT_SF_LSDA) {
+               pr_err("Sample data was lost\n");
+               cpuhw->flags |= PMU_F_ERR_LSDA;
+               sf_disable();
+       }
+
+       /* Invalid sampling buffer entry */
+       if (alert & (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE)) {
+               pr_err("A sampling buffer entry is incorrect (alert=0x%x)\n",
+                      alert);
+               cpuhw->flags |= PMU_F_ERR_IBE;
+               sf_disable();
+       }
+}
+
+static int cpumf_pmu_notifier(struct notifier_block *self,
+                             unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long) hcpu;
+       int flags;
+
+       /* Ignore the notification if no events are scheduled on the PMU.
+        * This might be racy...
+        */
+       if (!atomic_read(&num_events))
+               return NOTIFY_OK;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+               flags = PMC_INIT;
+               smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
+               break;
+       case CPU_DOWN_PREPARE:
+               flags = PMC_RELEASE;
+               smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static int param_get_sfb_size(char *buffer, const struct kernel_param *kp)
+{
+       if (!cpum_sf_avail())
+               return -ENODEV;
+       return sprintf(buffer, "%lu,%lu", CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB);
+}
+
+static int param_set_sfb_size(const char *val, const struct kernel_param *kp)
+{
+       int rc;
+       unsigned long min, max;
+
+       if (!cpum_sf_avail())
+               return -ENODEV;
+       if (!val || !strlen(val))
+               return -EINVAL;
+
+       /* Valid parameter values: "min,max" or "max" */
+       min = CPUM_SF_MIN_SDB;
+       max = CPUM_SF_MAX_SDB;
+       if (strchr(val, ','))
+               rc = (sscanf(val, "%lu,%lu", &min, &max) == 2) ? 0 : -EINVAL;
+       else
+               rc = kstrtoul(val, 10, &max);
+
+       if (min < 2 || min >= max || max > get_num_physpages())
+               rc = -EINVAL;
+       if (rc)
+               return rc;
+
+       sfb_set_limits(min, max);
+       pr_info("The sampling buffer limits have changed to: "
+               "min=%lu max=%lu (diag=x%lu)\n",
+               CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB, CPUM_SF_SDB_DIAG_FACTOR);
+       return 0;
+}
+
+#define param_check_sfb_size(name, p) __param_check(name, p, void)
+static struct kernel_param_ops param_ops_sfb_size = {
+       .set = param_set_sfb_size,
+       .get = param_get_sfb_size,
+};
+
+#define RS_INIT_FAILURE_QSI      0x0001
+#define RS_INIT_FAILURE_BSDES    0x0002
+#define RS_INIT_FAILURE_ALRT     0x0003
+#define RS_INIT_FAILURE_PERF     0x0004
+static void __init pr_cpumsf_err(unsigned int reason)
+{
+       pr_err("Sampling facility support for perf is not available: "
+              "reason=%04x\n", reason);
+}
+
+static int __init init_cpum_sampling_pmu(void)
+{
+       struct hws_qsi_info_block si;
+       int err;
+
+       if (!cpum_sf_avail())
+               return -ENODEV;
+
+       memset(&si, 0, sizeof(si));
+       if (qsi(&si)) {
+               pr_cpumsf_err(RS_INIT_FAILURE_QSI);
+               return -ENODEV;
+       }
+
+       if (si.bsdes != sizeof(struct hws_basic_entry)) {
+               pr_cpumsf_err(RS_INIT_FAILURE_BSDES);
+               return -EINVAL;
+       }
+
+       if (si.ad)
+               sfb_set_limits(CPUM_SF_MIN_SDB, CPUM_SF_MAX_SDB);
+
+       sfdbg = debug_register(KMSG_COMPONENT, 2, 1, 80);
+       if (!sfdbg)
+               pr_err("Registering for s390dbf failed\n");
+       debug_register_view(sfdbg, &debug_sprintf_view);
+
+       err = register_external_interrupt(0x1407, cpumf_measurement_alert);
+       if (err) {
+               pr_cpumsf_err(RS_INIT_FAILURE_ALRT);
+               goto out;
+       }
+
+       err = perf_pmu_register(&cpumf_sampling, "cpum_sf", PERF_TYPE_RAW);
+       if (err) {
+               pr_cpumsf_err(RS_INIT_FAILURE_PERF);
+               unregister_external_interrupt(0x1407, cpumf_measurement_alert);
+               goto out;
+       }
+       perf_cpu_notifier(cpumf_pmu_notifier);
+out:
+       return err;
+}
+arch_initcall(init_cpum_sampling_pmu);
+core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640);
index 2343c218b8f991224e0d3fb44e6838354cfb7e7e..5d2dfa31c4efad44028d41b60b6d43631ecaedc6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Performance event support for s390x
  *
- *  Copyright IBM Corp. 2012
+ *  Copyright IBM Corp. 2012, 2013
  *  Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
  *
  * This program is free software; you can redistribute it and/or modify
 #include <linux/kvm_host.h>
 #include <linux/percpu.h>
 #include <linux/export.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
 #include <asm/irq.h>
 #include <asm/cpu_mf.h>
 #include <asm/lowcore.h>
 #include <asm/processor.h>
+#include <asm/sysinfo.h>
 
 const char *perf_pmu_name(void)
 {
        if (cpum_cf_avail() || cpum_sf_avail())
-               return "CPU-measurement facilities (CPUMF)";
+               return "CPU-Measurement Facilities (CPU-MF)";
        return "pmu";
 }
 EXPORT_SYMBOL(perf_pmu_name);
@@ -35,6 +39,8 @@ int perf_num_counters(void)
 
        if (cpum_cf_avail())
                num += PERF_CPUM_CF_MAX_CTR;
+       if (cpum_sf_avail())
+               num += PERF_CPUM_SF_MAX_CTR;
 
        return num;
 }
@@ -54,7 +60,7 @@ static bool is_in_guest(struct pt_regs *regs)
 {
        if (user_mode(regs))
                return false;
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+#if IS_ENABLED(CONFIG_KVM)
        return instruction_pointer(regs) == (unsigned long) &sie_exit;
 #else
        return false;
@@ -83,8 +89,31 @@ static unsigned long perf_misc_guest_flags(struct pt_regs *regs)
                                        : PERF_RECORD_MISC_GUEST_KERNEL;
 }
 
+static unsigned long perf_misc_flags_sf(struct pt_regs *regs)
+{
+       struct perf_sf_sde_regs *sde_regs;
+       unsigned long flags;
+
+       sde_regs = (struct perf_sf_sde_regs *) &regs->int_parm_long;
+       if (sde_regs->in_guest)
+               flags = user_mode(regs) ? PERF_RECORD_MISC_GUEST_USER
+                                       : PERF_RECORD_MISC_GUEST_KERNEL;
+       else
+               flags = user_mode(regs) ? PERF_RECORD_MISC_USER
+                                       : PERF_RECORD_MISC_KERNEL;
+       return flags;
+}
+
 unsigned long perf_misc_flags(struct pt_regs *regs)
 {
+       /* Check if the cpum_sf PMU has created the pt_regs structure.
+        * In this case, perf misc flags can be easily extracted.  Otherwise,
+        * do regular checks on the pt_regs content.
+        */
+       if (regs->int_code == 0x1407 && regs->int_parm == CPU_MF_INT_SF_PRA)
+               if (!regs->gprs[15])
+                       return perf_misc_flags_sf(regs);
+
        if (is_in_guest(regs))
                return perf_misc_guest_flags(regs);
 
@@ -92,27 +121,107 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
                               : PERF_RECORD_MISC_KERNEL;
 }
 
-void perf_event_print_debug(void)
+void print_debug_cf(void)
 {
        struct cpumf_ctr_info cf_info;
-       unsigned long flags;
-       int cpu;
-
-       if (!cpum_cf_avail())
-               return;
-
-       local_irq_save(flags);
+       int cpu = smp_processor_id();
 
-       cpu = smp_processor_id();
        memset(&cf_info, 0, sizeof(cf_info));
        if (!qctri(&cf_info))
                pr_info("CPU[%i] CPUM_CF: ver=%u.%u A=%04x E=%04x C=%04x\n",
                        cpu, cf_info.cfvn, cf_info.csvn,
                        cf_info.auth_ctl, cf_info.enable_ctl, cf_info.act_ctl);
+}
+
+static void print_debug_sf(void)
+{
+       struct hws_qsi_info_block si;
+       int cpu = smp_processor_id();
 
+       memset(&si, 0, sizeof(si));
+       if (qsi(&si))
+               return;
+
+       pr_info("CPU[%i] CPUM_SF: basic=%i diag=%i min=%lu max=%lu cpu_speed=%u\n",
+               cpu, si.as, si.ad, si.min_sampl_rate, si.max_sampl_rate,
+               si.cpu_speed);
+
+       if (si.as)
+               pr_info("CPU[%i] CPUM_SF: Basic-sampling: a=%i e=%i c=%i"
+                       " bsdes=%i tear=%016lx dear=%016lx\n", cpu,
+                       si.as, si.es, si.cs, si.bsdes, si.tear, si.dear);
+       if (si.ad)
+               pr_info("CPU[%i] CPUM_SF: Diagnostic-sampling: a=%i e=%i c=%i"
+                       " dsdes=%i tear=%016lx dear=%016lx\n", cpu,
+                       si.ad, si.ed, si.cd, si.dsdes, si.tear, si.dear);
+}
+
+void perf_event_print_debug(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (cpum_cf_avail())
+               print_debug_cf();
+       if (cpum_sf_avail())
+               print_debug_sf();
        local_irq_restore(flags);
 }
 
+/* Service level infrastructure */
+static void sl_print_counter(struct seq_file *m)
+{
+       struct cpumf_ctr_info ci;
+
+       memset(&ci, 0, sizeof(ci));
+       if (qctri(&ci))
+               return;
+
+       seq_printf(m, "CPU-MF: Counter facility: version=%u.%u "
+                  "authorization=%04x\n", ci.cfvn, ci.csvn, ci.auth_ctl);
+}
+
+static void sl_print_sampling(struct seq_file *m)
+{
+       struct hws_qsi_info_block si;
+
+       memset(&si, 0, sizeof(si));
+       if (qsi(&si))
+               return;
+
+       if (!si.as && !si.ad)
+               return;
+
+       seq_printf(m, "CPU-MF: Sampling facility: min_rate=%lu max_rate=%lu"
+                  " cpu_speed=%u\n", si.min_sampl_rate, si.max_sampl_rate,
+                  si.cpu_speed);
+       if (si.as)
+               seq_printf(m, "CPU-MF: Sampling facility: mode=basic"
+                          " sample_size=%u\n", si.bsdes);
+       if (si.ad)
+               seq_printf(m, "CPU-MF: Sampling facility: mode=diagnostic"
+                          " sample_size=%u\n", si.dsdes);
+}
+
+static void service_level_perf_print(struct seq_file *m,
+                                    struct service_level *sl)
+{
+       if (cpum_cf_avail())
+               sl_print_counter(m);
+       if (cpum_sf_avail())
+               sl_print_sampling(m);
+}
+
+static struct service_level service_level_perf = {
+       .seq_print = service_level_perf_print,
+};
+
+static int __init service_level_perf_register(void)
+{
+       return register_service_level(&service_level_perf);
+}
+arch_initcall(service_level_perf_register);
+
 /* See also arch/s390/kernel/traps.c */
 static unsigned long __store_trace(struct perf_callchain_entry *entry,
                                   unsigned long sp,
@@ -172,3 +281,44 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry,
        __store_trace(entry, head, S390_lowcore.thread_info,
                      S390_lowcore.thread_info + THREAD_SIZE);
 }
+
+/* Perf defintions for PMU event attributes in sysfs */
+ssize_t cpumf_events_sysfs_show(struct device *dev,
+                               struct device_attribute *attr, char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr;
+
+       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+       return sprintf(page, "event=0x%04llx,name=%s\n",
+                      pmu_attr->id, attr->attr.name);
+}
+
+/* Reserve/release functions for sharing perf hardware */
+static DEFINE_SPINLOCK(perf_hw_owner_lock);
+static void *perf_sampling_owner;
+
+int perf_reserve_sampling(void)
+{
+       int err;
+
+       err = 0;
+       spin_lock(&perf_hw_owner_lock);
+       if (perf_sampling_owner) {
+               pr_warn("The sampling facility is already reserved by %p\n",
+                       perf_sampling_owner);
+               err = -EBUSY;
+       } else
+               perf_sampling_owner = __builtin_return_address(0);
+       spin_unlock(&perf_hw_owner_lock);
+       return err;
+}
+EXPORT_SYMBOL(perf_reserve_sampling);
+
+void perf_release_sampling(void)
+{
+       spin_lock(&perf_hw_owner_lock);
+       WARN_ON(!perf_sampling_owner);
+       perf_sampling_owner = NULL;
+       spin_unlock(&perf_hw_owner_lock);
+}
+EXPORT_SYMBOL(perf_release_sampling);
index 7ed0d4e2a435452733173767b56af52163334980..dd145321d2151d11f37c7694968f384326eb7804 100644 (file)
@@ -261,20 +261,18 @@ static inline unsigned long brk_rnd(void)
 
 unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
-       unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd());
+       unsigned long ret;
 
-       if (ret < mm->brk)
-               return mm->brk;
-       return ret;
+       ret = PAGE_ALIGN(mm->brk + brk_rnd());
+       return (ret > mm->brk) ? ret : mm->brk;
 }
 
 unsigned long randomize_et_dyn(unsigned long base)
 {
-       unsigned long ret = PAGE_ALIGN(base + brk_rnd());
+       unsigned long ret;
 
        if (!(current->flags & PF_RANDOMIZE))
                return base;
-       if (ret < base)
-               return base;
-       return ret;
+       ret = PAGE_ALIGN(base + brk_rnd());
+       return (ret > base) ? ret : base;
 }
index e65c91c591e8b99e4189f31b403a35ad06837f4f..f6be6087a0e98edb3d2917228cb65b4657b61d11 100644 (file)
@@ -56,25 +56,26 @@ void update_cr_regs(struct task_struct *task)
 #ifdef CONFIG_64BIT
        /* Take care of the enable/disable of transactional execution. */
        if (MACHINE_HAS_TE) {
-               unsigned long cr[3], cr_new[3];
+               unsigned long cr, cr_new;
 
-               __ctl_store(cr, 0, 2);
-               cr_new[1] = cr[1];
+               __ctl_store(cr, 0, 0);
                /* Set or clear transaction execution TXC bit 8. */
+               cr_new = cr | (1UL << 55);
                if (task->thread.per_flags & PER_FLAG_NO_TE)
-                       cr_new[0] = cr[0] & ~(1UL << 55);
-               else
-                       cr_new[0] = cr[0] | (1UL << 55);
+                       cr_new &= ~(1UL << 55);
+               if (cr_new != cr)
+                       __ctl_load(cr, 0, 0);
                /* Set or clear transaction execution TDC bits 62 and 63. */
-               cr_new[2] = cr[2] & ~3UL;
+               __ctl_store(cr, 2, 2);
+               cr_new = cr & ~3UL;
                if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
                        if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
-                               cr_new[2] |= 1UL;
+                               cr_new |= 1UL;
                        else
-                               cr_new[2] |= 2UL;
+                               cr_new |= 2UL;
                }
-               if (memcmp(&cr_new, &cr, sizeof(cr)))
-                       __ctl_load(cr_new, 0, 2);
+               if (cr_new != cr)
+                       __ctl_load(cr_new, 2, 2);
        }
 #endif
        /* Copy user specified PER registers */
@@ -107,15 +108,11 @@ void update_cr_regs(struct task_struct *task)
 void user_enable_single_step(struct task_struct *task)
 {
        set_tsk_thread_flag(task, TIF_SINGLE_STEP);
-       if (task == current)
-               update_cr_regs(task);
 }
 
 void user_disable_single_step(struct task_struct *task)
 {
        clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
-       if (task == current)
-               update_cr_regs(task);
 }
 
 /*
index 3bac589844a747c22136810d0f63600139111e3a..9f60467938d177ca6e6ffc0a45fa563b518b0693 100644 (file)
@@ -5,7 +5,7 @@
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
 #endif
-#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+#if IS_ENABLED(CONFIG_KVM)
 EXPORT_SYMBOL(sie64a);
 EXPORT_SYMBOL(sie_exit);
 #endif
index 4444875266ee028bdcc4d43604a4dea591a1a47c..09e2f468f48bc874e61c3d12b9d751b04c5f0126 100644 (file)
@@ -373,7 +373,7 @@ static void __init setup_lowcore(void)
 
        /*
         * Set up PSW restart to call ipl.c:do_restart(). Copy the relevant
-        * restart data to the absolute zero lowcore. This is necesary if
+        * restart data to the absolute zero lowcore. This is necessary if
         * PSW restart is done on an offline CPU that has lowcore zero.
         */
        lc->restart_stack = (unsigned long) restart_stack;
@@ -1023,6 +1023,7 @@ void __init setup_arch(char **cmdline_p)
        setup_vmcoreinfo();
        setup_lowcore();
 
+       smp_fill_possible_mask();
         cpu_init();
        s390_init_cpu_topology();
 
index dc4a534650604a972967ab5dedd2c1b7155c29ad..a7125b62a9a6c1f77289a0d834358fea1971cb87 100644 (file)
@@ -59,7 +59,7 @@ enum {
 };
 
 struct pcpu {
-       struct cpu cpu;
+       struct cpu *cpu;
        struct _lowcore *lowcore;       /* lowcore page(s) for the cpu */
        unsigned long async_stack;      /* async stack for the cpu */
        unsigned long panic_stack;      /* panic stack for the cpu */
@@ -159,9 +159,9 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)
 {
        int order;
 
-       set_bit(ec_bit, &pcpu->ec_mask);
-       order = pcpu_running(pcpu) ?
-               SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL;
+       if (test_and_set_bit(ec_bit, &pcpu->ec_mask))
+               return;
+       order = pcpu_running(pcpu) ? SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL;
        pcpu_sigp_retry(pcpu, order, 0);
 }
 
@@ -721,18 +721,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
        return 0;
 }
 
-static int __init setup_possible_cpus(char *s)
-{
-       int max, cpu;
+static unsigned int setup_possible_cpus __initdata;
 
-       if (kstrtoint(s, 0, &max) < 0)
-               return 0;
-       init_cpu_possible(cpumask_of(0));
-       for (cpu = 1; cpu < max && cpu < nr_cpu_ids; cpu++)
-               set_cpu_possible(cpu, true);
+static int __init _setup_possible_cpus(char *s)
+{
+       get_option(&s, &setup_possible_cpus);
        return 0;
 }
-early_param("possible_cpus", setup_possible_cpus);
+early_param("possible_cpus", _setup_possible_cpus);
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -775,6 +771,17 @@ void __noreturn cpu_die(void)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+void __init smp_fill_possible_mask(void)
+{
+       unsigned int possible, cpu;
+
+       possible = setup_possible_cpus;
+       if (!possible)
+               possible = MACHINE_IS_VM ? 64 : nr_cpu_ids;
+       for (cpu = 0; cpu < possible && cpu < nr_cpu_ids; cpu++)
+               set_cpu_possible(cpu, true);
+}
+
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        /* request the 0x1201 emergency signal external interrupt */
@@ -958,7 +965,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action,
                          void *hcpu)
 {
        unsigned int cpu = (unsigned int)(long)hcpu;
-       struct cpu *c = &pcpu_devices[cpu].cpu;
+       struct cpu *c = pcpu_devices[cpu].cpu;
        struct device *s = &c->dev;
        int err = 0;
 
@@ -975,10 +982,15 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action,
 
 static int smp_add_present_cpu(int cpu)
 {
-       struct cpu *c = &pcpu_devices[cpu].cpu;
-       struct device *s = &c->dev;
+       struct device *s;
+       struct cpu *c;
        int rc;
 
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c)
+               return -ENOMEM;
+       pcpu_devices[cpu].cpu = c;
+       s = &c->dev;
        c->hotpluggable = 1;
        rc = register_cpu(c, cpu);
        if (rc)
index a84476f2a9bb3ae488eb7a936021a744a822dd31..613649096783401e0cf9acf73069dff48a35e438 100644 (file)
@@ -125,7 +125,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
                psal[i] = 0x80000000;
 
        lowcore->paste[4] = (u32)(addr_t) psal;
-       psal[0] = 0x20000000;
+       psal[0] = 0x02000000;
        psal[2] = (u32)(addr_t) aste;
        *(unsigned long *) (aste + 2) = segment_table +
                _ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT;
index 5be8e472f57d1d0debe31c849b4177492380d957..65fc3979c2f11bb037fd7f646c18a1188b4c4553 100644 (file)
@@ -46,18 +46,13 @@ __kernel_clock_gettime:
        jnm     3f
        a       %r0,__VDSO_TK_MULT(%r5)
 3:     alr     %r0,%r2
-       al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
-       al      %r1,__VDSO_XTIME_NSEC+4(%r5)
-       brc     12,4f
-       ahi     %r0,1
-4:     al      %r0,__VDSO_WTOM_NSEC(%r5)       /*  + wall_to_monotonic.nsec */
+       al      %r0,__VDSO_WTOM_NSEC(%r5)
        al      %r1,__VDSO_WTOM_NSEC+4(%r5)
        brc     12,5f
        ahi     %r0,1
 5:     l       %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
        srdl    %r0,0(%r2)                      /*  >> tk->shift */
-       l       %r2,__VDSO_XTIME_SEC+4(%r5)
-       al      %r2,__VDSO_WTOM_SEC+4(%r5)
+       l       %r2,__VDSO_WTOM_SEC+4(%r5)
        cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
        jne     1b
        basr    %r5,0
index 176e1f75f9aa6c1554dbf0818b7d4cd6661c0846..34deba7c7ed1d8b18036b0b07f9b7cd9d41e9259 100644 (file)
@@ -23,7 +23,9 @@ __kernel_clock_getres:
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC
        je      0f
-       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
+       je      0f
+       cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        jne     2f
        larl    %r5,_vdso_data
        icm     %r0,15,__LC_ECTG_OK(%r5)
index 0add1072ba306623665148816155f951f0baeeda..91940ed33a4ab21686f890481545cbfdd9404468 100644 (file)
@@ -22,7 +22,9 @@ __kernel_clock_gettime:
        larl    %r5,_vdso_data
        cghi    %r2,__CLOCK_REALTIME
        je      4f
-       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
+       je      9f
+       cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        je      9f
        cghi    %r2,__CLOCK_MONOTONIC
        jne     12f
@@ -35,13 +37,11 @@ __kernel_clock_gettime:
        jnz     0b
        stck    48(%r15)                        /* Store TOD clock */
        lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
-       lg      %r0,__VDSO_XTIME_SEC(%r5)       /* tk->xtime_sec */
-       alg     %r0,__VDSO_WTOM_SEC(%r5)        /*  + wall_to_monotonic.sec */
+       lg      %r0,__VDSO_WTOM_SEC(%r5)
        lg      %r1,48(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
-       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
-       alg     %r1,__VDSO_WTOM_NSEC(%r5)       /*  + wall_to_monotonic.nsec */
+       alg     %r1,__VDSO_WTOM_NSEC(%r5)
        srlg    %r1,%r1,0(%r2)                  /*  >> tk->shift */
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     0b
index 2440602e6df1e19ab442b3eafd6f18b6342792ec..d101dae62771c5d180d5c177e727da7b6edc89f6 100644 (file)
@@ -275,7 +275,7 @@ static int handle_io_inst(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
        } else {
                /*
-                * Set condition code 3 to stop the guest from issueing channel
+                * Set condition code 3 to stop the guest from issuing channel
                 * I/O instructions.
                 */
                kvm_s390_set_psw_cc(vcpu, 3);
index dbdab3e7a1a6266ca3b96cd692d298896bc9902f..0632dc50da78b88557ca61c766b29bccbb30a64d 100644 (file)
@@ -74,8 +74,8 @@ static size_t copy_in_kernel(size_t count, void __user *to,
 
 /*
  * Returns kernel address for user virtual address. If the returned address is
- * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
- * contains the (negative) exception code.
+ * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occurred and the
+ * address contains the (negative) exception code.
  */
 #ifdef CONFIG_64BIT
 
index e794c88f699a4584a742a3006eb443e706e5c96e..3584ed9b20a183de8c58cb4521c99517c2532c9a 100644 (file)
@@ -293,7 +293,7 @@ static int gmap_alloc_table(struct gmap *gmap,
  * @addr: address in the guest address space
  * @len: length of the memory area to unmap
  *
- * Returns 0 if the unmap succeded, -EINVAL if not.
+ * Returns 0 if the unmap succeeded, -EINVAL if not.
  */
 int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
 {
@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(gmap_unmap_segment);
  * @from: source address in the parent address space
  * @to: target address in the guest address space
  *
- * Returns 0 if the mmap succeded, -EINVAL or -ENOMEM if not.
+ * Returns 0 if the mmap succeeded, -EINVAL or -ENOMEM if not.
  */
 int gmap_map_segment(struct gmap *gmap, unsigned long from,
                     unsigned long to, unsigned long len)
index 16871da3737164d986412ff40cc8fb95c2c7119b..708d60e4006676486b3892195b165ede007d2544 100644 (file)
@@ -368,14 +368,16 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
                EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
                /* lhi %r4,0 */
                EMIT4(0xa7480000);
-               /* dr %r4,%r12 */
-               EMIT2(0x1d4c);
+               /* dlr %r4,%r12 */
+               EMIT4(0xb997004c);
                break;
-       case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */
-               /* m %r4,<d(K)>(%r13) */
-               EMIT4_DISP(0x5c40d000, EMIT_CONST(K));
-               /* lr %r5,%r4 */
-               EMIT2(0x1854);
+       case BPF_S_ALU_DIV_K: /* A /= K */
+               if (K == 1)
+                       break;
+               /* lhi %r4,0 */
+               EMIT4(0xa7480000);
+               /* dl %r4,<d(K)>(%r13) */
+               EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
                break;
        case BPF_S_ALU_MOD_X: /* A %= X */
                jit->seen |= SEEN_XREG | SEEN_RET0;
@@ -385,16 +387,21 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
                EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
                /* lhi %r4,0 */
                EMIT4(0xa7480000);
-               /* dr %r4,%r12 */
-               EMIT2(0x1d4c);
+               /* dlr %r4,%r12 */
+               EMIT4(0xb997004c);
                /* lr %r5,%r4 */
                EMIT2(0x1854);
                break;
        case BPF_S_ALU_MOD_K: /* A %= K */
+               if (K == 1) {
+                       /* lhi %r5,0 */
+                       EMIT4(0xa7580000);
+                       break;
+               }
                /* lhi %r4,0 */
                EMIT4(0xa7480000);
-               /* d %r4,<d(K)>(%r13) */
-               EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
+               /* dl %r4,<d(K)>(%r13) */
+               EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
                /* lr %r5,%r4 */
                EMIT2(0x1854);
                break;
index 231cecafc2f147d4aa90564dc1907b6f9cc4661c..a32c96761eab5be0ab6db221ba5f1a0d91634e5b 100644 (file)
@@ -26,9 +26,6 @@
 #define MAX_NUM_SDB 511
 #define MIN_NUM_SDB 1
 
-#define ALERT_REQ_MASK   0x4000000000000000ul
-#define BUFFER_FULL_MASK 0x8000000000000000ul
-
 DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
 
 struct hws_execute_parms {
@@ -44,6 +41,7 @@ static DEFINE_MUTEX(hws_sem_oom);
 
 static unsigned char hws_flush_all;
 static unsigned int hws_oom;
+static unsigned int hws_alert;
 static struct workqueue_struct *hws_wq;
 
 static unsigned int hws_state;
@@ -65,43 +63,6 @@ static unsigned long interval;
 static unsigned long min_sampler_rate;
 static unsigned long max_sampler_rate;
 
-static int ssctl(void *buffer)
-{
-       int cc;
-
-       /* set in order to detect a program check */
-       cc = 1;
-
-       asm volatile(
-               "0: .insn s,0xB2870000,0(%1)\n"
-               "1: ipm %0\n"
-               "   srl %0,28\n"
-               "2:\n"
-               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-               : "+d" (cc), "+a" (buffer)
-               : "m" (*((struct hws_ssctl_request_block *)buffer))
-               : "cc", "memory");
-
-       return cc ? -EINVAL : 0 ;
-}
-
-static int qsi(void *buffer)
-{
-       int cc;
-       cc = 1;
-
-       asm volatile(
-               "0: .insn s,0xB2860000,0(%1)\n"
-               "1: lhi %0,0\n"
-               "2:\n"
-               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-               : "=d" (cc), "+a" (buffer)
-               : "m" (*((struct hws_qsi_info_block *)buffer))
-               : "cc", "memory");
-
-       return cc ? -EINVAL : 0;
-}
-
 static void execute_qsi(void *parms)
 {
        struct hws_execute_parms *ep = parms;
@@ -113,7 +74,7 @@ static void execute_ssctl(void *parms)
 {
        struct hws_execute_parms *ep = parms;
 
-       ep->rc = ssctl(ep->buffer);
+       ep->rc = lsctl(ep->buffer);
 }
 
 static int smp_ctl_ssctl_stop(int cpu)
@@ -214,17 +175,6 @@ static int smp_ctl_qsi(int cpu)
        return ep.rc;
 }
 
-static inline unsigned long *trailer_entry_ptr(unsigned long v)
-{
-       void *ret;
-
-       ret = (void *)v;
-       ret += PAGE_SIZE;
-       ret -= sizeof(struct hws_trailer_entry);
-
-       return (unsigned long *) ret;
-}
-
 static void hws_ext_handler(struct ext_code ext_code,
                            unsigned int param32, unsigned long param64)
 {
@@ -233,6 +183,9 @@ static void hws_ext_handler(struct ext_code ext_code,
        if (!(param32 & CPU_MF_INT_SF_MASK))
                return;
 
+       if (!hws_alert)
+               return;
+
        inc_irq_stat(IRQEXT_CMS);
        atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32);
 
@@ -256,16 +209,6 @@ static void init_all_cpu_buffers(void)
        }
 }
 
-static int is_link_entry(unsigned long *s)
-{
-       return *s & 0x1ul ? 1 : 0;
-}
-
-static unsigned long *get_next_sdbt(unsigned long *s)
-{
-       return (unsigned long *) (*s & ~0x1ul);
-}
-
 static int prepare_cpu_buffers(void)
 {
        int cpu;
@@ -353,7 +296,7 @@ static int allocate_sdbt(int cpu)
                        }
                        *sdbt = sdb;
                        trailer = trailer_entry_ptr(*sdbt);
-                       *trailer = ALERT_REQ_MASK;
+                       *trailer = SDB_TE_ALERT_REQ_MASK;
                        sdbt++;
                        mutex_unlock(&hws_sem_oom);
                }
@@ -829,7 +772,7 @@ static void worker_on_interrupt(unsigned int cpu)
 
                trailer = trailer_entry_ptr(*sdbt);
                /* leave loop if no more work to do */
-               if (!(*trailer & BUFFER_FULL_MASK)) {
+               if (!(*trailer & SDB_TE_BUFFER_FULL_MASK)) {
                        done = 1;
                        if (!hws_flush_all)
                                continue;
@@ -856,7 +799,7 @@ static void worker_on_interrupt(unsigned int cpu)
 static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt,
                unsigned long *dear)
 {
-       struct hws_data_entry *sample_data_ptr;
+       struct hws_basic_entry *sample_data_ptr;
        unsigned long *trailer;
 
        trailer = trailer_entry_ptr(*sdbt);
@@ -866,7 +809,7 @@ static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt,
                trailer = dear;
        }
 
-       sample_data_ptr = (struct hws_data_entry *)(*sdbt);
+       sample_data_ptr = (struct hws_basic_entry *)(*sdbt);
 
        while ((unsigned long *)sample_data_ptr < trailer) {
                struct pt_regs *regs = NULL;
@@ -1002,6 +945,7 @@ int hwsampler_deallocate(void)
                goto deallocate_exit;
 
        irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
+       hws_alert = 0;
        deallocate_sdbt();
 
        hws_state = HWS_DEALLOCATED;
@@ -1116,6 +1060,7 @@ int hwsampler_shutdown(void)
 
                if (hws_state == HWS_STOPPED) {
                        irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
+                       hws_alert = 0;
                        deallocate_sdbt();
                }
                if (hws_wq) {
@@ -1190,6 +1135,7 @@ start_all_exit:
        hws_oom = 1;
        hws_flush_all = 0;
        /* now let them in, 1407 CPUMF external interrupts */
+       hws_alert = 1;
        irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT);
 
        return 0;
index 0022e1ebfbde9063c349820df37b4dc5f29c0e20..a483d06f2fa78e0740213f51d4a7782ccff27fea 100644 (file)
@@ -9,27 +9,7 @@
 #define HWSAMPLER_H_
 
 #include <linux/workqueue.h>
-
-struct hws_qsi_info_block          /* QUERY SAMPLING information block  */
-{ /* Bit(s) */
-       unsigned int b0_13:14;      /* 0-13: zeros                       */
-       unsigned int as:1;          /* 14: sampling authorisation control*/
-       unsigned int b15_21:7;      /* 15-21: zeros                      */
-       unsigned int es:1;          /* 22: sampling enable control       */
-       unsigned int b23_29:7;      /* 23-29: zeros                      */
-       unsigned int cs:1;          /* 30: sampling activation control   */
-       unsigned int:1;             /* 31: reserved                      */
-       unsigned int bsdes:16;      /* 4-5: size of sampling entry       */
-       unsigned int:16;            /* 6-7: reserved                     */
-       unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
-       unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
-       unsigned long tear;         /* 24-31: TEAR contents              */
-       unsigned long dear;         /* 32-39: DEAR contents              */
-       unsigned int rsvrd0;        /* 40-43: reserved                   */
-       unsigned int cpu_speed;     /* 44-47: CPU speed                  */
-       unsigned long long rsvrd1;  /* 48-55: reserved                   */
-       unsigned long long rsvrd2;  /* 56-63: reserved                   */
-};
+#include <asm/cpu_mf.h>
 
 struct hws_ssctl_request_block     /* SET SAMPLING CONTROLS req block   */
 { /* bytes 0 - 7  Bit(s) */
@@ -68,36 +48,6 @@ struct hws_cpu_buffer {
        unsigned int stop_mode:1;
 };
 
-struct hws_data_entry {
-       unsigned int def:16;        /* 0-15  Data Entry Format           */
-       unsigned int R:4;           /* 16-19 reserved                    */
-       unsigned int U:4;           /* 20-23 Number of unique instruct.  */
-       unsigned int z:2;           /* zeros                             */
-       unsigned int T:1;           /* 26 PSW DAT mode                   */
-       unsigned int W:1;           /* 27 PSW wait state                 */
-       unsigned int P:1;           /* 28 PSW Problem state              */
-       unsigned int AS:2;          /* 29-30 PSW address-space control   */
-       unsigned int I:1;           /* 31 entry valid or invalid         */
-       unsigned int:16;
-       unsigned int prim_asn:16;   /* primary ASN                       */
-       unsigned long long ia;      /* Instruction Address               */
-       unsigned long long gpp;     /* Guest Program Parameter           */
-       unsigned long long hpp;     /* Host Program Parameter            */
-};
-
-struct hws_trailer_entry {
-       unsigned int f:1;           /* 0 - Block Full Indicator          */
-       unsigned int a:1;           /* 1 - Alert request control         */
-       unsigned long:62;           /* 2 - 63: Reserved                  */
-       unsigned long overflow;     /* 64 - sample Overflow count        */
-       unsigned long timestamp;    /* 16 - time-stamp                   */
-       unsigned long timestamp1;   /*                                   */
-       unsigned long reserved1;    /* 32 -Reserved                      */
-       unsigned long reserved2;    /*                                   */
-       unsigned long progusage1;   /* 48 - reserved for programming use */
-       unsigned long progusage2;   /*                                   */
-};
-
 int hwsampler_setup(void);
 int hwsampler_shutdown(void);
 int hwsampler_allocate(unsigned long sdbt, unsigned long sdb);
index 04e1b6a8536297cc61f2bacc0187c0b6a7089573..9ffe645d59898cbe5e9e88f95c9a08342b91bb00 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/oprofile.h>
+#include <linux/perf_event.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -67,6 +68,21 @@ module_param_call(cpu_type, set_cpu_type, NULL, NULL, 0);
 MODULE_PARM_DESC(cpu_type, "Force legacy basic mode sampling"
                           "(report cpu_type \"timer\"");
 
+static int __oprofile_hwsampler_start(void)
+{
+       int retval;
+
+       retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks);
+       if (retval)
+               return retval;
+
+       retval = hwsampler_start_all(oprofile_hw_interval);
+       if (retval)
+               hwsampler_deallocate();
+
+       return retval;
+}
+
 static int oprofile_hwsampler_start(void)
 {
        int retval;
@@ -76,13 +92,13 @@ static int oprofile_hwsampler_start(void)
        if (!hwsampler_running)
                return timer_ops.start();
 
-       retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks);
+       retval = perf_reserve_sampling();
        if (retval)
                return retval;
 
-       retval = hwsampler_start_all(oprofile_hw_interval);
+       retval = __oprofile_hwsampler_start();
        if (retval)
-               hwsampler_deallocate();
+               perf_release_sampling();
 
        return retval;
 }
@@ -96,6 +112,7 @@ static void oprofile_hwsampler_stop(void)
 
        hwsampler_stop_all();
        hwsampler_deallocate();
+       perf_release_sampling();
        return;
 }
 
index bf7c73d71eef1ee46ee9bcec9516be70fcc2dc27..0820362c7b0f190ec66029597dee6d006d9487c0 100644 (file)
@@ -919,17 +919,23 @@ static void zpci_mem_exit(void)
        kmem_cache_destroy(zdev_fmb_cache);
 }
 
-static unsigned int s390_pci_probe;
+static unsigned int s390_pci_probe = 1;
+static unsigned int s390_pci_initialized;
 
 char * __init pcibios_setup(char *str)
 {
-       if (!strcmp(str, "on")) {
-               s390_pci_probe = 1;
+       if (!strcmp(str, "off")) {
+               s390_pci_probe = 0;
                return NULL;
        }
        return str;
 }
 
+bool zpci_is_enabled(void)
+{
+       return s390_pci_initialized;
+}
+
 static int __init pci_base_init(void)
 {
        int rc;
@@ -961,6 +967,7 @@ static int __init pci_base_init(void)
        if (rc)
                goto out_find;
 
+       s390_pci_initialized = 1;
        return 0;
 
 out_find:
@@ -978,5 +985,6 @@ subsys_initcall_sync(pci_base_init);
 
 void zpci_rescan(void)
 {
-       clp_rescan_pci_devices_simple();
+       if (zpci_is_enabled())
+               clp_rescan_pci_devices_simple();
 }
index 9b83d080902dfb6d406c1fb026c95414d7494a53..60c11a629d96d0220d6b01cf1e1425d41c0ffaab 100644 (file)
@@ -285,7 +285,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
                flags |= ZPCI_TABLE_PROTECTED;
 
        if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) {
-               atomic64_add(nr_pages, (atomic64_t *) &zdev->fmb->mapped_pages);
+               atomic64_add(nr_pages, &zdev->fmb->mapped_pages);
                return dma_addr + (offset & ~PAGE_MASK);
        }
 
@@ -313,7 +313,7 @@ static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
                zpci_err_hex(&dma_addr, sizeof(dma_addr));
        }
 
-       atomic64_add(npages, (atomic64_t *) &zdev->fmb->unmapped_pages);
+       atomic64_add(npages, &zdev->fmb->unmapped_pages);
        iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT;
        dma_free_iommu(zdev, iommu_page_index, npages);
 }
@@ -332,7 +332,6 @@ static void *s390_dma_alloc(struct device *dev, size_t size,
        if (!page)
                return NULL;
 
-       atomic64_add(size / PAGE_SIZE, (atomic64_t *) &zdev->fmb->allocated_pages);
        pa = page_to_phys(page);
        memset((void *) pa, 0, size);
 
@@ -343,6 +342,7 @@ static void *s390_dma_alloc(struct device *dev, size_t size,
                return NULL;
        }
 
+       atomic64_add(size / PAGE_SIZE, &zdev->fmb->allocated_pages);
        if (dma_handle)
                *dma_handle = map;
        return (void *) pa;
@@ -352,8 +352,11 @@ static void s390_dma_free(struct device *dev, size_t size,
                          void *pa, dma_addr_t dma_handle,
                          struct dma_attrs *attrs)
 {
-       s390_dma_unmap_pages(dev, dma_handle, PAGE_ALIGN(size),
-                            DMA_BIDIRECTIONAL, NULL);
+       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+
+       size = PAGE_ALIGN(size);
+       atomic64_sub(size / PAGE_SIZE, &zdev->fmb->allocated_pages);
+       s390_dma_unmap_pages(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
        free_pages((unsigned long) pa, get_order(size));
 }
 
index 800f064b0da7c9a32c3910ecefdfb3e6979d7f9b..01e251b1da0cb82c6ecc263fcd5474c19c34d28d 100644 (file)
@@ -43,9 +43,8 @@ struct zpci_ccdf_avail {
        u16 pec;                        /* PCI event code */
 } __packed;
 
-void zpci_event_error(void *data)
+static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
 {
-       struct zpci_ccdf_err *ccdf = data;
        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
 
        zpci_err("error CCDF:\n");
@@ -58,9 +57,14 @@ void zpci_event_error(void *data)
               pci_name(zdev->pdev), ccdf->pec, ccdf->fid);
 }
 
-void zpci_event_availability(void *data)
+void zpci_event_error(void *data)
+{
+       if (zpci_is_enabled())
+               __zpci_event_error(data);
+}
+
+static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
 {
-       struct zpci_ccdf_avail *ccdf = data;
        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
        struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
        int ret;
@@ -75,6 +79,7 @@ void zpci_event_availability(void *data)
                if (!zdev || zdev->state == ZPCI_FN_STATE_CONFIGURED)
                        break;
                zdev->state = ZPCI_FN_STATE_CONFIGURED;
+               zdev->fh = ccdf->fh;
                ret = zpci_enable_device(zdev);
                if (ret)
                        break;
@@ -98,9 +103,14 @@ void zpci_event_availability(void *data)
 
                break;
        case 0x0304: /* Configured -> Standby */
-               if (pdev)
+               if (pdev) {
+                       /* Give the driver a hint that the function is
+                        * already unusable. */
+                       pdev->error_state = pci_channel_io_perm_failure;
                        pci_stop_and_remove_bus_device(pdev);
+               }
 
+               zdev->fh = ccdf->fh;
                zpci_disable_device(zdev);
                zdev->state = ZPCI_FN_STATE_STANDBY;
                break;
@@ -108,6 +118,8 @@ void zpci_event_availability(void *data)
                clp_rescan_pci_devices();
                break;
        case 0x0308: /* Standby -> Reserved */
+               if (!zdev)
+                       break;
                pci_stop_root_bus(zdev->bus);
                pci_remove_root_bus(zdev->bus);
                break;
@@ -115,3 +127,9 @@ void zpci_event_availability(void *data)
                break;
        }
 }
+
+void zpci_event_availability(void *data)
+{
+       if (zpci_is_enabled())
+               __zpci_event_availability(data);
+}
index f3414ade77a37c2628f2fa104efccdd1ec0bbc23..fe7471eb0167cb92e313d86169f0b77e964845df 100644 (file)
@@ -1,6 +1,7 @@
 
 header-y +=
 
+generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += trace_clock.h
 generic-y += xor.h
diff --git a/arch/score/include/asm/barrier.h b/arch/score/include/asm/barrier.h
deleted file mode 100644 (file)
index 0eacb64..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _ASM_SCORE_BARRIER_H
-#define _ASM_SCORE_BARRIER_H
-
-#define mb()           barrier()
-#define rmb()          barrier()
-#define wmb()          barrier()
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
-
-#define set_mb(var, value)             do {var = value; wmb(); } while (0)
-
-#endif /* _ASM_SCORE_BARRIER_H */
index 9b0979f4df7a5331cdc07ea468c4e0a033510d53..ce298317a73e5da295b398ff140b14a267a3977e 100644 (file)
@@ -66,6 +66,7 @@ config SUPERH32
        select PERF_EVENTS
        select ARCH_HIBERNATION_POSSIBLE if MMU
        select SPARSE_IRQ
+       select HAVE_CC_STACKPROTECTOR
 
 config SUPERH64
        def_bool ARCH = "sh64"
@@ -695,20 +696,6 @@ config SECCOMP
 
          If unsure, say N.
 
-config CC_STACKPROTECTOR
-       bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
-       depends on SUPERH32
-       help
-         This option turns on the -fstack-protector GCC feature. This
-         feature puts, at the beginning of functions, a canary value on
-         the stack just before the return address, and validates
-         the value just before actually returning.  Stack based buffer
-         overflows (that need to overwrite this return address) now also
-         overwrite the canary, which gets detected and the attack is then
-         neutralized via a kernel panic.
-
-         This feature requires gcc version 4.2 or above.
-
 config SMP
        bool "Symmetric multi-processing support"
        depends on SYS_SUPPORTS_SMP
index aed701c7b11bb0208ffc3cf50efe2fb0ba0673f6..d4d16e4be07c246d5941c799e9f4cff5d091d702 100644 (file)
@@ -199,10 +199,6 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y)
   KBUILD_CFLAGS += -fasynchronous-unwind-tables
 endif
 
-ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
-  KBUILD_CFLAGS += -fstack-protector
-endif
-
 libs-$(CONFIG_SUPERH32)                := arch/sh/lib/ $(libs-y)
 libs-$(CONFIG_SUPERH64)                := arch/sh/lib64/ $(libs-y)
 
index 72c103dae3009914bed58e521ec175eaf7c1fc7c..43715308b06874c115d1a5477b00beea79d68a7c 100644 (file)
 #if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
 #define mb()           __asm__ __volatile__ ("synco": : :"memory")
 #define rmb()          mb()
-#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
+#define wmb()          mb()
 #define ctrl_barrier() __icbi(PAGE_OFFSET)
-#define read_barrier_depends() do { } while(0)
 #else
-#define mb()           __asm__ __volatile__ ("": : :"memory")
-#define rmb()          mb()
-#define wmb()          __asm__ __volatile__ ("": : :"memory")
 #define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
-#define read_barrier_depends() do { } while(0)
-#endif
-
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
 #endif
 
 #define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
 
+#include <asm-generic/barrier.h>
+
 #endif /* __ASM_SH_BARRIER_H */
index 2a0a596ebf67d948663df3009d1ca14c8b09dabc..d77f2f6c7ff0761de1b51f09eb8926923c817681 100644 (file)
@@ -20,6 +20,11 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(empty_zero_page);
+#ifdef CONFIG_FLATMEM
+/* need in pfn_valid macro */
+EXPORT_SYMBOL(min_low_pfn);
+EXPORT_SYMBOL(max_low_pfn);
+#endif
 
 #define DECLARE_EXPORT(name)           \
        extern void name(void);EXPORT_SYMBOL(name)
index 7b95f29e31749ec180e67028424580fadda1c3af..3baff31e58cf22c30b2d770162ee3c4b10c087ea 100644 (file)
@@ -6,7 +6,7 @@ lib-y  = delay.o memmove.o memchr.o \
         checksum.o strlen.o div64.o div64-generic.o
 
 # Extracted from libgcc
-lib-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
+obj-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
         ashlsi3.o ashrsi3.o ashiftrt.o lshrsi3.o \
         udiv_qrnnd.o
 
index c1b76654ee76a8cf79ef87d25bd7a44d45479d46..ae69eda288f41774e0e799b182672bddb0b9e493 100644 (file)
@@ -1,15 +1,7 @@
 #ifndef __SPARC_BARRIER_H
 #define __SPARC_BARRIER_H
 
-/* XXX Change this if we ever use a PSO mode kernel. */
-#define mb()   __asm__ __volatile__ ("" : : : "memory")
-#define rmb()  mb()
-#define wmb()  mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
-#define smp_mb()       __asm__ __volatile__("":::"memory")
-#define smp_rmb()      __asm__ __volatile__("":::"memory")
-#define smp_wmb()      __asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends()     do { } while(0)
+#include <asm/processor.h> /* for nop() */
+#include <asm-generic/barrier.h>
 
 #endif /* !(__SPARC_BARRIER_H) */
index 95d45986f908d4224d6b5bf6ec4d5e2a4d697ceb..b5aad964558e756bbf6c3f3c3e29616dceabde94 100644 (file)
@@ -53,4 +53,19 @@ do { __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
 
 #define smp_read_barrier_depends()     do { } while(0)
 
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ___p1;                                                          \
+})
+
 #endif /* !(__SPARC64_BARRIER_H) */
index 8358dc144959aacc8b369830c21c130593b9a804..0f9e94537eee78d9d41fffe82e32fc0098811ed2 100644 (file)
@@ -619,7 +619,7 @@ static inline unsigned long pte_present(pte_t pte)
 }
 
 #define pte_accessible pte_accessible
-static inline unsigned long pte_accessible(pte_t a)
+static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
 {
        return pte_val(a) & _PAGE_VALID;
 }
@@ -847,7 +847,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
         * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
         *             and SUN4V pte layout, so this inline test is fine.
         */
-       if (likely(mm != &init_mm) && pte_accessible(orig))
+       if (likely(mm != &init_mm) && pte_accessible(mm, orig))
                tlb_batch_add(mm, addr, ptep, orig, fullmm);
 }
 
index e562d3caee57457a3b188f13b2959d47a7f835b4..ad7e178337f12f2f753f66ec2a9c26dae65c9f68 100644 (file)
@@ -262,8 +262,8 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long);
 extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
-#define __copy_to_user_inatomic ___copy_to_user
-#define __copy_from_user_inatomic ___copy_from_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 struct pt_regs;
 extern unsigned long compute_effective_address(struct pt_regs *,
index 070ed141aac79728da15f406289219a9c385fe27..76663b019eb5207f389655dac5133afce6e553aa 100644 (file)
@@ -854,7 +854,7 @@ int dma_supported(struct device *dev, u64 device_mask)
                return 1;
 
 #ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return pci64_dma_supported(to_pci_dev(dev), device_mask);
 #endif
 
index 2096468de9b27f7dd2bb54f17e3b308f8d359836..e7e215dfa86668750c9490331d94b288ab78857c 100644 (file)
@@ -666,10 +666,9 @@ EXPORT_SYMBOL(dma_ops);
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-#ifdef CONFIG_PCI
-       if (dev->bus == &pci_bus_type)
+       if (dev_is_pci(dev))
                return 1;
-#endif
+
        return 0;
 }
 EXPORT_SYMBOL(dma_supported);
index 60b19f50c80a8f9d7f31b4b4105ed4fcded6a5ca..b45fe3fb4d2cfbc7999d34a1b25baf9bc0278c2e 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
 #include <linux/ftrace.h>
+#include <linux/context_tracking.h>
 
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
index b66a5338231e965252fef5f23234141bb2fc8f85..b085311dcd0ea9f81840e1fc2550c4f870e984eb 100644 (file)
@@ -123,11 +123,12 @@ void smp_callin(void)
                rmb();
 
        set_cpu_online(cpuid, true);
-       local_irq_enable();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
 
+       local_irq_enable();
+
        cpu_startup_entry(CPUHP_ONLINE);
 }
 
index 218b6b23c378f888ef6ab0accf7ee4882e2911e2..01fe9946d388de469e140532b3f973f8a6db28fb 100644 (file)
@@ -497,9 +497,20 @@ void bpf_jit_compile(struct sk_filter *fp)
                        case BPF_S_ALU_MUL_K:   /* A *= K */
                                emit_alu_K(MUL, K);
                                break;
-                       case BPF_S_ALU_DIV_K:   /* A /= K */
-                               emit_alu_K(MUL, K);
-                               emit_read_y(r_A);
+                       case BPF_S_ALU_DIV_K:   /* A /= K with K != 0*/
+                               if (K == 1)
+                                       break;
+                               emit_write_y(G0);
+#ifdef CONFIG_SPARC32
+                               /* The Sparc v8 architecture requires
+                                * three instructions between a %y
+                                * register write and the first use.
+                                */
+                               emit_nop();
+                               emit_nop();
+                               emit_nop();
+#endif
+                               emit_alu_K(DIV, K);
                                break;
                        case BPF_S_ALU_DIV_X:   /* A /= X; */
                                emit_cmpi(r_X, 0);
index a9a73da5865d4cae6f8803723c9e9488df095ced..b5a05d050a8f6d27778fa09899b0915bbb10a1fe 100644 (file)
 #include <arch/spr_def.h>
 #include <asm/timex.h>
 
-/*
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier.  All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads.  This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies.  See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     b = 2;
- *     memory_barrier();
- *     p = &b;                         q = p;
- *                                     read_barrier_depends();
- *                                     d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().  However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- *     CPU 0                           CPU 1
- *
- *     a = 2;
- *     memory_barrier();
- *     b = 3;                          y = b;
- *                                     read_barrier_depends();
- *                                     x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like this where there are no data dependencies.
- */
-#define read_barrier_depends() do { } while (0)
-
 #define __sync()       __insn_mf()
 
 #include <hv/syscall_public.h>
@@ -125,20 +72,7 @@ mb_incoherent(void)
 #define mb()           fast_mb()
 #define iob()          fast_iob()
 
-#ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-#endif
-
-#define set_mb(var, value) \
-       do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_TILE_BARRIER_H */
index 48d92bbe62e9eae2460df5fb99bdd83974b9aecb..36e658a4291c685e12d554dfd74ac153179591dc 100644 (file)
@@ -33,12 +33,11 @@ MODE_INCLUDE        += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
 HEADER_ARCH    := $(SUBARCH)
 
-# Additional ARCH settings for x86
-ifeq ($(SUBARCH),i386)
-        HEADER_ARCH := x86
+ifneq ($(filter $(SUBARCH),x86 x86_64 i386),)
+       HEADER_ARCH := x86
 endif
-ifeq ($(SUBARCH),x86_64)
-        HEADER_ARCH := x86
+
+ifdef CONFIG_64BIT
        KBUILD_CFLAGS += -mcmodel=large
 endif
 
index 4d6fdf68edf31cf31b993081a6d9432dff6e3c5b..799d7e413bf57247f258b25ad6306a91b363e67c 100644 (file)
@@ -19,7 +19,7 @@ struct stack_frame {
        unsigned long return_address;
 };
 
-static void print_stack_trace(unsigned long *sp, unsigned long bp)
+static void do_stack_trace(unsigned long *sp, unsigned long bp)
 {
        int reliable;
        unsigned long addr;
@@ -94,5 +94,5 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        }
        printk(KERN_CONT "\n");
 
-       print_stack_trace(sp, bp);
+       do_stack_trace(sp, bp);
 }
index a6620e5336b68f0a8836e463b40e497db4332a99..83d6a520f4bd7a6611df605e62945f8e84c40aa4 100644 (file)
 #define dsb() __asm__ __volatile__ ("" : : : "memory")
 #define dmb() __asm__ __volatile__ ("" : : : "memory")
 
-#define mb()                           barrier()
-#define rmb()                          barrier()
-#define wmb()                          barrier()
-#define smp_mb()                       barrier()
-#define smp_rmb()                      barrier()
-#define smp_wmb()                      barrier()
-#define read_barrier_depends()         do { } while (0)
-#define smp_read_barrier_depends()     do { } while (0)
-
-#define set_mb(var, value)             do { var = value; smp_mb(); } while (0)
+#include <asm-generic/barrier.h>
 
 #endif /* __UNICORE_BARRIER_H__ */
index e903c71f7e69822d2ce5240b957399dbab783037..cd18b8393400343aea897ef45de4d11610c05c10 100644 (file)
@@ -26,6 +26,7 @@ config X86
        select HAVE_AOUT if X86_32
        select HAVE_UNSTABLE_SCHED_CLOCK
        select ARCH_SUPPORTS_NUMA_BALANCING
+       select ARCH_SUPPORTS_INT128 if X86_64
        select ARCH_WANTS_PROT_NUMA_PROT_NONE
        select HAVE_IDE
        select HAVE_OPROFILE
@@ -124,6 +125,7 @@ config X86
        select RTC_LIB
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
+       select HAVE_CC_STACKPROTECTOR
 
 config INSTRUCTION_DECODER
        def_bool y
@@ -437,42 +439,26 @@ config X86_INTEL_CE
          This option compiles in support for the CE4100 SOC for settop
          boxes and media devices.
 
-config X86_WANT_INTEL_MID
+config X86_INTEL_MID
        bool "Intel MID platform support"
        depends on X86_32
        depends on X86_EXTENDED_PLATFORM
-       ---help---
-         Select to build a kernel capable of supporting Intel MID platform
-         systems which do not have the PCI legacy interfaces (Moorestown,
-         Medfield). If you are building for a PC class system say N here.
-
-if X86_WANT_INTEL_MID
-
-config X86_INTEL_MID
-       bool
-
-config X86_MDFLD
-       bool "Medfield MID platform"
        depends on PCI
        depends on PCI_GOANY
        depends on X86_IO_APIC
-       select X86_INTEL_MID
        select SFI
+       select I2C
        select DW_APB_TIMER
        select APB_TIMER
-       select I2C
-       select SPI
        select INTEL_SCU_IPC
-       select X86_PLATFORM_DEVICES
        select MFD_INTEL_MSIC
        ---help---
-         Medfield is Intel's Low Power Intel Architecture (LPIA) based Moblin
-         Internet Device(MID) platform. 
-         Unlike standard x86 PCs, Medfield does not have many legacy devices
-         nor standard legacy replacement devices/features. e.g. Medfield does
-         not contain i8259, i8254, HPET, legacy BIOS, most of the io ports.
+         Select to build a kernel capable of supporting Intel MID (Mobile
+         Internet Device) platform systems which do not have the PCI legacy
+         interfaces. If you are building for a PC class system say N here.
 
-endif
+         Intel MID platforms are based on an Intel processor and chipset which
+         consume less power than most of the x86 derivatives.
 
 config X86_INTEL_LPSS
        bool "Intel Low Power Subsystem Support"
@@ -1079,10 +1065,6 @@ config MICROCODE_OLD_INTERFACE
        def_bool y
        depends on MICROCODE
 
-config MICROCODE_INTEL_LIB
-       def_bool y
-       depends on MICROCODE_INTEL
-
 config MICROCODE_INTEL_EARLY
        def_bool n
 
@@ -1616,22 +1598,6 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
-config CC_STACKPROTECTOR
-       bool "Enable -fstack-protector buffer overflow detection"
-       ---help---
-         This option turns on the -fstack-protector GCC feature. This
-         feature puts, at the beginning of functions, a canary value on
-         the stack just before the return address, and validates
-         the value just before actually returning.  Stack based buffer
-         overflows (that need to overwrite this return address) now also
-         overwrite the canary, which gets detected and the attack is then
-         neutralized via a kernel panic.
-
-         This feature requires gcc version 4.2 or above, or a distribution
-         gcc with the feature backported. Older versions are automatically
-         detected and for those versions, this configuration option is
-         ignored. (and a warning is printed during bootup)
-
 source kernel/Kconfig.hz
 
 config KEXEC
@@ -1727,16 +1693,67 @@ config RELOCATABLE
 
          Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
          it has been loaded at and the compile time physical address
-         (CONFIG_PHYSICAL_START) is ignored.
+         (CONFIG_PHYSICAL_START) is used as the minimum location.
 
-# Relocation on x86-32 needs some additional build support
+config RANDOMIZE_BASE
+       bool "Randomize the address of the kernel image"
+       depends on RELOCATABLE
+       depends on !HIBERNATION
+       default n
+       ---help---
+          Randomizes the physical and virtual address at which the
+          kernel image is decompressed, as a security feature that
+          deters exploit attempts relying on knowledge of the location
+          of kernel internals.
+
+          Entropy is generated using the RDRAND instruction if it is
+          supported. If RDTSC is supported, it is used as well. If
+          neither RDRAND nor RDTSC are supported, then randomness is
+          read from the i8254 timer.
+
+          The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET,
+          and aligned according to PHYSICAL_ALIGN. Since the kernel is
+          built using 2GiB addressing, and PHYSICAL_ALGIN must be at a
+          minimum of 2MiB, only 10 bits of entropy is theoretically
+          possible. At best, due to page table layouts, 64-bit can use
+          9 bits of entropy and 32-bit uses 8 bits.
+
+          If unsure, say N.
+
+config RANDOMIZE_BASE_MAX_OFFSET
+       hex "Maximum kASLR offset allowed" if EXPERT
+       depends on RANDOMIZE_BASE
+       range 0x0 0x20000000 if X86_32
+       default "0x20000000" if X86_32
+       range 0x0 0x40000000 if X86_64
+       default "0x40000000" if X86_64
+       ---help---
+         The lesser of RANDOMIZE_BASE_MAX_OFFSET and available physical
+         memory is used to determine the maximal offset in bytes that will
+         be applied to the kernel when kernel Address Space Layout
+         Randomization (kASLR) is active. This must be a multiple of
+         PHYSICAL_ALIGN.
+
+         On 32-bit this is limited to 512MiB by page table layouts. The
+         default is 512MiB.
+
+         On 64-bit this is limited by how the kernel fixmap page table is
+         positioned, so this cannot be larger than 1GiB currently. Without
+         RANDOMIZE_BASE, there is a 512MiB to 1.5GiB split between kernel
+         and modules. When RANDOMIZE_BASE_MAX_OFFSET is above 512MiB, the
+         modules area will shrink to compensate, up to the current maximum
+         1GiB to 1GiB split. The default is 1GiB.
+
+         If unsure, leave at the default value.
+
+# Relocation on x86 needs some additional build support
 config X86_NEED_RELOCS
        def_bool y
-       depends on X86_32 && RELOCATABLE
+       depends on RANDOMIZE_BASE || (X86_32 && RELOCATABLE)
 
 config PHYSICAL_ALIGN
        hex "Alignment value to which kernel should be aligned"
-       default "0x1000000"
+       default "0x200000"
        range 0x2000 0x1000000 if X86_32
        range 0x200000 0x1000000 if X86_64
        ---help---
@@ -2392,6 +2409,14 @@ config X86_DMA_REMAP
        bool
        depends on STA2X11
 
+config IOSF_MBI
+       bool
+       depends on PCI
+       ---help---
+         To be selected by modules requiring access to the Intel OnChip System
+         Fabric (IOSF) Sideband MailBox Interface (MBI). For MBI platforms
+         enumerable by PCI.
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
index 41250fb33985e179f63b399cfb6a2d10c93a4e29..13b22e0f681dbeff951dde5055e7f594778a98a1 100644 (file)
@@ -31,6 +31,9 @@ ifeq ($(CONFIG_X86_32),y)
 
         KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return
 
+        # Don't autogenerate MMX or SSE instructions
+        KBUILD_CFLAGS += -mno-mmx -mno-sse
+
         # Never want PIC in a 32-bit kernel, prevent breakage with GCC built
         # with nonstandard options
         KBUILD_CFLAGS += -fno-pic
@@ -57,8 +60,11 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
+        # Don't autogenerate MMX or SSE instructions
+        KBUILD_CFLAGS += -mno-mmx -mno-sse
+
        # Use -mpreferred-stack-boundary=3 if supported.
-       KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3)
+       KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
 
         # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
         cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
@@ -83,13 +89,11 @@ else
         KBUILD_CFLAGS += -maccumulate-outgoing-args
 endif
 
+# Make sure compiler does not have buggy stack-protector support.
 ifdef CONFIG_CC_STACKPROTECTOR
        cc_has_sp := $(srctree)/scripts/gcc-x86_$(BITS)-has-stack-protector.sh
-        ifeq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
-                stackp-y := -fstack-protector
-                KBUILD_CFLAGS += $(stackp-y)
-        else
-                $(warning stack protector enabled but no compiler support)
+        ifneq ($(shell $(CONFIG_SHELL) $(cc_has_sp) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
+                $(warning stack-protector enabled but compiler support broken)
         endif
 endif
 
index dce69a2568963bf97efa8a3598be4645cc93834b..de70669180052163de7a34a21e92302b4c50128e 100644 (file)
@@ -20,7 +20,7 @@ targets               := vmlinux.bin setup.bin setup.elf bzImage
 targets                += fdimage fdimage144 fdimage288 image.iso mtools.conf
 subdir-                := compressed
 
-setup-y                += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
+setup-y                += a20.o bioscall.o cmdline.o copy.o cpu.o cpuflags.o cpucheck.o
 setup-y                += early_serial_console.o edd.o header.o main.o mca.o memory.o
 setup-y                += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
 setup-y                += video-mode.o version.o
@@ -53,18 +53,18 @@ $(obj)/cpustr.h: $(obj)/mkcpustr FORCE
 
 # How to compile the 16-bit code.  Note we always compile for -march=i386,
 # that way we can complain to the user if the CPU is insufficient.
-KBUILD_CFLAGS  := $(USERINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+KBUILD_CFLAGS  := $(USERINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ \
                   -DDISABLE_BRANCH_PROFILING \
                   -Wall -Wstrict-prototypes \
                   -march=i386 -mregparm=3 \
                   -include $(srctree)/$(src)/code16gcc.h \
                   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
+                  -mno-mmx -mno-sse \
                   $(call cc-option, -ffreestanding) \
                   $(call cc-option, -fno-toplevel-reorder,\
-                       $(call cc-option, -fno-unit-at-a-time)) \
+                  $(call cc-option, -fno-unit-at-a-time)) \
                   $(call cc-option, -fno-stack-protector) \
                   $(call cc-option, -mpreferred-stack-boundary=2)
-KBUILD_CFLAGS  += $(call cc-option, -m32)
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
 
index 1dfbf64e52a2b013d19c4551837db384e890d80a..d401b4a262b09aacf56fb74fcadbfc03fe9595bb 100644 (file)
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------------
  *
- *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *   Copyright 2009-2014 Intel Corporation; author H. Peter Anvin
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2 or (at your
@@ -13,8 +13,8 @@
  * touching registers they shouldn't be.
  */
 
-       .code16gcc
-       .text
+       .code16
+       .section ".inittext","ax"
        .globl  intcall
        .type   intcall, @function
 intcall:
index ef72baeff48475cd1ce9583880c33b9970b1b556..50f8c5e0f37e1d2dd7030da9d72c5be21e2ee282 100644 (file)
@@ -26,9 +26,8 @@
 #include <asm/boot.h>
 #include <asm/setup.h>
 #include "bitops.h"
-#include <asm/cpufeature.h>
-#include <asm/processor-flags.h>
 #include "ctype.h"
+#include "cpuflags.h"
 
 /* Useful macros */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -307,14 +306,7 @@ static inline int cmdline_find_option_bool(const char *option)
        return __cmdline_find_option_bool(cmd_line_ptr, option);
 }
 
-
 /* cpu.c, cpucheck.c */
-struct cpu_features {
-       int level;              /* Family, or 64 for x86-64 */
-       int model;
-       u32 flags[NCAPINTS];
-};
-extern struct cpu_features cpu;
 int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
 int validate_cpu(void);
 
index dcd90df10ab4e271dd6ee0e3ed737015326efa18..0fcd9133790c566423b313fccef95a0768bd0d07 100644 (file)
@@ -13,6 +13,7 @@ KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 cflags-$(CONFIG_X86_32) := -march=i386
 cflags-$(CONFIG_X86_64) := -mcmodel=small
 KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -mno-mmx -mno-sse
 KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
 KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
 
@@ -27,7 +28,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 
 VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
        $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
-       $(obj)/piggy.o
+       $(obj)/piggy.o $(obj)/cpuflags.o $(obj)/aslr.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
new file mode 100644 (file)
index 0000000..90a21f4
--- /dev/null
@@ -0,0 +1,316 @@
+#include "misc.h"
+
+#ifdef CONFIG_RANDOMIZE_BASE
+#include <asm/msr.h>
+#include <asm/archrandom.h>
+#include <asm/e820.h>
+
+#include <generated/compile.h>
+#include <linux/module.h>
+#include <linux/uts.h>
+#include <linux/utsname.h>
+#include <generated/utsrelease.h>
+
+/* Simplified build-specific string for starting entropy. */
+static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+               LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
+
+#define I8254_PORT_CONTROL     0x43
+#define I8254_PORT_COUNTER0    0x40
+#define I8254_CMD_READBACK     0xC0
+#define I8254_SELECT_COUNTER0  0x02
+#define I8254_STATUS_NOTREADY  0x40
+static inline u16 i8254(void)
+{
+       u16 status, timer;
+
+       do {
+               outb(I8254_PORT_CONTROL,
+                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+               status = inb(I8254_PORT_COUNTER0);
+               timer  = inb(I8254_PORT_COUNTER0);
+               timer |= inb(I8254_PORT_COUNTER0) << 8;
+       } while (status & I8254_STATUS_NOTREADY);
+
+       return timer;
+}
+
+static unsigned long rotate_xor(unsigned long hash, const void *area,
+                               size_t size)
+{
+       size_t i;
+       unsigned long *ptr = (unsigned long *)area;
+
+       for (i = 0; i < size / sizeof(hash); i++) {
+               /* Rotate by odd number of bits and XOR. */
+               hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
+               hash ^= ptr[i];
+       }
+
+       return hash;
+}
+
+/* Attempt to create a simple but unpredictable starting entropy. */
+static unsigned long get_random_boot(void)
+{
+       unsigned long hash = 0;
+
+       hash = rotate_xor(hash, build_str, sizeof(build_str));
+       hash = rotate_xor(hash, real_mode, sizeof(*real_mode));
+
+       return hash;
+}
+
+static unsigned long get_random_long(void)
+{
+#ifdef CONFIG_X86_64
+       const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
+#else
+       const unsigned long mix_const = 0x3f39e593UL;
+#endif
+       unsigned long raw, random = get_random_boot();
+       bool use_i8254 = true;
+
+       debug_putstr("KASLR using");
+
+       if (has_cpuflag(X86_FEATURE_RDRAND)) {
+               debug_putstr(" RDRAND");
+               if (rdrand_long(&raw)) {
+                       random ^= raw;
+                       use_i8254 = false;
+               }
+       }
+
+       if (has_cpuflag(X86_FEATURE_TSC)) {
+               debug_putstr(" RDTSC");
+               rdtscll(raw);
+
+               random ^= raw;
+               use_i8254 = false;
+       }
+
+       if (use_i8254) {
+               debug_putstr(" i8254");
+               random ^= i8254();
+       }
+
+       /* Circular multiply for better bit diffusion */
+       asm("mul %3"
+           : "=a" (random), "=d" (raw)
+           : "a" (random), "rm" (mix_const));
+       random += raw;
+
+       debug_putstr("...\n");
+
+       return random;
+}
+
+struct mem_vector {
+       unsigned long start;
+       unsigned long size;
+};
+
+#define MEM_AVOID_MAX 5
+struct mem_vector mem_avoid[MEM_AVOID_MAX];
+
+static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
+{
+       /* Item at least partially before region. */
+       if (item->start < region->start)
+               return false;
+       /* Item at least partially after region. */
+       if (item->start + item->size > region->start + region->size)
+               return false;
+       return true;
+}
+
+static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two)
+{
+       /* Item one is entirely before item two. */
+       if (one->start + one->size <= two->start)
+               return false;
+       /* Item one is entirely after item two. */
+       if (one->start >= two->start + two->size)
+               return false;
+       return true;
+}
+
+static void mem_avoid_init(unsigned long input, unsigned long input_size,
+                          unsigned long output, unsigned long output_size)
+{
+       u64 initrd_start, initrd_size;
+       u64 cmd_line, cmd_line_size;
+       unsigned long unsafe, unsafe_len;
+       char *ptr;
+
+       /*
+        * Avoid the region that is unsafe to overlap during
+        * decompression (see calculations at top of misc.c).
+        */
+       unsafe_len = (output_size >> 12) + 32768 + 18;
+       unsafe = (unsigned long)input + input_size - unsafe_len;
+       mem_avoid[0].start = unsafe;
+       mem_avoid[0].size = unsafe_len;
+
+       /* Avoid initrd. */
+       initrd_start  = (u64)real_mode->ext_ramdisk_image << 32;
+       initrd_start |= real_mode->hdr.ramdisk_image;
+       initrd_size  = (u64)real_mode->ext_ramdisk_size << 32;
+       initrd_size |= real_mode->hdr.ramdisk_size;
+       mem_avoid[1].start = initrd_start;
+       mem_avoid[1].size = initrd_size;
+
+       /* Avoid kernel command line. */
+       cmd_line  = (u64)real_mode->ext_cmd_line_ptr << 32;
+       cmd_line |= real_mode->hdr.cmd_line_ptr;
+       /* Calculate size of cmd_line. */
+       ptr = (char *)(unsigned long)cmd_line;
+       for (cmd_line_size = 0; ptr[cmd_line_size++]; )
+               ;
+       mem_avoid[2].start = cmd_line;
+       mem_avoid[2].size = cmd_line_size;
+
+       /* Avoid heap memory. */
+       mem_avoid[3].start = (unsigned long)free_mem_ptr;
+       mem_avoid[3].size = BOOT_HEAP_SIZE;
+
+       /* Avoid stack memory. */
+       mem_avoid[4].start = (unsigned long)free_mem_end_ptr;
+       mem_avoid[4].size = BOOT_STACK_SIZE;
+}
+
+/* Does this memory vector overlap a known avoided area? */
+bool mem_avoid_overlap(struct mem_vector *img)
+{
+       int i;
+
+       for (i = 0; i < MEM_AVOID_MAX; i++) {
+               if (mem_overlaps(img, &mem_avoid[i]))
+                       return true;
+       }
+
+       return false;
+}
+
+unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN];
+unsigned long slot_max = 0;
+
+static void slots_append(unsigned long addr)
+{
+       /* Overflowing the slots list should be impossible. */
+       if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
+                       CONFIG_PHYSICAL_ALIGN)
+               return;
+
+       slots[slot_max++] = addr;
+}
+
+static unsigned long slots_fetch_random(void)
+{
+       /* Handle case of no slots stored. */
+       if (slot_max == 0)
+               return 0;
+
+       return slots[get_random_long() % slot_max];
+}
+
+static void process_e820_entry(struct e820entry *entry,
+                              unsigned long minimum,
+                              unsigned long image_size)
+{
+       struct mem_vector region, img;
+
+       /* Skip non-RAM entries. */
+       if (entry->type != E820_RAM)
+               return;
+
+       /* Ignore entries entirely above our maximum. */
+       if (entry->addr >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
+               return;
+
+       /* Ignore entries entirely below our minimum. */
+       if (entry->addr + entry->size < minimum)
+               return;
+
+       region.start = entry->addr;
+       region.size = entry->size;
+
+       /* Potentially raise address to minimum location. */
+       if (region.start < minimum)
+               region.start = minimum;
+
+       /* Potentially raise address to meet alignment requirements. */
+       region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
+
+       /* Did we raise the address above the bounds of this e820 region? */
+       if (region.start > entry->addr + entry->size)
+               return;
+
+       /* Reduce size by any delta from the original address. */
+       region.size -= region.start - entry->addr;
+
+       /* Reduce maximum size to fit end of image within maximum limit. */
+       if (region.start + region.size > CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
+               region.size = CONFIG_RANDOMIZE_BASE_MAX_OFFSET - region.start;
+
+       /* Walk each aligned slot and check for avoided areas. */
+       for (img.start = region.start, img.size = image_size ;
+            mem_contains(&region, &img) ;
+            img.start += CONFIG_PHYSICAL_ALIGN) {
+               if (mem_avoid_overlap(&img))
+                       continue;
+               slots_append(img.start);
+       }
+}
+
+static unsigned long find_random_addr(unsigned long minimum,
+                                     unsigned long size)
+{
+       int i;
+       unsigned long addr;
+
+       /* Make sure minimum is aligned. */
+       minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+
+       /* Verify potential e820 positions, appending to slots list. */
+       for (i = 0; i < real_mode->e820_entries; i++) {
+               process_e820_entry(&real_mode->e820_map[i], minimum, size);
+       }
+
+       return slots_fetch_random();
+}
+
+unsigned char *choose_kernel_location(unsigned char *input,
+                                     unsigned long input_size,
+                                     unsigned char *output,
+                                     unsigned long output_size)
+{
+       unsigned long choice = (unsigned long)output;
+       unsigned long random;
+
+       if (cmdline_find_option_bool("nokaslr")) {
+               debug_putstr("KASLR disabled...\n");
+               goto out;
+       }
+
+       /* Record the various known unsafe memory ranges. */
+       mem_avoid_init((unsigned long)input, input_size,
+                      (unsigned long)output, output_size);
+
+       /* Walk e820 and find a random address. */
+       random = find_random_addr(choice, output_size);
+       if (!random) {
+               debug_putstr("KASLR could not find suitable E820 region...\n");
+               goto out;
+       }
+
+       /* Always enforce the minimum. */
+       if (random < choice)
+               goto out;
+
+       choice = random;
+out:
+       return (unsigned char *)choice;
+}
+
+#endif /* CONFIG_RANDOMIZE_BASE */
index bffd73b45b1f27a4dc6cdd2ab6ee5451cd1bbd0d..b68e3033e6b9bd6fa76f89e3fbaa034823790ad7 100644 (file)
@@ -1,6 +1,6 @@
 #include "misc.h"
 
-#ifdef CONFIG_EARLY_PRINTK
+#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
 
 static unsigned long fs;
 static inline void set_fs(unsigned long seg)
diff --git a/arch/x86/boot/compressed/cpuflags.c b/arch/x86/boot/compressed/cpuflags.c
new file mode 100644 (file)
index 0000000..aa31346
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef CONFIG_RANDOMIZE_BASE
+
+#include "../cpuflags.c"
+
+bool has_cpuflag(int flag)
+{
+       get_cpuflags();
+
+       return test_bit(flag, cpu.flags);
+}
+
+#endif
index 5d6f6891b1881ee812c060bc730915d73d4d7f65..9116aac232c746ae4f5262508fba437db9fbb431 100644 (file)
@@ -117,9 +117,11 @@ preferred_addr:
        addl    %eax, %ebx
        notl    %eax
        andl    %eax, %ebx
-#else
-       movl    $LOAD_PHYSICAL_ADDR, %ebx
+       cmpl    $LOAD_PHYSICAL_ADDR, %ebx
+       jge     1f
 #endif
+       movl    $LOAD_PHYSICAL_ADDR, %ebx
+1:
 
        /* Target address to relocate to for decompression */
        addl    $z_extract_offset, %ebx
@@ -191,14 +193,14 @@ relocated:
        leal    boot_heap(%ebx), %eax
        pushl   %eax            /* heap area */
        pushl   %esi            /* real mode pointer */
-       call    decompress_kernel
+       call    decompress_kernel /* returns kernel location in %eax */
        addl    $24, %esp
 
 /*
  * Jump to the decompressed kernel.
  */
        xorl    %ebx, %ebx
-       jmp     *%ebp
+       jmp     *%eax
 
 /*
  * Stack and heap for uncompression
index c337422b575de190280334ef5cd61214441644f9..c5c1ae0997e7b223128b009a220b899e22ffeb25 100644 (file)
@@ -94,9 +94,11 @@ ENTRY(startup_32)
        addl    %eax, %ebx
        notl    %eax
        andl    %eax, %ebx
-#else
-       movl    $LOAD_PHYSICAL_ADDR, %ebx
+       cmpl    $LOAD_PHYSICAL_ADDR, %ebx
+       jge     1f
 #endif
+       movl    $LOAD_PHYSICAL_ADDR, %ebx
+1:
 
        /* Target address to relocate to for decompression */
        addl    $z_extract_offset, %ebx
@@ -269,9 +271,11 @@ preferred_addr:
        addq    %rax, %rbp
        notq    %rax
        andq    %rax, %rbp
-#else
-       movq    $LOAD_PHYSICAL_ADDR, %rbp
+       cmpq    $LOAD_PHYSICAL_ADDR, %rbp
+       jge     1f
 #endif
+       movq    $LOAD_PHYSICAL_ADDR, %rbp
+1:
 
        /* Target address to relocate to for decompression */
        leaq    z_extract_offset(%rbp), %rbx
@@ -339,13 +343,13 @@ relocated:
        movl    $z_input_len, %ecx      /* input_len */
        movq    %rbp, %r8               /* output target address */
        movq    $z_output_len, %r9      /* decompressed length */
-       call    decompress_kernel
+       call    decompress_kernel       /* returns kernel location in %rax */
        popq    %rsi
 
 /*
  * Jump to the decompressed kernel.
  */
-       jmp     *%rbp
+       jmp     *%rax
 
        .code32
 no_longmode:
index 434f077d2c4d7b664216e6adaa22ac44ea51786a..196eaf373a06ad89c11bc9133a5c97b0e5ebc6d9 100644 (file)
@@ -112,14 +112,8 @@ struct boot_params *real_mode;             /* Pointer to real-mode data */
 void *memset(void *s, int c, size_t n);
 void *memcpy(void *dest, const void *src, size_t n);
 
-#ifdef CONFIG_X86_64
-#define memptr long
-#else
-#define memptr unsigned
-#endif
-
-static memptr free_mem_ptr;
-static memptr free_mem_end_ptr;
+memptr free_mem_ptr;
+memptr free_mem_end_ptr;
 
 static char *vidmem;
 static int vidport;
@@ -395,7 +389,7 @@ static void parse_elf(void *output)
        free(phdrs);
 }
 
-asmlinkage void decompress_kernel(void *rmode, memptr heap,
+asmlinkage void *decompress_kernel(void *rmode, memptr heap,
                                  unsigned char *input_data,
                                  unsigned long input_len,
                                  unsigned char *output,
@@ -422,6 +416,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        free_mem_ptr     = heap;        /* Heap */
        free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
 
+       output = choose_kernel_location(input_data, input_len,
+                                       output, output_len);
+
+       /* Validate memory location choices. */
        if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
                error("Destination address inappropriately aligned");
 #ifdef CONFIG_X86_64
@@ -441,5 +439,5 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        parse_elf(output);
        handle_relocations(output, output_len);
        debug_putstr("done.\nBooting the kernel.\n");
-       return;
+       return output;
 }
index 674019d8e2355901b69de5c55cfb92669c5628be..24e3e569a13ce9bf1ba620811ff4b09d6fa6e32d 100644 (file)
 #define BOOT_BOOT_H
 #include "../ctype.h"
 
+#ifdef CONFIG_X86_64
+#define memptr long
+#else
+#define memptr unsigned
+#endif
+
 /* misc.c */
+extern memptr free_mem_ptr;
+extern memptr free_mem_end_ptr;
 extern struct boot_params *real_mode;          /* Pointer to real-mode data */
 void __putstr(const char *s);
 #define error_putstr(__x)  __putstr(__x)
@@ -39,23 +47,40 @@ static inline void debug_putstr(const char *s)
 
 #endif
 
-#ifdef CONFIG_EARLY_PRINTK
-
+#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
 /* cmdline.c */
 int cmdline_find_option(const char *option, char *buffer, int bufsize);
 int cmdline_find_option_bool(const char *option);
+#endif
 
-/* early_serial_console.c */
-extern int early_serial_base;
-void console_init(void);
 
+#if CONFIG_RANDOMIZE_BASE
+/* aslr.c */
+unsigned char *choose_kernel_location(unsigned char *input,
+                                     unsigned long input_size,
+                                     unsigned char *output,
+                                     unsigned long output_size);
+/* cpuflags.c */
+bool has_cpuflag(int flag);
 #else
+static inline
+unsigned char *choose_kernel_location(unsigned char *input,
+                                     unsigned long input_size,
+                                     unsigned char *output,
+                                     unsigned long output_size)
+{
+       return output;
+}
+#endif
 
+#ifdef CONFIG_EARLY_PRINTK
 /* early_serial_console.c */
+extern int early_serial_base;
+void console_init(void);
+#else
 static const int early_serial_base;
 static inline void console_init(void)
 { }
-
 #endif
 
 #endif
index 11f272c6f5e9e0c2fcf11b030ee6d6df3cf2dd64..1eb7d298b47d5466d39e1f0ae8804dc4ebe172bb 100644 (file)
@@ -14,7 +14,7 @@
  * Memory copy routines
  */
 
-       .code16gcc
+       .code16
        .text
 
 GLOBAL(memcpy)
@@ -30,7 +30,7 @@ GLOBAL(memcpy)
        rep; movsb
        popw    %di
        popw    %si
-       ret
+       retl
 ENDPROC(memcpy)
 
 GLOBAL(memset)
@@ -45,25 +45,25 @@ GLOBAL(memset)
        andw    $3, %cx
        rep; stosb
        popw    %di
-       ret
+       retl
 ENDPROC(memset)
 
 GLOBAL(copy_from_fs)
        pushw   %ds
        pushw   %fs
        popw    %ds
-       call    memcpy
+       calll   memcpy
        popw    %ds
-       ret
+       retl
 ENDPROC(copy_from_fs)
 
 GLOBAL(copy_to_fs)
        pushw   %es
        pushw   %fs
        popw    %es
-       call    memcpy
+       calll   memcpy
        popw    %es
-       ret
+       retl
 ENDPROC(copy_to_fs)
 
 #if 0 /* Not currently used, but can be enabled as needed */
@@ -71,17 +71,17 @@ GLOBAL(copy_from_gs)
        pushw   %ds
        pushw   %gs
        popw    %ds
-       call    memcpy
+       calll   memcpy
        popw    %ds
-       ret
+       retl
 ENDPROC(copy_from_gs)
 
 GLOBAL(copy_to_gs)
        pushw   %es
        pushw   %gs
        popw    %es
-       call    memcpy
+       calll   memcpy
        popw    %es
-       ret
+       retl
 ENDPROC(copy_to_gs)
 #endif
index 4d3ff037201ffbee0bb468e04d069b02909d094d..100a9a10076a649e7e7008a3579867391ca16fa4 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/required-features.h>
 #include <asm/msr-index.h>
 
-struct cpu_features cpu;
-static u32 cpu_vendor[3];
 static u32 err_flags[NCAPINTS];
 
 static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
@@ -69,92 +67,8 @@ static int is_transmeta(void)
               cpu_vendor[2] == A32('M', 'x', '8', '6');
 }
 
-static int has_fpu(void)
-{
-       u16 fcw = -1, fsw = -1;
-       u32 cr0;
-
-       asm("movl %%cr0,%0" : "=r" (cr0));
-       if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
-               cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
-               asm volatile("movl %0,%%cr0" : : "r" (cr0));
-       }
-
-       asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
-                    : "+m" (fsw), "+m" (fcw));
-
-       return fsw == 0 && (fcw & 0x103f) == 0x003f;
-}
-
-static int has_eflag(u32 mask)
-{
-       u32 f0, f1;
-
-       asm("pushfl ; "
-           "pushfl ; "
-           "popl %0 ; "
-           "movl %0,%1 ; "
-           "xorl %2,%1 ; "
-           "pushl %1 ; "
-           "popfl ; "
-           "pushfl ; "
-           "popl %1 ; "
-           "popfl"
-           : "=&r" (f0), "=&r" (f1)
-           : "ri" (mask));
-
-       return !!((f0^f1) & mask);
-}
-
-static void get_flags(void)
-{
-       u32 max_intel_level, max_amd_level;
-       u32 tfms;
-
-       if (has_fpu())
-               set_bit(X86_FEATURE_FPU, cpu.flags);
-
-       if (has_eflag(X86_EFLAGS_ID)) {
-               asm("cpuid"
-                   : "=a" (max_intel_level),
-                     "=b" (cpu_vendor[0]),
-                     "=d" (cpu_vendor[1]),
-                     "=c" (cpu_vendor[2])
-                   : "a" (0));
-
-               if (max_intel_level >= 0x00000001 &&
-                   max_intel_level <= 0x0000ffff) {
-                       asm("cpuid"
-                           : "=a" (tfms),
-                             "=c" (cpu.flags[4]),
-                             "=d" (cpu.flags[0])
-                           : "a" (0x00000001)
-                           : "ebx");
-                       cpu.level = (tfms >> 8) & 15;
-                       cpu.model = (tfms >> 4) & 15;
-                       if (cpu.level >= 6)
-                               cpu.model += ((tfms >> 16) & 0xf) << 4;
-               }
-
-               asm("cpuid"
-                   : "=a" (max_amd_level)
-                   : "a" (0x80000000)
-                   : "ebx", "ecx", "edx");
-
-               if (max_amd_level >= 0x80000001 &&
-                   max_amd_level <= 0x8000ffff) {
-                       u32 eax = 0x80000001;
-                       asm("cpuid"
-                           : "+a" (eax),
-                             "=c" (cpu.flags[6]),
-                             "=d" (cpu.flags[1])
-                           : : "ebx");
-               }
-       }
-}
-
 /* Returns a bitmask of which words we have error bits in */
-static int check_flags(void)
+static int check_cpuflags(void)
 {
        u32 err;
        int i;
@@ -187,8 +101,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
        if (has_eflag(X86_EFLAGS_AC))
                cpu.level = 4;
 
-       get_flags();
-       err = check_flags();
+       get_cpuflags();
+       err = check_cpuflags();
 
        if (test_bit(X86_FEATURE_LM, cpu.flags))
                cpu.level = 64;
@@ -207,8 +121,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                eax &= ~(1 << 15);
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
-               get_flags();    /* Make sure it really did something */
-               err = check_flags();
+               get_cpuflags(); /* Make sure it really did something */
+               err = check_cpuflags();
        } else if (err == 0x01 &&
                   !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) &&
                   is_centaur() && cpu.model >= 6) {
@@ -223,7 +137,7 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
                set_bit(X86_FEATURE_CX8, cpu.flags);
-               err = check_flags();
+               err = check_cpuflags();
        } else if (err == 0x01 && is_transmeta()) {
                /* Transmeta might have masked feature bits in word 0 */
 
@@ -238,7 +152,7 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                    : : "ecx", "ebx");
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
-               err = check_flags();
+               err = check_cpuflags();
        }
 
        if (err_flags_ptr)
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
new file mode 100644 (file)
index 0000000..a9fcb7c
--- /dev/null
@@ -0,0 +1,104 @@
+#include <linux/types.h>
+#include "bitops.h"
+
+#include <asm/processor-flags.h>
+#include <asm/required-features.h>
+#include <asm/msr-index.h>
+#include "cpuflags.h"
+
+struct cpu_features cpu;
+u32 cpu_vendor[3];
+
+static bool loaded_flags;
+
+static int has_fpu(void)
+{
+       u16 fcw = -1, fsw = -1;
+       unsigned long cr0;
+
+       asm volatile("mov %%cr0,%0" : "=r" (cr0));
+       if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
+               cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
+               asm volatile("mov %0,%%cr0" : : "r" (cr0));
+       }
+
+       asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+                    : "+m" (fsw), "+m" (fcw));
+
+       return fsw == 0 && (fcw & 0x103f) == 0x003f;
+}
+
+int has_eflag(unsigned long mask)
+{
+       unsigned long f0, f1;
+
+       asm volatile("pushf     \n\t"
+                    "pushf     \n\t"
+                    "pop %0    \n\t"
+                    "mov %0,%1 \n\t"
+                    "xor %2,%1 \n\t"
+                    "push %1   \n\t"
+                    "popf      \n\t"
+                    "pushf     \n\t"
+                    "pop %1    \n\t"
+                    "popf"
+                    : "=&r" (f0), "=&r" (f1)
+                    : "ri" (mask));
+
+       return !!((f0^f1) & mask);
+}
+
+/* Handle x86_32 PIC using ebx. */
+#if defined(__i386__) && defined(__PIC__)
+# define EBX_REG "=r"
+#else
+# define EBX_REG "=b"
+#endif
+
+static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
+{
+       asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif  \n\t"
+                    "cpuid                                     \n\t"
+                    ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif  \n\t"
+                   : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
+                   : "a" (id)
+       );
+}
+
+void get_cpuflags(void)
+{
+       u32 max_intel_level, max_amd_level;
+       u32 tfms;
+       u32 ignored;
+
+       if (loaded_flags)
+               return;
+       loaded_flags = true;
+
+       if (has_fpu())
+               set_bit(X86_FEATURE_FPU, cpu.flags);
+
+       if (has_eflag(X86_EFLAGS_ID)) {
+               cpuid(0x0, &max_intel_level, &cpu_vendor[0], &cpu_vendor[2],
+                     &cpu_vendor[1]);
+
+               if (max_intel_level >= 0x00000001 &&
+                   max_intel_level <= 0x0000ffff) {
+                       cpuid(0x1, &tfms, &ignored, &cpu.flags[4],
+                             &cpu.flags[0]);
+                       cpu.level = (tfms >> 8) & 15;
+                       cpu.model = (tfms >> 4) & 15;
+                       if (cpu.level >= 6)
+                               cpu.model += ((tfms >> 16) & 0xf) << 4;
+               }
+
+               cpuid(0x80000000, &max_amd_level, &ignored, &ignored,
+                     &ignored);
+
+               if (max_amd_level >= 0x80000001 &&
+                   max_amd_level <= 0x8000ffff) {
+                       cpuid(0x80000001, &ignored, &ignored, &cpu.flags[6],
+                             &cpu.flags[1]);
+               }
+       }
+}
diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h
new file mode 100644 (file)
index 0000000..ea97697
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef BOOT_CPUFLAGS_H
+#define BOOT_CPUFLAGS_H
+
+#include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
+
+struct cpu_features {
+       int level;              /* Family, or 64 for x86-64 */
+       int model;
+       u32 flags[NCAPINTS];
+};
+
+extern struct cpu_features cpu;
+extern u32 cpu_vendor[3];
+
+int has_eflag(unsigned long mask);
+void get_cpuflags(void);
+
+#endif
index 9ec06a1f6d61b2d64f6520bb68d1b0e047af1276..ec3b8ba68096c5434d523c1182196f6ab42f8239 100644 (file)
@@ -391,7 +391,14 @@ xloadflags:
 #else
 # define XLF23 0
 #endif
-                       .word XLF0 | XLF1 | XLF23
+
+#if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC)
+# define XLF4 XLF_EFI_KEXEC
+#else
+# define XLF4 0
+#endif
+
+                       .word XLF0 | XLF1 | XLF23 | XLF4
 
 cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
                                                 #added with boot protocol
index 0d9ec770f2f8770f8e5a320300ea47f3bf39b9bb..e6a92455740e6a5dfc64c5b1a1193a693594feab 100644 (file)
 
 #ifdef CONFIG_ARCH_RANDOM
 
+/* Instead of arch_get_random_long() when alternatives haven't run. */
+static inline int rdrand_long(unsigned long *v)
+{
+       int ok;
+       asm volatile("1: " RDRAND_LONG "\n\t"
+                    "jc 2f\n\t"
+                    "decl %0\n\t"
+                    "jnz 1b\n\t"
+                    "2:"
+                    : "=r" (ok), "=a" (*v)
+                    : "0" (RDRAND_RETRY_LOOPS));
+       return ok;
+}
+
 #define GET_RANDOM(name, type, rdrand, nop)                    \
 static inline int name(type *v)                                        \
 {                                                              \
@@ -68,6 +82,13 @@ GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
 
 #endif /* CONFIG_X86_64 */
 
+#else
+
+static inline int rdrand_long(unsigned long *v)
+{
+       return 0;
+}
+
 #endif  /* CONFIG_ARCH_RANDOM */
 
 extern void x86_init_rdrand(struct cpuinfo_x86 *c);
index da31c8b8a92ddd0459bc1b6a0a7058f4d1f93766..b17f4f48ecd7d9a48646a295c7ffaaa544399fa8 100644 (file)
@@ -77,7 +77,7 @@ static inline void atomic_sub(int i, atomic_t *v)
  */
 static inline int atomic_sub_and_test(int i, atomic_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", "e");
 }
 
 /**
@@ -141,7 +141,7 @@ static inline int atomic_inc_and_test(atomic_t *v)
  */
 static inline int atomic_add_negative(int i, atomic_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", "s");
 }
 
 /**
index 3f065c985aeed272d120e3cec19f04b9ee9f5254..46e9052bbd28cdea457130607cd5a50ddc5c6204 100644 (file)
@@ -72,7 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)
  */
 static inline int atomic64_sub_and_test(long i, atomic64_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", "e");
 }
 
 /**
@@ -138,7 +138,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v)
  */
 static inline int atomic64_add_negative(long i, atomic64_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", "s");
 }
 
 /**
index c6cd358a1eec806a779371a631a97a8de2d28912..04a48903b2eb31973080d60d36cfd93b3fc68a5f 100644 (file)
 #endif
 #define smp_read_barrier_depends()     read_barrier_depends()
 #define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
+#else /* !SMP */
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
 #define smp_wmb()      barrier()
 #define smp_read_barrier_depends()     do { } while (0)
 #define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif /* SMP */
+
+#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE)
+
+/*
+ * For either of these options x86 doesn't have a strong TSO memory
+ * model and we should fall back to full barriers.
+ */
+
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ___p1;                                                          \
+})
+
+#else /* regular x86 TSO memory ordering */
+
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
+
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       barrier();                                                      \
+       ___p1;                                                          \
+})
+
 #endif
 
 /*
index 6d76d093598930ce24476118fd68d690bb78035c..9fc1af74dc8393a5107742f12f82dd47be1db0ea 100644 (file)
@@ -205,7 +205,7 @@ static inline void change_bit(long nr, volatile unsigned long *addr)
  */
 static inline int test_and_set_bit(long nr, volatile unsigned long *addr)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, "Ir", nr, "%0", "c");
 }
 
 /**
@@ -251,7 +251,7 @@ static inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
  */
 static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, "Ir", nr, "%0", "c");
 }
 
 /**
@@ -304,7 +304,7 @@ static inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
  */
 static inline int test_and_change_bit(long nr, volatile unsigned long *addr)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, "Ir", nr, "%0", "c");
 }
 
 static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
index 65c6e6e3a5521bc73e843a5459b63ec99e02d689..3b978c472d08b51aa8ff33d7fab589a3205fc87a 100644 (file)
@@ -1,6 +1,24 @@
 #ifndef _ASM_X86_EFI_H
 #define _ASM_X86_EFI_H
 
+/*
+ * We map the EFI regions needed for runtime services non-contiguously,
+ * with preserved alignment on virtual addresses starting from -4G down
+ * for a total max space of 64G. This way, we provide for stable runtime
+ * services addresses across kernels so that a kexec'd kernel can still
+ * use them.
+ *
+ * This is the main reason why we're doing stable VA mappings for RT
+ * services.
+ *
+ * This flag is used in conjuction with a chicken bit called
+ * "efi=old_map" which can be used as a fallback to the old runtime
+ * services mapping method in case there's some b0rkage with a
+ * particular EFI implementation (haha, it is hard to hold up the
+ * sarcasm here...).
+ */
+#define EFI_OLD_MEMMAP         EFI_ARCH_1
+
 #ifdef CONFIG_X86_32
 
 #define EFI_LOADER_SIGNATURE   "EL32"
@@ -69,24 +87,31 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
        efi_call6((f), (u64)(a1), (u64)(a2), (u64)(a3),         \
                  (u64)(a4), (u64)(a5), (u64)(a6))
 
+#define _efi_call_virtX(x, f, ...)                                     \
+({                                                                     \
+       efi_status_t __s;                                               \
+                                                                       \
+       efi_sync_low_kernel_mappings();                                 \
+       preempt_disable();                                              \
+       __s = efi_call##x((void *)efi.systab->runtime->f, __VA_ARGS__); \
+       preempt_enable();                                               \
+       __s;                                                            \
+})
+
 #define efi_call_virt0(f)                              \
-       efi_call0((efi.systab->runtime->f))
-#define efi_call_virt1(f, a1)                                  \
-       efi_call1((efi.systab->runtime->f), (u64)(a1))
-#define efi_call_virt2(f, a1, a2)                                      \
-       efi_call2((efi.systab->runtime->f), (u64)(a1), (u64)(a2))
-#define efi_call_virt3(f, a1, a2, a3)                                  \
-       efi_call3((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3))
-#define efi_call_virt4(f, a1, a2, a3, a4)                              \
-       efi_call4((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3), (u64)(a4))
-#define efi_call_virt5(f, a1, a2, a3, a4, a5)                          \
-       efi_call5((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3), (u64)(a4), (u64)(a5))
-#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)                      \
-       efi_call6((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
+       _efi_call_virtX(0, f)
+#define efi_call_virt1(f, a1)                          \
+       _efi_call_virtX(1, f, (u64)(a1))
+#define efi_call_virt2(f, a1, a2)                      \
+       _efi_call_virtX(2, f, (u64)(a1), (u64)(a2))
+#define efi_call_virt3(f, a1, a2, a3)                  \
+       _efi_call_virtX(3, f, (u64)(a1), (u64)(a2), (u64)(a3))
+#define efi_call_virt4(f, a1, a2, a3, a4)              \
+       _efi_call_virtX(4, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4))
+#define efi_call_virt5(f, a1, a2, a3, a4, a5)          \
+       _efi_call_virtX(5, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4), (u64)(a5))
+#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
+       _efi_call_virtX(6, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
                                 u32 type, u64 attribute);
@@ -95,12 +120,28 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
 
 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);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
 extern void efi_unmap_memmap(void);
 extern void efi_memory_uc(u64 addr, unsigned long size);
+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 void __init old_map_region(efi_memory_desc_t *md);
+
+struct efi_setup_data {
+       u64 fw_vendor;
+       u64 runtime;
+       u64 tables;
+       u64 smbios;
+       u64 reserved[8];
+};
+
+extern u64 efi_setup;
 
 #ifdef CONFIG_EFI
 
@@ -110,7 +151,7 @@ static inline bool efi_is_native(void)
 }
 
 extern struct console early_efi_console;
-
+extern void parse_efi_setup(u64 phys_addr, u32 data_len);
 #else
 /*
  * IF EFI is not configured, have the EFI calls return -ENOSYS.
@@ -122,6 +163,7 @@ extern struct console early_efi_console;
 #define efi_call4(_f, _a1, _a2, _a3, _a4)              (-ENOSYS)
 #define efi_call5(_f, _a1, _a2, _a3, _a4, _a5)         (-ENOSYS)
 #define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6)    (-ENOSYS)
+static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
 #endif /* CONFIG_EFI */
 
 #endif /* _ASM_X86_EFI_H */
index c49a613c6452fc66afdf5de52572dc8d033a8fcc..cea1c76d49bf5b04344bb17c353bab35869cf01a 100644 (file)
@@ -293,12 +293,13 @@ static inline int restore_fpu_checking(struct task_struct *tsk)
        /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
           is pending.  Clear the x87 state here by setting it to fixed
           values. "m" is a random variable that should be in L1 */
-       alternative_input(
-               ASM_NOP8 ASM_NOP2,
-               "emms\n\t"              /* clear stack tags */
-               "fildl %P[addr]",       /* set F?P to defined value */
-               X86_FEATURE_FXSAVE_LEAK,
-               [addr] "m" (tsk->thread.fpu.has_fpu));
+       if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) {
+               asm volatile(
+                       "fnclex\n\t"
+                       "emms\n\t"
+                       "fildl %P[addr]"        /* set F?P to defined value */
+                       : : [addr] "m" (tsk->thread.fpu.has_fpu));
+       }
 
        return fpu_restore_checking(&tsk->thread.fpu);
 }
index cba45d99ac1aad92db4464362480d5e799b1ff7f..67d69b8e2d20d0b005930df7a4340c107b86bce7 100644 (file)
@@ -191,6 +191,9 @@ extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
 #define trace_interrupt interrupt
 #endif
 
+#define VECTOR_UNDEFINED       -1
+#define VECTOR_RETRIGGERED     -2
+
 typedef int vector_irq_t[NR_VECTORS];
 DECLARE_PER_CPU(vector_irq_t, vector_irq);
 extern void setup_vector_irq(int cpu);
index 459769d39263e22c4050309d59090e2dc1fbb108..e34e097b6f9de43598eefc8a4894804be0b51256 100644 (file)
@@ -51,10 +51,41 @@ struct devs_id {
 enum intel_mid_cpu_type {
        /* 1 was Moorestown */
        INTEL_MID_CPU_CHIP_PENWELL = 2,
+       INTEL_MID_CPU_CHIP_CLOVERVIEW,
+       INTEL_MID_CPU_CHIP_TANGIER,
 };
 
 extern enum intel_mid_cpu_type __intel_mid_cpu_chip;
 
+/**
+ * struct intel_mid_ops - Interface between intel-mid & sub archs
+ * @arch_setup: arch_setup function to re-initialize platform
+ *             structures (x86_init, x86_platform_init)
+ *
+ * This structure can be extended if any new interface is required
+ * between intel-mid & its sub arch files.
+ */
+struct intel_mid_ops {
+       void (*arch_setup)(void);
+};
+
+/* Helper API's for INTEL_MID_OPS_INIT */
+#define DECLARE_INTEL_MID_OPS_INIT(cpuname, cpuid)     \
+                               [cpuid] = get_##cpuname##_ops
+
+/* Maximum number of CPU ops */
+#define MAX_CPU_OPS(a) (sizeof(a)/sizeof(void *))
+
+/*
+ * For every new cpu addition, a weak get_<cpuname>_ops() function needs be
+ * declared in arch/x86/platform/intel_mid/intel_mid_weak_decls.h.
+ */
+#define INTEL_MID_OPS_INIT {\
+       DECLARE_INTEL_MID_OPS_INIT(penwell, INTEL_MID_CPU_CHIP_PENWELL), \
+       DECLARE_INTEL_MID_OPS_INIT(cloverview, INTEL_MID_CPU_CHIP_CLOVERVIEW), \
+       DECLARE_INTEL_MID_OPS_INIT(tangier, INTEL_MID_CPU_CHIP_TANGIER) \
+};
+
 #ifdef CONFIG_X86_INTEL_MID
 
 static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void)
@@ -86,8 +117,21 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
  * Penwell uses spread spectrum clock, so the freq number is not exactly
  * the same as reported by MSR based on SDM.
  */
-#define PENWELL_FSB_FREQ_83SKU         83200
-#define PENWELL_FSB_FREQ_100SKU        99840
+#define FSB_FREQ_83SKU 83200
+#define FSB_FREQ_100SKU        99840
+#define FSB_FREQ_133SKU        133000
+
+#define FSB_FREQ_167SKU        167000
+#define FSB_FREQ_200SKU        200000
+#define FSB_FREQ_267SKU        267000
+#define FSB_FREQ_333SKU        333000
+#define FSB_FREQ_400SKU        400000
+
+/* Bus Select SoC Fuse value */
+#define BSEL_SOC_FUSE_MASK     0x7
+#define BSEL_SOC_FUSE_001      0x1 /* FSB 133MHz */
+#define BSEL_SOC_FUSE_101      0x5 /* FSB 100MHz */
+#define BSEL_SOC_FUSE_111      0x7 /* FSB 83MHz */
 
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX   8
diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h
new file mode 100644 (file)
index 0000000..8e71c79
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * iosf_mbi.h: Intel OnChip System Fabric MailBox access support
+ */
+
+#ifndef IOSF_MBI_SYMS_H
+#define IOSF_MBI_SYMS_H
+
+#define MBI_MCR_OFFSET         0xD0
+#define MBI_MDR_OFFSET         0xD4
+#define MBI_MCRX_OFFSET                0xD8
+
+#define MBI_RD_MASK            0xFEFFFFFF
+#define MBI_WR_MASK            0X01000000
+
+#define MBI_MASK_HI            0xFFFFFF00
+#define MBI_MASK_LO            0x000000FF
+#define MBI_ENABLE             0xF0
+
+/* Baytrail available units */
+#define BT_MBI_UNIT_AUNIT      0x00
+#define BT_MBI_UNIT_SMC                0x01
+#define BT_MBI_UNIT_CPU                0x02
+#define BT_MBI_UNIT_BUNIT      0x03
+#define BT_MBI_UNIT_PMC                0x04
+#define BT_MBI_UNIT_GFX                0x06
+#define BT_MBI_UNIT_SMI                0x0C
+#define BT_MBI_UNIT_USB                0x43
+#define BT_MBI_UNIT_SATA       0xA3
+#define BT_MBI_UNIT_PCIE       0xA6
+
+/* Baytrail read/write opcodes */
+#define BT_MBI_AUNIT_READ      0x10
+#define BT_MBI_AUNIT_WRITE     0x11
+#define BT_MBI_SMC_READ                0x10
+#define BT_MBI_SMC_WRITE       0x11
+#define BT_MBI_CPU_READ                0x10
+#define BT_MBI_CPU_WRITE       0x11
+#define BT_MBI_BUNIT_READ      0x10
+#define BT_MBI_BUNIT_WRITE     0x11
+#define BT_MBI_PMC_READ                0x06
+#define BT_MBI_PMC_WRITE       0x07
+#define BT_MBI_GFX_READ                0x00
+#define BT_MBI_GFX_WRITE       0x01
+#define BT_MBI_SMIO_READ       0x06
+#define BT_MBI_SMIO_WRITE      0x07
+#define BT_MBI_USB_READ                0x06
+#define BT_MBI_USB_WRITE       0x07
+#define BT_MBI_SATA_READ       0x00
+#define BT_MBI_SATA_WRITE      0x01
+#define BT_MBI_PCIE_READ       0x00
+#define BT_MBI_PCIE_WRITE      0x01
+
+/**
+ * iosf_mbi_read() - MailBox Interface read command
+ * @port:      port indicating subunit being accessed
+ * @opcode:    port specific read or write opcode
+ * @offset:    register address offset
+ * @mdr:       register data to be read
+ *
+ * Locking is handled by spinlock - cannot sleep.
+ * Return: Nonzero on error
+ */
+int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr);
+
+/**
+ * iosf_mbi_write() - MailBox unmasked write command
+ * @port:      port indicating subunit being accessed
+ * @opcode:    port specific read or write opcode
+ * @offset:    register address offset
+ * @mdr:       register data to be written
+ *
+ * Locking is handled by spinlock - cannot sleep.
+ * Return: Nonzero on error
+ */
+int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr);
+
+/**
+ * iosf_mbi_modify() - MailBox masked write command
+ * @port:      port indicating subunit being accessed
+ * @opcode:    port specific read or write opcode
+ * @offset:    register address offset
+ * @mdr:       register data being modified
+ * @mask:      mask indicating bits in mdr to be modified
+ *
+ * Locking is handled by spinlock - cannot sleep.
+ * Return: Nonzero on error
+ */
+int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask);
+
+#endif /* IOSF_MBI_SYMS_H */
index 0ea10f27d61354e79c5adfad9452a8542ef4b7a6..cb6cfcd034cf719d626232430ab6af0e46a1874c 100644 (file)
@@ -25,6 +25,7 @@ extern void irq_ctx_init(int cpu);
 
 #ifdef CONFIG_HOTPLUG_CPU
 #include <linux/cpumask.h>
+extern int check_irq_vectors_for_cpu_disable(void);
 extern void fixup_irqs(void);
 extern void irq_force_complete_move(int);
 #endif
index 5b23e605e707cb21e254f7ce964029a48b69ee54..4ad6560847b1f5f7c20644b52e27505339880e79 100644 (file)
@@ -52,7 +52,7 @@ static inline void local_sub(long i, local_t *l)
  */
 static inline int local_sub_and_test(long i, local_t *l)
 {
-       GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, "er", i, "%0", "e");
 }
 
 /**
@@ -92,7 +92,7 @@ static inline int local_inc_and_test(local_t *l)
  */
 static inline int local_add_negative(long i, local_t *l)
 {
-       GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, "er", i, "%0", "s");
 }
 
 /**
index c696a8687567690a8f2c7785284f65dcddfeb103..6e4ce2df87cf68cb3305878b72650e711124a6bf 100644 (file)
@@ -118,7 +118,6 @@ extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
 
 #include <linux/percpu.h>
-#include <linux/init.h>
 #include <linux/atomic.h>
 
 extern int mce_p5_enabled;
index f98bd6625318210adb03615f3b282b6454db319d..b59827e765292459247baa6866329ddec3e7fa91 100644 (file)
@@ -1,6 +1,21 @@
 #ifndef _ASM_X86_MICROCODE_H
 #define _ASM_X86_MICROCODE_H
 
+#define native_rdmsr(msr, val1, val2)                  \
+do {                                                   \
+       u64 __val = native_read_msr((msr));             \
+       (void)((val1) = (u32)__val);                    \
+       (void)((val2) = (u32)(__val >> 32));            \
+} while (0)
+
+#define native_wrmsr(msr, low, high)                   \
+       native_write_msr(msr, low, high)
+
+#define native_wrmsrl(msr, val)                                \
+       native_write_msr((msr),                         \
+                        (u32)((u64)(val)),             \
+                        (u32)((u64)(val) >> 32))
+
 struct cpu_signature {
        unsigned int sig;
        unsigned int pf;
index 4c019179a57dd97d6b48ae064ef1faea0dc2e7f7..b7b10b82d3e510bcad0faf2d2b82675b635a6b7d 100644 (file)
@@ -61,11 +61,10 @@ extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
 extern int apply_microcode_amd(int cpu);
 extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
 
+#define PATCH_MAX_SIZE PAGE_SIZE
+extern u8 amd_ucode_patch[PATCH_MAX_SIZE];
+
 #ifdef CONFIG_MICROCODE_AMD_EARLY
-#ifdef CONFIG_X86_32
-#define MPB_MAX_SIZE PAGE_SIZE
-extern u8 amd_bsp_mpb[MPB_MAX_SIZE];
-#endif
 extern void __init load_ucode_amd_bsp(void);
 extern void load_ucode_amd_ap(void);
 extern int __init save_microcode_in_initrd_amd(void);
index 3142a94c7b4bf90314838fa8beb67c4e7ed0b363..3e6b4920ef5de2c39cc1e3fb582fe7f0f0a586a7 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_X86_MPSPEC_H
 #define _ASM_X86_MPSPEC_H
 
-#include <linux/init.h>
 
 #include <asm/mpspec_def.h>
 #include <asm/x86_init.h>
index 2f366d0ac6b4699b9e4bf5449f3fe7c8a95104bc..1da25a5f96f92486c8971856123fa000fdc3abc0 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_MWAIT_H
 #define _ASM_X86_MWAIT_H
 
+#include <linux/sched.h>
+
 #define MWAIT_SUBSTATE_MASK            0xf
 #define MWAIT_CSTATE_MASK              0xf
 #define MWAIT_SUBSTATE_SIZE            4
 
 #define MWAIT_ECX_INTERRUPT_BREAK      0x1
 
+static inline void __monitor(const void *eax, unsigned long ecx,
+                            unsigned long edx)
+{
+       /* "monitor %eax, %ecx, %edx;" */
+       asm volatile(".byte 0x0f, 0x01, 0xc8;"
+                    :: "a" (eax), "c" (ecx), "d"(edx));
+}
+
+static inline void __mwait(unsigned long eax, unsigned long ecx)
+{
+       /* "mwait %eax, %ecx;" */
+       asm volatile(".byte 0x0f, 0x01, 0xc9;"
+                    :: "a" (eax), "c" (ecx));
+}
+
+/*
+ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+ * which can obviate IPI to trigger checking of need_resched.
+ * We execute MONITOR against need_resched and enter optimized wait state
+ * through MWAIT. Whenever someone changes need_resched, we would be woken
+ * up from MWAIT (without an IPI).
+ *
+ * New with Core Duo processors, MWAIT can take some hints based on CPU
+ * capability.
+ */
+static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
+{
+       if (!current_set_polling_and_test()) {
+               if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) {
+                       mb();
+                       clflush((void *)&current_thread_info()->flags);
+                       mb();
+               }
+
+               __monitor((void *)&current_thread_info()->flags, 0, 0);
+               if (!need_resched())
+                       __mwait(eax, ecx);
+       }
+       current_clr_polling();
+}
+
 #endif /* _ASM_X86_MWAIT_H */
index c87892442e53d4081f4ff1276524e0298cf73617..775873d3be55617a49e15c3460ae22a94dabad75 100644 (file)
@@ -71,6 +71,7 @@ extern bool __virt_addr_valid(unsigned long kaddr);
 #include <asm-generic/getorder.h>
 
 #define __HAVE_ARCH_GATE_AREA 1
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_PAGE_H */
index 4d550d04b6099bf444e8291ffdfde9538a4e47df..904f528cc8e82ae638e25a2bdeec23fed332eb7a 100644 (file)
@@ -5,10 +5,6 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_HUGETLB_PAGE
-#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#endif
-
 #define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET)
 #ifdef CONFIG_DEBUG_VIRTUAL
 extern unsigned long __phys_addr(unsigned long);
index 43dcd804ebd5732aea40415e6f4a419e363701c9..8de6d9cf3b954a7f31bcb756c92c20cc08db5759 100644 (file)
 #define __VIRTUAL_MASK_SHIFT   47
 
 /*
- * Kernel image size is limited to 512 MB (see level2_kernel_pgt in
- * arch/x86/kernel/head_64.S), and it is mapped here:
+ * Kernel image size is limited to 1GiB due to the fixmap living in the
+ * next 1GiB (see level2_kernel_pgt in arch/x86/kernel/head_64.S). Use
+ * 512MiB by default, leaving 1.5GiB for modules once the page tables
+ * are fully set up. If kernel ASLR is configured, it can extend the
+ * kernel page table mapping, reducing the size of the modules area.
  */
-#define KERNEL_IMAGE_SIZE      (512 * 1024 * 1024)
+#define KERNEL_IMAGE_SIZE_DEFAULT      (512 * 1024 * 1024)
+#if defined(CONFIG_RANDOMIZE_BASE) && \
+       CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE_DEFAULT
+#define KERNEL_IMAGE_SIZE   CONFIG_RANDOMIZE_BASE_MAX_OFFSET
+#else
+#define KERNEL_IMAGE_SIZE      KERNEL_IMAGE_SIZE_DEFAULT
+#endif
 
 #endif /* _ASM_X86_PAGE_64_DEFS_H */
index 3bf2dd0cf61fec9615253fe3b70d3c3764a35e93..0d193e23464707e3d56111e2d429664104a3649f 100644 (file)
@@ -55,6 +55,13 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
 #endif
 
+/* Bit manipulation helper on pte/pgoff entry */
+static inline unsigned long pte_bitop(unsigned long value, unsigned int rightshift,
+                                     unsigned long mask, unsigned int leftshift)
+{
+       return ((value >> rightshift) & mask) << leftshift;
+}
+
 #ifdef CONFIG_MEM_SOFT_DIRTY
 
 /*
@@ -71,31 +78,34 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define PTE_FILE_BITS2         (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1)
 #define PTE_FILE_BITS3         (PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1)
 
-#define pte_to_pgoff(pte)                                              \
-       ((((pte).pte_low >> (PTE_FILE_SHIFT1))                          \
-         & ((1U << PTE_FILE_BITS1) - 1)))                              \
-       + ((((pte).pte_low >> (PTE_FILE_SHIFT2))                        \
-           & ((1U << PTE_FILE_BITS2) - 1))                             \
-          << (PTE_FILE_BITS1))                                         \
-       + ((((pte).pte_low >> (PTE_FILE_SHIFT3))                        \
-           & ((1U << PTE_FILE_BITS3) - 1))                             \
-          << (PTE_FILE_BITS1 + PTE_FILE_BITS2))                        \
-       + ((((pte).pte_low >> (PTE_FILE_SHIFT4)))                       \
-           << (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3))
-
-#define pgoff_to_pte(off)                                              \
-       ((pte_t) { .pte_low =                                           \
-        ((((off)) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1)  \
-        + ((((off) >> PTE_FILE_BITS1)                                  \
-            & ((1U << PTE_FILE_BITS2) - 1))                            \
-           << PTE_FILE_SHIFT2)                                         \
-        + ((((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2))               \
-            & ((1U << PTE_FILE_BITS3) - 1))                            \
-           << PTE_FILE_SHIFT3)                                         \
-        + ((((off) >>                                                  \
-             (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)))      \
-           << PTE_FILE_SHIFT4)                                         \
-        + _PAGE_FILE })
+#define PTE_FILE_MASK1         ((1U << PTE_FILE_BITS1) - 1)
+#define PTE_FILE_MASK2         ((1U << PTE_FILE_BITS2) - 1)
+#define PTE_FILE_MASK3         ((1U << PTE_FILE_BITS3) - 1)
+
+#define PTE_FILE_LSHIFT2       (PTE_FILE_BITS1)
+#define PTE_FILE_LSHIFT3       (PTE_FILE_BITS1 + PTE_FILE_BITS2)
+#define PTE_FILE_LSHIFT4       (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)
+
+static __always_inline pgoff_t pte_to_pgoff(pte_t pte)
+{
+       return (pgoff_t)
+               (pte_bitop(pte.pte_low, PTE_FILE_SHIFT1, PTE_FILE_MASK1,  0)                +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT2, PTE_FILE_MASK2,  PTE_FILE_LSHIFT2) +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT3, PTE_FILE_MASK3,  PTE_FILE_LSHIFT3) +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT4,           -1UL,  PTE_FILE_LSHIFT4));
+}
+
+static __always_inline pte_t pgoff_to_pte(pgoff_t off)
+{
+       return (pte_t){
+               .pte_low =
+                       pte_bitop(off,                0, PTE_FILE_MASK1,  PTE_FILE_SHIFT1) +
+                       pte_bitop(off, PTE_FILE_LSHIFT2, PTE_FILE_MASK2,  PTE_FILE_SHIFT2) +
+                       pte_bitop(off, PTE_FILE_LSHIFT3, PTE_FILE_MASK3,  PTE_FILE_SHIFT3) +
+                       pte_bitop(off, PTE_FILE_LSHIFT4,           -1UL,  PTE_FILE_SHIFT4) +
+                       _PAGE_FILE,
+       };
+}
 
 #else /* CONFIG_MEM_SOFT_DIRTY */
 
@@ -115,22 +125,30 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define PTE_FILE_BITS1         (PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1)
 #define PTE_FILE_BITS2         (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1)
 
-#define pte_to_pgoff(pte)                                              \
-       ((((pte).pte_low >> PTE_FILE_SHIFT1)                            \
-         & ((1U << PTE_FILE_BITS1) - 1))                               \
-        + ((((pte).pte_low >> PTE_FILE_SHIFT2)                         \
-            & ((1U << PTE_FILE_BITS2) - 1)) << PTE_FILE_BITS1)         \
-        + (((pte).pte_low >> PTE_FILE_SHIFT3)                          \
-           << (PTE_FILE_BITS1 + PTE_FILE_BITS2)))
-
-#define pgoff_to_pte(off)                                              \
-       ((pte_t) { .pte_low =                                           \
-        (((off) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1)    \
-        + ((((off) >> PTE_FILE_BITS1) & ((1U << PTE_FILE_BITS2) - 1))  \
-           << PTE_FILE_SHIFT2)                                         \
-        + (((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2))                \
-           << PTE_FILE_SHIFT3)                                         \
-        + _PAGE_FILE })
+#define PTE_FILE_MASK1         ((1U << PTE_FILE_BITS1) - 1)
+#define PTE_FILE_MASK2         ((1U << PTE_FILE_BITS2) - 1)
+
+#define PTE_FILE_LSHIFT2       (PTE_FILE_BITS1)
+#define PTE_FILE_LSHIFT3       (PTE_FILE_BITS1 + PTE_FILE_BITS2)
+
+static __always_inline pgoff_t pte_to_pgoff(pte_t pte)
+{
+       return (pgoff_t)
+               (pte_bitop(pte.pte_low, PTE_FILE_SHIFT1, PTE_FILE_MASK1,  0)                +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT2, PTE_FILE_MASK2,  PTE_FILE_LSHIFT2) +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT3,           -1UL,  PTE_FILE_LSHIFT3));
+}
+
+static __always_inline pte_t pgoff_to_pte(pgoff_t off)
+{
+       return (pte_t){
+               .pte_low =
+                       pte_bitop(off,                0, PTE_FILE_MASK1,  PTE_FILE_SHIFT1) +
+                       pte_bitop(off, PTE_FILE_LSHIFT2, PTE_FILE_MASK2,  PTE_FILE_SHIFT2) +
+                       pte_bitop(off, PTE_FILE_LSHIFT3,           -1UL,  PTE_FILE_SHIFT3) +
+                       _PAGE_FILE,
+       };
+}
 
 #endif /* CONFIG_MEM_SOFT_DIRTY */
 
index 3d1999458709231affdc977df99530acf3a833ac..bbc8b12fa443d47ee9a8faa59b36767e7aec866c 100644 (file)
@@ -452,9 +452,16 @@ static inline int pte_present(pte_t a)
 }
 
 #define pte_accessible pte_accessible
-static inline int pte_accessible(pte_t a)
+static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
 {
-       return pte_flags(a) & _PAGE_PRESENT;
+       if (pte_flags(a) & _PAGE_PRESENT)
+               return true;
+
+       if ((pte_flags(a) & (_PAGE_PROTNONE | _PAGE_NUMA)) &&
+                       mm_tlb_flush_pending(mm))
+               return true;
+
+       return false;
 }
 
 static inline int pte_hidden(pte_t pte)
index 2d883440cb9a282f948d7062684c52789e95d90f..c883bf726398a2556d50b984736ad068bc0dd44c 100644 (file)
@@ -58,7 +58,7 @@ typedef struct { pteval_t pte; } pte_t;
 #define VMALLOC_START    _AC(0xffffc90000000000, UL)
 #define VMALLOC_END      _AC(0xffffe8ffffffffff, UL)
 #define VMEMMAP_START   _AC(0xffffea0000000000, UL)
-#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+#define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)
 #define MODULES_END      _AC(0xffffffffff000000, UL)
 #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
 
index 0ecac257fb26cffd2bb9a6ece7b7a5976eca3c84..a83aa44bb1fb831cac7cda82a590c05ea0e47235 100644 (file)
@@ -382,7 +382,8 @@ static inline void update_page_count(int level, unsigned long pages) { }
  */
 extern pte_t *lookup_address(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);
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_X86_PGTABLE_DEFS_H */
index 8729723636fd1632eebd92197dd292fa26de10d7..c8b051933b1b384ccd723267d99c9ff052875dff 100644 (file)
@@ -7,6 +7,12 @@
 
 DECLARE_PER_CPU(int, __preempt_count);
 
+/*
+ * We use the PREEMPT_NEED_RESCHED bit as an inverted NEED_RESCHED such
+ * that a decrement hitting 0 means we can and should reschedule.
+ */
+#define PREEMPT_ENABLED        (0 + PREEMPT_NEED_RESCHED)
+
 /*
  * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
  * that think a non-zero value indicates we cannot preempt.
@@ -74,6 +80,11 @@ static __always_inline void __preempt_count_sub(int val)
        __this_cpu_add_4(__preempt_count, -val);
 }
 
+/*
+ * Because we keep PREEMPT_NEED_RESCHED set when we do _not_ need to reschedule
+ * a decrement which hits zero means we have no preempt_count and should
+ * reschedule.
+ */
 static __always_inline bool __preempt_count_dec_and_test(void)
 {
        GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e");
index 865c39910cc89190ccc6a3a7596751c9aaa5c186..fdedd38fd0fc7feeabc26f8b366b525b65685904 100644 (file)
@@ -27,7 +27,6 @@ struct mm_struct;
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <linux/math64.h>
-#include <linux/init.h>
 #include <linux/err.h>
 #include <linux/irqflags.h>
 
@@ -72,6 +71,7 @@ extern u16 __read_mostly tlb_lli_4m[NR_INFO];
 extern u16 __read_mostly tlb_lld_4k[NR_INFO];
 extern u16 __read_mostly tlb_lld_2m[NR_INFO];
 extern u16 __read_mostly tlb_lld_4m[NR_INFO];
+extern u16 __read_mostly tlb_lld_1g[NR_INFO];
 extern s8  __read_mostly tlb_flushall_shift;
 
 /*
@@ -717,29 +717,6 @@ static inline void sync_core(void)
 #endif
 }
 
-static inline void __monitor(const void *eax, unsigned long ecx,
-                            unsigned long edx)
-{
-       /* "monitor %eax, %ecx, %edx;" */
-       asm volatile(".byte 0x0f, 0x01, 0xc8;"
-                    :: "a" (eax), "c" (ecx), "d"(edx));
-}
-
-static inline void __mwait(unsigned long eax, unsigned long ecx)
-{
-       /* "mwait %eax, %ecx;" */
-       asm volatile(".byte 0x0f, 0x01, 0xc9;"
-                    :: "a" (eax), "c" (ecx));
-}
-
-static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
-{
-       trace_hardirqs_on();
-       /* "mwait %eax, %ecx;" */
-       asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
-                    :: "a" (eax), "c" (ecx));
-}
-
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void init_amd_e400_c1e_mask(void);
 
index 942a08623a1a09db57171fa60d03c664b7e8aa46..14fd6fd75a19b8d62c983e7120fadbf151eb5043 100644 (file)
@@ -60,7 +60,6 @@ struct pt_regs {
 
 #endif /* !__i386__ */
 
-#include <linux/init.h>
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt_types.h>
 #endif
index 1ff990f1de8e3f58f21fda00bc1a646b96eaba2b..8f7866a5b9a41df67475892353979c005ce8c09b 100644 (file)
@@ -16,8 +16,8 @@ cc_label:                                                             \
 #define GEN_UNARY_RMWcc(op, var, arg0, cc)                             \
        __GEN_RMWcc(op " " arg0, var, cc)
 
-#define GEN_BINARY_RMWcc(op, var, val, arg0, cc)                       \
-       __GEN_RMWcc(op " %1, " arg0, var, cc, "er" (val))
+#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
+       __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val))
 
 #else /* !CC_HAVE_ASM_GOTO */
 
@@ -33,8 +33,8 @@ do {                                                                  \
 #define GEN_UNARY_RMWcc(op, var, arg0, cc)                             \
        __GEN_RMWcc(op " " arg0, var, cc)
 
-#define GEN_BINARY_RMWcc(op, var, val, arg0, cc)                       \
-       __GEN_RMWcc(op " %2, " arg0, var, cc, "er" (val))
+#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
+       __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val))
 
 #endif /* CC_HAVE_ASM_GOTO */
 
index 59bcf4e22418573b4a9d98ada8a6ee45cf12565a..d62c9f809bc5f6b9866a71a28a46b90d24e6df19 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <uapi/asm/setup.h>
 
-
 #define COMMAND_LINE_SIZE 2048
 
 #include <linux/linkage.h>
@@ -29,6 +28,8 @@
 #include <asm/bootparam.h>
 #include <asm/x86_init.h>
 
+extern u64 relocated_ramdisk;
+
 /* Interrupt control for vSMPowered x86_64 systems */
 #ifdef CONFIG_X86_64
 void vsmp_init(void);
index 4137890e88e3ad6144a7bde7910674b7801e84b7..8cd27e08e23c47cec2f736b6b674b921554eb680 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_X86_SMP_H
 #ifndef __ASSEMBLY__
 #include <linux/cpumask.h>
-#include <linux/init.h>
 #include <asm/percpu.h>
 
 /*
index 34baa0eb5d0c972109fba546e4402508f7cda6fa..a04eabd43d06621dfadb38d01869f2f22adce783 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef _ASM_X86_TIMER_H
 #define _ASM_X86_TIMER_H
-#include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/percpu.h>
 #include <linux/interrupt.h>
+#include <linux/math64.h>
 
 #define TICK_SIZE (tick_nsec / 1000)
 
@@ -12,68 +12,26 @@ extern int recalibrate_cpu_khz(void);
 
 extern int no_timer_check;
 
-/* Accelerators for sched_clock()
- * convert from cycles(64bits) => nanoseconds (64bits)
- *  basic equation:
- *             ns = cycles / (freq / ns_per_sec)
- *             ns = cycles * (ns_per_sec / freq)
- *             ns = cycles * (10^9 / (cpu_khz * 10^3))
- *             ns = cycles * (10^6 / cpu_khz)
+/*
+ * We use the full linear equation: f(x) = a + b*x, in order to allow
+ * a continuous function in the face of dynamic freq changes.
  *
- *     Then we use scaling math (suggested by george@mvista.com) to get:
- *             ns = cycles * (10^6 * SC / cpu_khz) / SC
- *             ns = cycles * cyc2ns_scale / SC
+ * Continuity means that when our frequency changes our slope (b); we want to
+ * ensure that: f(t) == f'(t), which gives: a + b*t == a' + b'*t.
  *
- *     And since SC is a constant power of two, we can convert the div
- *  into a shift.
+ * Without an offset (a) the above would not be possible.
  *
- *  We can use khz divisor instead of mhz to keep a better precision, since
- *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
- *  (mathieu.desnoyers@polymtl.ca)
- *
- *                     -johnstul@us.ibm.com "math is hard, lets go shopping!"
- *
- * In:
- *
- * ns = cycles * cyc2ns_scale / SC
- *
- * Although we may still have enough bits to store the value of ns,
- * in some cases, we may not have enough bits to store cycles * cyc2ns_scale,
- * leading to an incorrect result.
- *
- * To avoid this, we can decompose 'cycles' into quotient and remainder
- * of division by SC.  Then,
- *
- * ns = (quot * SC + rem) * cyc2ns_scale / SC
- *    = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC
- *
- *                     - sqazi@google.com
+ * See the comment near cycles_2_ns() for details on how we compute (b).
  */
-
-DECLARE_PER_CPU(unsigned long, cyc2ns);
-DECLARE_PER_CPU(unsigned long long, cyc2ns_offset);
-
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-
-static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
-{
-       int cpu = smp_processor_id();
-       unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
-       ns += mult_frac(cyc, per_cpu(cyc2ns, cpu),
-                       (1UL << CYC2NS_SCALE_FACTOR));
-       return ns;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
-       unsigned long long ns;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ns = __cycles_2_ns(cyc);
-       local_irq_restore(flags);
-
-       return ns;
-}
+struct cyc2ns_data {
+       u32 cyc2ns_mul;
+       u32 cyc2ns_shift;
+       u64 cyc2ns_offset;
+       u32 __count;
+       /* u32 hole */
+}; /* 24 bytes -- do not grow */
+
+extern struct cyc2ns_data *cyc2ns_read_begin(void);
+extern void cyc2ns_read_end(struct cyc2ns_data *);
 
 #endif /* _ASM_X86_TIMER_H */
index 2874df24e7a448cd56631d87f5ac9e0fdd00cbc7..4cab890007a7267ecc7ce148eaa1fdfbee4a49df 100644 (file)
@@ -71,6 +71,17 @@ DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi);
  */
 DEFINE_IRQ_VECTOR_EVENT(irq_work);
 
+/*
+ * We must dis-allow sampling irq_work_exit() because perf event sampling
+ * itself can cause irq_work, which would lead to an infinite loop;
+ *
+ *  1) irq_work_exit happens
+ *  2) generates perf sample
+ *  3) generates irq_work
+ *  4) goto 1
+ */
+TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0);
+
 /*
  * call_function - called when entering/exiting a call function interrupt
  * vector handler
index 235be70d5bb4d0e936fba155a785b82bb639ee1b..57ae63cd6ee2ec8aba5135a33e363267b65e4075 100644 (file)
@@ -65,4 +65,7 @@ extern int notsc_setup(char *);
 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);
+
 #endif /* _ASM_X86_TSC_H */
index 48ff838552688776dc2ee93bdb7bf8be188521fd..0d592e0a5b84fa3c3738ce8400e34df5bb552eb0 100644 (file)
 /*
  * Test whether a block of memory is a valid user space address.
  * Returns 0 if the range is valid, nonzero otherwise.
- *
- * This is equivalent to the following test:
- * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64)
- *
- * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry...
  */
+static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit)
+{
+       /*
+        * If we have used "sizeof()" for the size,
+        * we know it won't overflow the limit (but
+        * it might overflow the 'addr', so it's
+        * important to subtract the size from the
+        * limit, not add it to the address).
+        */
+       if (__builtin_constant_p(size))
+               return addr > limit - size;
+
+       /* Arbitrary sizes? Be careful about overflow */
+       addr += size;
+       if (addr < size)
+               return true;
+       return addr > limit;
+}
 
 #define __range_not_ok(addr, size, limit)                              \
 ({                                                                     \
-       unsigned long flag, roksum;                                     \
        __chk_user_ptr(addr);                                           \
-       asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0"             \
-           : "=&r" (flag), "=r" (roksum)                               \
-           : "1" (addr), "g" ((long)(size)),                           \
-             "rm" (limit));                                            \
-       flag;                                                           \
+       __chk_range_not_ok((unsigned long __force)(addr), size, limit); \
 })
 
 /**
@@ -78,7 +86,7 @@
  * this function, memory access functions may still return -EFAULT.
  */
 #define access_ok(type, addr, size) \
-       (likely(__range_not_ok(addr, size, user_addr_max()) == 0))
+       likely(!__range_not_ok(addr, size, user_addr_max()))
 
 /*
  * The exception table consists of pairs of addresses relative to the
index 190413d0de57b20a3334a9fcaaf8bcfbdd6fd14f..12a26b979bf163008ebd1dc5b7cdff3ca5876f0b 100644 (file)
@@ -204,13 +204,13 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
 static __must_check __always_inline int
 __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
 {
-       return __copy_from_user_nocheck(dst, (__force const void *)src, size);
+       return __copy_from_user_nocheck(dst, src, size);
 }
 
 static __must_check __always_inline int
 __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
 {
-       return __copy_to_user_nocheck((__force void *)dst, src, size);
+       return __copy_to_user_nocheck(dst, src, size);
 }
 
 extern long __copy_user_nocache(void *dst, const void __user *src,
index 9c3733c5f8f795c8fa08ef58f5c279e75060cfcd..225b0988043a0a78ac9092a9af7a265122c685cd 100644 (file)
@@ -6,6 +6,7 @@
 #define SETUP_E820_EXT                 1
 #define SETUP_DTB                      2
 #define SETUP_PCI                      3
+#define SETUP_EFI                      4
 
 /* ram_size flags */
 #define RAMDISK_IMAGE_START_MASK       0x07FF
@@ -23,6 +24,7 @@
 #define XLF_CAN_BE_LOADED_ABOVE_4G     (1<<1)
 #define XLF_EFI_HANDOVER_32            (1<<2)
 #define XLF_EFI_HANDOVER_64            (1<<3)
+#define XLF_EFI_KEXEC                  (1<<4)
 
 #ifndef __ASSEMBLY__
 
index 37813b5ddc37472dba6c64b8ff3f2508dc085de0..59cea185ad1dd14e7079220d283ed8a99b072104 100644 (file)
 #define MSR_AMD64_PATCH_LOADER         0xc0010020
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD64_LS_CFG               0xc0011020
 #define MSR_AMD64_DC_CFG               0xc0011022
 #define MSR_AMD64_BU_CFG2              0xc001102a
 #define MSR_AMD64_IBSFETCHCTL          0xc0011030
index 9b0a34e2cd793dcb6cfe911a99d457b102296966..cb648c84b327992a7bfb3fc82dd54d7d9dafe2a5 100644 (file)
@@ -29,10 +29,11 @@ obj-$(CONFIG_X86_64)        += sys_x86_64.o x8664_ksyms_64.o
 obj-y                  += syscall_$(BITS).o
 obj-$(CONFIG_X86_64)   += vsyscall_64.o
 obj-$(CONFIG_X86_64)   += vsyscall_emu_64.o
+obj-$(CONFIG_SYSFS)    += ksysfs.o
 obj-y                  += bootflag.o e820.o
 obj-y                  += pci-dma.o quirks.o topology.o kdebugfs.o
 obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
-obj-y                  += tsc.o io_delay.o rtc.o
+obj-y                  += tsc.o tsc_msr.o io_delay.o rtc.o
 obj-y                  += pci-iommu_table.o
 obj-y                  += resource.o
 
@@ -91,15 +92,6 @@ obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o
 
 obj-$(CONFIG_PCSPKR_PLATFORM)  += pcspeaker.o
 
-obj-$(CONFIG_MICROCODE_EARLY)          += microcode_core_early.o
-obj-$(CONFIG_MICROCODE_INTEL_EARLY)    += microcode_intel_early.o
-obj-$(CONFIG_MICROCODE_INTEL_LIB)      += microcode_intel_lib.o
-microcode-y                            := microcode_core.o
-microcode-$(CONFIG_MICROCODE_INTEL)    += microcode_intel.o
-microcode-$(CONFIG_MICROCODE_AMD)      += microcode_amd.o
-obj-$(CONFIG_MICROCODE_AMD_EARLY)      += microcode_amd_early.o
-obj-$(CONFIG_MICROCODE)                        += microcode.o
-
 obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 
 obj-$(CONFIG_SWIOTLB)                  += pci-swiotlb.o
@@ -111,6 +103,7 @@ obj-$(CONFIG_EFI)                   += sysfb_efi.o
 
 obj-$(CONFIG_PERF_EVENTS)              += perf_regs.o
 obj-$(CONFIG_TRACING)                  += tracepoint.o
+obj-$(CONFIG_IOSF_MBI)                 += iosf_mbi.o
 
 ###
 # 64 bit specific files
index d2b7f27781bce0a559580d0596980b66a8865920..e69182fd01cfe4c9694a2178de43a8c784a30f4a 100644 (file)
@@ -150,29 +150,6 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
 }
 EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
 
-/*
- * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
- * which can obviate IPI to trigger checking of need_resched.
- * We execute MONITOR against need_resched and enter optimized wait state
- * through MWAIT. Whenever someone changes need_resched, we would be woken
- * up from MWAIT (without an IPI).
- *
- * New with Core Duo processors, MWAIT can take some hints based on CPU
- * capability.
- */
-void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
-{
-       if (!need_resched()) {
-               if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
-                       clflush((void *)&current_thread_info()->flags);
-
-               __monitor((void *)&current_thread_info()->flags, 0, 0);
-               smp_mb();
-               if (!need_resched())
-                       __mwait(ax, cx);
-       }
-}
-
 void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
 {
        unsigned int cpu = smp_processor_id();
index d278736bf774f7d5c61bd64aa735f6de829b1075..7f26c9a70a9e0ada12f46382d7ee2cd73b2d5f29 100644 (file)
@@ -74,6 +74,13 @@ unsigned int max_physical_apicid;
  */
 physid_mask_t phys_cpu_present_map;
 
+/*
+ * Processor to be disabled specified by kernel parameter
+ * disable_cpu_apicid=<int>, mostly used for the kdump 2nd kernel to
+ * avoid undefined behaviour caused by sending INIT from AP to BSP.
+ */
+static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID;
+
 /*
  * Map cpu index to physical APIC ID
  */
@@ -1968,7 +1975,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs)
  */
 static inline void __smp_error_interrupt(struct pt_regs *regs)
 {
-       u32 v0, v1;
+       u32 v;
        u32 i = 0;
        static const char * const error_interrupt_reason[] = {
                "Send CS error",                /* APIC Error Bit 0 */
@@ -1982,21 +1989,20 @@ static inline void __smp_error_interrupt(struct pt_regs *regs)
        };
 
        /* First tickle the hardware, only then report what went on. -- REW */
-       v0 = apic_read(APIC_ESR);
        apic_write(APIC_ESR, 0);
-       v1 = apic_read(APIC_ESR);
+       v = apic_read(APIC_ESR);
        ack_APIC_irq();
        atomic_inc(&irq_err_count);
 
-       apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)",
-                   smp_processor_id(), v0 , v1);
+       apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x",
+                   smp_processor_id(), v);
 
-       v1 = v1 & 0xff;
-       while (v1) {
-               if (v1 & 0x1)
+       v &= 0xff;
+       while (v) {
+               if (v & 0x1)
                        apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
                i++;
-               v1 >>= 1;
+               v >>= 1;
        }
 
        apic_printk(APIC_DEBUG, KERN_CONT "\n");
@@ -2114,6 +2120,39 @@ int generic_processor_info(int apicid, int version)
        bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
                                phys_cpu_present_map);
 
+       /*
+        * boot_cpu_physical_apicid is designed to have the apicid
+        * returned by read_apic_id(), i.e, the apicid of the
+        * currently booting-up processor. However, on some platforms,
+        * it is temporarily modified by the apicid reported as BSP
+        * through MP table. Concretely:
+        *
+        * - arch/x86/kernel/mpparse.c: MP_processor_info()
+        * - arch/x86/mm/amdtopology.c: amd_numa_init()
+        * - arch/x86/platform/visws/visws_quirks.c: MP_processor_info()
+        *
+        * This function is executed with the modified
+        * boot_cpu_physical_apicid. So, disabled_cpu_apicid kernel
+        * parameter doesn't work to disable APs on kdump 2nd kernel.
+        *
+        * Since fixing handling of boot_cpu_physical_apicid requires
+        * another discussion and tests on each platform, we leave it
+        * for now and here we use read_apic_id() directly in this
+        * function, generic_processor_info().
+        */
+       if (disabled_cpu_apicid != BAD_APICID &&
+           disabled_cpu_apicid != read_apic_id() &&
+           disabled_cpu_apicid == apicid) {
+               int thiscpu = num_processors + disabled_cpus;
+
+               pr_warning("APIC: Disabling requested cpu."
+                          " Processor %d/0x%x ignored.\n",
+                          thiscpu, apicid);
+
+               disabled_cpus++;
+               return -ENODEV;
+       }
+
        /*
         * If boot cpu has not been detected yet, then only allow upto
         * nr_cpu_ids - 1 processors and keep one slot free for boot cpu
@@ -2592,3 +2631,12 @@ static int __init lapic_insert_resource(void)
  * that is using request_resource
  */
 late_initcall(lapic_insert_resource);
+
+static int __init apic_set_disabled_cpu_apicid(char *arg)
+{
+       if (!arg || !get_option(&arg, &disabled_cpu_apicid))
+               return -EINVAL;
+
+       return 0;
+}
+early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid);
index 00c77cf78e9e1839973923076053fdf92d75a54e..5d5b9eb2b7a417d692be43ecdda99cfe9e781fa4 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
-#include <linux/init.h>
 #include <linux/hardirq.h>
 #include <linux/module.h>
 #include <asm/smp.h>
index e145f28b40993d4753d714f9247a46a8507fa959..191ce75c0e54b8f2808cce5f730f5d62c18dfa09 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
index e63a5bd2a78f55de2c356b665751558a73bc18da..a43f068ebec1c0867f91d2de2eff54cc5a89e8d4 100644 (file)
@@ -1142,9 +1142,10 @@ next:
                if (test_bit(vector, used_vectors))
                        goto next;
 
-               for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
-                       if (per_cpu(vector_irq, new_cpu)[vector] != -1)
+               for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) {
+                       if (per_cpu(vector_irq, new_cpu)[vector] > VECTOR_UNDEFINED)
                                goto next;
+               }
                /* Found one! */
                current_vector = vector;
                current_offset = offset;
@@ -1183,7 +1184,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
 
        vector = cfg->vector;
        for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)
-               per_cpu(vector_irq, cpu)[vector] = -1;
+               per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
 
        cfg->vector = 0;
        cpumask_clear(cfg->domain);
@@ -1191,11 +1192,10 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
        if (likely(!cfg->move_in_progress))
                return;
        for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {
-               for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
-                                                               vector++) {
+               for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
                        if (per_cpu(vector_irq, cpu)[vector] != irq)
                                continue;
-                       per_cpu(vector_irq, cpu)[vector] = -1;
+                       per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
                        break;
                }
        }
@@ -1228,12 +1228,12 @@ void __setup_vector_irq(int cpu)
        /* Mark the free vectors */
        for (vector = 0; vector < NR_VECTORS; ++vector) {
                irq = per_cpu(vector_irq, cpu)[vector];
-               if (irq < 0)
+               if (irq <= VECTOR_UNDEFINED)
                        continue;
 
                cfg = irq_cfg(irq);
                if (!cpumask_test_cpu(cpu, cfg->domain))
-                       per_cpu(vector_irq, cpu)[vector] = -1;
+                       per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
        }
        raw_spin_unlock(&vector_lock);
 }
@@ -2202,13 +2202,13 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
 
        me = smp_processor_id();
        for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
-               unsigned int irq;
+               int irq;
                unsigned int irr;
                struct irq_desc *desc;
                struct irq_cfg *cfg;
                irq = __this_cpu_read(vector_irq[vector]);
 
-               if (irq == -1)
+               if (irq <= VECTOR_UNDEFINED)
                        continue;
 
                desc = irq_to_desc(irq);
index 7434d8556d091612f688e2325dc6e2c8abfcde77..62071569bd50d8137758a64be8b5b1c32329b240 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
-#include <linux/init.h>
 
 #include <linux/mm.h>
 #include <linux/delay.h>
index 77c95c0e1bf77d2ba06aa737ef22bebb8a0a1c22..00146f9b0254315acfb191015314fedf35fa9ab0 100644 (file)
@@ -29,7 +29,6 @@
 #define pr_fmt(fmt) "summit: %s: " fmt, __func__
 
 #include <linux/mm.h>
-#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/bios_ebda.h>
 
index 140e29db478d78b9b16dc9cda9c58ed89fe8650d..cac85ee6913f70ca64f3a8656dbff5d5cc603348 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
-#include <linux/init.h>
 #include <linux/dmar.h>
 #include <linux/cpu.h>
 
index 562a76d433c8e286a45ecfb28bf5d88cd7ccd50a..de231e328cae310bf4a39a1fb70ebc83993bb67c 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
-#include <linux/init.h>
 #include <linux/dmar.h>
 
 #include <asm/smp.h>
index 47b56a7e99cbcf2e4387fd087cddbfb1c35060bc..7fd54f09b011e21fa6b24282c5110be928c730be 100644 (file)
@@ -36,12 +36,13 @@ obj-$(CONFIG_CPU_SUP_AMD)           += perf_event_amd_iommu.o
 endif
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_knc.o perf_event_p4.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o perf_event_intel_rapl.o
 endif
 
 
 obj-$(CONFIG_X86_MCE)                  += mcheck/
 obj-$(CONFIG_MTRR)                     += mtrr/
+obj-$(CONFIG_MICROCODE)                        += microcode/
 
 obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o perf_event_amd_ibs.o
 
index bca023bdd6b2a8b4525d10145795408dee4fa01b..d3153e281d7291e78bb57d647d388171f4d006b2 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/export.h>
-#include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/elf.h>
 #include <linux/mm.h>
@@ -487,7 +486,7 @@ static void early_init_amd(struct cpuinfo_x86 *c)
                set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
                set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
                if (!check_tsc_unstable())
-                       sched_clock_stable = 1;
+                       set_sched_clock_stable();
        }
 
 #ifdef CONFIG_X86_64
@@ -508,6 +507,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
        }
 #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));
+       }
+
 }
 
 static const int amd_erratum_383[];
@@ -790,14 +799,10 @@ static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
        }
 
        /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
-       if (!((eax >> 16) & mask)) {
-               u32 a, b, c, d;
-
-               cpuid(0x80000005, &a, &b, &c, &d);
-               tlb_lld_2m[ENTRIES] = (a >> 16) & 0xff;
-       } else {
+       if (!((eax >> 16) & mask))
+               tlb_lld_2m[ENTRIES] = (cpuid_eax(0x80000005) >> 16) & 0xff;
+       else
                tlb_lld_2m[ENTRIES] = (eax >> 16) & mask;
-       }
 
        /* a 4M entry uses two 2M entries */
        tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1;
index 8d5652dc99dd53aa9516f87d5945a22b4624a5e7..8779edab684efdcd04fd93d22d79d4633c6fd4f9 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/bitops.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/e820.h>
index 6abc172b82581163e7acb99dbfa57dde9ef38fb9..24b6fd10625a5a95aeb0331da66cea8c148a08c9 100644 (file)
@@ -472,6 +472,7 @@ u16 __read_mostly tlb_lli_4m[NR_INFO];
 u16 __read_mostly tlb_lld_4k[NR_INFO];
 u16 __read_mostly tlb_lld_2m[NR_INFO];
 u16 __read_mostly tlb_lld_4m[NR_INFO];
+u16 __read_mostly tlb_lld_1g[NR_INFO];
 
 /*
  * tlb_flushall_shift shows the balance point in replacing cr3 write
@@ -486,13 +487,13 @@ void cpu_detect_tlb(struct cpuinfo_x86 *c)
        if (this_cpu->c_detect_tlb)
                this_cpu->c_detect_tlb(c);
 
-       printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \
-               "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n"          \
+       printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n"
+               "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n"
                "tlb_flushall_shift: %d\n",
                tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES],
                tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES],
                tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES],
-               tlb_flushall_shift);
+               tlb_lld_1g[ENTRIES], tlb_flushall_shift);
 }
 
 void detect_ht(struct cpuinfo_x86 *c)
index d0969c75ab54bb6bf8f41f41981e27a62478ddd8..aaf152e79637384781d264afbff76a58da9489cc 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
index dc1ec0dff939ecff5e55bcccaeb5bea322ad982a..3db61c644e440e8af7b978320b546a25336055f4 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/init.h>
 #include <linux/kernel.h>
 
 #include <linux/string.h>
@@ -93,7 +92,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
                set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
                set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
                if (!check_tsc_unstable())
-                       sched_clock_stable = 1;
+                       set_sched_clock_stable();
        }
 
        /* Penwell and Cloverview have the TSC which doesn't sleep on S3 */
@@ -387,7 +386,8 @@ static void init_intel(struct cpuinfo_x86 *c)
                        set_cpu_cap(c, X86_FEATURE_PEBS);
        }
 
-       if (c->x86 == 6 && c->x86_model == 29 && cpu_has_clflush)
+       if (c->x86 == 6 && cpu_has_clflush &&
+           (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
                set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
 
 #ifdef CONFIG_X86_64
@@ -505,6 +505,7 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 #define TLB_DATA0_2M_4M        0x23
 
 #define STLB_4K                0x41
+#define STLB_4K_2M     0x42
 
 static const struct _tlb_table intel_tlb_table[] = {
        { 0x01, TLB_INST_4K,            32,     " TLB_INST 4 KByte pages, 4-way set associative" },
@@ -525,13 +526,20 @@ static const struct _tlb_table intel_tlb_table[] = {
        { 0x5b, TLB_DATA_4K_4M,         64,     " TLB_DATA 4 KByte and 4 MByte pages" },
        { 0x5c, TLB_DATA_4K_4M,         128,    " TLB_DATA 4 KByte and 4 MByte pages" },
        { 0x5d, TLB_DATA_4K_4M,         256,    " TLB_DATA 4 KByte and 4 MByte pages" },
+       { 0x61, TLB_INST_4K,            48,     " TLB_INST 4 KByte pages, full associative" },
+       { 0x63, TLB_DATA_1G,            4,      " TLB_DATA 1 GByte pages, 4-way set associative" },
+       { 0x76, TLB_INST_2M_4M,         8,      " TLB_INST 2-MByte or 4-MByte pages, fully associative" },
        { 0xb0, TLB_INST_4K,            128,    " TLB_INST 4 KByte pages, 4-way set associative" },
        { 0xb1, TLB_INST_2M_4M,         4,      " TLB_INST 2M pages, 4-way, 8 entries or 4M pages, 4-way entries" },
        { 0xb2, TLB_INST_4K,            64,     " TLB_INST 4KByte pages, 4-way set associative" },
        { 0xb3, TLB_DATA_4K,            128,    " TLB_DATA 4 KByte pages, 4-way set associative" },
        { 0xb4, TLB_DATA_4K,            256,    " TLB_DATA 4 KByte pages, 4-way associative" },
+       { 0xb5, TLB_INST_4K,            64,     " TLB_INST 4 KByte pages, 8-way set ssociative" },
+       { 0xb6, TLB_INST_4K,            128,    " TLB_INST 4 KByte pages, 8-way set ssociative" },
        { 0xba, TLB_DATA_4K,            64,     " TLB_DATA 4 KByte pages, 4-way associative" },
        { 0xc0, TLB_DATA_4K_4M,         8,      " TLB_DATA 4 KByte and 4 MByte pages, 4-way associative" },
+       { 0xc1, STLB_4K_2M,             1024,   " STLB 4 KByte and 2 MByte pages, 8-way associative" },
+       { 0xc2, TLB_DATA_2M_4M,         16,     " DTLB 2 MByte/4MByte pages, 4-way associative" },
        { 0xca, STLB_4K,                512,    " STLB 4 KByte pages, 4-way associative" },
        { 0x00, 0, 0 }
 };
@@ -557,6 +565,20 @@ static void intel_tlb_lookup(const unsigned char desc)
                if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries)
                        tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries;
                break;
+       case STLB_4K_2M:
+               if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries;
+               if (tlb_lld_4k[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lld_4k[ENTRIES] = intel_tlb_table[k].entries;
+               if (tlb_lli_2m[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lli_2m[ENTRIES] = intel_tlb_table[k].entries;
+               if (tlb_lld_2m[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lld_2m[ENTRIES] = intel_tlb_table[k].entries;
+               if (tlb_lli_4m[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lli_4m[ENTRIES] = intel_tlb_table[k].entries;
+               if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries;
+               break;
        case TLB_INST_ALL:
                if (tlb_lli_4k[ENTRIES] < intel_tlb_table[k].entries)
                        tlb_lli_4k[ENTRIES] = intel_tlb_table[k].entries;
@@ -602,6 +624,10 @@ static void intel_tlb_lookup(const unsigned char desc)
                if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries)
                        tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries;
                break;
+       case TLB_DATA_1G:
+               if (tlb_lld_1g[ENTRIES] < intel_tlb_table[k].entries)
+                       tlb_lld_1g[ENTRIES] = intel_tlb_table[k].entries;
+               break;
        }
 }
 
index de8b60a53f695f486664d0dac307279d31207be8..a1aef9533154b8c7be7cbc5dd271cadf78761093 100644 (file)
 #include <linux/acpi.h>
 #include <linux/cper.h>
 #include <acpi/apei.h>
+#include <acpi/ghes.h>
 #include <asm/mce.h>
 
 #include "mce-internal.h"
 
-void apei_mce_report_mem_error(int corrected, struct cper_sec_mem_err *mem_err)
+void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err)
 {
        struct mce m;
 
-       /* Only corrected MC is reported */
-       if (!corrected || !(mem_err->validation_bits & CPER_MEM_VALID_PA))
+       if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
                return;
 
        mce_setup(&m);
        m.bank = 1;
-       /* Fake a memory read corrected error with unknown channel */
+       /* Fake a memory read error with unknown channel */
        m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | 0x9f;
+
+       if (severity >= GHES_SEV_RECOVERABLE)
+               m.status |= MCI_STATUS_UC;
+       if (severity >= GHES_SEV_PANIC)
+               m.status |= MCI_STATUS_PCC;
+
        m.addr = mem_err->physical_addr;
        mce_log(&m);
        mce_notify_irq();
index b3218cdee95f43a14ce2681e8a339e2cca28bcaa..4d5419b249da5353afb24edd23c8410d60f8079d 100644 (file)
@@ -1638,15 +1638,15 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
 
 static void mce_start_timer(unsigned int cpu, struct timer_list *t)
 {
-       unsigned long iv = mce_adjust_timer(check_interval * HZ);
-
-       __this_cpu_write(mce_next_interval, iv);
+       unsigned long iv = check_interval * HZ;
 
        if (mca_cfg.ignore_ce || !iv)
                return;
 
+       per_cpu(mce_next_interval, cpu) = iv;
+
        t->expires = round_jiffies(jiffies + iv);
-       add_timer_on(t, smp_processor_id());
+       add_timer_on(t, cpu);
 }
 
 static void __mcheck_cpu_init_timer(void)
@@ -2272,8 +2272,10 @@ static int mce_device_create(unsigned int cpu)
        dev->release = &mce_device_release;
 
        err = device_register(dev);
-       if (err)
+       if (err) {
+               put_device(dev);
                return err;
+       }
 
        for (i = 0; mce_device_attrs[i]; i++) {
                err = device_create_file(dev, mce_device_attrs[i]);
index 4cfe0458ca665a5311cc57512f121878e616ea9f..fb6156fee6f79dcc07559a9765f3702d7365506d 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/gfp.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/sched.h>
index 1c044b1ccc593cd973a321faa63edd7c27bd446b..a3042989398c1cdb7d33da49bf7dea1887e00aa5 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/processor.h>
index e9a701aecaa14a3959e8c2176e14a9be308d8bcd..7dc5564d0cdf57c0e7ca8c181f87f3ebb6f6ceb2 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/mce.h>
diff --git a/arch/x86/kernel/cpu/microcode/Makefile b/arch/x86/kernel/cpu/microcode/Makefile
new file mode 100644 (file)
index 0000000..285c854
--- /dev/null
@@ -0,0 +1,7 @@
+microcode-y                            := core.o
+obj-$(CONFIG_MICROCODE)                        += microcode.o
+microcode-$(CONFIG_MICROCODE_INTEL)    += intel.o intel_lib.o
+microcode-$(CONFIG_MICROCODE_AMD)      += amd.o
+obj-$(CONFIG_MICROCODE_EARLY)          += core_early.o
+obj-$(CONFIG_MICROCODE_INTEL_EARLY)    += intel_early.o
+obj-$(CONFIG_MICROCODE_AMD_EARLY)      += amd_early.o
similarity index 96%
rename from arch/x86/kernel/microcode_amd.c
rename to arch/x86/kernel/cpu/microcode/amd.c
index c3d4cc972eca6baa8b470a8d80f557afd949e65b..4a6ff747aaadc464bd6683d6fa598354028c43fc 100644 (file)
@@ -182,10 +182,10 @@ int __apply_microcode_amd(struct microcode_amd *mc_amd)
 {
        u32 rev, dummy;
 
-       wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
+       native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
 
        /* verify patch application was successful */
-       rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+       native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
        if (rev != mc_amd->hdr.patch_id)
                return -1;
 
@@ -332,6 +332,9 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
        patch->patch_id  = mc_hdr->patch_id;
        patch->equiv_cpu = proc_id;
 
+       pr_debug("%s: Added patch_id: 0x%08x, proc_id: 0x%04x\n",
+                __func__, patch->patch_id, proc_id);
+
        /* ... and add to cache. */
        update_cache(patch);
 
@@ -390,9 +393,9 @@ enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
        if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
                struct ucode_patch *p = find_patch(smp_processor_id());
                if (p) {
-                       memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
-                       memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
-                                                          MPB_MAX_SIZE));
+                       memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
+                       memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
+                                                              PATCH_MAX_SIZE));
                }
        }
 #endif
similarity index 55%
rename from arch/x86/kernel/microcode_amd_early.c
rename to arch/x86/kernel/cpu/microcode/amd_early.c
index 6073104ccaa36bca776290155e42a30bdd444a8d..8384c0fa206f17d4ff3cffb55f427962c863fdc2 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2013 Advanced Micro Devices, Inc.
  *
  * Author: Jacob Shin <jacob.shin@amd.com>
+ * Fixes: Borislav Petkov <bp@suse.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <asm/setup.h>
 #include <asm/microcode_amd.h>
 
-static bool ucode_loaded;
+/*
+ * This points to the current valid container of microcode patches which we will
+ * save from the initrd before jettisoning its contents.
+ */
+static u8 *container;
+static size_t container_size;
+
 static u32 ucode_new_rev;
-static unsigned long ucode_offset;
-static size_t ucode_size;
+u8 amd_ucode_patch[PATCH_MAX_SIZE];
+static u16 this_equiv_id;
+
+struct cpio_data ucode_cpio;
 
 /*
  * Microcode patch container file is prepended to the initrd in cpio format.
@@ -32,9 +41,6 @@ static struct cpio_data __init find_ucode_in_initrd(void)
        char *path;
        void *start;
        size_t size;
-       unsigned long *uoffset;
-       size_t *usize;
-       struct cpio_data cd;
 
 #ifdef CONFIG_X86_32
        struct boot_params *p;
@@ -47,30 +53,50 @@ static struct cpio_data __init find_ucode_in_initrd(void)
        path    = (char *)__pa_nodebug(ucode_path);
        start   = (void *)p->hdr.ramdisk_image;
        size    = p->hdr.ramdisk_size;
-       uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
-       usize   = (size_t *)__pa_nodebug(&ucode_size);
 #else
        path    = ucode_path;
        start   = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
        size    = boot_params.hdr.ramdisk_size;
-       uoffset = &ucode_offset;
-       usize   = &ucode_size;
 #endif
 
-       cd = find_cpio_data(path, start, size, &offset);
-       if (!cd.data)
-               return cd;
+       return find_cpio_data(path, start, size, &offset);
+}
 
-       if (*(u32 *)cd.data != UCODE_MAGIC) {
-               cd.data = NULL;
-               cd.size = 0;
-               return cd;
-       }
+static size_t compute_container_size(u8 *data, u32 total_size)
+{
+       size_t size = 0;
+       u32 *header = (u32 *)data;
 
-       *uoffset = (u8 *)cd.data - (u8 *)start;
-       *usize   = cd.size;
+       if (header[0] != UCODE_MAGIC ||
+           header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
+           header[2] == 0)                            /* size */
+               return size;
 
-       return cd;
+       size = header[2] + CONTAINER_HDR_SZ;
+       total_size -= size;
+       data += size;
+
+       while (total_size) {
+               u16 patch_size;
+
+               header = (u32 *)data;
+
+               if (header[0] != UCODE_UCODE_TYPE)
+                       break;
+
+               /*
+                * Sanity-check patch size.
+                */
+               patch_size = header[1];
+               if (patch_size > PATCH_MAX_SIZE)
+                       break;
+
+               size       += patch_size + SECTION_HDR_SIZE;
+               data       += patch_size + SECTION_HDR_SIZE;
+               total_size -= patch_size + SECTION_HDR_SIZE;
+       }
+
+       return size;
 }
 
 /*
@@ -85,23 +111,22 @@ static struct cpio_data __init find_ucode_in_initrd(void)
 static void apply_ucode_in_initrd(void *ucode, size_t size)
 {
        struct equiv_cpu_entry *eq;
+       size_t *cont_sz;
        u32 *header;
-       u8  *data;
+       u8  *data, **cont;
        u16 eq_id = 0;
        int offset, left;
-       u32 rev, eax;
+       u32 rev, eax, ebx, ecx, edx;
        u32 *new_rev;
-       unsigned long *uoffset;
-       size_t *usize;
 
 #ifdef CONFIG_X86_32
        new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
-       uoffset = (unsigned long *)__pa_nodebug(&ucode_offset);
-       usize   = (size_t *)__pa_nodebug(&ucode_size);
+       cont_sz = (size_t *)__pa_nodebug(&container_size);
+       cont    = (u8 **)__pa_nodebug(&container);
 #else
        new_rev = &ucode_new_rev;
-       uoffset = &ucode_offset;
-       usize   = &ucode_size;
+       cont_sz = &container_size;
+       cont    = &container;
 #endif
 
        data   = ucode;
@@ -109,23 +134,37 @@ static void apply_ucode_in_initrd(void *ucode, size_t size)
        header = (u32 *)data;
 
        /* find equiv cpu table */
-
-       if (header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
+       if (header[0] != UCODE_MAGIC ||
+           header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
            header[2] == 0)                            /* size */
                return;
 
-       eax = cpuid_eax(0x00000001);
+       eax = 0x00000001;
+       ecx = 0;
+       native_cpuid(&eax, &ebx, &ecx, &edx);
 
        while (left > 0) {
                eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
 
+               *cont = data;
+
+               /* Advance past the container header */
                offset = header[2] + CONTAINER_HDR_SZ;
                data  += offset;
                left  -= offset;
 
                eq_id = find_equiv_id(eq, eax);
-               if (eq_id)
+               if (eq_id) {
+                       this_equiv_id = eq_id;
+                       *cont_sz = compute_container_size(*cont, left + offset);
+
+                       /*
+                        * truncate how much we need to iterate over in the
+                        * ucode update loop below
+                        */
+                       left = *cont_sz - offset;
                        break;
+               }
 
                /*
                 * support multiple container files appended together. if this
@@ -145,19 +184,18 @@ static void apply_ucode_in_initrd(void *ucode, size_t size)
 
                /* mark where the next microcode container file starts */
                offset    = data - (u8 *)ucode;
-               *uoffset += offset;
-               *usize   -= offset;
                ucode     = data;
        }
 
        if (!eq_id) {
-               *usize = 0;
+               *cont = NULL;
+               *cont_sz = 0;
                return;
        }
 
        /* find ucode and update if needed */
 
-       rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
+       native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
 
        while (left > 0) {
                struct microcode_amd *mc;
@@ -168,73 +206,83 @@ static void apply_ucode_in_initrd(void *ucode, size_t size)
                        break;
 
                mc = (struct microcode_amd *)(data + SECTION_HDR_SIZE);
-               if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id)
-                       if (__apply_microcode_amd(mc) == 0) {
+
+               if (eq_id == mc->hdr.processor_rev_id && rev < mc->hdr.patch_id) {
+
+                       if (!__apply_microcode_amd(mc)) {
                                rev = mc->hdr.patch_id;
                                *new_rev = rev;
+
+                               /* save ucode patch */
+                               memcpy(amd_ucode_patch, mc,
+                                      min_t(u32, header[1], PATCH_MAX_SIZE));
                        }
+               }
 
                offset  = header[1] + SECTION_HDR_SIZE;
                data   += offset;
                left   -= offset;
        }
-
-       /* mark where this microcode container file ends */
-       offset  = *usize - (data - (u8 *)ucode);
-       *usize -= offset;
-
-       if (!(*new_rev))
-               *usize = 0;
 }
 
 void __init load_ucode_amd_bsp(void)
 {
-       struct cpio_data cd = find_ucode_in_initrd();
-       if (!cd.data)
+       struct cpio_data cp;
+       void **data;
+       size_t *size;
+
+#ifdef CONFIG_X86_32
+       data =  (void **)__pa_nodebug(&ucode_cpio.data);
+       size = (size_t *)__pa_nodebug(&ucode_cpio.size);
+#else
+       data = &ucode_cpio.data;
+       size = &ucode_cpio.size;
+#endif
+
+       cp = find_ucode_in_initrd();
+       if (!cp.data)
                return;
 
-       apply_ucode_in_initrd(cd.data, cd.size);
+       *data = cp.data;
+       *size = cp.size;
+
+       apply_ucode_in_initrd(cp.data, cp.size);
 }
 
 #ifdef CONFIG_X86_32
-u8 amd_bsp_mpb[MPB_MAX_SIZE];
-
 /*
  * On 32-bit, since AP's early load occurs before paging is turned on, we
  * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during
  * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During
- * save_microcode_in_initrd_amd() BSP's patch is copied to amd_bsp_mpb, which
- * is used upon resume from suspend.
+ * save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch,
+ * which is used upon resume from suspend.
  */
 void load_ucode_amd_ap(void)
 {
        struct microcode_amd *mc;
-       unsigned long *initrd;
-       unsigned long *uoffset;
        size_t *usize;
-       void *ucode;
+       void **ucode;
 
-       mc = (struct microcode_amd *)__pa(amd_bsp_mpb);
+       mc = (struct microcode_amd *)__pa(amd_ucode_patch);
        if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
                __apply_microcode_amd(mc);
                return;
        }
 
-       initrd  = (unsigned long *)__pa(&initrd_start);
-       uoffset = (unsigned long *)__pa(&ucode_offset);
-       usize   = (size_t *)__pa(&ucode_size);
+       ucode = (void *)__pa_nodebug(&container);
+       usize = (size_t *)__pa_nodebug(&container_size);
 
-       if (!*usize || !*initrd)
+       if (!*ucode || !*usize)
                return;
 
-       ucode = (void *)((unsigned long)__pa(*initrd) + *uoffset);
-       apply_ucode_in_initrd(ucode, *usize);
+       apply_ucode_in_initrd(*ucode, *usize);
 }
 
 static void __init collect_cpu_sig_on_bsp(void *arg)
 {
        unsigned int cpu = smp_processor_id();
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
        uci->cpu_sig.sig = cpuid_eax(0x00000001);
 }
 #else
@@ -242,36 +290,54 @@ void load_ucode_amd_ap(void)
 {
        unsigned int cpu = smp_processor_id();
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+       struct equiv_cpu_entry *eq;
+       struct microcode_amd *mc;
        u32 rev, eax;
+       u16 eq_id;
+
+       /* Exit if called on the BSP. */
+       if (!cpu)
+               return;
+
+       if (!container)
+               return;
 
        rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
-       eax = cpuid_eax(0x00000001);
 
        uci->cpu_sig.rev = rev;
        uci->cpu_sig.sig = eax;
 
-       if (cpu && !ucode_loaded) {
-               void *ucode;
+       eax = cpuid_eax(0x00000001);
+       eq  = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ);
 
-               if (!ucode_size || !initrd_start)
-                       return;
+       eq_id = find_equiv_id(eq, eax);
+       if (!eq_id)
+               return;
+
+       if (eq_id == this_equiv_id) {
+               mc = (struct microcode_amd *)amd_ucode_patch;
 
-               ucode = (void *)(initrd_start + ucode_offset);
-               eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
-               if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
+               if (mc && rev < mc->hdr.patch_id) {
+                       if (!__apply_microcode_amd(mc))
+                               ucode_new_rev = mc->hdr.patch_id;
+               }
+
+       } else {
+               if (!ucode_cpio.data)
                        return;
 
-               ucode_loaded = true;
+               /*
+                * AP has a different equivalence ID than BSP, looks like
+                * mixed-steppings silicon so go through the ucode blob anew.
+                */
+               apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size);
        }
-
-       apply_microcode_amd(cpu);
 }
 #endif
 
 int __init save_microcode_in_initrd_amd(void)
 {
        enum ucode_state ret;
-       void *ucode;
        u32 eax;
 
 #ifdef CONFIG_X86_32
@@ -280,22 +346,35 @@ int __init save_microcode_in_initrd_amd(void)
 
        if (!uci->cpu_sig.sig)
                smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+
+       /*
+        * 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.
+        */
+       container = (u8 *)(__va((u32)relocated_ramdisk) +
+                          ((u32)container - boot_params.hdr.ramdisk_image));
 #endif
        if (ucode_new_rev)
                pr_info("microcode: updated early to new patch_level=0x%08x\n",
                        ucode_new_rev);
 
-       if (ucode_loaded || !ucode_size || !initrd_start)
-               return 0;
+       if (!container)
+               return -EINVAL;
 
-       ucode = (void *)(initrd_start + ucode_offset);
        eax   = cpuid_eax(0x00000001);
        eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
 
-       ret = load_microcode_amd(eax, ucode, ucode_size);
+       ret = load_microcode_amd(eax, container, container_size);
        if (ret != UCODE_OK)
                return -EINVAL;
 
-       ucode_loaded = true;
+       /*
+        * This will be freed any msec now, stash patches for the current
+        * family and switch to patch cache for cpu hotplug, etc later.
+        */
+       container = NULL;
+       container_size = 0;
+
        return 0;
 }
similarity index 98%
rename from arch/x86/kernel/microcode_intel_early.c
rename to arch/x86/kernel/cpu/microcode/intel_early.c
index 1575deb2e636af5699e20af86a0ba63818c9ae5c..18f739129e72080c4c41c863361473e0412b414c 100644 (file)
@@ -365,16 +365,6 @@ out:
        return state;
 }
 
-#define native_rdmsr(msr, val1, val2)          \
-do {                                           \
-       u64 __val = native_read_msr((msr));     \
-       (void)((val1) = (u32)__val);            \
-       (void)((val2) = (u32)(__val >> 32));    \
-} while (0)
-
-#define native_wrmsr(msr, low, high)           \
-       native_write_msr(msr, low, high);
-
 static int collect_cpu_info_early(struct ucode_cpu_info *uci)
 {
        unsigned int val[2];
index 8e132931614d618b03b9f7d69a492b793a27bc30..b88645191fe559b89b8d330c984865d07dbae21b 100644 (file)
@@ -1883,21 +1883,27 @@ static struct pmu pmu = {
 
 void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
 {
+       struct cyc2ns_data *data;
+
        userpg->cap_user_time = 0;
        userpg->cap_user_time_zero = 0;
        userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc;
        userpg->pmc_width = x86_pmu.cntval_bits;
 
-       if (!sched_clock_stable)
+       if (!sched_clock_stable())
                return;
 
+       data = cyc2ns_read_begin();
+
        userpg->cap_user_time = 1;
-       userpg->time_mult = this_cpu_read(cyc2ns);
-       userpg->time_shift = CYC2NS_SCALE_FACTOR;
-       userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;
+       userpg->time_mult = data->cyc2ns_mul;
+       userpg->time_shift = data->cyc2ns_shift;
+       userpg->time_offset = data->cyc2ns_offset - now;
 
        userpg->cap_user_time_zero = 1;
-       userpg->time_zero = this_cpu_read(cyc2ns_offset);
+       userpg->time_zero = data->cyc2ns_offset;
+
+       cyc2ns_read_end(data);
 }
 
 /*
index fd00bb29425d4da50194241c6ae3835775e12e6e..c1a861829d817a2749372060df21c6d689294fff 100644 (file)
@@ -262,11 +262,20 @@ struct cpu_hw_events {
        __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
 
-#define EVENT_CONSTRAINT_END           \
-       EVENT_CONSTRAINT(0, 0, 0)
+/*
+ * We define the end marker as having a weight of -1
+ * to enable blacklisting of events using a counter bitmask
+ * of zero and thus a weight of zero.
+ * The end marker has a weight that cannot possibly be
+ * obtained from counting the bits in the bitmask.
+ */
+#define EVENT_CONSTRAINT_END { .weight = -1 }
 
+/*
+ * Check for end marker with weight == -1
+ */
 #define for_each_event_constraint(e, c)        \
-       for ((e) = (c); (e)->weight; (e)++)
+       for ((e) = (c); (e)->weight != -1; (e)++)
 
 /*
  * Extra registers for specific events.
index e09f0bfb7b8f23b3206ed623289df4b9bff67605..4b8e4d3cd6ea62bc9c9047e869fa84cbd9cbe33a 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/apic.h>
 
@@ -816,6 +817,18 @@ out:
        return ret;
 }
 
+static void ibs_eilvt_setup(void)
+{
+       /*
+        * Force LVT offset assignment for family 10h: The offsets are
+        * not assigned by the BIOS for this family, so the OS is
+        * responsible for doing it. If the OS assignment fails, fall
+        * back to BIOS settings and try to setup this.
+        */
+       if (boot_cpu_data.x86 == 0x10)
+               force_ibs_eilvt_setup();
+}
+
 static inline int get_ibs_lvt_offset(void)
 {
        u64 val;
@@ -851,6 +864,36 @@ static void clear_APIC_ibs(void *dummy)
                setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
 }
 
+#ifdef CONFIG_PM
+
+static int perf_ibs_suspend(void)
+{
+       clear_APIC_ibs(NULL);
+       return 0;
+}
+
+static void perf_ibs_resume(void)
+{
+       ibs_eilvt_setup();
+       setup_APIC_ibs(NULL);
+}
+
+static struct syscore_ops perf_ibs_syscore_ops = {
+       .resume         = perf_ibs_resume,
+       .suspend        = perf_ibs_suspend,
+};
+
+static void perf_ibs_pm_init(void)
+{
+       register_syscore_ops(&perf_ibs_syscore_ops);
+}
+
+#else
+
+static inline void perf_ibs_pm_init(void) { }
+
+#endif
+
 static int
 perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
 {
@@ -877,18 +920,12 @@ static __init int amd_ibs_init(void)
        if (!caps)
                return -ENODEV; /* ibs not supported by the cpu */
 
-       /*
-        * Force LVT offset assignment for family 10h: The offsets are
-        * not assigned by the BIOS for this family, so the OS is
-        * responsible for doing it. If the OS assignment fails, fall
-        * back to BIOS settings and try to setup this.
-        */
-       if (boot_cpu_data.x86 == 0x10)
-               force_ibs_eilvt_setup();
+       ibs_eilvt_setup();
 
        if (!ibs_eilvt_valid())
                goto out;
 
+       perf_ibs_pm_init();
        get_online_cpus();
        ibs_caps = caps;
        /* make ibs_caps visible to other cpus: */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
new file mode 100644 (file)
index 0000000..5ad35ad
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ * perf_event_intel_rapl.c: support Intel RAPL energy consumption counters
+ * Copyright (C) 2013 Google, Inc., Stephane Eranian
+ *
+ * Intel RAPL interface is specified in the IA-32 Manual Vol3b
+ * section 14.7.1 (September 2013)
+ *
+ * RAPL provides more controls than just reporting energy consumption
+ * however here we only expose the 3 energy consumption free running
+ * counters (pp0, pkg, dram).
+ *
+ * Each of those counters increments in a power unit defined by the
+ * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules
+ * but it can vary.
+ *
+ * Counter to rapl events mappings:
+ *
+ *  pp0 counter: consumption of all physical cores (power plane 0)
+ *       event: rapl_energy_cores
+ *    perf code: 0x1
+ *
+ *  pkg counter: consumption of the whole processor package
+ *       event: rapl_energy_pkg
+ *    perf code: 0x2
+ *
+ * dram counter: consumption of the dram domain (servers only)
+ *       event: rapl_energy_dram
+ *    perf code: 0x3
+ *
+ * dram counter: consumption of the builtin-gpu domain (client only)
+ *       event: rapl_energy_gpu
+ *    perf code: 0x4
+ *
+ * We manage those counters as free running (read-only). They may be
+ * use simultaneously by other tools, such as turbostat.
+ *
+ * The events only support system-wide mode counting. There is no
+ * sampling support because it does not make sense and is not
+ * supported by the RAPL hardware.
+ *
+ * Because we want to avoid floating-point operations in the kernel,
+ * the events are all reported in fixed point arithmetic (32.32).
+ * Tools must adjust the counts to convert them to Watts using
+ * the duration of the measurement. Tools may use a function such as
+ * ldexp(raw_count, -32);
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+#include <asm/cpu_device_id.h>
+#include "perf_event.h"
+
+/*
+ * RAPL energy status counters
+ */
+#define RAPL_IDX_PP0_NRG_STAT  0       /* all cores */
+#define INTEL_RAPL_PP0         0x1     /* pseudo-encoding */
+#define RAPL_IDX_PKG_NRG_STAT  1       /* entire package */
+#define INTEL_RAPL_PKG         0x2     /* pseudo-encoding */
+#define RAPL_IDX_RAM_NRG_STAT  2       /* DRAM */
+#define INTEL_RAPL_RAM         0x3     /* pseudo-encoding */
+#define RAPL_IDX_PP1_NRG_STAT  3       /* DRAM */
+#define INTEL_RAPL_PP1         0x4     /* pseudo-encoding */
+
+/* Clients have PP0, PKG */
+#define RAPL_IDX_CLN   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_PP1_NRG_STAT)
+
+/* Servers have PP0, PKG, RAM */
+#define RAPL_IDX_SRV   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_RAM_NRG_STAT)
+
+/*
+ * event code: LSB 8 bits, passed in attr->config
+ * any other bit is reserved
+ */
+#define RAPL_EVENT_MASK        0xFFULL
+
+#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format)          \
+static ssize_t __rapl_##_var##_show(struct kobject *kobj,      \
+                               struct kobj_attribute *attr,    \
+                               char *page)                     \
+{                                                              \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
+       return sprintf(page, _format "\n");                     \
+}                                                              \
+static struct kobj_attribute format_attr_##_var =              \
+       __ATTR(_name, 0444, __rapl_##_var##_show, NULL)
+
+#define RAPL_EVENT_DESC(_name, _config)                                \
+{                                                              \
+       .attr   = __ATTR(_name, 0444, rapl_event_show, NULL),   \
+       .config = _config,                                      \
+}
+
+#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
+
+struct rapl_pmu {
+       spinlock_t       lock;
+       int              hw_unit;  /* 1/2^hw_unit Joule */
+       int              n_active; /* number of active events */
+       struct list_head active_list;
+       struct pmu       *pmu; /* pointer to rapl_pmu_class */
+       ktime_t          timer_interval; /* in ktime_t unit */
+       struct hrtimer   hrtimer;
+};
+
+static struct pmu rapl_pmu_class;
+static cpumask_t rapl_cpu_mask;
+static int rapl_cntr_mask;
+
+static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu);
+static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu_to_free);
+
+static inline u64 rapl_read_counter(struct perf_event *event)
+{
+       u64 raw;
+       rdmsrl(event->hw.event_base, raw);
+       return raw;
+}
+
+static inline u64 rapl_scale(u64 v)
+{
+       /*
+        * scale delta to smallest unit (1/2^32)
+        * users must then scale back: count * 1/(1e9*2^32) to get Joules
+        * or use ldexp(count, -32).
+        * Watts = Joules/Time delta
+        */
+       return v << (32 - __get_cpu_var(rapl_pmu)->hw_unit);
+}
+
+static u64 rapl_event_update(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 prev_raw_count, new_raw_count;
+       s64 delta, sdelta;
+       int shift = RAPL_CNTR_WIDTH;
+
+again:
+       prev_raw_count = local64_read(&hwc->prev_count);
+       rdmsrl(event->hw.event_base, new_raw_count);
+
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                           new_raw_count) != prev_raw_count) {
+               cpu_relax();
+               goto again;
+       }
+
+       /*
+        * Now we have the new raw value and have updated the prev
+        * timestamp already. We can now calculate the elapsed delta
+        * (event-)time and add that to the generic event.
+        *
+        * Careful, not all hw sign-extends above the physical width
+        * of the count.
+        */
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       sdelta = rapl_scale(delta);
+
+       local64_add(sdelta, &event->count);
+
+       return new_raw_count;
+}
+
+static void rapl_start_hrtimer(struct rapl_pmu *pmu)
+{
+       __hrtimer_start_range_ns(&pmu->hrtimer,
+                       pmu->timer_interval, 0,
+                       HRTIMER_MODE_REL_PINNED, 0);
+}
+
+static void rapl_stop_hrtimer(struct rapl_pmu *pmu)
+{
+       hrtimer_cancel(&pmu->hrtimer);
+}
+
+static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       struct perf_event *event;
+       unsigned long flags;
+
+       if (!pmu->n_active)
+               return HRTIMER_NORESTART;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       list_for_each_entry(event, &pmu->active_list, active_entry) {
+               rapl_event_update(event);
+       }
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+
+       hrtimer_forward_now(hrtimer, pmu->timer_interval);
+
+       return HRTIMER_RESTART;
+}
+
+static void rapl_hrtimer_init(struct rapl_pmu *pmu)
+{
+       struct hrtimer *hr = &pmu->hrtimer;
+
+       hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hr->function = rapl_hrtimer_handle;
+}
+
+static void __rapl_pmu_event_start(struct rapl_pmu *pmu,
+                                  struct perf_event *event)
+{
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       event->hw.state = 0;
+
+       list_add_tail(&event->active_entry, &pmu->active_list);
+
+       local64_set(&event->hw.prev_count, rapl_read_counter(event));
+
+       pmu->n_active++;
+       if (pmu->n_active == 1)
+               rapl_start_hrtimer(pmu);
+}
+
+static void rapl_pmu_event_start(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+       __rapl_pmu_event_start(pmu, event);
+       spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static void rapl_pmu_event_stop(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       /* mark event as deactivated and stopped */
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               WARN_ON_ONCE(pmu->n_active <= 0);
+               pmu->n_active--;
+               if (pmu->n_active == 0)
+                       rapl_stop_hrtimer(pmu);
+
+               list_del(&event->active_entry);
+
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       /* check if update of sw counter is necessary */
+       if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               rapl_event_update(event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static int rapl_pmu_event_add(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       if (mode & PERF_EF_START)
+               __rapl_pmu_event_start(pmu, event);
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+
+       return 0;
+}
+
+static void rapl_pmu_event_del(struct perf_event *event, int flags)
+{
+       rapl_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static int rapl_pmu_event_init(struct perf_event *event)
+{
+       u64 cfg = event->attr.config & RAPL_EVENT_MASK;
+       int bit, msr, ret = 0;
+
+       /* only look at RAPL events */
+       if (event->attr.type != rapl_pmu_class.type)
+               return -ENOENT;
+
+       /* check only supported bits are set */
+       if (event->attr.config & ~RAPL_EVENT_MASK)
+               return -EINVAL;
+
+       /*
+        * check event is known (determines counter)
+        */
+       switch (cfg) {
+       case INTEL_RAPL_PP0:
+               bit = RAPL_IDX_PP0_NRG_STAT;
+               msr = MSR_PP0_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_PKG:
+               bit = RAPL_IDX_PKG_NRG_STAT;
+               msr = MSR_PKG_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_RAM:
+               bit = RAPL_IDX_RAM_NRG_STAT;
+               msr = MSR_DRAM_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_PP1:
+               bit = RAPL_IDX_PP1_NRG_STAT;
+               msr = MSR_PP1_ENERGY_STATUS;
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* check event supported */
+       if (!(rapl_cntr_mask & (1 << bit)))
+               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;
+
+       /* must be done before validate_group */
+       event->hw.event_base = msr;
+       event->hw.config = cfg;
+       event->hw.idx = bit;
+
+       return ret;
+}
+
+static void rapl_pmu_event_read(struct perf_event *event)
+{
+       rapl_event_update(event);
+}
+
+static ssize_t rapl_get_attr_cpumask(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &rapl_cpu_mask);
+
+       buf[n++] = '\n';
+       buf[n] = '\0';
+       return n;
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);
+
+static struct attribute *rapl_pmu_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_attr_group = {
+       .attrs = rapl_pmu_attrs,
+};
+
+EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
+EVENT_ATTR_STR(energy-pkg  ,   rapl_pkg, "event=0x02");
+EVENT_ATTR_STR(energy-ram  ,   rapl_ram, "event=0x03");
+EVENT_ATTR_STR(energy-gpu  ,   rapl_gpu, "event=0x04");
+
+EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
+EVENT_ATTR_STR(energy-pkg.unit  ,   rapl_pkg_unit, "Joules");
+EVENT_ATTR_STR(energy-ram.unit  ,   rapl_ram_unit, "Joules");
+EVENT_ATTR_STR(energy-gpu.unit  ,   rapl_gpu_unit, "Joules");
+
+/*
+ * we compute in 0.23 nJ increments regardless of MSR
+ */
+EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
+EVENT_ATTR_STR(energy-pkg.scale,     rapl_pkg_scale, "2.3283064365386962890625e-10");
+EVENT_ATTR_STR(energy-ram.scale,     rapl_ram_scale, "2.3283064365386962890625e-10");
+EVENT_ATTR_STR(energy-gpu.scale,     rapl_gpu_scale, "2.3283064365386962890625e-10");
+
+static struct attribute *rapl_events_srv_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_ram),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_ram_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_ram_scale),
+       NULL,
+};
+
+static struct attribute *rapl_events_cln_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_gpu),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_gpu_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_gpu_scale),
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_events_group = {
+       .name = "events",
+       .attrs = NULL, /* patched at runtime */
+};
+
+DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7");
+static struct attribute *rapl_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_format_group = {
+       .name = "format",
+       .attrs = rapl_formats_attr,
+};
+
+const struct attribute_group *rapl_attr_groups[] = {
+       &rapl_pmu_attr_group,
+       &rapl_pmu_format_group,
+       &rapl_pmu_events_group,
+       NULL,
+};
+
+static struct pmu rapl_pmu_class = {
+       .attr_groups    = rapl_attr_groups,
+       .task_ctx_nr    = perf_invalid_context, /* system-wide only */
+       .event_init     = rapl_pmu_event_init,
+       .add            = rapl_pmu_event_add, /* must have */
+       .del            = rapl_pmu_event_del, /* must have */
+       .start          = rapl_pmu_event_start,
+       .stop           = rapl_pmu_event_stop,
+       .read           = rapl_pmu_event_read,
+};
+
+static void rapl_cpu_exit(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
+       int i, phys_id = topology_physical_package_id(cpu);
+       int target = -1;
+
+       /* find a new cpu on same package */
+       for_each_online_cpu(i) {
+               if (i == cpu)
+                       continue;
+               if (phys_id == topology_physical_package_id(i)) {
+                       target = i;
+                       break;
+               }
+       }
+       /*
+        * clear cpu from cpumask
+        * if was set in cpumask and still some cpu on package,
+        * then move to new cpu
+        */
+       if (cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask) && target >= 0)
+               cpumask_set_cpu(target, &rapl_cpu_mask);
+
+       WARN_ON(cpumask_empty(&rapl_cpu_mask));
+       /*
+        * migrate events and context to new cpu
+        */
+       if (target >= 0)
+               perf_pmu_migrate_context(pmu->pmu, cpu, target);
+
+       /* cancel overflow polling timer for CPU */
+       rapl_stop_hrtimer(pmu);
+}
+
+static void rapl_cpu_init(int cpu)
+{
+       int i, phys_id = topology_physical_package_id(cpu);
+
+       /* check if phys_is is already covered */
+       for_each_cpu(i, &rapl_cpu_mask) {
+               if (phys_id == topology_physical_package_id(i))
+                       return;
+       }
+       /* was not found, so add it */
+       cpumask_set_cpu(cpu, &rapl_cpu_mask);
+}
+
+static int rapl_cpu_prepare(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
+       int phys_id = topology_physical_package_id(cpu);
+       u64 ms;
+
+       if (pmu)
+               return 0;
+
+       if (phys_id < 0)
+               return -1;
+
+       pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
+       if (!pmu)
+               return -1;
+
+       spin_lock_init(&pmu->lock);
+
+       INIT_LIST_HEAD(&pmu->active_list);
+
+       /*
+        * grab power unit as: 1/2^unit Joules
+        *
+        * we cache in local PMU instance
+        */
+       rdmsrl(MSR_RAPL_POWER_UNIT, pmu->hw_unit);
+       pmu->hw_unit = (pmu->hw_unit >> 8) & 0x1FULL;
+       pmu->pmu = &rapl_pmu_class;
+
+       /*
+        * use reference of 200W for scaling the timeout
+        * to avoid missing counter overflows.
+        * 200W = 200 Joules/sec
+        * divide interval by 2 to avoid lockstep (2 * 100)
+        * if hw unit is 32, then we use 2 ms 1/200/2
+        */
+       if (pmu->hw_unit < 32)
+               ms = (1000 / (2 * 100)) * (1ULL << (32 - pmu->hw_unit - 1));
+       else
+               ms = 2;
+
+       pmu->timer_interval = ms_to_ktime(ms);
+
+       rapl_hrtimer_init(pmu);
+
+       /* set RAPL pmu for this cpu for now */
+       per_cpu(rapl_pmu, cpu) = pmu;
+       per_cpu(rapl_pmu_to_free, cpu) = NULL;
+
+       return 0;
+}
+
+static void rapl_cpu_kfree(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu_to_free, cpu);
+
+       kfree(pmu);
+
+       per_cpu(rapl_pmu_to_free, cpu) = NULL;
+}
+
+static int rapl_cpu_dying(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
+
+       if (!pmu)
+               return 0;
+
+       per_cpu(rapl_pmu, cpu) = NULL;
+
+       per_cpu(rapl_pmu_to_free, cpu) = pmu;
+
+       return 0;
+}
+
+static int rapl_cpu_notifier(struct notifier_block *self,
+                            unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               rapl_cpu_prepare(cpu);
+               break;
+       case CPU_STARTING:
+               rapl_cpu_init(cpu);
+               break;
+       case CPU_UP_CANCELED:
+       case CPU_DYING:
+               rapl_cpu_dying(cpu);
+               break;
+       case CPU_ONLINE:
+       case CPU_DEAD:
+               rapl_cpu_kfree(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               rapl_cpu_exit(cpu);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct x86_cpu_id rapl_cpu_match[] = {
+       [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },
+       [1] = {},
+};
+
+static int __init rapl_pmu_init(void)
+{
+       struct rapl_pmu *pmu;
+       int cpu, ret;
+
+       /*
+        * check for Intel processor family 6
+        */
+       if (!x86_match_cpu(rapl_cpu_match))
+               return 0;
+
+       /* check supported CPU */
+       switch (boot_cpu_data.x86_model) {
+       case 42: /* Sandy Bridge */
+       case 58: /* Ivy Bridge */
+       case 60: /* Haswell */
+       case 69: /* Haswell-Celeron */
+               rapl_cntr_mask = RAPL_IDX_CLN;
+               rapl_pmu_events_group.attrs = rapl_events_cln_attr;
+               break;
+       case 45: /* Sandy Bridge-EP */
+       case 62: /* IvyTown */
+               rapl_cntr_mask = RAPL_IDX_SRV;
+               rapl_pmu_events_group.attrs = rapl_events_srv_attr;
+               break;
+
+       default:
+               /* unsupported */
+               return 0;
+       }
+       get_online_cpus();
+
+       for_each_online_cpu(cpu) {
+               rapl_cpu_prepare(cpu);
+               rapl_cpu_init(cpu);
+       }
+
+       perf_cpu_notifier(rapl_cpu_notifier);
+
+       ret = perf_pmu_register(&rapl_pmu_class, "power", -1);
+       if (WARN_ON(ret)) {
+               pr_info("RAPL PMU detected, registration failed (%d), RAPL PMU disabled\n", ret);
+               put_online_cpus();
+               return -1;
+       }
+
+       pmu = __get_cpu_var(rapl_pmu);
+
+       pr_info("RAPL PMU detected, hw unit 2^-%d Joules,"
+               " API unit is 2^-32 Joules,"
+               " %d fixed counters"
+               " %llu ms ovfl timer\n",
+               pmu->hw_unit,
+               hweight32(rapl_cntr_mask),
+               ktime_to_ms(pmu->timer_interval));
+
+       put_online_cpus();
+
+       return 0;
+}
+device_initcall(rapl_pmu_init);
index 88db010845cb26a2594170acc2387cee75a20bbc..384df5105fbc9883626ec5482151babd43ce482a 100644 (file)
@@ -31,20 +31,6 @@ static int __init x86_rdrand_setup(char *s)
 }
 __setup("nordrand", x86_rdrand_setup);
 
-/* We can't use arch_get_random_long() here since alternatives haven't run */
-static inline int rdrand_long(unsigned long *v)
-{
-       int ok;
-       asm volatile("1: " RDRAND_LONG "\n\t"
-                    "jc 2f\n\t"
-                    "decl %0\n\t"
-                    "jnz 1b\n\t"
-                    "2:"
-                    : "=r" (ok), "=a" (*v)
-                    : "0" (RDRAND_RETRY_LOOPS));
-       return ok;
-}
-
 /*
  * Force a reseed cycle; we are architecturally guaranteed a reseed
  * after no more than 512 128-bit chunks of random data.  This also
index aa0430d69b900ba0eabdb8d2764ee5fc4b902f67..3fa0e5ad86b4456168acc1efc210130303308256 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/init.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include "cpu.h"
index 75c5ad5d35cc1af6af4eb0b07028d7a48061394d..ef9c2a0078bd662649178de4b01766ec3f354907 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <asm/processor.h>
 #include "cpu.h"
 
index 18677a90d6a35e1b5823d3f33501229197e21219..a57902efe2d597be4af85c9d52d995360d54dadb 100644 (file)
@@ -7,7 +7,6 @@
  *
  */
 
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
index 5d3fe8d36e4ac71fb262f94bef68417d3e782c42..f6dfd9334b67e54aa0a9eda6cfac7f1094cf80d9 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/fs.h>
 
index 51e2988c5728d5d57b5b8f0ef035258cc292b2c1..a2a4f4697889657675289e15e358b7f354ea2225 100644 (file)
@@ -1082,7 +1082,7 @@ ENTRY(ftrace_caller)
        pushl $0        /* Pass NULL as regs pointer */
        movl 4*4(%esp), %eax
        movl 0x4(%ebp), %edx
-       leal function_trace_op, %ecx
+       movl function_trace_op, %ecx
        subl $MCOUNT_INSN_SIZE, %eax
 
 .globl ftrace_call
@@ -1140,7 +1140,7 @@ ENTRY(ftrace_regs_caller)
        movl 12*4(%esp), %eax   /* Load ip (1st parameter) */
        subl $MCOUNT_INSN_SIZE, %eax    /* Adjust ip */
        movl 0x4(%ebp), %edx    /* Load parent ip (2nd parameter) */
-       leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
+       movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
        pushl %esp              /* Save pt_regs as 4th parameter */
 
 GLOBAL(ftrace_regs_call)
index e21b0785a85b2fc2f2ca1615820d5e432a9f4675..1e96c3628bf24fc4fe0086ac6f9dc70b2c1c590d 100644 (file)
@@ -88,7 +88,7 @@ END(function_hook)
        MCOUNT_SAVE_FRAME \skip
 
        /* Load the ftrace_ops into the 3rd parameter */
-       leaq function_trace_op, %rdx
+       movq function_trace_op(%rip), %rdx
 
        /* Load ip into the first parameter */
        movq RIP(%rsp), %rdi
index f66ff162dce864a5db31949969271049396f8552..a67b47c31314ba7a2e30d7d9fc356ffc16f4f072 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/hw_breakpoint.h>
diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c
new file mode 100644 (file)
index 0000000..c3aae66
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * IOSF-SB MailBox Interface Driver
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * 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.
+ *
+ *
+ * The IOSF-SB is a fabric bus available on Atom based SOC's that uses a
+ * mailbox interface (MBI) to communicate with mutiple devices. This
+ * driver implements access to this interface for those platforms that can
+ * enumerate the device using PCI.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+
+#include <asm/iosf_mbi.h>
+
+static DEFINE_SPINLOCK(iosf_mbi_lock);
+
+static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset)
+{
+       return (op << 24) | (port << 16) | (offset << 8) | MBI_ENABLE;
+}
+
+static struct pci_dev *mbi_pdev;       /* one mbi device */
+
+static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr)
+{
+       int result;
+
+       if (!mbi_pdev)
+               return -ENODEV;
+
+       if (mcrx) {
+               result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET,
+                                               mcrx);
+               if (result < 0)
+                       goto fail_read;
+       }
+
+       result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr);
+       if (result < 0)
+               goto fail_read;
+
+       result = pci_read_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr);
+       if (result < 0)
+               goto fail_read;
+
+       return 0;
+
+fail_read:
+       dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
+       return result;
+}
+
+static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
+{
+       int result;
+
+       if (!mbi_pdev)
+               return -ENODEV;
+
+       result = pci_write_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr);
+       if (result < 0)
+               goto fail_write;
+
+       if (mcrx) {
+               result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET,
+                                               mcrx);
+               if (result < 0)
+                       goto fail_write;
+       }
+
+       result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr);
+       if (result < 0)
+               goto fail_write;
+
+       return 0;
+
+fail_write:
+       dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
+       return result;
+}
+
+int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
+{
+       u32 mcr, mcrx;
+       unsigned long flags;
+       int ret;
+
+       /*Access to the GFX unit is handled by GPU code */
+       if (port == BT_MBI_UNIT_GFX) {
+               WARN_ON(1);
+               return -EPERM;
+       }
+
+       mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
+       mcrx = offset & MBI_MASK_HI;
+
+       spin_lock_irqsave(&iosf_mbi_lock, flags);
+       ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr);
+       spin_unlock_irqrestore(&iosf_mbi_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(iosf_mbi_read);
+
+int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr)
+{
+       u32 mcr, mcrx;
+       unsigned long flags;
+       int ret;
+
+       /*Access to the GFX unit is handled by GPU code */
+       if (port == BT_MBI_UNIT_GFX) {
+               WARN_ON(1);
+               return -EPERM;
+       }
+
+       mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
+       mcrx = offset & MBI_MASK_HI;
+
+       spin_lock_irqsave(&iosf_mbi_lock, flags);
+       ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr);
+       spin_unlock_irqrestore(&iosf_mbi_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(iosf_mbi_write);
+
+int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
+{
+       u32 mcr, mcrx;
+       u32 value;
+       unsigned long flags;
+       int ret;
+
+       /*Access to the GFX unit is handled by GPU code */
+       if (port == BT_MBI_UNIT_GFX) {
+               WARN_ON(1);
+               return -EPERM;
+       }
+
+       mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
+       mcrx = offset & MBI_MASK_HI;
+
+       spin_lock_irqsave(&iosf_mbi_lock, flags);
+
+       /* Read current mdr value */
+       ret = iosf_mbi_pci_read_mdr(mcrx, mcr & MBI_RD_MASK, &value);
+       if (ret < 0) {
+               spin_unlock_irqrestore(&iosf_mbi_lock, flags);
+               return ret;
+       }
+
+       /* Apply mask */
+       value &= ~mask;
+       mdr &= mask;
+       value |= mdr;
+
+       /* Write back */
+       ret = iosf_mbi_pci_write_mdr(mcrx, mcr | MBI_WR_MASK, value);
+
+       spin_unlock_irqrestore(&iosf_mbi_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(iosf_mbi_modify);
+
+static int iosf_mbi_probe(struct pci_dev *pdev,
+                         const struct pci_device_id *unused)
+{
+       int ret;
+
+       ret = pci_enable_device(pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "error: could not enable device\n");
+               return ret;
+       }
+
+       mbi_pdev = pci_dev_get(pdev);
+       return 0;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) },
+       { 0, },
+};
+MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids);
+
+static struct pci_driver iosf_mbi_pci_driver = {
+       .name           = "iosf_mbi_pci",
+       .probe          = iosf_mbi_probe,
+       .id_table       = iosf_mbi_pci_ids,
+};
+
+static int __init iosf_mbi_init(void)
+{
+       return pci_register_driver(&iosf_mbi_pci_driver);
+}
+
+static void __exit iosf_mbi_exit(void)
+{
+       pci_unregister_driver(&iosf_mbi_pci_driver);
+       if (mbi_pdev) {
+               pci_dev_put(mbi_pdev);
+               mbi_pdev = NULL;
+       }
+}
+
+module_init(iosf_mbi_init);
+module_exit(iosf_mbi_exit);
+
+MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
+MODULE_DESCRIPTION("IOSF Mailbox Interface accessor");
+MODULE_LICENSE("GPL v2");
index 22d0687e7fda15163b04b771ac1a0e2170e1bf46..dbb60878b744d9678fac331ef446894e13410de3 100644 (file)
@@ -193,9 +193,13 @@ __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
        if (!handle_irq(irq, regs)) {
                ack_APIC_irq();
 
-               if (printk_ratelimit())
-                       pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
-                               __func__, smp_processor_id(), vector, irq);
+               if (irq != VECTOR_RETRIGGERED) {
+                       pr_emerg_ratelimited("%s: %d.%d No irq handler for vector (irq %d)\n",
+                                            __func__, smp_processor_id(),
+                                            vector, irq);
+               } else {
+                       __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
+               }
        }
 
        irq_exit();
@@ -262,6 +266,76 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs)
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
 
 #ifdef CONFIG_HOTPLUG_CPU
+/*
+ * 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.
+ * This function is protected by stop_machine().
+ */
+int check_irq_vectors_for_cpu_disable(void)
+{
+       int irq, cpu;
+       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);
+       cpu_clear(this_cpu, online_new);
+
+       this_count = 0;
+       for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+               irq = __this_cpu_read(vector_irq[vector]);
+               if (irq >= 0) {
+                       desc = irq_to_desc(irq);
+                       data = irq_desc_get_irq_data(desc);
+                       cpumask_copy(&affinity_new, data->affinity);
+                       cpu_clear(this_cpu, affinity_new);
+
+                       /* Do not count inactive or per-cpu irqs. */
+                       if (!irq_has_action(irq) || irqd_is_per_cpu(data))
+                               continue;
+
+                       /*
+                        * A single irq may be mapped to multiple
+                        * cpu's vector_irq[] (for example IOAPIC cluster
+                        * mode).  In this case we have two
+                        * possibilities:
+                        *
+                        * 1) the resulting affinity mask is empty; that is
+                        * this the down'd cpu is the last cpu in the irq's
+                        * affinity mask, or
+                        *
+                        * 2) the resulting affinity mask is no longer
+                        * a subset of the online cpus but the affinity
+                        * mask is not zero; that is the down'd cpu is the
+                        * last online cpu in a user set affinity mask.
+                        */
+                       if (cpumask_empty(&affinity_new) ||
+                           !cpumask_subset(&affinity_new, &online_new))
+                               this_count++;
+               }
+       }
+
+       count = 0;
+       for_each_online_cpu(cpu) {
+               if (cpu == this_cpu)
+                       continue;
+               for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
+                    vector++) {
+                       if (per_cpu(vector_irq, cpu)[vector] < 0)
+                               count++;
+               }
+       }
+
+       if (count < this_count) {
+               pr_warn("CPU %d disable failed: CPU has %u vectors assigned and there are only %u available.\n",
+                       this_cpu, this_count, count);
+               return -ERANGE;
+       }
+       return 0;
+}
+
 /* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
 void fixup_irqs(void)
 {
@@ -344,7 +418,7 @@ void fixup_irqs(void)
        for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
                unsigned int irr;
 
-               if (__this_cpu_read(vector_irq[vector]) < 0)
+               if (__this_cpu_read(vector_irq[vector]) <= VECTOR_UNDEFINED)
                        continue;
 
                irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
@@ -355,11 +429,14 @@ void fixup_irqs(void)
                        data = irq_desc_get_irq_data(desc);
                        chip = irq_data_get_irq_chip(data);
                        raw_spin_lock(&desc->lock);
-                       if (chip->irq_retrigger)
+                       if (chip->irq_retrigger) {
                                chip->irq_retrigger(data);
+                               __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED);
+                       }
                        raw_spin_unlock(&desc->lock);
                }
-               __this_cpu_write(vector_irq[vector], -1);
+               if (__this_cpu_read(vector_irq[vector]) != VECTOR_RETRIGGERED)
+                       __this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
        }
 }
 #endif
index a2a1fbc594ff906d0727e9f44e7db6f02c876570..7f50156542fbde0fed0eeeca9bbf0d18566a54c9 100644 (file)
@@ -52,7 +52,7 @@ static struct irqaction irq2 = {
 };
 
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-       [0 ... NR_VECTORS - 1] = -1,
+       [0 ... NR_VECTORS - 1] = VECTOR_UNDEFINED,
 };
 
 int vector_used_by_percpu_irq(unsigned int vector)
@@ -60,7 +60,7 @@ int vector_used_by_percpu_irq(unsigned int vector)
        int cpu;
 
        for_each_online_cpu(cpu) {
-               if (per_cpu(vector_irq, cpu)[vector] != -1)
+               if (per_cpu(vector_irq, cpu)[vector] > VECTOR_UNDEFINED)
                        return 1;
        }
 
index 836f8322960e4b78c3263c3a18ed70cb67b589a7..7ec1d5f8d28339bce0b74191a1d458c6c8e5d5df 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/kgdb.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <linux/hw_breakpoint.h>
diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c
new file mode 100644 (file)
index 0000000..c2bedae
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Architecture specific sysfs attributes in /sys/kernel
+ *
+ * Copyright (C) 2007, Intel Corp.
+ *      Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2013, 2013 Red Hat, Inc.
+ *      Dave Young <dyoung@redhat.com>
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/setup.h>
+
+static ssize_t version_show(struct kobject *kobj,
+                           struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "0x%04x\n", boot_params.hdr.version);
+}
+
+static struct kobj_attribute boot_params_version_attr = __ATTR_RO(version);
+
+static ssize_t boot_params_data_read(struct file *fp, struct kobject *kobj,
+                                    struct bin_attribute *bin_attr,
+                                    char *buf, loff_t off, size_t count)
+{
+       memcpy(buf, (void *)&boot_params + off, count);
+       return count;
+}
+
+static struct bin_attribute boot_params_data_attr = {
+       .attr = {
+               .name = "data",
+               .mode = S_IRUGO,
+       },
+       .read = boot_params_data_read,
+       .size = sizeof(boot_params),
+};
+
+static struct attribute *boot_params_version_attrs[] = {
+       &boot_params_version_attr.attr,
+       NULL,
+};
+
+static struct bin_attribute *boot_params_data_attrs[] = {
+       &boot_params_data_attr,
+       NULL,
+};
+
+static struct attribute_group boot_params_attr_group = {
+       .attrs = boot_params_version_attrs,
+       .bin_attrs = boot_params_data_attrs,
+};
+
+static int kobj_to_setup_data_nr(struct kobject *kobj, int *nr)
+{
+       const char *name;
+
+       name = kobject_name(kobj);
+       return kstrtoint(name, 10, nr);
+}
+
+static int get_setup_data_paddr(int nr, u64 *paddr)
+{
+       int i = 0;
+       struct setup_data *data;
+       u64 pa_data = boot_params.hdr.setup_data;
+
+       while (pa_data) {
+               if (nr == i) {
+                       *paddr = pa_data;
+                       return 0;
+               }
+               data = ioremap_cache(pa_data, sizeof(*data));
+               if (!data)
+                       return -ENOMEM;
+
+               pa_data = data->next;
+               iounmap(data);
+               i++;
+       }
+       return -EINVAL;
+}
+
+static int __init get_setup_data_size(int nr, size_t *size)
+{
+       int i = 0;
+       struct setup_data *data;
+       u64 pa_data = boot_params.hdr.setup_data;
+
+       while (pa_data) {
+               data = ioremap_cache(pa_data, sizeof(*data));
+               if (!data)
+                       return -ENOMEM;
+               if (nr == i) {
+                       *size = data->len;
+                       iounmap(data);
+                       return 0;
+               }
+
+               pa_data = data->next;
+               iounmap(data);
+               i++;
+       }
+       return -EINVAL;
+}
+
+static ssize_t type_show(struct kobject *kobj,
+                        struct kobj_attribute *attr, char *buf)
+{
+       int nr, ret;
+       u64 paddr;
+       struct setup_data *data;
+
+       ret = kobj_to_setup_data_nr(kobj, &nr);
+       if (ret)
+               return ret;
+
+       ret = get_setup_data_paddr(nr, &paddr);
+       if (ret)
+               return ret;
+       data = ioremap_cache(paddr, sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       ret = sprintf(buf, "0x%x\n", data->type);
+       iounmap(data);
+       return ret;
+}
+
+static ssize_t setup_data_data_read(struct file *fp,
+                                   struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buf,
+                                   loff_t off, size_t count)
+{
+       int nr, ret = 0;
+       u64 paddr;
+       struct setup_data *data;
+       void *p;
+
+       ret = kobj_to_setup_data_nr(kobj, &nr);
+       if (ret)
+               return ret;
+
+       ret = get_setup_data_paddr(nr, &paddr);
+       if (ret)
+               return ret;
+       data = ioremap_cache(paddr, sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       if (off > data->len) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (count > data->len - off)
+               count = data->len - off;
+
+       if (!count)
+               goto out;
+
+       ret = count;
+       p = ioremap_cache(paddr + sizeof(*data), data->len);
+       if (!p) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       memcpy(buf, p + off, count);
+       iounmap(p);
+out:
+       iounmap(data);
+       return ret;
+}
+
+static struct kobj_attribute type_attr = __ATTR_RO(type);
+
+static struct bin_attribute data_attr = {
+       .attr = {
+               .name = "data",
+               .mode = S_IRUGO,
+       },
+       .read = setup_data_data_read,
+};
+
+static struct attribute *setup_data_type_attrs[] = {
+       &type_attr.attr,
+       NULL,
+};
+
+static struct bin_attribute *setup_data_data_attrs[] = {
+       &data_attr,
+       NULL,
+};
+
+static struct attribute_group setup_data_attr_group = {
+       .attrs = setup_data_type_attrs,
+       .bin_attrs = setup_data_data_attrs,
+};
+
+static int __init create_setup_data_node(struct kobject *parent,
+                                        struct kobject **kobjp, int nr)
+{
+       int ret = 0;
+       size_t size;
+       struct kobject *kobj;
+       char name[16]; /* should be enough for setup_data nodes numbers */
+       snprintf(name, 16, "%d", nr);
+
+       kobj = kobject_create_and_add(name, parent);
+       if (!kobj)
+               return -ENOMEM;
+
+       ret = get_setup_data_size(nr, &size);
+       if (ret)
+               goto out_kobj;
+
+       data_attr.size = size;
+       ret = sysfs_create_group(kobj, &setup_data_attr_group);
+       if (ret)
+               goto out_kobj;
+       *kobjp = kobj;
+
+       return 0;
+out_kobj:
+       kobject_put(kobj);
+       return ret;
+}
+
+static void __init cleanup_setup_data_node(struct kobject *kobj)
+{
+       sysfs_remove_group(kobj, &setup_data_attr_group);
+       kobject_put(kobj);
+}
+
+static int __init get_setup_data_total_num(u64 pa_data, int *nr)
+{
+       int ret = 0;
+       struct setup_data *data;
+
+       *nr = 0;
+       while (pa_data) {
+               *nr += 1;
+               data = ioremap_cache(pa_data, sizeof(*data));
+               if (!data) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               pa_data = data->next;
+               iounmap(data);
+       }
+
+out:
+       return ret;
+}
+
+static int __init create_setup_data_nodes(struct kobject *parent)
+{
+       struct kobject *setup_data_kobj, **kobjp;
+       u64 pa_data;
+       int i, j, nr, ret = 0;
+
+       pa_data = boot_params.hdr.setup_data;
+       if (!pa_data)
+               return 0;
+
+       setup_data_kobj = kobject_create_and_add("setup_data", parent);
+       if (!setup_data_kobj) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = get_setup_data_total_num(pa_data, &nr);
+       if (ret)
+               goto out_setup_data_kobj;
+
+       kobjp = kmalloc(sizeof(*kobjp) * nr, GFP_KERNEL);
+       if (!kobjp) {
+               ret = -ENOMEM;
+               goto out_setup_data_kobj;
+       }
+
+       for (i = 0; i < nr; i++) {
+               ret = create_setup_data_node(setup_data_kobj, kobjp + i, i);
+               if (ret)
+                       goto out_clean_nodes;
+       }
+
+       kfree(kobjp);
+       return 0;
+
+out_clean_nodes:
+       for (j = i - 1; j > 0; j--)
+               cleanup_setup_data_node(*(kobjp + j));
+       kfree(kobjp);
+out_setup_data_kobj:
+       kobject_put(setup_data_kobj);
+out:
+       return ret;
+}
+
+static int __init boot_params_ksysfs_init(void)
+{
+       int ret;
+       struct kobject *boot_params_kobj;
+
+       boot_params_kobj = kobject_create_and_add("boot_params",
+                                                 kernel_kobj);
+       if (!boot_params_kobj) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = sysfs_create_group(boot_params_kobj, &boot_params_attr_group);
+       if (ret)
+               goto out_boot_params_kobj;
+
+       ret = create_setup_data_nodes(boot_params_kobj);
+       if (ret)
+               goto out_create_group;
+
+       return 0;
+out_create_group:
+       sysfs_remove_group(boot_params_kobj, &boot_params_attr_group);
+out_boot_params_kobj:
+       kobject_put(boot_params_kobj);
+out:
+       return ret;
+}
+
+arch_initcall(boot_params_ksysfs_init);
index 5b19e4d78b008537ece6591cbb11fb3bf5fc57bd..1667b1de8d5d62c1b10f4b702c7e9699902f8406 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/mm.h>
 #include <linux/kexec.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/numa.h>
 #include <linux/ftrace.h>
 #include <linux/suspend.h>
index 871be4a84c7d752c1a322ed990ff18093b192c0b..da15918d1c81ba5398104d59eed64016bd6dc98e 100644 (file)
@@ -3,7 +3,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/string.h>
-#include <linux/init.h>
 #include <linux/gfp.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
index 6f1236c29c4b575ec429dcc34d23629321ca5c0a..0de43e98ce08604afa886ceba8e17b7c66583e97 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
-#include <linux/init.h>
 #include <linux/mc146818rtc.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
index da3c599584a3307f024c76f80c94e721016765e3..c752cb43e52f192f431a5f2ab91b9366e42ef5b0 100644 (file)
@@ -558,6 +558,17 @@ void native_machine_shutdown(void)
 {
        /* Stop the cpus and apics */
 #ifdef CONFIG_X86_IO_APIC
+       /*
+        * Disabling IO APIC before local APIC is a workaround for
+        * erratum AVR31 in "Intel Atom Processor C2000 Product Family
+        * Specification Update". In this situation, interrupts that target
+        * a Logical Processor whose Local APIC is either in the process of
+        * being hardware disabled or software disabled are neither delivered
+        * nor discarded. When this erratum occurs, the processor may hang.
+        *
+        * Even without the erratum, it still makes sense to quiet IO APIC
+        * before disabling Local APIC.
+        */
        disable_IO_APIC();
 #endif
 
index cb233bc9dee35681ccf85a2385ece964ee96847d..06853e6703541f8349106e17330f86621fa984db 100644 (file)
@@ -295,6 +295,8 @@ static void __init reserve_brk(void)
        _brk_start = 0;
 }
 
+u64 relocated_ramdisk;
+
 #ifdef CONFIG_BLK_DEV_INITRD
 
 static u64 __init get_ramdisk_image(void)
@@ -321,25 +323,24 @@ static void __init relocate_initrd(void)
        u64 ramdisk_image = get_ramdisk_image();
        u64 ramdisk_size  = get_ramdisk_size();
        u64 area_size     = PAGE_ALIGN(ramdisk_size);
-       u64 ramdisk_here;
        unsigned long slop, clen, mapaddr;
        char *p, *q;
 
        /* We need to move the initrd down into directly mapped mem */
-       ramdisk_here = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
-                                                area_size, PAGE_SIZE);
+       relocated_ramdisk = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped),
+                                                  area_size, PAGE_SIZE);
 
-       if (!ramdisk_here)
+       if (!relocated_ramdisk)
                panic("Cannot find place for new RAMDISK of size %lld\n",
-                        ramdisk_size);
+                     ramdisk_size);
 
        /* Note: this includes all the mem currently occupied by
           the initrd, we rely on that fact to keep the data intact. */
-       memblock_reserve(ramdisk_here, area_size);
-       initrd_start = ramdisk_here + PAGE_OFFSET;
+       memblock_reserve(relocated_ramdisk, area_size);
+       initrd_start = relocated_ramdisk + PAGE_OFFSET;
        initrd_end   = initrd_start + ramdisk_size;
        printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
-                        ramdisk_here, ramdisk_here + ramdisk_size - 1);
+              relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
 
        q = (char *)initrd_start;
 
@@ -363,7 +364,7 @@ static void __init relocate_initrd(void)
        printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
                " [mem %#010llx-%#010llx]\n",
                ramdisk_image, ramdisk_image + ramdisk_size - 1,
-               ramdisk_here, ramdisk_here + ramdisk_size - 1);
+               relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
 }
 
 static void __init early_reserve_initrd(void)
@@ -447,6 +448,9 @@ static void __init parse_setup_data(void)
                case SETUP_DTB:
                        add_dtb(pa_data);
                        break;
+               case SETUP_EFI:
+                       parse_efi_setup(pa_data, data_len);
+                       break;
                default:
                        break;
                }
@@ -823,6 +827,20 @@ static void __init trim_low_memory_range(void)
        memblock_reserve(0, ALIGN(reserve_low, PAGE_SIZE));
 }
        
+/*
+ * Dump out kernel offset information on panic.
+ */
+static int
+dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
+{
+       pr_emerg("Kernel Offset: 0x%lx from 0x%lx "
+                "(relocation range: 0x%lx-0x%lx)\n",
+                (unsigned long)&_text - __START_KERNEL, __START_KERNEL,
+                __START_KERNEL_map, MODULES_VADDR-1);
+
+       return 0;
+}
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -924,8 +942,6 @@ void __init setup_arch(char **cmdline_p)
        iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
        setup_memory_map();
        parse_setup_data();
-       /* update the e820_saved too */
-       e820_reserve_setup_data();
 
        copy_edd();
 
@@ -987,6 +1003,8 @@ void __init setup_arch(char **cmdline_p)
                early_dump_pci_devices();
 #endif
 
+       /* update the e820_saved too */
+       e820_reserve_setup_data();
        finish_e820_parsing();
 
        if (efi_enabled(EFI_BOOT))
@@ -1248,3 +1266,15 @@ void __init i386_reserve_resources(void)
 }
 
 #endif /* CONFIG_X86_32 */
+
+static struct notifier_block kernel_offset_notifier = {
+       .notifier_call = dump_kernel_offset
+};
+
+static int __init register_kernel_offset_dumper(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list,
+                                       &kernel_offset_notifier);
+       return 0;
+}
+__initcall(register_kernel_offset_dumper);
index 85dc05a3aa02b3251b64ae0406b95716c714cb85..a32da804252e374b5d266e6788653f24fc98705d 100644 (file)
@@ -1312,6 +1312,12 @@ void cpu_disable_common(void)
 
 int native_cpu_disable(void)
 {
+       int ret;
+
+       ret = check_irq_vectors_for_cpu_disable();
+       if (ret)
+               return ret;
+
        clear_local_APIC();
 
        cpu_disable_common();
@@ -1417,7 +1423,9 @@ static inline void mwait_play_dead(void)
                 * The WBINVD is insufficient due to the spurious-wakeup
                 * case where we return around the loop.
                 */
+               mb();
                clflush(mwait_ptr);
+               mb();
                __monitor(mwait_ptr, 0, 0);
                mb();
                __mwait(eax, 0);
index b857ed890b4c6264879c056db461d614a3d7a430..57409f6b8c623e38c1a60dfa1029bb9d194c99e6 100644 (file)
@@ -211,21 +211,17 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code)       \
        exception_exit(prev_state);                                     \
 }
 
-DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
-               regs->ip)
-DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow)
-DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds)
-DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN,
-               regs->ip)
-DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun",
-               coprocessor_segment_overrun)
-DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS)
-DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present)
+DO_ERROR_INFO(X86_TRAP_DE,     SIGFPE,  "divide error",                        divide_error,                FPE_INTDIV, regs->ip )
+DO_ERROR     (X86_TRAP_OF,     SIGSEGV, "overflow",                    overflow                                          )
+DO_ERROR     (X86_TRAP_BR,     SIGSEGV, "bounds",                      bounds                                            )
+DO_ERROR_INFO(X86_TRAP_UD,     SIGILL,  "invalid opcode",              invalid_op,                  ILL_ILLOPN, regs->ip )
+DO_ERROR     (X86_TRAP_OLD_MF, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun                       )
+DO_ERROR     (X86_TRAP_TS,     SIGSEGV, "invalid TSS",                 invalid_TSS                                       )
+DO_ERROR     (X86_TRAP_NP,     SIGBUS,  "segment not present",         segment_not_present                               )
 #ifdef CONFIG_X86_32
-DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment)
+DO_ERROR     (X86_TRAP_SS,     SIGBUS,  "stack segment",               stack_segment                                     )
 #endif
-DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check,
-               BUS_ADRALN, 0)
+DO_ERROR_INFO(X86_TRAP_AC,     SIGBUS,  "alignment check",             alignment_check,             BUS_ADRALN, 0        )
 
 #ifdef CONFIG_X86_64
 /* Runs on IST stack */
index 930e5d48f560d017afd88f2af1bbf2d368dd1209..a3acbac2ee7254d0fc67741e6146d74f3b85d58c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/clocksource.h>
 #include <linux/percpu.h>
 #include <linux/timex.h>
+#include <linux/static_key.h>
 
 #include <asm/hpet.h>
 #include <asm/timer.h>
@@ -37,13 +38,244 @@ static int __read_mostly tsc_unstable;
    erroneous rdtsc usage on !cpu_has_tsc processors */
 static int __read_mostly tsc_disabled = -1;
 
+static struct static_key __use_tsc = STATIC_KEY_INIT;
+
 int tsc_clocksource_reliable;
+
+/*
+ * Use a ring-buffer like data structure, where a writer advances the head by
+ * writing a new data entry and a reader advances the tail when it observes a
+ * new entry.
+ *
+ * Writers are made to wait on readers until there's space to write a new
+ * entry.
+ *
+ * This means that we can always use an {offset, mul} pair to compute a ns
+ * value that is 'roughly' in the right direction, even if we're writing a new
+ * {offset, mul} pair during the clock read.
+ *
+ * The down-side is that we can no longer guarantee strict monotonicity anymore
+ * (assuming the TSC was that to begin with), because while we compute the
+ * intersection point of the two clock slopes and make sure the time is
+ * continuous at the point of switching; we can no longer guarantee a reader is
+ * strictly before or after the switch point.
+ *
+ * It does mean a reader no longer needs to disable IRQs in order to avoid
+ * CPU-Freq updates messing with his times, and similarly an NMI reader will
+ * no longer run the risk of hitting half-written state.
+ */
+
+struct cyc2ns {
+       struct cyc2ns_data data[2];     /*  0 + 2*24 = 48 */
+       struct cyc2ns_data *head;       /* 48 + 8    = 56 */
+       struct cyc2ns_data *tail;       /* 56 + 8    = 64 */
+}; /* exactly fits one cacheline */
+
+static DEFINE_PER_CPU_ALIGNED(struct cyc2ns, cyc2ns);
+
+struct cyc2ns_data *cyc2ns_read_begin(void)
+{
+       struct cyc2ns_data *head;
+
+       preempt_disable();
+
+       head = this_cpu_read(cyc2ns.head);
+       /*
+        * Ensure we observe the entry when we observe the pointer to it.
+        * matches the wmb from cyc2ns_write_end().
+        */
+       smp_read_barrier_depends();
+       head->__count++;
+       barrier();
+
+       return head;
+}
+
+void cyc2ns_read_end(struct cyc2ns_data *head)
+{
+       barrier();
+       /*
+        * If we're the outer most nested read; update the tail pointer
+        * when we're done. This notifies possible pending writers
+        * that we've observed the head pointer and that the other
+        * entry is now free.
+        */
+       if (!--head->__count) {
+               /*
+                * x86-TSO does not reorder writes with older reads;
+                * therefore once this write becomes visible to another
+                * cpu, we must be finished reading the cyc2ns_data.
+                *
+                * matches with cyc2ns_write_begin().
+                */
+               this_cpu_write(cyc2ns.tail, head);
+       }
+       preempt_enable();
+}
+
+/*
+ * Begin writing a new @data entry for @cpu.
+ *
+ * Assumes some sort of write side lock; currently 'provided' by the assumption
+ * that cpufreq will call its notifiers sequentially.
+ */
+static struct cyc2ns_data *cyc2ns_write_begin(int cpu)
+{
+       struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu);
+       struct cyc2ns_data *data = c2n->data;
+
+       if (data == c2n->head)
+               data++;
+
+       /* XXX send an IPI to @cpu in order to guarantee a read? */
+
+       /*
+        * When we observe the tail write from cyc2ns_read_end(),
+        * the cpu must be done with that entry and its safe
+        * to start writing to it.
+        */
+       while (c2n->tail == data)
+               cpu_relax();
+
+       return data;
+}
+
+static void cyc2ns_write_end(int cpu, struct cyc2ns_data *data)
+{
+       struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu);
+
+       /*
+        * Ensure the @data writes are visible before we publish the
+        * entry. Matches the data-depencency in cyc2ns_read_begin().
+        */
+       smp_wmb();
+
+       ACCESS_ONCE(c2n->head) = data;
+}
+
+/*
+ * Accelerators for sched_clock()
+ * convert from cycles(64bits) => nanoseconds (64bits)
+ *  basic equation:
+ *              ns = cycles / (freq / ns_per_sec)
+ *              ns = cycles * (ns_per_sec / freq)
+ *              ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *              ns = cycles * (10^6 / cpu_khz)
+ *
+ *      Then we use scaling math (suggested by george@mvista.com) to get:
+ *              ns = cycles * (10^6 * SC / cpu_khz) / SC
+ *              ns = cycles * cyc2ns_scale / SC
+ *
+ *      And since SC is a constant power of two, we can convert the div
+ *  into a shift.
+ *
+ *  We can use khz divisor instead of mhz to keep a better precision, since
+ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
+ *  (mathieu.desnoyers@polymtl.ca)
+ *
+ *                      -johnstul@us.ibm.com "math is hard, lets go shopping!"
+ */
+
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static void cyc2ns_data_init(struct cyc2ns_data *data)
+{
+       data->cyc2ns_mul = 1U << CYC2NS_SCALE_FACTOR;
+       data->cyc2ns_shift = CYC2NS_SCALE_FACTOR;
+       data->cyc2ns_offset = 0;
+       data->__count = 0;
+}
+
+static void cyc2ns_init(int cpu)
+{
+       struct cyc2ns *c2n = &per_cpu(cyc2ns, cpu);
+
+       cyc2ns_data_init(&c2n->data[0]);
+       cyc2ns_data_init(&c2n->data[1]);
+
+       c2n->head = c2n->data;
+       c2n->tail = c2n->data;
+}
+
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+       struct cyc2ns_data *data, *tail;
+       unsigned long long ns;
+
+       /*
+        * See cyc2ns_read_*() for details; replicated in order to avoid
+        * an extra few instructions that came with the abstraction.
+        * Notable, it allows us to only do the __count and tail update
+        * dance when its actually needed.
+        */
+
+       preempt_disable();
+       data = this_cpu_read(cyc2ns.head);
+       tail = this_cpu_read(cyc2ns.tail);
+
+       if (likely(data == tail)) {
+               ns = data->cyc2ns_offset;
+               ns += mul_u64_u32_shr(cyc, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR);
+       } else {
+               data->__count++;
+
+               barrier();
+
+               ns = data->cyc2ns_offset;
+               ns += mul_u64_u32_shr(cyc, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR);
+
+               barrier();
+
+               if (!--data->__count)
+                       this_cpu_write(cyc2ns.tail, data);
+       }
+       preempt_enable();
+
+       return ns;
+}
+
+/* XXX surely we already have this someplace in the kernel?! */
+#define DIV_ROUND(n, d) (((n) + ((d) / 2)) / (d))
+
+static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
+{
+       unsigned long long tsc_now, ns_now;
+       struct cyc2ns_data *data;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       sched_clock_idle_sleep_event();
+
+       if (!cpu_khz)
+               goto done;
+
+       data = cyc2ns_write_begin(cpu);
+
+       rdtscll(tsc_now);
+       ns_now = cycles_2_ns(tsc_now);
+
+       /*
+        * Compute a new multiplier as per the above comment and ensure our
+        * time function is continuous; see the comment near struct
+        * cyc2ns_data.
+        */
+       data->cyc2ns_mul = DIV_ROUND(NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR, cpu_khz);
+       data->cyc2ns_shift = CYC2NS_SCALE_FACTOR;
+       data->cyc2ns_offset = ns_now -
+               mul_u64_u32_shr(tsc_now, data->cyc2ns_mul, CYC2NS_SCALE_FACTOR);
+
+       cyc2ns_write_end(cpu, data);
+
+done:
+       sched_clock_idle_wakeup_event(0);
+       local_irq_restore(flags);
+}
 /*
  * Scheduler clock - returns current time in nanosec units.
  */
 u64 native_sched_clock(void)
 {
-       u64 this_offset;
+       u64 tsc_now;
 
        /*
         * Fall back to jiffies if there's no TSC available:
@@ -53,16 +285,16 @@ u64 native_sched_clock(void)
         *   very important for it to be as fast as the platform
         *   can achieve it. )
         */
-       if (unlikely(tsc_disabled)) {
+       if (!static_key_false(&__use_tsc)) {
                /* No locking but a rare wrong value is not a big deal: */
                return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
        }
 
        /* read the Time Stamp Counter: */
-       rdtscll(this_offset);
+       rdtscll(tsc_now);
 
        /* return the value in ns */
-       return __cycles_2_ns(this_offset);
+       return cycles_2_ns(tsc_now);
 }
 
 /* We need to define a real function for sched_clock, to override the
@@ -419,6 +651,16 @@ unsigned long native_calibrate_tsc(void)
        unsigned long flags, latch, ms, fast_calibrate;
        int hpet = is_hpet_enabled(), i, loopmin;
 
+       /* Calibrate TSC using MSR for Intel Atom SoCs */
+       local_irq_save(flags);
+       i = try_msr_calibrate_tsc(&fast_calibrate);
+       local_irq_restore(flags);
+       if (i >= 0) {
+               if (i == 0)
+                       pr_warn("Fast TSC calibration using MSR failed\n");
+               return fast_calibrate;
+       }
+
        local_irq_save(flags);
        fast_calibrate = quick_pit_calibrate();
        local_irq_restore(flags);
@@ -589,61 +831,11 @@ int recalibrate_cpu_khz(void)
 EXPORT_SYMBOL(recalibrate_cpu_khz);
 
 
-/* Accelerators for sched_clock()
- * convert from cycles(64bits) => nanoseconds (64bits)
- *  basic equation:
- *              ns = cycles / (freq / ns_per_sec)
- *              ns = cycles * (ns_per_sec / freq)
- *              ns = cycles * (10^9 / (cpu_khz * 10^3))
- *              ns = cycles * (10^6 / cpu_khz)
- *
- *      Then we use scaling math (suggested by george@mvista.com) to get:
- *              ns = cycles * (10^6 * SC / cpu_khz) / SC
- *              ns = cycles * cyc2ns_scale / SC
- *
- *      And since SC is a constant power of two, we can convert the div
- *  into a shift.
- *
- *  We can use khz divisor instead of mhz to keep a better precision, since
- *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
- *  (mathieu.desnoyers@polymtl.ca)
- *
- *                      -johnstul@us.ibm.com "math is hard, lets go shopping!"
- */
-
-DEFINE_PER_CPU(unsigned long, cyc2ns);
-DEFINE_PER_CPU(unsigned long long, cyc2ns_offset);
-
-static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
-{
-       unsigned long long tsc_now, ns_now, *offset;
-       unsigned long flags, *scale;
-
-       local_irq_save(flags);
-       sched_clock_idle_sleep_event();
-
-       scale = &per_cpu(cyc2ns, cpu);
-       offset = &per_cpu(cyc2ns_offset, cpu);
-
-       rdtscll(tsc_now);
-       ns_now = __cycles_2_ns(tsc_now);
-
-       if (cpu_khz) {
-               *scale = ((NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR) +
-                               cpu_khz / 2) / cpu_khz;
-               *offset = ns_now - mult_frac(tsc_now, *scale,
-                                            (1UL << CYC2NS_SCALE_FACTOR));
-       }
-
-       sched_clock_idle_wakeup_event(0);
-       local_irq_restore(flags);
-}
-
 static unsigned long long cyc2ns_suspend;
 
 void tsc_save_sched_clock_state(void)
 {
-       if (!sched_clock_stable)
+       if (!sched_clock_stable())
                return;
 
        cyc2ns_suspend = sched_clock();
@@ -663,16 +855,26 @@ void tsc_restore_sched_clock_state(void)
        unsigned long flags;
        int cpu;
 
-       if (!sched_clock_stable)
+       if (!sched_clock_stable())
                return;
 
        local_irq_save(flags);
 
-       __this_cpu_write(cyc2ns_offset, 0);
+       /*
+        * We're comming out of suspend, there's no concurrency yet; don't
+        * bother being nice about the RCU stuff, just write to both
+        * data fields.
+        */
+
+       this_cpu_write(cyc2ns.data[0].cyc2ns_offset, 0);
+       this_cpu_write(cyc2ns.data[1].cyc2ns_offset, 0);
+
        offset = cyc2ns_suspend - sched_clock();
 
-       for_each_possible_cpu(cpu)
-               per_cpu(cyc2ns_offset, cpu) = offset;
+       for_each_possible_cpu(cpu) {
+               per_cpu(cyc2ns.data[0].cyc2ns_offset, cpu) = offset;
+               per_cpu(cyc2ns.data[1].cyc2ns_offset, cpu) = offset;
+       }
 
        local_irq_restore(flags);
 }
@@ -795,7 +997,7 @@ void mark_tsc_unstable(char *reason)
 {
        if (!tsc_unstable) {
                tsc_unstable = 1;
-               sched_clock_stable = 0;
+               clear_sched_clock_stable();
                disable_sched_clock_irqtime();
                pr_info("Marking TSC unstable due to %s\n", reason);
                /* Change only the rating, when not registered */
@@ -995,14 +1197,18 @@ void __init tsc_init(void)
         * speed as the bootup CPU. (cpufreq notifiers will fix this
         * up if their speed diverges)
         */
-       for_each_possible_cpu(cpu)
+       for_each_possible_cpu(cpu) {
+               cyc2ns_init(cpu);
                set_cyc2ns_scale(cpu_khz, cpu);
+       }
 
        if (tsc_disabled > 0)
                return;
 
        /* now allow native_sched_clock() to use rdtsc */
+
        tsc_disabled = 0;
+       static_key_slow_inc(&__use_tsc);
 
        if (!no_sched_irq_time)
                enable_sched_clock_irqtime();
diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
new file mode 100644 (file)
index 0000000..8b5434f
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * tsc_msr.c - MSR based TSC calibration on Intel Atom SoC platforms.
+ *
+ * TSC in Intel Atom SoC runs at a constant rate which can be figured
+ * by this formula:
+ * <maximum core-clock to bus-clock ratio> * <maximum resolved frequency>
+ * See Intel 64 and IA-32 System Programming Guid section 16.12 and 30.11.5
+ * for details.
+ * Especially some Intel Atom SoCs don't have PIT(i8254) or HPET, so MSR
+ * based calibration is the only option.
+ *
+ *
+ * Copyright (C) 2013 Intel Corporation
+ * Author: Bin Gao <bin.gao@intel.com>
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/kernel.h>
+#include <asm/processor.h>
+#include <asm/setup.h>
+#include <asm/apic.h>
+#include <asm/param.h>
+
+/* CPU reference clock frequency: in KHz */
+#define FREQ_83                83200
+#define FREQ_100       99840
+#define FREQ_133       133200
+#define FREQ_166       166400
+
+#define MAX_NUM_FREQS  8
+
+/*
+ * According to Intel 64 and IA-32 System Programming Guide,
+ * if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be
+ * read in MSR_PLATFORM_ID[12:8], otherwise in MSR_PERF_STAT[44:40].
+ * Unfortunately some Intel Atom SoCs aren't quite compliant to this,
+ * so we need manually differentiate SoC families. This is what the
+ * field msr_plat does.
+ */
+struct freq_desc {
+       u8 x86_family;  /* CPU family */
+       u8 x86_model;   /* model */
+       u8 msr_plat;    /* 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */
+       u32 freqs[MAX_NUM_FREQS];
+};
+
+static struct freq_desc freq_desc_tables[] = {
+       /* PNW */
+       { 6, 0x27, 0, { 0, 0, 0, 0, 0, FREQ_100, 0, FREQ_83 } },
+       /* CLV+ */
+       { 6, 0x35, 0, { 0, FREQ_133, 0, 0, 0, FREQ_100, 0, FREQ_83 } },
+       /* 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 } },
+       /* ANN */
+       { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } },
+};
+
+static int match_cpu(u8 family, u8 model)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(freq_desc_tables); i++) {
+               if ((family == freq_desc_tables[i].x86_family) &&
+                       (model == freq_desc_tables[i].x86_model))
+                       return i;
+       }
+
+       return -1;
+}
+
+/* Map CPU reference clock freq ID(0-7) to CPU reference clock freq(KHz) */
+#define id_to_freq(cpu_index, freq_id) \
+       (freq_desc_tables[cpu_index].freqs[freq_id])
+
+/*
+ * 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
+ */
+int try_msr_calibrate_tsc(unsigned long *fast_calibrate)
+{
+       int cpu_index;
+       u32 lo, hi, ratio, freq_id, freq;
+
+       cpu_index = match_cpu(boot_cpu_data.x86, boot_cpu_data.x86_model);
+       if (cpu_index < 0)
+               return -1;
+
+       *fast_calibrate = 0;
+
+       if (freq_desc_tables[cpu_index].msr_plat) {
+               rdmsr(MSR_PLATFORM_INFO, lo, hi);
+               ratio = (lo >> 8) & 0x1f;
+       } else {
+               rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+               ratio = (hi >> 8) & 0x1f;
+       }
+       pr_info("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
+
+       if (!ratio)
+               return 0;
+
+       /* Get FSB FREQ ID */
+       rdmsr(MSR_FSB_FREQ, lo, hi);
+       freq_id = lo & 0x7;
+       freq = id_to_freq(cpu_index, freq_id);
+       pr_info("Resolved frequency ID: %u, frequency: %u KHz\n",
+                               freq_id, freq);
+       if (!freq)
+               return 0;
+
+       /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
+       *fast_calibrate = freq * ratio;
+       pr_info("TSC runs at %lu KHz\n", *fast_calibrate);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+       lapic_timer_frequency = (freq * 1000) / HZ;
+       pr_info("lapic_timer_frequency = %d\n", lapic_timer_frequency);
+#endif
+
+       return 1;
+}
index adfdf56a3714ec3386dc61812cd5af56a88e8d40..26488487bc61e8fb5fcc76cf4ec245cb8ff1ebd7 100644 (file)
@@ -16,7 +16,6 @@
  */
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <asm/tsc.h>
index 5439117d5c4cccfa00d28dd64fb5aa8fd488261e..775702f649ca686ff7a1dcf467c5325b8a3e9c3c 100644 (file)
@@ -143,6 +143,8 @@ static inline int kvm_apic_id(struct kvm_lapic *apic)
        return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
 }
 
+#define KVM_X2APIC_CID_BITS 0
+
 static void recalculate_apic_map(struct kvm *kvm)
 {
        struct kvm_apic_map *new, *old = NULL;
@@ -180,7 +182,8 @@ static void recalculate_apic_map(struct kvm *kvm)
                if (apic_x2apic_mode(apic)) {
                        new->ldr_bits = 32;
                        new->cid_shift = 16;
-                       new->cid_mask = new->lid_mask = 0xffff;
+                       new->cid_mask = (1 << KVM_X2APIC_CID_BITS) - 1;
+                       new->lid_mask = 0xffff;
                } else if (kvm_apic_sw_enabled(apic) &&
                                !new->cid_mask /* flat mode */ &&
                                kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {
@@ -841,7 +844,8 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
        ASSERT(apic != NULL);
 
        /* if initial count is 0, current count should also be 0 */
-       if (kvm_apic_get_reg(apic, APIC_TMICT) == 0)
+       if (kvm_apic_get_reg(apic, APIC_TMICT) == 0 ||
+               apic->lapic_timer.period == 0)
                return 0;
 
        remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
@@ -1346,8 +1350,12 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                return;
        }
 
+       if (!kvm_vcpu_is_bsp(apic->vcpu))
+               value &= ~MSR_IA32_APICBASE_BSP;
+       vcpu->arch.apic_base = value;
+
        /* update jump label if enable bit changes */
-       if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
+       if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
                if (value & MSR_IA32_APICBASE_ENABLE)
                        static_key_slow_dec_deferred(&apic_hw_disabled);
                else
@@ -1355,10 +1363,6 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                recalculate_apic_map(vcpu->kvm);
        }
 
-       if (!kvm_vcpu_is_bsp(apic->vcpu))
-               value &= ~MSR_IA32_APICBASE_BSP;
-
-       vcpu->arch.apic_base = value;
        if ((old_value ^ value) & X2APIC_ENABLE) {
                if (value & X2APIC_ENABLE) {
                        u32 id = kvm_apic_id(apic);
@@ -1691,7 +1695,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
 {
        u32 data;
-       void *vapic;
 
        if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention))
                apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic);
@@ -1699,9 +1702,8 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
        if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
                return;
 
-       vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
-       data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
-       kunmap_atomic(vapic);
+       kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+                               sizeof(u32));
 
        apic_set_tpr(vcpu->arch.apic, data & 0xff);
 }
@@ -1737,7 +1739,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
        u32 data, tpr;
        int max_irr, max_isr;
        struct kvm_lapic *apic = vcpu->arch.apic;
-       void *vapic;
 
        apic_sync_pv_eoi_to_guest(vcpu, apic);
 
@@ -1753,18 +1754,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
                max_isr = 0;
        data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
 
-       vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
-       *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
-       kunmap_atomic(vapic);
+       kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+                               sizeof(u32));
 }
 
-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
 {
-       vcpu->arch.apic->vapic_addr = vapic_addr;
-       if (vapic_addr)
+       if (vapic_addr) {
+               if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+                                       &vcpu->arch.apic->vapic_cache,
+                                       vapic_addr, sizeof(u32)))
+                       return -EINVAL;
                __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
-       else
+       } else {
                __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
+       }
+
+       vcpu->arch.apic->vapic_addr = vapic_addr;
+       return 0;
 }
 
 int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
index c730ac9fe80188d15957bf9b556918036db892ab..c8b0d0d2da5ce2d67f9342fba000e60e1aec84eb 100644 (file)
@@ -34,7 +34,7 @@ struct kvm_lapic {
         */
        void *regs;
        gpa_t vapic_addr;
-       struct page *vapic_page;
+       struct gfn_to_hva_cache vapic_cache;
        unsigned long pending_events;
        unsigned int sipi_vector;
 };
@@ -76,7 +76,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
 void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset);
 void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector);
 
-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
 void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
 void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
 
index b2fe1c252f35f92e3b6707406998738a9275c8d2..da7837e1349da8ac4ac06468fb2f05e798e136f1 100644 (file)
@@ -8283,8 +8283,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
        vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
        kvm_set_cr4(vcpu, vmcs12->host_cr4);
 
-       if (nested_cpu_has_ept(vmcs12))
-               nested_ept_uninit_mmu_context(vcpu);
+       nested_ept_uninit_mmu_context(vcpu);
 
        kvm_set_cr3(vcpu, vmcs12->host_cr3);
        kvm_mmu_reset_context(vcpu);
index 21ef1ba184ae8500a70061f566ea55fde76cbfd2..5d004da1e35da9bdad0260f5d6b0f287330b194c 100644 (file)
@@ -3214,8 +3214,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = -EFAULT;
                if (copy_from_user(&va, argp, sizeof va))
                        goto out;
-               r = 0;
-               kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
+               r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
                break;
        }
        case KVM_X86_SETUP_MCE: {
@@ -5739,36 +5738,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
                        !kvm_event_needs_reinjection(vcpu);
 }
 
-static int vapic_enter(struct kvm_vcpu *vcpu)
-{
-       struct kvm_lapic *apic = vcpu->arch.apic;
-       struct page *page;
-
-       if (!apic || !apic->vapic_addr)
-               return 0;
-
-       page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-       if (is_error_page(page))
-               return -EFAULT;
-
-       vcpu->arch.apic->vapic_page = page;
-       return 0;
-}
-
-static void vapic_exit(struct kvm_vcpu *vcpu)
-{
-       struct kvm_lapic *apic = vcpu->arch.apic;
-       int idx;
-
-       if (!apic || !apic->vapic_addr)
-               return;
-
-       idx = srcu_read_lock(&vcpu->kvm->srcu);
-       kvm_release_page_dirty(apic->vapic_page);
-       mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-       srcu_read_unlock(&vcpu->kvm->srcu, idx);
-}
-
 static void update_cr8_intercept(struct kvm_vcpu *vcpu)
 {
        int max_irr, tpr;
@@ -6069,11 +6038,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
        struct kvm *kvm = vcpu->kvm;
 
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-       r = vapic_enter(vcpu);
-       if (r) {
-               srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
-               return r;
-       }
 
        r = 1;
        while (r > 0) {
@@ -6132,8 +6096,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 
        srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 
-       vapic_exit(vcpu);
-
        return r;
 }
 
index a30ca15be21c8a182b3bb937ac612d1863a046ee..dee945d555941a078f40049b24b8b4731aba6f2c 100644 (file)
@@ -186,7 +186,7 @@ ENTRY(copy_user_generic_unrolled)
 30:    shll $6,%ecx
        addl %ecx,%edx
        jmp 60f
-40:    lea (%rdx,%rcx,8),%rdx
+40:    leal (%rdx,%rcx,8),%edx
        jmp 60f
 50:    movl %ecx,%edx
 60:    jmp copy_user_handle_tail /* ecx is zerorest also */
@@ -236,8 +236,6 @@ ENDPROC(copy_user_generic_unrolled)
 ENTRY(copy_user_generic_string)
        CFI_STARTPROC
        ASM_STAC
-       andl %edx,%edx
-       jz 4f
        cmpl $8,%edx
        jb 2f           /* less than 8 bytes, go to byte copy loop */
        ALIGN_DESTINATION
@@ -249,12 +247,12 @@ ENTRY(copy_user_generic_string)
 2:     movl %edx,%ecx
 3:     rep
        movsb
-4:     xorl %eax,%eax
+       xorl %eax,%eax
        ASM_CLAC
        ret
 
        .section .fixup,"ax"
-11:    lea (%rdx,%rcx,8),%rcx
+11:    leal (%rdx,%rcx,8),%ecx
 12:    movl %ecx,%edx          /* ecx is zerorest also */
        jmp copy_user_handle_tail
        .previous
@@ -279,12 +277,10 @@ ENDPROC(copy_user_generic_string)
 ENTRY(copy_user_enhanced_fast_string)
        CFI_STARTPROC
        ASM_STAC
-       andl %edx,%edx
-       jz 2f
        movl %edx,%ecx
 1:     rep
        movsb
-2:     xorl %eax,%eax
+       xorl %eax,%eax
        ASM_CLAC
        ret
 
index 7c3bee636e2fc31bd4021d308da7e5af2bc65519..39d6a3db0b964a081d8cda51c76083ec8c682f10 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/timex.h>
 #include <linux/preempt.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/delay.h>
index 9ff85bb8dd698182fa6605ee565a00f7843e6303..9d591c895803101e2decbc85a0ce9f23a0b4eaeb 100644 (file)
@@ -641,6 +641,20 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
        /* Are we prepared to handle this kernel fault? */
        if (fixup_exception(regs)) {
+               /*
+                * Any interrupt that takes a fault gets the fixup. This makes
+                * the below recursive fault logic only apply to a faults from
+                * task context.
+                */
+               if (in_interrupt())
+                       return;
+
+               /*
+                * Per the above we're !in_interrupt(), aka. task context.
+                *
+                * In this case we need to make sure we're not recursively
+                * faulting through the emulate_vsyscall() logic.
+                */
                if (current_thread_info()->sig_on_uaccess_error && signal) {
                        tsk->thread.trap_nr = X86_TRAP_PF;
                        tsk->thread.error_code = error_code | PF_USER;
@@ -649,6 +663,10 @@ no_context(struct pt_regs *regs, unsigned long error_code,
                        /* XXX: hwpoison faults will set the wrong code. */
                        force_sig_info_fault(signal, si_code, address, tsk, 0);
                }
+
+               /*
+                * Barring that, we can do the fixup and be happy.
+                */
                return;
        }
 
index dd74e46828c0fc243740b61a18c2dea654fafb5e..0596e8e0cc1992b1fc32a00277a4f879cd07a8f3 100644 (file)
@@ -83,6 +83,12 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                pte_t pte = gup_get_pte(ptep);
                struct page *page;
 
+               /* Similar to the PMD case, NUMA hinting must take slow path */
+               if (pte_numa(pte)) {
+                       pte_unmap(ptep);
+                       return 0;
+               }
+
                if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
                        pte_unmap(ptep);
                        return 0;
@@ -167,6 +173,13 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
                if (unlikely(pmd_large(pmd))) {
+                       /*
+                        * NUMA hinting faults need to be handled in the GUP
+                        * slowpath for accounting purposes and so that they
+                        * can be serialised against THP migration.
+                        */
+                       if (pmd_numa(pmd))
+                               return 0;
                        if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
                                return 0;
                } else {
index 9d980d88b7477a82f757e75d0efda0c867c76d43..8c9f647ff9e111203af86f894a13b450e4513013 100644 (file)
@@ -87,9 +87,7 @@ int pmd_huge_support(void)
 }
 #endif
 
-/* x86_64 also uses this file */
-
-#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#ifdef CONFIG_HUGETLB_PAGE
 static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
                unsigned long addr, unsigned long len,
                unsigned long pgoff, unsigned long flags)
@@ -99,7 +97,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
 
        info.flags = 0;
        info.length = len;
-       info.low_limit = TASK_UNMAPPED_BASE;
+       info.low_limit = current->mm->mmap_legacy_base;
        info.high_limit = TASK_SIZE;
        info.align_mask = PAGE_MASK & ~huge_page_mask(h);
        info.align_offset = 0;
@@ -172,8 +170,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                return hugetlb_get_unmapped_area_topdown(file, addr, len,
                                pgoff, flags);
 }
-
-#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/
+#endif /* CONFIG_HUGETLB_PAGE */
 
 #ifdef CONFIG_X86_64
 static __init int setup_hugepagesz(char *opt)
index 4287f1ffba7ef2e42cc68839a38c3ecc0d6b1304..5bdc5430597cfea9056e08edb7902a098f28535c 100644 (file)
@@ -806,6 +806,9 @@ void __init mem_init(void)
        BUILD_BUG_ON(VMALLOC_START                      >= VMALLOC_END);
 #undef high_memory
 #undef __FIXADDR_TOP
+#ifdef CONFIG_RANDOMIZE_BASE
+       BUILD_BUG_ON(CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE);
+#endif
 
 #ifdef CONFIG_HIGHMEM
        BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE        > FIXADDR_START);
index e5d5e2ce9f7734036b7b411b5b357ff84788fa52..637ab34ed63284d1045f6031104aac7665be6427 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/rculist.h>
 #include <linux/spinlock.h>
 #include <linux/hash.h>
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/uaccess.h>
index 24aec58d6afdf4ec75390f15413ed26cb47653e8..c85da7bb6b603cf2cab624835ea2d6459958ce5b 100644 (file)
@@ -211,9 +211,13 @@ static void __init setup_node_data(int nid, u64 start, u64 end)
         */
        nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid);
        if (!nd_pa) {
-               pr_err("Cannot find %zu bytes in node %d\n",
-                      nd_size, nid);
-               return;
+               nd_pa = __memblock_alloc_base(nd_size, SMP_CACHE_BYTES,
+                                             MEMBLOCK_ALLOC_ACCESSIBLE);
+               if (!nd_pa) {
+                       pr_err("Cannot find %zu bytes in node %d\n",
+                              nd_size, nid);
+                       return;
+               }
        }
        nd = __va(nd_pa);
 
index d0b1773d9d2efb1b24ff9ed0da0d2bbea999fc7e..461bc82890240031a5c7466013fe4c3335a28a1a 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/kthread.h>
 #include <linux/random.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
index bb32480c2d713d57a52747f2f6e119a70286dc07..b3b19f46c0164c7169c9259a68836afbaeae1943 100644 (file)
@@ -30,6 +30,7 @@
  */
 struct cpa_data {
        unsigned long   *vaddr;
+       pgd_t           *pgd;
        pgprot_t        mask_set;
        pgprot_t        mask_clr;
        int             numpages;
@@ -322,17 +323,9 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
        return prot;
 }
 
-/*
- * Lookup the page table entry for a virtual address. Return a pointer
- * to the entry and the level of the mapping.
- *
- * Note: We return pud and pmd either when the entry is marked large
- * or when the present bit is not set. Otherwise we would return a
- * pointer to a nonexisting mapping.
- */
-pte_t *lookup_address(unsigned long address, unsigned int *level)
+static pte_t *__lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+                                     unsigned int *level)
 {
-       pgd_t *pgd = pgd_offset_k(address);
        pud_t *pud;
        pmd_t *pmd;
 
@@ -361,8 +354,31 @@ pte_t *lookup_address(unsigned long address, unsigned int *level)
 
        return pte_offset_kernel(pmd, address);
 }
+
+/*
+ * Lookup the page table entry for a virtual address. Return a pointer
+ * to the entry and the level of the mapping.
+ *
+ * Note: We return pud and pmd either when the entry is marked large
+ * or when the present bit is not set. Otherwise we would return a
+ * pointer to a nonexisting mapping.
+ */
+pte_t *lookup_address(unsigned long address, unsigned int *level)
+{
+        return __lookup_address_in_pgd(pgd_offset_k(address), address, level);
+}
 EXPORT_SYMBOL_GPL(lookup_address);
 
+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),
+                                              address, level);
+
+        return lookup_address(address, level);
+}
+
 /*
  * This is necessary because __pa() does not work on some
  * kinds of memory, like vmalloc() or the alloc_remap()
@@ -437,7 +453,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
         * Check for races, another CPU might have split this page
         * up already:
         */
-       tmp = lookup_address(address, &level);
+       tmp = _lookup_address_cpa(cpa, address, &level);
        if (tmp != kpte)
                goto out_unlock;
 
@@ -543,7 +559,8 @@ out_unlock:
 }
 
 static int
-__split_large_page(pte_t *kpte, unsigned long address, struct page *base)
+__split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
+                  struct page *base)
 {
        pte_t *pbase = (pte_t *)page_address(base);
        unsigned long pfn, pfninc = 1;
@@ -556,7 +573,7 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base)
         * Check for races, another CPU might have split this page
         * up for us already:
         */
-       tmp = lookup_address(address, &level);
+       tmp = _lookup_address_cpa(cpa, address, &level);
        if (tmp != kpte) {
                spin_unlock(&pgd_lock);
                return 1;
@@ -632,7 +649,8 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base)
        return 0;
 }
 
-static int split_large_page(pte_t *kpte, unsigned long address)
+static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
+                           unsigned long address)
 {
        struct page *base;
 
@@ -644,15 +662,390 @@ static int split_large_page(pte_t *kpte, unsigned long address)
        if (!base)
                return -ENOMEM;
 
-       if (__split_large_page(kpte, address, base))
+       if (__split_large_page(cpa, kpte, address, base))
                __free_page(base);
 
        return 0;
 }
 
+static bool try_to_free_pte_page(pte_t *pte)
+{
+       int i;
+
+       for (i = 0; i < PTRS_PER_PTE; i++)
+               if (!pte_none(pte[i]))
+                       return false;
+
+       free_page((unsigned long)pte);
+       return true;
+}
+
+static bool try_to_free_pmd_page(pmd_t *pmd)
+{
+       int i;
+
+       for (i = 0; i < PTRS_PER_PMD; i++)
+               if (!pmd_none(pmd[i]))
+                       return false;
+
+       free_page((unsigned long)pmd);
+       return true;
+}
+
+static bool unmap_pte_range(pmd_t *pmd, unsigned long start, unsigned long end)
+{
+       pte_t *pte = pte_offset_kernel(pmd, start);
+
+       while (start < end) {
+               set_pte(pte, __pte(0));
+
+               start += PAGE_SIZE;
+               pte++;
+       }
+
+       if (try_to_free_pte_page((pte_t *)pmd_page_vaddr(*pmd))) {
+               pmd_clear(pmd);
+               return true;
+       }
+       return false;
+}
+
+static void __unmap_pmd_range(pud_t *pud, pmd_t *pmd,
+                             unsigned long start, unsigned long end)
+{
+       if (unmap_pte_range(pmd, start, end))
+               if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud)))
+                       pud_clear(pud);
+}
+
+static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end)
+{
+       pmd_t *pmd = pmd_offset(pud, start);
+
+       /*
+        * Not on a 2MB page boundary?
+        */
+       if (start & (PMD_SIZE - 1)) {
+               unsigned long next_page = (start + PMD_SIZE) & PMD_MASK;
+               unsigned long pre_end = min_t(unsigned long, end, next_page);
+
+               __unmap_pmd_range(pud, pmd, start, pre_end);
+
+               start = pre_end;
+               pmd++;
+       }
+
+       /*
+        * Try to unmap in 2M chunks.
+        */
+       while (end - start >= PMD_SIZE) {
+               if (pmd_large(*pmd))
+                       pmd_clear(pmd);
+               else
+                       __unmap_pmd_range(pud, pmd, start, start + PMD_SIZE);
+
+               start += PMD_SIZE;
+               pmd++;
+       }
+
+       /*
+        * 4K leftovers?
+        */
+       if (start < end)
+               return __unmap_pmd_range(pud, pmd, start, end);
+
+       /*
+        * Try again to free the PMD page if haven't succeeded above.
+        */
+       if (!pud_none(*pud))
+               if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud)))
+                       pud_clear(pud);
+}
+
+static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end)
+{
+       pud_t *pud = pud_offset(pgd, start);
+
+       /*
+        * Not on a GB page boundary?
+        */
+       if (start & (PUD_SIZE - 1)) {
+               unsigned long next_page = (start + PUD_SIZE) & PUD_MASK;
+               unsigned long pre_end   = min_t(unsigned long, end, next_page);
+
+               unmap_pmd_range(pud, start, pre_end);
+
+               start = pre_end;
+               pud++;
+       }
+
+       /*
+        * Try to unmap in 1G chunks?
+        */
+       while (end - start >= PUD_SIZE) {
+
+               if (pud_large(*pud))
+                       pud_clear(pud);
+               else
+                       unmap_pmd_range(pud, start, start + PUD_SIZE);
+
+               start += PUD_SIZE;
+               pud++;
+       }
+
+       /*
+        * 2M leftovers?
+        */
+       if (start < end)
+               unmap_pmd_range(pud, start, end);
+
+       /*
+        * No need to try to free the PUD page because we'll free it in
+        * populate_pgd's error path
+        */
+}
+
+static int alloc_pte_page(pmd_t *pmd)
+{
+       pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+       if (!pte)
+               return -1;
+
+       set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
+       return 0;
+}
+
+static int alloc_pmd_page(pud_t *pud)
+{
+       pmd_t *pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+       if (!pmd)
+               return -1;
+
+       set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+       return 0;
+}
+
+static void populate_pte(struct cpa_data *cpa,
+                        unsigned long start, unsigned long end,
+                        unsigned num_pages, pmd_t *pmd, pgprot_t pgprot)
+{
+       pte_t *pte;
+
+       pte = pte_offset_kernel(pmd, start);
+
+       while (num_pages-- && start < end) {
+
+               /* deal with the NX bit */
+               if (!(pgprot_val(pgprot) & _PAGE_NX))
+                       cpa->pfn &= ~_PAGE_NX;
+
+               set_pte(pte, pfn_pte(cpa->pfn >> PAGE_SHIFT, pgprot));
+
+               start    += PAGE_SIZE;
+               cpa->pfn += PAGE_SIZE;
+               pte++;
+       }
+}
+
+static int populate_pmd(struct cpa_data *cpa,
+                       unsigned long start, unsigned long end,
+                       unsigned num_pages, pud_t *pud, pgprot_t pgprot)
+{
+       unsigned int cur_pages = 0;
+       pmd_t *pmd;
+
+       /*
+        * Not on a 2M boundary?
+        */
+       if (start & (PMD_SIZE - 1)) {
+               unsigned long pre_end = start + (num_pages << PAGE_SHIFT);
+               unsigned long next_page = (start + PMD_SIZE) & PMD_MASK;
+
+               pre_end   = min_t(unsigned long, pre_end, next_page);
+               cur_pages = (pre_end - start) >> PAGE_SHIFT;
+               cur_pages = min_t(unsigned int, num_pages, cur_pages);
+
+               /*
+                * Need a PTE page?
+                */
+               pmd = pmd_offset(pud, start);
+               if (pmd_none(*pmd))
+                       if (alloc_pte_page(pmd))
+                               return -1;
+
+               populate_pte(cpa, start, pre_end, cur_pages, pmd, pgprot);
+
+               start = pre_end;
+       }
+
+       /*
+        * We mapped them all?
+        */
+       if (num_pages == cur_pages)
+               return cur_pages;
+
+       while (end - start >= PMD_SIZE) {
+
+               /*
+                * We cannot use a 1G page so allocate a PMD page if needed.
+                */
+               if (pud_none(*pud))
+                       if (alloc_pmd_page(pud))
+                               return -1;
+
+               pmd = pmd_offset(pud, start);
+
+               set_pmd(pmd, __pmd(cpa->pfn | _PAGE_PSE | massage_pgprot(pgprot)));
+
+               start     += PMD_SIZE;
+               cpa->pfn  += PMD_SIZE;
+               cur_pages += PMD_SIZE >> PAGE_SHIFT;
+       }
+
+       /*
+        * Map trailing 4K pages.
+        */
+       if (start < end) {
+               pmd = pmd_offset(pud, start);
+               if (pmd_none(*pmd))
+                       if (alloc_pte_page(pmd))
+                               return -1;
+
+               populate_pte(cpa, start, end, num_pages - cur_pages,
+                            pmd, pgprot);
+       }
+       return num_pages;
+}
+
+static int populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
+                       pgprot_t pgprot)
+{
+       pud_t *pud;
+       unsigned long end;
+       int cur_pages = 0;
+
+       end = start + (cpa->numpages << PAGE_SHIFT);
+
+       /*
+        * Not on a Gb page boundary? => map everything up to it with
+        * smaller pages.
+        */
+       if (start & (PUD_SIZE - 1)) {
+               unsigned long pre_end;
+               unsigned long next_page = (start + PUD_SIZE) & PUD_MASK;
+
+               pre_end   = min_t(unsigned long, end, next_page);
+               cur_pages = (pre_end - start) >> PAGE_SHIFT;
+               cur_pages = min_t(int, (int)cpa->numpages, cur_pages);
+
+               pud = pud_offset(pgd, start);
+
+               /*
+                * Need a PMD page?
+                */
+               if (pud_none(*pud))
+                       if (alloc_pmd_page(pud))
+                               return -1;
+
+               cur_pages = populate_pmd(cpa, start, pre_end, cur_pages,
+                                        pud, pgprot);
+               if (cur_pages < 0)
+                       return cur_pages;
+
+               start = pre_end;
+       }
+
+       /* We mapped them all? */
+       if (cpa->numpages == cur_pages)
+               return cur_pages;
+
+       pud = pud_offset(pgd, start);
+
+       /*
+        * Map everything starting from the Gb boundary, possibly with 1G pages
+        */
+       while (end - start >= PUD_SIZE) {
+               set_pud(pud, __pud(cpa->pfn | _PAGE_PSE | massage_pgprot(pgprot)));
+
+               start     += PUD_SIZE;
+               cpa->pfn  += PUD_SIZE;
+               cur_pages += PUD_SIZE >> PAGE_SHIFT;
+               pud++;
+       }
+
+       /* Map trailing leftover */
+       if (start < end) {
+               int tmp;
+
+               pud = pud_offset(pgd, start);
+               if (pud_none(*pud))
+                       if (alloc_pmd_page(pud))
+                               return -1;
+
+               tmp = populate_pmd(cpa, start, end, cpa->numpages - cur_pages,
+                                  pud, pgprot);
+               if (tmp < 0)
+                       return cur_pages;
+
+               cur_pages += tmp;
+       }
+       return cur_pages;
+}
+
+/*
+ * Restrictions for kernel page table do not necessarily apply when mapping in
+ * an alternate 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 */
+       int ret;
+
+       pgd_entry = cpa->pgd + pgd_index(addr);
+
+       /*
+        * Allocate a PUD page and hand it down for mapping.
+        */
+       if (pgd_none(*pgd_entry)) {
+               pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+               if (!pud)
+                       return -1;
+
+               set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
+               allocd_pgd = true;
+       }
+
+       pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
+       pgprot_val(pgprot) |=  pgprot_val(cpa->mask_set);
+
+       ret = populate_pud(cpa, addr, pgd_entry, pgprot);
+       if (ret < 0) {
+               unmap_pud_range(pgd_entry, 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;
+}
+
 static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
                               int primary)
 {
+       if (cpa->pgd)
+               return populate_pgd(cpa, vaddr);
+
        /*
         * Ignore all non primary paths.
         */
@@ -697,7 +1090,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
        else
                address = *cpa->vaddr;
 repeat:
-       kpte = lookup_address(address, &level);
+       kpte = _lookup_address_cpa(cpa, address, &level);
        if (!kpte)
                return __cpa_process_fault(cpa, address, primary);
 
@@ -761,7 +1154,7 @@ repeat:
        /*
         * We have to split the large page:
         */
-       err = split_large_page(kpte, address);
+       err = split_large_page(cpa, kpte, address);
        if (!err) {
                /*
                 * Do a global flush tlb after splitting the large page
@@ -910,6 +1303,8 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
        int ret, cache, checkalias;
        unsigned long baddr = 0;
 
+       memset(&cpa, 0, sizeof(cpa));
+
        /*
         * Check, if we are requested to change a not supported
         * feature:
@@ -1356,6 +1751,7 @@ static int __set_pages_p(struct page *page, int numpages)
 {
        unsigned long tempaddr = (unsigned long) page_address(page);
        struct cpa_data cpa = { .vaddr = &tempaddr,
+                               .pgd = NULL,
                                .numpages = numpages,
                                .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
                                .mask_clr = __pgprot(0),
@@ -1374,6 +1770,7 @@ static int __set_pages_np(struct page *page, int numpages)
 {
        unsigned long tempaddr = (unsigned long) page_address(page);
        struct cpa_data cpa = { .vaddr = &tempaddr,
+                               .pgd = NULL,
                                .numpages = numpages,
                                .mask_set = __pgprot(0),
                                .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
@@ -1434,6 +1831,36 @@ bool kernel_page_present(struct page *page)
 
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
+int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
+                           unsigned numpages, unsigned long page_flags)
+{
+       int retval = -EINVAL;
+
+       struct cpa_data cpa = {
+               .vaddr = &address,
+               .pfn = pfn,
+               .pgd = pgd,
+               .numpages = numpages,
+               .mask_set = __pgprot(0),
+               .mask_clr = __pgprot(0),
+               .flags = 0,
+       };
+
+       if (!(__supported_pte_mask & _PAGE_NX))
+               goto out;
+
+       if (!(page_flags & _PAGE_NX))
+               cpa.mask_clr = __pgprot(_PAGE_NX);
+
+       cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
+
+       retval = __change_page_attr_set_clr(&cpa, 0);
+       __flush_tlb_all();
+
+out:
+       return retval;
+}
+
 /*
  * The testcases use internal knowledge of the implementation that shouldn't
  * be exposed to the rest of the kernel. Include these directly here.
index 26328e800869fc6ac1821c0ab3dcd2baa1506ec1..4ed75dd81d052ff96cc832702d174ad4d63bffec 100644 (file)
@@ -359,15 +359,21 @@ void bpf_jit_compile(struct sk_filter *fp)
                                EMIT2(0x89, 0xd0);      /* mov %edx,%eax */
                                break;
                        case BPF_S_ALU_MOD_K: /* A %= K; */
+                               if (K == 1) {
+                                       CLEAR_A();
+                                       break;
+                               }
                                EMIT2(0x31, 0xd2);      /* xor %edx,%edx */
                                EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
                                EMIT2(0xf7, 0xf1);      /* div %ecx */
                                EMIT2(0x89, 0xd0);      /* mov %edx,%eax */
                                break;
-                       case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
-                               EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */
-                               EMIT(K, 4);
-                               EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */
+                       case BPF_S_ALU_DIV_K: /* A /= K */
+                               if (K == 1)
+                                       break;
+                               EMIT2(0x31, 0xd2);      /* xor %edx,%edx */
+                               EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
+                               EMIT2(0xf7, 0xf1);      /* div %ecx */
                                break;
                        case BPF_S_ALU_AND_X:
                                seen |= SEEN_XREG;
index b046e070e08868f72e62b5ce804ffedd1689cc03..bca9e85daaa55d04d3e174657264920280be4636 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/delay.h>
 #include <linux/dmi.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/vgaarb.h>
 #include <asm/pci_x86.h>
 
index 51384ca727ad1ac4636fa7ce32efb5730ed7579d..84b9d672843db2e0da88d653300991947483628f 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/pci_x86.h>
 #include <asm/hw_irq.h>
 #include <asm/io_apic.h>
+#include <asm/intel-mid.h>
 
 #define PCIE_CAP_OFFSET        0x100
 
@@ -219,7 +220,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
        irq_attr.ioapic = mp_find_ioapic(dev->irq);
        irq_attr.ioapic_pin = dev->irq;
        irq_attr.trigger = 1; /* level */
-       irq_attr.polarity = 1; /* active low */
+       if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
+               irq_attr.polarity = 0; /* active high */
+       else
+               irq_attr.polarity = 1; /* active low */
        io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
 
        return 0;
index 6599a0027b76bb9ab3b390fe31e5ba0ae10ed124..81b506d5befd46e5a494d6cbef7aa71edceca7f1 100644 (file)
@@ -142,7 +142,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
                        efi_y += font->height;
                }
 
-               if (efi_y + font->height >= si->lfb_height) {
+               if (efi_y + font->height > si->lfb_height) {
                        u32 i;
 
                        efi_y -= font->height;
index 92c02344a060f2dacc7997185d6fd6bc04ed225e..d62ec87a2b26d5d51bf2228ac7c2155cf9e8b06e 100644 (file)
@@ -12,6 +12,8 @@
  *     Bibo Mao <bibo.mao@intel.com>
  *     Chandramouli Narayanan <mouli@linux.intel.com>
  *     Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2013 SuSE Labs
+ *     Borislav Petkov <bp@suse.de> - runtime services VA mapping
  *
  * Copied from efi_32.c to eliminate the duplicated code between EFI
  * 32/64 support code. --ying 2007-10-26
@@ -51,7 +53,7 @@
 #include <asm/x86_init.h>
 #include <asm/rtc.h>
 
-#define EFI_DEBUG      1
+#define EFI_DEBUG
 
 #define EFI_MIN_RESERVE 5120
 
@@ -74,6 +76,8 @@ static __initdata efi_config_table_type_t arch_tables[] = {
        {NULL_GUID, NULL, NULL},
 };
 
+u64 efi_setup;         /* efi setup_data physical address */
+
 /*
  * Returns 1 if 'facility' is enabled, 0 otherwise.
  */
@@ -110,7 +114,6 @@ static int __init setup_storage_paranoia(char *arg)
 }
 early_param("efi_no_storage_paranoia", setup_storage_paranoia);
 
-
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
        unsigned long flags;
@@ -398,9 +401,9 @@ int __init efi_memblock_x86_reserve_range(void)
        return 0;
 }
 
-#if EFI_DEBUG
 static void __init print_efi_memmap(void)
 {
+#ifdef EFI_DEBUG
        efi_memory_desc_t *md;
        void *p;
        int i;
@@ -415,8 +418,8 @@ static void __init print_efi_memmap(void)
                        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
                        (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
        }
-}
 #endif  /*  EFI_DEBUG  */
+}
 
 void __init efi_reserve_boot_services(void)
 {
@@ -436,7 +439,7 @@ void __init efi_reserve_boot_services(void)
                 * - Not within any part of the kernel
                 * - Not the bios reserved area
                */
-               if ((start+size >= __pa_symbol(_text)
+               if ((start + size > __pa_symbol(_text)
                                && start <= __pa_symbol(_end)) ||
                        !e820_all_mapped(start, start+size, E820_RAM) ||
                        memblock_is_region_reserved(start, size)) {
@@ -489,18 +492,27 @@ static int __init efi_systab_init(void *phys)
 {
        if (efi_enabled(EFI_64BIT)) {
                efi_system_table_64_t *systab64;
+               struct efi_setup_data *data = NULL;
                u64 tmp = 0;
 
+               if (efi_setup) {
+                       data = early_memremap(efi_setup, sizeof(*data));
+                       if (!data)
+                               return -ENOMEM;
+               }
                systab64 = early_ioremap((unsigned long)phys,
                                         sizeof(*systab64));
                if (systab64 == NULL) {
                        pr_err("Couldn't map the system table!\n");
+                       if (data)
+                               early_iounmap(data, sizeof(*data));
                        return -ENOMEM;
                }
 
                efi_systab.hdr = systab64->hdr;
-               efi_systab.fw_vendor = systab64->fw_vendor;
-               tmp |= systab64->fw_vendor;
+               efi_systab.fw_vendor = data ? (unsigned long)data->fw_vendor :
+                                             systab64->fw_vendor;
+               tmp |= data ? data->fw_vendor : systab64->fw_vendor;
                efi_systab.fw_revision = systab64->fw_revision;
                efi_systab.con_in_handle = systab64->con_in_handle;
                tmp |= systab64->con_in_handle;
@@ -514,15 +526,20 @@ static int __init efi_systab_init(void *phys)
                tmp |= systab64->stderr_handle;
                efi_systab.stderr = systab64->stderr;
                tmp |= systab64->stderr;
-               efi_systab.runtime = (void *)(unsigned long)systab64->runtime;
-               tmp |= systab64->runtime;
+               efi_systab.runtime = data ?
+                                    (void *)(unsigned long)data->runtime :
+                                    (void *)(unsigned long)systab64->runtime;
+               tmp |= data ? data->runtime : systab64->runtime;
                efi_systab.boottime = (void *)(unsigned long)systab64->boottime;
                tmp |= systab64->boottime;
                efi_systab.nr_tables = systab64->nr_tables;
-               efi_systab.tables = systab64->tables;
-               tmp |= systab64->tables;
+               efi_systab.tables = data ? (unsigned long)data->tables :
+                                          systab64->tables;
+               tmp |= data ? data->tables : systab64->tables;
 
                early_iounmap(systab64, sizeof(*systab64));
+               if (data)
+                       early_iounmap(data, sizeof(*data));
 #ifdef CONFIG_X86_32
                if (tmp >> 32) {
                        pr_err("EFI data located above 4GB, disabling EFI.\n");
@@ -626,6 +643,62 @@ static int __init efi_memmap_init(void)
        return 0;
 }
 
+/*
+ * A number of config table entries get remapped to virtual addresses
+ * after entering EFI virtual mode. However, the kexec kernel requires
+ * their physical addresses therefore we pass them via setup_data and
+ * correct those entries to their respective physical addresses here.
+ *
+ * Currently only handles smbios which is necessary for some firmware
+ * implementation.
+ */
+static int __init efi_reuse_config(u64 tables, int nr_tables)
+{
+       int i, sz, ret = 0;
+       void *p, *tablep;
+       struct efi_setup_data *data;
+
+       if (!efi_setup)
+               return 0;
+
+       if (!efi_enabled(EFI_64BIT))
+               return 0;
+
+       data = early_memremap(efi_setup, sizeof(*data));
+       if (!data) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       if (!data->smbios)
+               goto out_memremap;
+
+       sz = sizeof(efi_config_table_64_t);
+
+       p = tablep = early_memremap(tables, nr_tables * sz);
+       if (!p) {
+               pr_err("Could not map Configuration table!\n");
+               ret = -ENOMEM;
+               goto out_memremap;
+       }
+
+       for (i = 0; i < efi.systab->nr_tables; i++) {
+               efi_guid_t guid;
+
+               guid = ((efi_config_table_64_t *)p)->guid;
+
+               if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
+                       ((efi_config_table_64_t *)p)->table = data->smbios;
+               p += sz;
+       }
+       early_iounmap(tablep, nr_tables * sz);
+
+out_memremap:
+       early_iounmap(data, sizeof(*data));
+out:
+       return ret;
+}
+
 void __init efi_init(void)
 {
        efi_char16_t *c16;
@@ -651,6 +724,10 @@ void __init efi_init(void)
 
        set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
 
+       efi.config_table = (unsigned long)efi.systab->tables;
+       efi.fw_vendor    = (unsigned long)efi.systab->fw_vendor;
+       efi.runtime      = (unsigned long)efi.systab->runtime;
+
        /*
         * Show what we know for posterity
         */
@@ -667,6 +744,9 @@ void __init efi_init(void)
                efi.systab->hdr.revision >> 16,
                efi.systab->hdr.revision & 0xffff, vendor);
 
+       if (efi_reuse_config(efi.systab->tables, efi.systab->nr_tables))
+               return;
+
        if (efi_config_init(arch_tables))
                return;
 
@@ -684,22 +764,12 @@ void __init efi_init(void)
                        return;
                set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
        }
-
        if (efi_memmap_init())
                return;
 
        set_bit(EFI_MEMMAP, &x86_efi_facility);
 
-#ifdef CONFIG_X86_32
-       if (efi_is_native()) {
-               x86_platform.get_wallclock = efi_get_time;
-               x86_platform.set_wallclock = efi_set_rtc_mmss;
-       }
-#endif
-
-#if EFI_DEBUG
        print_efi_memmap();
-#endif
 }
 
 void __init efi_late_init(void)
@@ -748,36 +818,38 @@ void efi_memory_uc(u64 addr, unsigned long size)
        set_memory_uc(addr, npages);
 }
 
-/*
- * This function will switch the EFI runtime services to virtual mode.
- * Essentially, look through the EFI memmap and map every region that
- * has the runtime attribute bit set in its memory descriptor and update
- * that memory descriptor with the virtual address obtained from ioremap().
- * This enables the runtime services to be called without having to
- * thunk back into physical mode for every invocation.
- */
-void __init efi_enter_virtual_mode(void)
+void __init old_map_region(efi_memory_desc_t *md)
 {
-       efi_memory_desc_t *md, *prev_md = NULL;
-       efi_status_t status;
+       u64 start_pfn, end_pfn, end;
        unsigned long size;
-       u64 end, systab, start_pfn, end_pfn;
-       void *p, *va, *new_memmap = NULL;
-       int count = 0;
+       void *va;
 
-       efi.systab = NULL;
+       start_pfn = PFN_DOWN(md->phys_addr);
+       size      = md->num_pages << PAGE_SHIFT;
+       end       = md->phys_addr + size;
+       end_pfn   = PFN_UP(end);
 
-       /*
-        * We don't do virtual mode, since we don't do runtime services, on
-        * non-native EFI
-        */
+       if (pfn_range_is_mapped(start_pfn, end_pfn)) {
+               va = __va(md->phys_addr);
 
-       if (!efi_is_native()) {
-               efi_unmap_memmap();
-               return;
-       }
+               if (!(md->attribute & EFI_MEMORY_WB))
+                       efi_memory_uc((u64)(unsigned long)va, size);
+       } else
+               va = efi_ioremap(md->phys_addr, size,
+                                md->type, md->attribute);
+
+       md->virt_addr = (u64) (unsigned long) va;
+       if (!va)
+               pr_err("ioremap of 0x%llX failed!\n",
+                      (unsigned long long)md->phys_addr);
+}
+
+/* Merge contiguous regions of the same type and attribute */
+static void __init efi_merge_regions(void)
+{
+       void *p;
+       efi_memory_desc_t *md, *prev_md = NULL;
 
-       /* Merge contiguous regions of the same type and attribute */
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                u64 prev_size;
                md = p;
@@ -803,6 +875,77 @@ void __init efi_enter_virtual_mode(void)
                }
                prev_md = md;
        }
+}
+
+static void __init get_systab_virt_addr(efi_memory_desc_t *md)
+{
+       unsigned long size;
+       u64 end, systab;
+
+       size = md->num_pages << EFI_PAGE_SHIFT;
+       end = md->phys_addr + size;
+       systab = (u64)(unsigned long)efi_phys.systab;
+       if (md->phys_addr <= systab && systab < end) {
+               systab += md->virt_addr - md->phys_addr;
+               efi.systab = (efi_system_table_t *)(unsigned long)systab;
+       }
+}
+
+static int __init save_runtime_map(void)
+{
+       efi_memory_desc_t *md;
+       void *tmp, *p, *q = NULL;
+       int count = 0;
+
+       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+               md = p;
+
+               if (!(md->attribute & EFI_MEMORY_RUNTIME) ||
+                   (md->type == EFI_BOOT_SERVICES_CODE) ||
+                   (md->type == EFI_BOOT_SERVICES_DATA))
+                       continue;
+               tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL);
+               if (!tmp)
+                       goto out;
+               q = tmp;
+
+               memcpy(q + count * memmap.desc_size, md, memmap.desc_size);
+               count++;
+       }
+
+       efi_runtime_map_setup(q, count, memmap.desc_size);
+
+       return 0;
+out:
+       kfree(q);
+       return -ENOMEM;
+}
+
+/*
+ * 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)
+{
+       void *p;
+       efi_memory_desc_t *md;
+
+       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);
+       }
+
+}
+
+/*
+ * Map efi memory ranges for runtime serivce and update new_memmap with virtual
+ * addresses.
+ */
+static void * __init efi_map_regions(int *count)
+{
+       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;
@@ -814,53 +957,95 @@ void __init efi_enter_virtual_mode(void)
                                continue;
                }
 
-               size = md->num_pages << EFI_PAGE_SHIFT;
-               end = md->phys_addr + size;
+               efi_map_region(md);
+               get_systab_virt_addr(md);
 
-               start_pfn = PFN_DOWN(md->phys_addr);
-               end_pfn = PFN_UP(end);
-               if (pfn_range_is_mapped(start_pfn, end_pfn)) {
-                       va = __va(md->phys_addr);
+               tmp = krealloc(new_memmap, (*count + 1) * memmap.desc_size,
+                              GFP_KERNEL);
+               if (!tmp)
+                       goto out;
+               new_memmap = tmp;
+               memcpy(new_memmap + (*count * memmap.desc_size), md,
+                      memmap.desc_size);
+               (*count)++;
+       }
 
-                       if (!(md->attribute & EFI_MEMORY_WB))
-                               efi_memory_uc((u64)(unsigned long)va, size);
-               } else
-                       va = efi_ioremap(md->phys_addr, size,
-                                        md->type, md->attribute);
+       return new_memmap;
+out:
+       kfree(new_memmap);
+       return NULL;
+}
+
+/*
+ * This function will switch the EFI runtime services to virtual mode.
+ * Essentially, we look through the EFI memmap and map every region that
+ * has the runtime attribute bit set in its memory descriptor into the
+ * ->trampoline_pgd page table using a top-down VA allocation scheme.
+ *
+ * The old method which used to update that memory descriptor with the
+ * virtual address obtained from ioremap() is still supported when the
+ * kernel is booted with efi=old_map on its command line. Same old
+ * method enabled the runtime services to be called without having to
+ * thunk back into physical mode for every invocation.
+ *
+ * The new method does a pagetable switch in a preemption-safe manner
+ * so that we're in a different address space when calling a runtime
+ * function. For function arguments passing we do copy the PGDs of the
+ * kernel page table into ->trampoline_pgd prior to each call.
+ *
+ * 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.
+ */
+void __init efi_enter_virtual_mode(void)
+{
+       efi_status_t status;
+       void *new_memmap = NULL;
+       int err, count = 0;
 
-               md->virt_addr = (u64) (unsigned long) va;
+       efi.systab = NULL;
 
-               if (!va) {
-                       pr_err("ioremap of 0x%llX failed!\n",
-                              (unsigned long long)md->phys_addr);
-                       continue;
-               }
+       /*
+        * 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;
+       }
 
-               systab = (u64) (unsigned long) efi_phys.systab;
-               if (md->phys_addr <= systab && systab < end) {
-                       systab += md->virt_addr - md->phys_addr;
-                       efi.systab = (efi_system_table_t *) (unsigned long) systab;
+       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;
                }
-               new_memmap = krealloc(new_memmap,
-                                     (count + 1) * memmap.desc_size,
-                                     GFP_KERNEL);
-               memcpy(new_memmap + (count * memmap.desc_size), md,
-                      memmap.desc_size);
-               count++;
        }
 
+       err = save_runtime_map();
+       if (err)
+               pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
+
        BUG_ON(!efi.systab);
 
-       status = phys_efi_set_virtual_address_map(
-               memmap.desc_size * count,
-               memmap.desc_size,
-               memmap.desc_version,
-               (efi_memory_desc_t *)__pa(new_memmap));
+       efi_setup_page_tables();
+       efi_sync_low_kernel_mappings();
 
-       if (status != EFI_SUCCESS) {
-               pr_alert("Unable to switch EFI into virtual mode "
-                        "(status=%lx)!\n", status);
-               panic("EFI call to SetVirtualAddressMap() failed!");
+       if (!efi_setup) {
+               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!");
+               }
        }
 
        /*
@@ -883,7 +1068,8 @@ void __init efi_enter_virtual_mode(void)
        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 (__supported_pte_mask & _PAGE_NX)
+
+       if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
                runtime_code_page_mkexec();
 
        kfree(new_memmap);
@@ -1013,3 +1199,15 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
        return EFI_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(efi_query_variable_store);
+
+static int __init parse_efi_cmdline(char *str)
+{
+       if (*str == '=')
+               str++;
+
+       if (!strncmp(str, "old_map", 7))
+               set_bit(EFI_OLD_MEMMAP, &x86_efi_facility);
+
+       return 0;
+}
+early_param("efi", parse_efi_cmdline);
index 40e446941dd7eceb587b2b4572c96279631e5f56..249b183cf41799d473012321435b2bdedf979903 100644 (file)
  * claim EFI runtime service handler exclusively and to duplicate a memory in
  * low memory space say 0 - 3G.
  */
-
 static unsigned long efi_rt_eflags;
 
+void efi_sync_low_kernel_mappings(void) {}
+void efi_setup_page_tables(void) {}
+
+void __init efi_map_region(efi_memory_desc_t *md)
+{
+       old_map_region(md);
+}
+
+void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
+void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
+
 void efi_call_phys_prelog(void)
 {
        struct desc_ptr gdt_descr;
index 39a0e7f1f0a3ec1c7601888d30c724a5b8660e19..6284f158a47d851b1f4a0ca3f951e20ac5c3ffd7 100644 (file)
 #include <asm/efi.h>
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
+#include <asm/realmode.h>
 
 static pgd_t *save_pgd __initdata;
 static unsigned long efi_flags __initdata;
 
+/*
+ * We allocate runtime services regions bottom-up, starting from -4G, i.e.
+ * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
+ */
+static u64 efi_va      = -4 * (1UL << 30);
+#define EFI_VA_END     (-68 * (1UL << 30))
+
+/*
+ * Scratch space used for switching the pagetable in the EFI stub
+ */
+struct efi_scratch {
+       u64 r15;
+       u64 prev_cr3;
+       pgd_t *efi_pgt;
+       bool use_pgd;
+};
+
 static void __init early_code_mapping_set_exec(int executable)
 {
        efi_memory_desc_t *md;
@@ -65,6 +83,9 @@ void __init efi_call_phys_prelog(void)
        int pgd;
        int n_pgds;
 
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
        early_code_mapping_set_exec(1);
        local_irq_save(efi_flags);
 
@@ -86,6 +107,10 @@ void __init efi_call_phys_epilog(void)
         */
        int pgd;
        int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
+
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
        for (pgd = 0; pgd < n_pgds; pgd++)
                set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);
        kfree(save_pgd);
@@ -94,6 +119,96 @@ void __init efi_call_phys_epilog(void)
        early_code_mapping_set_exec(0);
 }
 
+/*
+ * Add low kernel mappings for passing arguments to EFI functions.
+ */
+void efi_sync_low_kernel_mappings(void)
+{
+       unsigned num_pgds;
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
+       num_pgds = pgd_index(MODULES_END - 1) - pgd_index(PAGE_OFFSET);
+
+       memcpy(pgd + pgd_index(PAGE_OFFSET),
+               init_mm.pgd + pgd_index(PAGE_OFFSET),
+               sizeof(pgd_t) * num_pgds);
+}
+
+void efi_setup_page_tables(void)
+{
+       efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd;
+
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               efi_scratch.use_pgd = true;
+}
+
+static void __init __map_region(efi_memory_desc_t *md, u64 va)
+{
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+       unsigned long pf = 0;
+
+       if (!(md->attribute & EFI_MEMORY_WB))
+               pf |= _PAGE_PCD;
+
+       if (kernel_map_pages_in_pgd(pgd, md->phys_addr, va, md->num_pages, pf))
+               pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n",
+                          md->phys_addr, va);
+}
+
+void __init efi_map_region(efi_memory_desc_t *md)
+{
+       unsigned long size = md->num_pages << PAGE_SHIFT;
+       u64 pa = md->phys_addr;
+
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return old_map_region(md);
+
+       /*
+        * Make sure the 1:1 mappings are present as a catch-all for b0rked
+        * firmware which doesn't update all internal pointers after switching
+        * to virtual mode and would otherwise crap on us.
+        */
+       __map_region(md, md->phys_addr);
+
+       efi_va -= size;
+
+       /* Is PA 2M-aligned? */
+       if (!(pa & (PMD_SIZE - 1))) {
+               efi_va &= PMD_MASK;
+       } else {
+               u64 pa_offset = pa & (PMD_SIZE - 1);
+               u64 prev_va = efi_va;
+
+               /* get us the same offset within this 2M page */
+               efi_va = (efi_va & PMD_MASK) + pa_offset;
+
+               if (efi_va > prev_va)
+                       efi_va -= PMD_SIZE;
+       }
+
+       if (efi_va < EFI_VA_END) {
+               pr_warn(FW_WARN "VA address range overflow!\n");
+               return;
+       }
+
+       /* Do the VA map */
+       __map_region(md, efi_va);
+       md->virt_addr = efi_va;
+}
+
+/*
+ * kexec kernel will use efi_map_region_fixed to map efi runtime memory ranges.
+ * md->virt_addr is the original virtual address which had been mapped in kexec
+ * 1st kernel.
+ */
+void __init efi_map_region_fixed(efi_memory_desc_t *md)
+{
+       __map_region(md, md->virt_addr);
+}
+
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
                                 u32 type, u64 attribute)
 {
@@ -113,3 +228,8 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
 
        return (void __iomem *)__va(phys_addr);
 }
+
+void __init parse_efi_setup(u64 phys_addr, u32 data_len)
+{
+       efi_setup = phys_addr + sizeof(struct setup_data);
+}
index 4c07ccab8146f0bbed2850f586a68f126b2bc7eb..88073b1402988b49eb6c5e95f9f801a14d40f144 100644 (file)
        mov %rsi, %cr0;                 \
        mov (%rsp), %rsp
 
+       /* stolen from gcc */
+       .macro FLUSH_TLB_ALL
+       movq %r15, efi_scratch(%rip)
+       movq %r14, efi_scratch+8(%rip)
+       movq %cr4, %r15
+       movq %r15, %r14
+       andb $0x7f, %r14b
+       movq %r14, %cr4
+       movq %r15, %cr4
+       movq efi_scratch+8(%rip), %r14
+       movq efi_scratch(%rip), %r15
+       .endm
+
+       .macro SWITCH_PGT
+       cmpb $0, efi_scratch+24(%rip)
+       je 1f
+       movq %r15, efi_scratch(%rip)            # r15
+       # save previous CR3
+       movq %cr3, %r15
+       movq %r15, efi_scratch+8(%rip)          # prev_cr3
+       movq efi_scratch+16(%rip), %r15         # EFI pgt
+       movq %r15, %cr3
+       1:
+       .endm
+
+       .macro RESTORE_PGT
+       cmpb $0, efi_scratch+24(%rip)
+       je 2f
+       movq efi_scratch+8(%rip), %r15
+       movq %r15, %cr3
+       movq efi_scratch(%rip), %r15
+       FLUSH_TLB_ALL
+       2:
+       .endm
+
 ENTRY(efi_call0)
        SAVE_XMM
        subq $32, %rsp
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -47,7 +84,9 @@ ENTRY(efi_call1)
        SAVE_XMM
        subq $32, %rsp
        mov  %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -57,7 +96,9 @@ ENTRY(efi_call2)
        SAVE_XMM
        subq $32, %rsp
        mov  %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -68,7 +109,9 @@ ENTRY(efi_call3)
        subq $32, %rsp
        mov  %rcx, %r8
        mov  %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -80,7 +123,9 @@ ENTRY(efi_call4)
        mov %r8, %r9
        mov %rcx, %r8
        mov %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -93,7 +138,9 @@ ENTRY(efi_call5)
        mov %r8, %r9
        mov %rcx, %r8
        mov %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $48, %rsp
        RESTORE_XMM
        ret
@@ -109,8 +156,15 @@ ENTRY(efi_call6)
        mov %r8, %r9
        mov %rcx, %r8
        mov %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $48, %rsp
        RESTORE_XMM
        ret
 ENDPROC(efi_call6)
+
+       .data
+ENTRY(efi_scratch)
+       .fill 3,8,0
+       .byte 0
index 01cc29ea5ff713f5f1afe366e837a332e4990b48..0a8ee703b9fae9cbfd2205376650563bf7b9eecb 100644 (file)
@@ -1,6 +1,6 @@
-obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o
-obj-$(CONFIG_X86_INTEL_MID) += intel_mid_vrtc.o
+obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o
 obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o
+
 # SFI specific code
 ifdef CONFIG_X86_INTEL_MID
 obj-$(CONFIG_SFI) += sfi.o device_libs/
index 0d942c1d26d578f2229d981c367d50a51cee9730..69a783689d21b7c2c7ac9db8c21f10b6582a318d 100644 (file)
@@ -22,7 +22,9 @@ static void __init *emc1403_platform_data(void *info)
        int intr = get_gpio_by_name("thermal_int");
        int intr2nd = get_gpio_by_name("thermal_alert");
 
-       if (intr == -1 || intr2nd == -1)
+       if (intr < 0)
+               return NULL;
+       if (intr2nd < 0)
                return NULL;
 
        i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
index a013a4834bbe7d8eb8fec5413551dad090a7b484..dccae6b0413f86a2f5fd91bfe3d8384553829d25 100644 (file)
@@ -66,7 +66,7 @@ static int __init pb_keys_init(void)
                gb[i].gpio = get_gpio_by_name(gb[i].desc);
                pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc,
                                        gb[i].gpio);
-               if (gb[i].gpio == -1)
+               if (gb[i].gpio < 0)
                        continue;
 
                if (i != good)
index 15278c11f7147b16e39b043bc68f0cbd07212728..54226de7541a7f43149b068657184e04b10f123f 100644 (file)
@@ -21,7 +21,9 @@ static void __init *lis331dl_platform_data(void *info)
        int intr = get_gpio_by_name("accel_int");
        int intr2nd = get_gpio_by_name("accel_2");
 
-       if (intr == -1 || intr2nd == -1)
+       if (intr < 0)
+               return NULL;
+       if (intr2nd < 0)
                return NULL;
 
        i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
index 94ade10024ae01c6934b1f64d209005d495ec438..2c8acbc1e9ad906840d85269de5a428e45c4838f 100644 (file)
@@ -48,7 +48,7 @@ static void __init *max7315_platform_data(void *info)
        gpio_base = get_gpio_by_name(base_pin_name);
        intr = get_gpio_by_name(intr_pin_name);
 
-       if (gpio_base == -1)
+       if (gpio_base < 0)
                return NULL;
        max7315->gpio_base = gpio_base;
        if (intr != -1) {
index dd28d63c84fb1ba345aeab89c7fa547c40a9c8fc..cfe9a47a1e8778409d2819e6ed20823ad5b299b6 100644 (file)
@@ -19,7 +19,7 @@ static void *mpu3050_platform_data(void *info)
        struct i2c_board_info *i2c_info = info;
        int intr = get_gpio_by_name("mpu3050_int");
 
-       if (intr == -1)
+       if (intr < 0)
                return NULL;
 
        i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
index d87182a09263156147c706286bcb2a68bbefb44f..65c2a9a19db4d0f69378ff2effc390f3ad48f8ef 100644 (file)
@@ -26,7 +26,7 @@ static void __init *pmic_gpio_platform_data(void *info)
        static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
        int gpio_base = get_gpio_by_name("pmic_gpio_base");
 
-       if (gpio_base == -1)
+       if (gpio_base < 0)
                gpio_base = 64;
        pmic_gpio_pdata.gpio_base = gpio_base;
        pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
index 22881c9a6737b1ae4a0e7d20f163a0de553ec7de..33be0b3be6e12080fd63ae249829b93504174cc6 100644 (file)
@@ -34,10 +34,10 @@ static void *tca6416_platform_data(void *info)
        gpio_base = get_gpio_by_name(base_pin_name);
        intr = get_gpio_by_name(intr_pin_name);
 
-       if (gpio_base == -1)
+       if (gpio_base < 0)
                return NULL;
        tca6416.gpio_base = gpio_base;
-       if (intr != -1) {
+       if (intr >= 0) {
                i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
                tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
        } else {
index 4f702f554f6e011cfcb248af5d1088526a714e6a..e0bd082a80e00f15db9ab0435818eb35dbd59926 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/io.h>
 
 #include <asm/fixmap.h>
index f90e290f689f380150b0983ddd363480f98d8c25..1bbedc4b0f88d46bee5000779c4ef5aa4e4d0411 100644 (file)
@@ -35,6 +35,8 @@
 #include <asm/apb_timer.h>
 #include <asm/reboot.h>
 
+#include "intel_mid_weak_decls.h"
+
 /*
  * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
  * cmdline option x86_intel_mid_timer can be used to override the configuration
 
 enum intel_mid_timer_options intel_mid_timer_options;
 
+/* intel_mid_ops to store sub arch ops */
+struct intel_mid_ops *intel_mid_ops;
+/* getter function for sub arch ops*/
+static void *(*get_intel_mid_ops[])(void) = INTEL_MID_OPS_INIT;
 enum intel_mid_cpu_type __intel_mid_cpu_chip;
 EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
 
 static void intel_mid_power_off(void)
 {
-}
+};
 
 static void intel_mid_reboot(void)
 {
@@ -72,32 +78,6 @@ static void intel_mid_reboot(void)
 
 static unsigned long __init intel_mid_calibrate_tsc(void)
 {
-       unsigned long fast_calibrate;
-       u32 lo, hi, ratio, fsb;
-
-       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
-       pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
-       ratio = (hi >> 8) & 0x1f;
-       pr_debug("ratio is %d\n", ratio);
-       if (!ratio) {
-               pr_err("read a zero ratio, should be incorrect!\n");
-               pr_err("force tsc ratio to 16 ...\n");
-               ratio = 16;
-       }
-       rdmsr(MSR_FSB_FREQ, lo, hi);
-       if ((lo & 0x7) == 0x7)
-               fsb = PENWELL_FSB_FREQ_83SKU;
-       else
-               fsb = PENWELL_FSB_FREQ_100SKU;
-       fast_calibrate = ratio * fsb;
-       pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
-       lapic_timer_frequency = fsb * 1000 / HZ;
-       /* mark tsc clocksource as reliable */
-       set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
-
-       if (fast_calibrate)
-               return fast_calibrate;
-
        return 0;
 }
 
@@ -125,13 +105,37 @@ static void __init intel_mid_time_init(void)
 
 static void intel_mid_arch_setup(void)
 {
-       if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
-               __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
-       else {
+       if (boot_cpu_data.x86 != 6) {
                pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
                        boot_cpu_data.x86, boot_cpu_data.x86_model);
                __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
+               goto out;
        }
+
+       switch (boot_cpu_data.x86_model) {
+       case 0x35:
+               __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_CLOVERVIEW;
+               break;
+       case 0x3C:
+       case 0x4A:
+               __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_TANGIER;
+               break;
+       case 0x27:
+       default:
+               __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
+               break;
+       }
+
+       if (__intel_mid_cpu_chip < MAX_CPU_OPS(get_intel_mid_ops))
+               intel_mid_ops = get_intel_mid_ops[__intel_mid_cpu_chip]();
+       else {
+               intel_mid_ops = get_intel_mid_ops[INTEL_MID_CPU_CHIP_PENWELL]();
+               pr_info("ARCH: Uknown SoC, assuming PENWELL!\n");
+       }
+
+out:
+       if (intel_mid_ops->arch_setup)
+               intel_mid_ops->arch_setup();
 }
 
 /* MID systems don't have i8042 controller */
diff --git a/arch/x86/platform/intel-mid/intel_mid_weak_decls.h b/arch/x86/platform/intel-mid/intel_mid_weak_decls.h
new file mode 100644 (file)
index 0000000..a537ffc
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * intel_mid_weak_decls.h: Weak declarations of intel-mid.c
+ *
+ * (C) Copyright 2013 Intel 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+
+/* __attribute__((weak)) makes these declarations overridable */
+/* For every CPU addition a new get_<cpuname>_ops interface needs
+ * to be added.
+ */
+extern void * __cpuinit get_penwell_ops(void) __attribute__((weak));
+extern void * __cpuinit get_cloverview_ops(void) __attribute__((weak));
+extern void * __init get_tangier_ops(void) __attribute__((weak));
diff --git a/arch/x86/platform/intel-mid/mfld.c b/arch/x86/platform/intel-mid/mfld.c
new file mode 100644 (file)
index 0000000..4f7884e
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * mfld.c: Intel Medfield platform setup code
+ *
+ * (C) Copyright 2013 Intel 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+
+#include <asm/apic.h>
+#include <asm/intel-mid.h>
+#include <asm/intel_mid_vrtc.h>
+
+#include "intel_mid_weak_decls.h"
+
+static void penwell_arch_setup(void);
+/* penwell arch ops */
+static struct intel_mid_ops penwell_ops = {
+       .arch_setup = penwell_arch_setup,
+};
+
+static void mfld_power_off(void)
+{
+}
+
+static unsigned long __init mfld_calibrate_tsc(void)
+{
+       unsigned long fast_calibrate;
+       u32 lo, hi, ratio, fsb;
+
+       rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+       pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+       ratio = (hi >> 8) & 0x1f;
+       pr_debug("ratio is %d\n", ratio);
+       if (!ratio) {
+               pr_err("read a zero ratio, should be incorrect!\n");
+               pr_err("force tsc ratio to 16 ...\n");
+               ratio = 16;
+       }
+       rdmsr(MSR_FSB_FREQ, lo, hi);
+       if ((lo & 0x7) == 0x7)
+               fsb = FSB_FREQ_83SKU;
+       else
+               fsb = FSB_FREQ_100SKU;
+       fast_calibrate = ratio * fsb;
+       pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+       lapic_timer_frequency = fsb * 1000 / HZ;
+       /* mark tsc clocksource as reliable */
+       set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+
+       if (fast_calibrate)
+               return fast_calibrate;
+
+       return 0;
+}
+
+static void __init penwell_arch_setup()
+{
+       x86_platform.calibrate_tsc = mfld_calibrate_tsc;
+       pm_power_off = mfld_power_off;
+}
+
+void * __cpuinit get_penwell_ops()
+{
+       return &penwell_ops;
+}
+
+void * __cpuinit get_cloverview_ops()
+{
+       return &penwell_ops;
+}
diff --git a/arch/x86/platform/intel-mid/mrfl.c b/arch/x86/platform/intel-mid/mrfl.c
new file mode 100644 (file)
index 0000000..09d1015
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * mrfl.c: Intel Merrifield platform specific setup code
+ *
+ * (C) Copyright 2013 Intel 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+
+#include <asm/apic.h>
+#include <asm/intel-mid.h>
+
+#include "intel_mid_weak_decls.h"
+
+static unsigned long __init tangier_calibrate_tsc(void)
+{
+       unsigned long fast_calibrate;
+       u32 lo, hi, ratio, fsb, bus_freq;
+
+       /* *********************** */
+       /* Compute TSC:Ratio * FSB */
+       /* *********************** */
+
+       /* Compute Ratio */
+       rdmsr(MSR_PLATFORM_INFO, lo, hi);
+       pr_debug("IA32 PLATFORM_INFO is 0x%x : %x\n", hi, lo);
+
+       ratio = (lo >> 8) & 0xFF;
+       pr_debug("ratio is %d\n", ratio);
+       if (!ratio) {
+               pr_err("Read a zero ratio, force tsc ratio to 4 ...\n");
+               ratio = 4;
+       }
+
+       /* Compute FSB */
+       rdmsr(MSR_FSB_FREQ, lo, hi);
+       pr_debug("Actual FSB frequency detected by SOC 0x%x : %x\n",
+                       hi, lo);
+
+       bus_freq = lo & 0x7;
+       pr_debug("bus_freq = 0x%x\n", bus_freq);
+
+       if (bus_freq == 0)
+               fsb = FSB_FREQ_100SKU;
+       else if (bus_freq == 1)
+               fsb = FSB_FREQ_100SKU;
+       else if (bus_freq == 2)
+               fsb = FSB_FREQ_133SKU;
+       else if (bus_freq == 3)
+               fsb = FSB_FREQ_167SKU;
+       else if (bus_freq == 4)
+               fsb = FSB_FREQ_83SKU;
+       else if (bus_freq == 5)
+               fsb = FSB_FREQ_400SKU;
+       else if (bus_freq == 6)
+               fsb = FSB_FREQ_267SKU;
+       else if (bus_freq == 7)
+               fsb = FSB_FREQ_333SKU;
+       else {
+               BUG();
+               pr_err("Invalid bus_freq! Setting to minimal value!\n");
+               fsb = FSB_FREQ_100SKU;
+       }
+
+       /* TSC = FSB Freq * Resolved HFM Ratio */
+       fast_calibrate = ratio * fsb;
+       pr_debug("calculate tangier tsc %lu KHz\n", fast_calibrate);
+
+       /* ************************************ */
+       /* Calculate Local APIC Timer Frequency */
+       /* ************************************ */
+       lapic_timer_frequency = (fsb * 1000) / HZ;
+
+       pr_debug("Setting lapic_timer_frequency = %d\n",
+                       lapic_timer_frequency);
+
+       /* mark tsc clocksource as reliable */
+       set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+
+       if (fast_calibrate)
+               return fast_calibrate;
+
+       return 0;
+}
+
+static void __init tangier_arch_setup(void)
+{
+       x86_platform.calibrate_tsc = tangier_calibrate_tsc;
+}
+
+/* tangier arch ops */
+static struct intel_mid_ops tangier_ops = {
+       .arch_setup = tangier_arch_setup,
+};
+
+void * __cpuinit get_tangier_ops()
+{
+       return &tangier_ops;
+}
index c84c1ca396bfa80914ecd3108ffcee7df6074c87..994c40bd7cb7c8cc54dc4f9fec2be2ea7f74a4af 100644 (file)
@@ -224,7 +224,7 @@ int get_gpio_by_name(const char *name)
                if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
                        return pentry->pin_no;
        }
-       return -1;
+       return -EINVAL;
 }
 
 void __init intel_scu_device_register(struct platform_device *pdev)
@@ -250,7 +250,7 @@ static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
                        sdev->modalias);
                return;
        }
-       memcpy(new_dev, sdev, sizeof(*sdev));
+       *new_dev = *sdev;
 
        spi_devs[spi_next_dev++] = new_dev;
 }
@@ -271,7 +271,7 @@ static void __init intel_scu_i2c_device_register(int bus,
                        idev->type);
                return;
        }
-       memcpy(new_dev, idev, sizeof(*idev));
+       *new_dev = *idev;
 
        i2c_bus[i2c_next_dev] = bus;
        i2c_devs[i2c_next_dev++] = new_dev;
@@ -337,6 +337,8 @@ static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry,
        pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
                pentry->name, pentry->irq);
        pdata = intel_mid_sfi_get_pdata(dev, pentry);
+       if (IS_ERR(pdata))
+               return;
 
        pdev = platform_device_alloc(pentry->name, 0);
        if (pdev == NULL) {
@@ -370,6 +372,8 @@ static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry,
                spi_info.chip_select);
 
        pdata = intel_mid_sfi_get_pdata(dev, &spi_info);
+       if (IS_ERR(pdata))
+               return;
 
        spi_info.platform_data = pdata;
        if (dev->delay)
@@ -395,6 +399,8 @@ static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry,
                i2c_info.addr);
        pdata = intel_mid_sfi_get_pdata(dev, &i2c_info);
        i2c_info.platform_data = pdata;
+       if (IS_ERR(pdata))
+               return;
 
        if (dev->delay)
                intel_scu_i2c_device_register(pentry->host_num, &i2c_info);
@@ -443,13 +449,35 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
                         * so we have to enable them one by one here
                         */
                        ioapic = mp_find_ioapic(irq);
-                       irq_attr.ioapic = ioapic;
-                       irq_attr.ioapic_pin = irq;
-                       irq_attr.trigger = 1;
-                       irq_attr.polarity = 1;
-                       io_apic_set_pci_routing(NULL, irq, &irq_attr);
-               } else
+                       if (ioapic >= 0) {
+                               irq_attr.ioapic = ioapic;
+                               irq_attr.ioapic_pin = irq;
+                               irq_attr.trigger = 1;
+                               if (intel_mid_identify_cpu() ==
+                                               INTEL_MID_CPU_CHIP_TANGIER) {
+                                       if (!strncmp(pentry->name,
+                                                       "r69001-ts-i2c", 13))
+                                               /* active low */
+                                               irq_attr.polarity = 1;
+                                       else if (!strncmp(pentry->name,
+                                                       "synaptics_3202", 14))
+                                               /* active low */
+                                               irq_attr.polarity = 1;
+                                       else if (irq == 41)
+                                               /* fast_int_1 */
+                                               irq_attr.polarity = 1;
+                                       else
+                                               /* active high */
+                                               irq_attr.polarity = 0;
+                               } else {
+                                       /* PNW and CLV go with active low */
+                                       irq_attr.polarity = 1;
+                               }
+                               io_apic_set_pci_routing(NULL, irq, &irq_attr);
+                       }
+               } else {
                        irq = 0; /* No irq */
+               }
 
                dev = get_device_id(pentry->type, pentry->name);
 
index e6cb80f620afffc8882e6bcdaf627b1c32215d41..4d171e8640efe7e049a07e2b89d7dd1c5c3eb0de 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/pm.h>
 #include <asm/io.h>
 
index 0f92173a12b6ee1a1d5512c867585cd1ee07fc12..dfe605ac1bcd52a6e1a7f2227e12091f09e4243c 100644 (file)
@@ -433,15 +433,49 @@ static void reset_with_ipi(struct pnmask *distribution, struct bau_control *bcp)
        return;
 }
 
-static inline unsigned long cycles_2_us(unsigned long long cyc)
+/*
+ * Not to be confused with cycles_2_ns() from tsc.c; this gives a relative
+ * number, not an absolute. It converts a duration in cycles to a duration in
+ * ns.
+ */
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
 {
+       struct cyc2ns_data *data = cyc2ns_read_begin();
        unsigned long long ns;
-       unsigned long us;
-       int cpu = smp_processor_id();
 
-       ns =  (cyc * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR;
-       us = ns / 1000;
-       return us;
+       ns = mul_u64_u32_shr(cyc, data->cyc2ns_mul, data->cyc2ns_shift);
+
+       cyc2ns_read_end(data);
+       return ns;
+}
+
+/*
+ * The reverse of the above; converts a duration in ns to a duration in cycles.
+ */ 
+static inline unsigned long long ns_2_cycles(unsigned long long ns)
+{
+       struct cyc2ns_data *data = cyc2ns_read_begin();
+       unsigned long long cyc;
+
+       cyc = (ns << data->cyc2ns_shift) / data->cyc2ns_mul;
+
+       cyc2ns_read_end(data);
+       return cyc;
+}
+
+static inline unsigned long cycles_2_us(unsigned long long cyc)
+{
+       return cycles_2_ns(cyc) / NSEC_PER_USEC;
+}
+
+static inline cycles_t sec_2_cycles(unsigned long sec)
+{
+       return ns_2_cycles(sec * NSEC_PER_SEC);
+}
+
+static inline unsigned long long usec_2_cycles(unsigned long usec)
+{
+       return ns_2_cycles(usec * NSEC_PER_USEC);
 }
 
 /*
@@ -668,16 +702,6 @@ static int wait_completion(struct bau_desc *bau_desc,
                                                                bcp, try);
 }
 
-static inline cycles_t sec_2_cycles(unsigned long sec)
-{
-       unsigned long ns;
-       cycles_t cyc;
-
-       ns = sec * 1000000000;
-       cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id()));
-       return cyc;
-}
-
 /*
  * Our retries are blocked by all destination sw ack resources being
  * in use, and a timeout is pending. In that case hardware immediately
@@ -1070,12 +1094,13 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        unsigned long status;
 
        bcp = &per_cpu(bau_control, cpu);
-       stat = bcp->statp;
-       stat->s_enters++;
 
        if (bcp->nobau)
                return cpumask;
 
+       stat = bcp->statp;
+       stat->s_enters++;
+
        if (bcp->busy) {
                descriptor_status =
                        read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_0);
@@ -1326,16 +1351,6 @@ static void ptc_seq_stop(struct seq_file *file, void *data)
 {
 }
 
-static inline unsigned long long usec_2_cycles(unsigned long microsec)
-{
-       unsigned long ns;
-       unsigned long long cyc;
-
-       ns = microsec * 1000;
-       cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id()));
-       return cyc;
-}
-
 /*
  * Display the statistics thru /proc/sgi_uv/ptc_statistics
  * 'data' points to the cpu number
index a44f457e70a19f7ffce772c5497e0090ee514db6..bad628a620c4ef7647986bf22f63402b7d451be2 100644 (file)
@@ -29,12 +29,10 @@ void __init reserve_real_mode(void)
 void __init setup_real_mode(void)
 {
        u16 real_mode_seg;
-       u32 *rel;
+       const u32 *rel;
        u32 count;
-       u32 *ptr;
-       u16 *seg;
-       int i;
        unsigned char *base;
+       unsigned long phys_base;
        struct trampoline_header *trampoline_header;
        size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
 #ifdef CONFIG_X86_64
@@ -46,23 +44,23 @@ void __init setup_real_mode(void)
 
        memcpy(base, real_mode_blob, size);
 
-       real_mode_seg = __pa(base) >> 4;
+       phys_base = __pa(base);
+       real_mode_seg = phys_base >> 4;
+
        rel = (u32 *) real_mode_relocs;
 
        /* 16-bit segment relocations. */
-       count = rel[0];
-       rel = &rel[1];
-       for (i = 0; i < count; i++) {
-               seg = (u16 *) (base + rel[i]);
+       count = *rel++;
+       while (count--) {
+               u16 *seg = (u16 *) (base + *rel++);
                *seg = real_mode_seg;
        }
 
        /* 32-bit linear relocations. */
-       count = rel[i];
-       rel =  &rel[i + 1];
-       for (i = 0; i < count; i++) {
-               ptr = (u32 *) (base + rel[i]);
-               *ptr += __pa(base);
+       count = *rel++;
+       while (count--) {
+               u32 *ptr = (u32 *) (base + *rel++);
+               *ptr += phys_base;
        }
 
        /* Must be perfomed *after* relocation. */
index 88692871823f9910aeb071ad44a86d8c5c251411..9cac82588cbc49d86bc9457586941c69763d7749 100644 (file)
@@ -73,9 +73,10 @@ KBUILD_CFLAGS        := $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \
                   -march=i386 -mregparm=3 \
                   -include $(srctree)/$(src)/../../boot/code16gcc.h \
                   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
+                  -mno-mmx -mno-sse \
                   $(call cc-option, -ffreestanding) \
                   $(call cc-option, -fno-toplevel-reorder,\
-                       $(call cc-option, -fno-unit-at-a-time)) \
+                  $(call cc-option, -fno-unit-at-a-time)) \
                   $(call cc-option, -fno-stack-protector) \
                   $(call cc-option, -mpreferred-stack-boundary=2)
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
index f932ea61d1c844fd39fc4024570c0c334ee8a0b6..d66c607bdc580941b387981c5ac5837e8274a511 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/linkage.h>
-#include <linux/init.h>
 #include <asm/segment.h>
 #include <asm/page_types.h>
 #include <asm/processor-flags.h>
index c1b2791183e7a60baf62c6754dc0c90ce82a8d19..48ddd76bc4c3d202fe77740bda68a91edd8b1ee2 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/init.h>
 #include <asm/segment.h>
 #include <asm/page_types.h>
 #include "realmode.h"
index bb360dc39d215ea2191fb6cfeada9a2ffba5000a..dac7b20d2f9de40f0244f623e8560c304394c178 100644 (file)
@@ -25,7 +25,6 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/init.h>
 #include <asm/pgtable_types.h>
 #include <asm/page_types.h>
 #include <asm/msr.h>
index aabfb8380a1c6cf91e5af8aaed9dd30bd088d9de..96bc506ac6de7db16e1b0dd7ce161587e60f673c 100644 (file)
 348    i386    process_vm_writev       sys_process_vm_writev           compat_sys_process_vm_writev
 349    i386    kcmp                    sys_kcmp
 350    i386    finit_module            sys_finit_module
+351    i386    sched_setattr           sys_sched_setattr
+352    i386    sched_getattr           sys_sched_getattr
index 38ae65dfd14ffe91904b4fc409ece711f84e61e9..a12bddc7ccea11edf9f7125d8353f04759d2cfb0 100644 (file)
 311    64      process_vm_writev       sys_process_vm_writev
 312    common  kcmp                    sys_kcmp
 313    common  finit_module            sys_finit_module
+314    common  sched_setattr           sys_sched_setattr
+315    common  sched_getattr           sys_sched_getattr
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index f7bab68a4b83e4094db9b70c50292fddd88098c1..11f9285a2ff66726b6c62c7eb608e03f516dcc27 100644 (file)
@@ -722,15 +722,25 @@ static void percpu_init(void)
 
 /*
  * Check to see if a symbol lies in the .data..percpu section.
- * For some as yet not understood reason the "__init_begin"
- * symbol which immediately preceeds the .data..percpu section
- * also shows up as it it were part of it so we do an explict
- * check for that symbol name and ignore it.
+ *
+ * The linker incorrectly associates some symbols with the
+ * .data..percpu section so we also need to check the symbol
+ * name to make sure that we classify the symbol correctly.
+ *
+ * The GNU linker incorrectly associates:
+ *     __init_begin
+ *     __per_cpu_load
+ *
+ * The "gold" linker incorrectly associates:
+ *     init_per_cpu__irq_stack_union
+ *     init_per_cpu__gdt_page
  */
 static int is_percpu_sym(ElfW(Sym) *sym, const char *symname)
 {
        return (sym->st_shndx == per_cpu_shndx) &&
-               strcmp(symname, "__init_begin");
+               strcmp(symname, "__init_begin") &&
+               strcmp(symname, "__per_cpu_load") &&
+               strncmp(symname, "init_per_cpu_", 13);
 }
 
 
index 2ada505067cceca9001bda33bb6aa66941d34b0d..eb5d7a56f8d4b5627171d70c6df94513a99e09d0 100644 (file)
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
 
        ts->tv_nsec = 0;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ns = gtod->wall_time_snsec;
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts)
 
        ts->tv_nsec = 0;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->monotonic_time_sec;
                ns = gtod->monotonic_time_snsec;
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts)
 {
        unsigned long seq;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                ts->tv_sec = gtod->wall_time_coarse.tv_sec;
                ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts)
 {
        unsigned long seq;
        do {
-               seq = read_seqcount_begin_no_lockdep(&gtod->seq);
+               seq = raw_read_seqcount_begin(&gtod->seq);
                ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
                ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
        } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
index 01f5e3b4613cb88212dee66e191711ae8bd814c6..1e13eb8c9656f79b44d9907f0a9290c39978f7c1 100644 (file)
@@ -1,6 +1,5 @@
 #include <asm/page_types.h>
 #include <linux/linkage.h>
-#include <linux/init.h>
 
 __PAGE_ALIGNED_DATA
 
index d6b9a7f42a8a43cddad7443494e20993a704af3b..295f1c7543d8bdc27a602ea0a3949e98b6a9f523 100644 (file)
@@ -1,6 +1,5 @@
 #include <asm/page_types.h>
 #include <linux/linkage.h>
-#include <linux/init.h>
 
 __PAGE_ALIGNED_DATA
 
index ef021677d536538c817021c89f0841ada0ed0c30..e1ee6b51dfc586abd8dc04d1188385a1b6d16d3b 100644 (file)
@@ -9,21 +9,14 @@
 #ifndef _XTENSA_SYSTEM_H
 #define _XTENSA_SYSTEM_H
 
-#define smp_read_barrier_depends() do { } while(0)
-#define read_barrier_depends() do { } while(0)
-
 #define mb()  ({ __asm__ __volatile__("memw" : : : "memory"); })
 #define rmb() barrier()
 #define wmb() mb()
 
 #ifdef CONFIG_SMP
 #error smp_* not defined
-#else
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
 #endif
 
-#define set_mb(var, value)     do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
 
 #endif /* _XTENSA_SYSTEM_H */
index 1610b22edf0992da4cdeb1657688527d5867e76c..86154eab95239fdd6300ddc665f03650b80f1a5b 100644 (file)
@@ -435,9 +435,9 @@ static inline uint64_t blkg_stat_read(struct blkg_stat *stat)
        uint64_t v;
 
        do {
-               start = u64_stats_fetch_begin(&stat->syncp);
+               start = u64_stats_fetch_begin_bh(&stat->syncp);
                v = stat->cnt;
-       } while (u64_stats_fetch_retry(&stat->syncp, start));
+       } while (u64_stats_fetch_retry_bh(&stat->syncp, start));
 
        return v;
 }
@@ -508,9 +508,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
        struct blkg_rwstat tmp;
 
        do {
-               start = u64_stats_fetch_begin(&rwstat->syncp);
+               start = u64_stats_fetch_begin_bh(&rwstat->syncp);
                tmp = *rwstat;
-       } while (u64_stats_fetch_retry(&rwstat->syncp, start));
+       } while (u64_stats_fetch_retry_bh(&rwstat->syncp, start));
 
        return tmp;
 }
index 331e627301eaacbced43537469cb9f9914b6747c..fb6f3c0ffa494f4f2adcce6fc35c95ecf383c9a8 100644 (file)
@@ -502,15 +502,6 @@ void blk_abort_flushes(struct request_queue *q)
        }
 }
 
-static void bio_end_flush(struct bio *bio, int err)
-{
-       if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       if (bio->bi_private)
-               complete(bio->bi_private);
-       bio_put(bio);
-}
-
 /**
  * blkdev_issue_flush - queue a flush
  * @bdev:      blockdev to issue flush for
@@ -526,7 +517,6 @@ static void bio_end_flush(struct bio *bio, int err)
 int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                sector_t *error_sector)
 {
-       DECLARE_COMPLETION_ONSTACK(wait);
        struct request_queue *q;
        struct bio *bio;
        int ret = 0;
@@ -548,13 +538,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                return -ENXIO;
 
        bio = bio_alloc(gfp_mask, 0);
-       bio->bi_end_io = bio_end_flush;
        bio->bi_bdev = bdev;
-       bio->bi_private = &wait;
 
-       bio_get(bio);
-       submit_bio(WRITE_FLUSH, bio);
-       wait_for_completion_io(&wait);
+       ret = submit_bio_wait(WRITE_FLUSH, bio);
 
        /*
         * The driver must store the error location in ->bi_sector, if
@@ -564,9 +550,6 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
        if (error_sector)
                *error_sector = bio->bi_sector;
 
-       if (!bio_flagged(bio, BIO_UPTODATE))
-               ret = -EIO;
-
        bio_put(bio);
        return ret;
 }
index ba6cf8e9aa0a598a50d4b24eb2c8f2914bf5c5ef..b91ce75bd35db9e00edb4c4af0a0e3036fd66df8 100644 (file)
@@ -335,9 +335,22 @@ static struct kobj_type blk_mq_hw_ktype = {
 void blk_mq_unregister_disk(struct gendisk *disk)
 {
        struct request_queue *q = disk->queue;
+       struct blk_mq_hw_ctx *hctx;
+       struct blk_mq_ctx *ctx;
+       int i, j;
+
+       queue_for_each_hw_ctx(q, hctx, i) {
+               hctx_for_each_ctx(hctx, ctx, j) {
+                       kobject_del(&ctx->kobj);
+                       kobject_put(&ctx->kobj);
+               }
+               kobject_del(&hctx->kobj);
+               kobject_put(&hctx->kobj);
+       }
 
        kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
        kobject_del(&q->mq_kobj);
+       kobject_put(&q->mq_kobj);
 
        kobject_put(&disk_to_dev(disk)->kobj);
 }
index cdc629cf075b74f27f7801565ec3d90f3e299ce0..c79126e110308e8b1ea4b322506a425ceeb3085c 100644 (file)
@@ -202,10 +202,12 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
                if (rq) {
                        blk_mq_rq_ctx_init(q, ctx, rq, rw);
                        break;
-               } else if (!(gfp & __GFP_WAIT))
-                       break;
+               }
 
                blk_mq_put_ctx(ctx);
+               if (!(gfp & __GFP_WAIT))
+                       break;
+
                __blk_mq_run_hw_queue(hctx);
                blk_mq_wait_for_tags(hctx->tags);
        } while (1);
@@ -222,7 +224,8 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
                return NULL;
 
        rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved);
-       blk_mq_put_ctx(rq->mq_ctx);
+       if (rq)
+               blk_mq_put_ctx(rq->mq_ctx);
        return rq;
 }
 
@@ -235,7 +238,8 @@ struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw,
                return NULL;
 
        rq = blk_mq_alloc_request_pinned(q, rw, gfp, true);
-       blk_mq_put_ctx(rq->mq_ctx);
+       if (rq)
+               blk_mq_put_ctx(rq->mq_ctx);
        return rq;
 }
 EXPORT_SYMBOL(blk_mq_alloc_reserved_request);
@@ -308,12 +312,12 @@ void blk_mq_complete_request(struct request *rq, int error)
 
        blk_account_io_completion(rq, bytes);
 
+       blk_account_io_done(rq);
+
        if (rq->end_io)
                rq->end_io(rq, error);
        else
                blk_mq_free_request(rq);
-
-       blk_account_io_done(rq);
 }
 
 void __blk_mq_end_io(struct request *rq, int error)
index ef5356cd280a54c086e4f8ff964245e38748a391..850246206b1258a697f83e86c39acc9b0a17f973 100644 (file)
@@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
        struct hash_ctx *ctx = ask->private;
        int err;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        lock_sock(sk);
        sg_init_table(ctx->sgl.sg, 1);
        sg_set_page(ctx->sgl.sg, page, size, offset);
index 6a6dfc062d2a47f04449fbb0e1c3f3852be337dc..a19c027b29bde504ac8eae4b4572947a69ed2335 100644 (file)
@@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
        struct skcipher_sg_list *sgl;
        int err = -EINVAL;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        lock_sock(sk);
        if (!ctx->more && ctx->used)
                goto unlock;
index 1875e7026e8f7fad661e2051cdc139f733d6c19a..e1223559d5dfd233cbc15184c9dc607fb34fae2e 100644 (file)
@@ -380,9 +380,10 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
        if (!err) {
                struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
                struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-               struct ablkcipher_request *abreq = aead_request_ctx(areq);
-               u8 *iv = (u8 *)(abreq + 1) +
-                        crypto_ablkcipher_reqsize(ctx->enc);
+               struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq);
+               struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+                                                           + ctx->reqoff);
+               u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc);
 
                err = crypto_authenc_genicv(areq, iv, 0);
        }
index 3e05499d183aa8e49d41b83be448e7f52d76b10c..1df84217f7c9320dbfc5174f91ce394667c36447 100644 (file)
@@ -271,7 +271,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
        }
 
        /* compute plaintext into mac */
-       get_data_to_compute(cipher, pctx, plain, cryptlen);
+       if (cryptlen)
+               get_data_to_compute(cipher, pctx, plain, cryptlen);
 
 out:
        return err;
index 1ab8258fcf560735237a198b2037c102e229d20b..001f07cdb828d59101521162109b9f101c34a319 100644 (file)
@@ -1242,6 +1242,10 @@ static int do_test(int m)
                ret += tcrypt_test("cmac(des3_ede)");
                break;
 
+       case 155:
+               ret += tcrypt_test("authenc(hmac(sha1),cbc(aes))");
+               break;
+
        case 200:
                test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
                                speed_template_16_24_32);
index 432afc03e7c3f9c1040ac54033950eb9e17c0727..77955507f6f1f73a044554a7d738074c98f9829e 100644 (file)
@@ -503,16 +503,16 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                goto out;
                        }
 
-                       sg_init_one(&sg[0], input,
-                                   template[i].ilen + (enc ? authsize : 0));
-
                        if (diff_dst) {
                                output = xoutbuf[0];
                                output += align_offset;
+                               sg_init_one(&sg[0], input, template[i].ilen);
                                sg_init_one(&sgout[0], output,
+                                           template[i].rlen);
+                       } else {
+                               sg_init_one(&sg[0], input,
                                            template[i].ilen +
                                                (enc ? authsize : 0));
-                       } else {
                                output = input;
                        }
 
@@ -612,12 +612,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                memcpy(q, template[i].input + temp,
                                       template[i].tap[k]);
 
-                               n = template[i].tap[k];
-                               if (k == template[i].np - 1 && enc)
-                                       n += authsize;
-                               if (offset_in_page(q) + n < PAGE_SIZE)
-                                       q[n] = 0;
-
                                sg_set_buf(&sg[k], q, template[i].tap[k]);
 
                                if (diff_dst) {
@@ -625,13 +619,17 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                            offset_in_page(IDX[k]);
 
                                        memset(q, 0, template[i].tap[k]);
-                                       if (offset_in_page(q) + n < PAGE_SIZE)
-                                               q[n] = 0;
 
                                        sg_set_buf(&sgout[k], q,
                                                   template[i].tap[k]);
                                }
 
+                               n = template[i].tap[k];
+                               if (k == template[i].np - 1 && enc)
+                                       n += authsize;
+                               if (offset_in_page(q) + n < PAGE_SIZE)
+                                       q[n] = 0;
+
                                temp += template[i].tap[k];
                        }
 
@@ -650,10 +648,10 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                        goto out;
                                }
 
-                               sg[k - 1].length += authsize;
-
                                if (diff_dst)
                                        sgout[k - 1].length += authsize;
+                               else
+                                       sg[k - 1].length += authsize;
                        }
 
                        sg_init_table(asg, template[i].anp);
index 5d9248526d780b06c51bee967cdd088c9c90e5e5..4770de5707b9b9eb0a4c27f14c7ec9ad13035257 100644 (file)
@@ -348,7 +348,6 @@ source "drivers/acpi/apei/Kconfig"
 config ACPI_EXTLOG
        tristate "Extended Error Log support"
        depends on X86_MCE && X86_LOCAL_APIC
-       select EFI
        select UEFI_CPER
        default n
        help
index 8711e3797165fa73fd0c401cedbb54c61eb68e4a..3c2e4aa529c479e92090c8862deaadcf0a8645e5 100644 (file)
@@ -207,7 +207,7 @@ static int acpi_ac_probe(struct platform_device *pdev)
                goto end;
 
        result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac);
        if (result) {
                power_supply_unregister(&ac->charger);
                goto end;
@@ -255,7 +255,7 @@ static int acpi_ac_remove(struct platform_device *pdev)
                return -EINVAL;
 
        acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
+                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler);
 
        ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
index a6869e110ce5650a86b6f666bc28347031c16275..5d33c54154050b452b996e4433ab676e4829f50e 100644 (file)
@@ -12,6 +12,7 @@
 #include <acpi/acpi_bus.h>
 #include <linux/cper.h>
 #include <linux/ratelimit.h>
+#include <linux/edac.h>
 #include <asm/cpu.h>
 #include <asm/mce.h>
 
@@ -43,6 +44,8 @@ struct extlog_l1_head {
        u8  rev1[12];
 };
 
+static int old_edac_report_status;
+
 static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295";
 
 /* L1 table related physical address */
@@ -150,7 +153,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
 
        rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu);
 
-       return NOTIFY_DONE;
+       return NOTIFY_STOP;
 }
 
 static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret)
@@ -231,8 +234,12 @@ static int __init extlog_init(void)
        u64 cap;
        int rc;
 
-       rc = -ENODEV;
+       if (get_edac_report_status() == EDAC_REPORTING_FORCE) {
+               pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n");
+               return -EPERM;
+       }
 
+       rc = -ENODEV;
        rdmsrl(MSR_IA32_MCG_CAP, cap);
        if (!(cap & MCG_ELOG_P))
                return rc;
@@ -287,6 +294,12 @@ static int __init extlog_init(void)
        if (elog_buf == NULL)
                goto err_release_elog;
 
+       /*
+        * eMCA event report method has higher priority than EDAC method,
+        * unless EDAC event report method is mandatory.
+        */
+       old_edac_report_status = get_edac_report_status();
+       set_edac_report_status(EDAC_REPORTING_DISABLED);
        mce_register_decode_chain(&extlog_mce_dec);
        /* enable OS to be involved to take over management from BIOS */
        ((struct extlog_l1_head *)extlog_l1_addr)->flags |= FLAG_OS_OPTIN;
@@ -308,6 +321,7 @@ err:
 
 static void __exit extlog_exit(void)
 {
+       set_edac_report_status(old_edac_report_status);
        mce_unregister_decode_chain(&extlog_mce_dec);
        ((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
        if (extlog_l1_addr)
index fc6008fbce35bd99f390d15af6e7471b1ca0438a..509452a62f964d6914ef1bbe2a4f7f26b9ff5076 100644 (file)
@@ -193,10 +193,7 @@ static int power_saving_thread(void *data)
                                        CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
                        stop_critical_timings();
 
-                       __monitor((void *)&current_thread_info()->flags, 0, 0);
-                       smp_mb();
-                       if (!need_resched())
-                               __mwait(power_saving_mwait_eax, 1);
+                       mwait_idle_with_hints(power_saving_mwait_eax, 1);
 
                        start_critical_timings();
                        if (lapic_marked_unstable)
index 786294bb682c104f111525ca17df7ccfafab0d88..3650b21832279a91568266208059296fadfab94c 100644 (file)
@@ -2,7 +2,6 @@ config ACPI_APEI
        bool "ACPI Platform Error Interface (APEI)"
        select MISC_FILESYSTEMS
        select PSTORE
-       select EFI
        select UEFI_CPER
        depends on X86
        help
index 6d2c49b86b7fa82434bdb0b2ce1906c95dce00ca..e55584a072c632e35ad221f3cc4855e915baa0b0 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/rculist.h>
 #include <linux/interrupt.h>
 #include <linux/debugfs.h>
+#include <asm/unaligned.h>
 
 #include "apei-internal.h"
 
@@ -567,8 +568,7 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
        bit_offset = reg->bit_offset;
        access_size_code = reg->access_width;
        space_id = reg->space_id;
-       /* Handle possible alignment issues */
-       memcpy(paddr, &reg->address, sizeof(*paddr));
+       *paddr = get_unaligned(&reg->address);
        if (!*paddr) {
                pr_warning(FW_BUG APEI_PFX
                           "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
index fb57d03e698bd3b7ae2d4194d69dc3478ca09025..7dcc8a824aae304f05a52b7fc9f087e36916f093 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <acpi/acpi.h>
+#include <asm/unaligned.h>
 
 #include "apei-internal.h"
 
@@ -216,7 +217,7 @@ static void check_vendor_extension(u64 paddr,
 static void *einj_get_parameter_address(void)
 {
        int i;
-       u64 paddrv4 = 0, paddrv5 = 0;
+       u64 pa_v4 = 0, pa_v5 = 0;
        struct acpi_whea_header *entry;
 
        entry = EINJ_TAB_ENTRY(einj_tab);
@@ -225,30 +226,28 @@ static void *einj_get_parameter_address(void)
                    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
                    entry->register_region.space_id ==
                    ACPI_ADR_SPACE_SYSTEM_MEMORY)
-                       memcpy(&paddrv4, &entry->register_region.address,
-                              sizeof(paddrv4));
+                       pa_v4 = get_unaligned(&entry->register_region.address);
                if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS &&
                    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
                    entry->register_region.space_id ==
                    ACPI_ADR_SPACE_SYSTEM_MEMORY)
-                       memcpy(&paddrv5, &entry->register_region.address,
-                              sizeof(paddrv5));
+                       pa_v5 = get_unaligned(&entry->register_region.address);
                entry++;
        }
-       if (paddrv5) {
+       if (pa_v5) {
                struct set_error_type_with_address *v5param;
 
-               v5param = acpi_os_map_memory(paddrv5, sizeof(*v5param));
+               v5param = acpi_os_map_memory(pa_v5, sizeof(*v5param));
                if (v5param) {
                        acpi5 = 1;
-                       check_vendor_extension(paddrv5, v5param);
+                       check_vendor_extension(pa_v5, v5param);
                        return v5param;
                }
        }
-       if (param_extension && paddrv4) {
+       if (param_extension && pa_v4) {
                struct einj_parameter *v4param;
 
-               v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
+               v4param = acpi_os_map_memory(pa_v4, sizeof(*v4param));
                if (!v4param)
                        return NULL;
                if (v4param->reserved1 || v4param->reserved2) {
@@ -416,7 +415,8 @@ out:
        return rc;
 }
 
-static int __einj_error_inject(u32 type, u64 param1, u64 param2)
+static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
+                              u64 param3, u64 param4)
 {
        struct apei_exec_context ctx;
        u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT;
@@ -446,6 +446,12 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
                                break;
                        }
                        v5param->flags = vendor_flags;
+               } else if (flags) {
+                               v5param->flags = flags;
+                               v5param->memory_address = param1;
+                               v5param->memory_address_range = param2;
+                               v5param->apicid = param3;
+                               v5param->pcie_sbdf = param4;
                } else {
                        switch (type) {
                        case ACPI_EINJ_PROCESSOR_CORRECTABLE:
@@ -514,11 +520,17 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
 }
 
 /* Inject the specified hardware error */
-static int einj_error_inject(u32 type, u64 param1, u64 param2)
+static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
+                            u64 param3, u64 param4)
 {
        int rc;
        unsigned long pfn;
 
+       /* If user manually set "flags", make sure it is legal */
+       if (flags && (flags &
+               ~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF)))
+               return -EINVAL;
+
        /*
         * We need extra sanity checks for memory errors.
         * Other types leap directly to injection.
@@ -532,7 +544,7 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2)
        if (type & ACPI5_VENDOR_BIT) {
                if (vendor_flags != SETWA_FLAGS_MEM)
                        goto inject;
-       } else if (!(type & MEM_ERROR_MASK))
+       } else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM))
                goto inject;
 
        /*
@@ -546,15 +558,18 @@ static int einj_error_inject(u32 type, u64 param1, u64 param2)
 
 inject:
        mutex_lock(&einj_mutex);
-       rc = __einj_error_inject(type, param1, param2);
+       rc = __einj_error_inject(type, flags, param1, param2, param3, param4);
        mutex_unlock(&einj_mutex);
 
        return rc;
 }
 
 static u32 error_type;
+static u32 error_flags;
 static u64 error_param1;
 static u64 error_param2;
+static u64 error_param3;
+static u64 error_param4;
 static struct dentry *einj_debug_dir;
 
 static int available_error_type_show(struct seq_file *m, void *v)
@@ -648,7 +663,8 @@ static int error_inject_set(void *data, u64 val)
        if (!error_type)
                return -EINVAL;
 
-       return einj_error_inject(error_type, error_param1, error_param2);
+       return einj_error_inject(error_type, error_flags, error_param1, error_param2,
+               error_param3, error_param4);
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL,
@@ -729,6 +745,10 @@ static int __init einj_init(void)
        rc = -ENOMEM;
        einj_param = einj_get_parameter_address();
        if ((param_extension || acpi5) && einj_param) {
+               fentry = debugfs_create_x32("flags", S_IRUSR | S_IWUSR,
+                                           einj_debug_dir, &error_flags);
+               if (!fentry)
+                       goto err_unmap;
                fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
                                            einj_debug_dir, &error_param1);
                if (!fentry)
@@ -737,6 +757,14 @@ static int __init einj_init(void)
                                            einj_debug_dir, &error_param2);
                if (!fentry)
                        goto err_unmap;
+               fentry = debugfs_create_x64("param3", S_IRUSR | S_IWUSR,
+                                           einj_debug_dir, &error_param3);
+               if (!fentry)
+                       goto err_unmap;
+               fentry = debugfs_create_x64("param4", S_IRUSR | S_IWUSR,
+                                           einj_debug_dir, &error_param4);
+               if (!fentry)
+                       goto err_unmap;
 
                fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
                                            einj_debug_dir, &notrigger);
index 26311f23c824f91354b3e47fe6fa5e5e448275dc..ed65e9c4b5b0415c1dcc77690a4add725a49a0bd 100644 (file)
@@ -611,7 +611,7 @@ static void __erst_record_id_cache_compact(void)
                if (entries[i] == APEI_ERST_INVALID_RECORD_ID)
                        continue;
                if (wpos != i)
-                       memcpy(&entries[wpos], &entries[i], sizeof(entries[i]));
+                       entries[wpos] = entries[i];
                wpos++;
        }
        erst_record_id_cache.len = wpos;
@@ -942,6 +942,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info erst_info = {
        .owner          = THIS_MODULE,
        .name           = "erst",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = erst_open_pstore,
        .close          = erst_close_pstore,
        .read           = erst_reader,
index a30bc313787be65523797da950f3982e13844c35..46766ef7ef5de9be5cfa6f95d7f81a6039f9e4ec 100644 (file)
@@ -413,27 +413,31 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev)
 {
 #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
        unsigned long pfn;
+       int flags = -1;
        int sec_sev = ghes_severity(gdata->error_severity);
        struct cper_sec_mem_err *mem_err;
        mem_err = (struct cper_sec_mem_err *)(gdata + 1);
 
-       if (sec_sev == GHES_SEV_CORRECTED &&
-           (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) &&
-           (mem_err->validation_bits & CPER_MEM_VALID_PA)) {
-               pfn = mem_err->physical_addr >> PAGE_SHIFT;
-               if (pfn_valid(pfn))
-                       memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE);
-               else if (printk_ratelimit())
-                       pr_warn(FW_WARN GHES_PFX
-                       "Invalid address in generic error data: %#llx\n",
-                       mem_err->physical_addr);
-       }
-       if (sev == GHES_SEV_RECOVERABLE &&
-           sec_sev == GHES_SEV_RECOVERABLE &&
-           mem_err->validation_bits & CPER_MEM_VALID_PA) {
-               pfn = mem_err->physical_addr >> PAGE_SHIFT;
-               memory_failure_queue(pfn, 0, 0);
+       if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
+               return;
+
+       pfn = mem_err->physical_addr >> PAGE_SHIFT;
+       if (!pfn_valid(pfn)) {
+               pr_warn_ratelimited(FW_WARN GHES_PFX
+               "Invalid address in generic error data: %#llx\n",
+               mem_err->physical_addr);
+               return;
        }
+
+       /* iff following two events can be handled properly by now */
+       if (sec_sev == GHES_SEV_CORRECTED &&
+           (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED))
+               flags = MF_SOFT_OFFLINE;
+       if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE)
+               flags = 0;
+
+       if (flags != -1)
+               memory_failure_queue(pfn, 0, flags);
 #endif
 }
 
@@ -453,8 +457,7 @@ static void ghes_do_proc(struct ghes *ghes,
                        ghes_edac_report_mem_error(ghes, sev, mem_err);
 
 #ifdef CONFIG_X86_MCE
-                       apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED,
-                                                 mem_err);
+                       apei_mce_report_mem_error(sev, mem_err);
 #endif
                        ghes_handle_memory_failure(gdata, sev);
                }
index fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68..5876a49dfd386a4653325d99fcc69aa8452b12e1 100644 (file)
@@ -62,6 +62,7 @@ MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
 MODULE_DESCRIPTION("ACPI Battery Driver");
 MODULE_LICENSE("GPL");
 
+static int battery_bix_broken_package;
 static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -416,7 +417,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
                return -ENODEV;
        }
-       if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+
+       if (battery_bix_broken_package)
+               result = extract_package(battery, buffer.pointer,
+                               extended_info_offsets + 1,
+                               ARRAY_SIZE(extended_info_offsets) - 1);
+       else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
                result = extract_package(battery, buffer.pointer,
                                extended_info_offsets,
                                ARRAY_SIZE(extended_info_offsets));
@@ -754,6 +760,17 @@ static int battery_notify(struct notifier_block *nb,
        return 0;
 }
 
+static struct dmi_system_id bat_dmi_table[] = {
+       {
+               .ident = "NEC LZ750/LS",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
+               },
+       },
+       {},
+};
+
 static int acpi_battery_add(struct acpi_device *device)
 {
        int result = 0;
@@ -846,6 +863,9 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 {
        if (acpi_disabled)
                return;
+
+       if (dmi_check_system(bat_dmi_table))
+               battery_bix_broken_package = 1;
        acpi_bus_register_driver(&acpi_battery_driver);
 }
 
index bba9b72e25f8235e6d12593bdd16bb378c7af25a..0710004055c809f3059cde2337373503666fd96f 100644 (file)
@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data)
 }
 EXPORT_SYMBOL(acpi_bus_get_private_data);
 
+void acpi_bus_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       if (adev)
+               adev->flags.no_hotplug = true;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
+
 static void acpi_print_osc_error(acpi_handle handle,
        struct acpi_osc_context *context, char *error)
 {
index 644516d9bde6cf18a824d29c3ae1730de30fd1a6..f90c56c8379e8c9c69d99a0a5366780a850fe3b9 100644 (file)
@@ -727,11 +727,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
        if (unlikely(!pr))
                return -EINVAL;
 
-       if (cx->entry_method == ACPI_CSTATE_FFH) {
-               if (current_set_polling_and_test())
-                       return -EINVAL;
-       }
-
        lapic_timer_state_broadcast(pr, cx, 1);
        acpi_idle_do_entry(cx);
 
@@ -785,11 +780,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        if (unlikely(!pr))
                return -EINVAL;
 
-       if (cx->entry_method == ACPI_CSTATE_FFH) {
-               if (current_set_polling_and_test())
-                       return -EINVAL;
-       }
-
        /*
         * Must be done before busmaster disable as we might need to
         * access HPET !
@@ -841,11 +831,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                }
        }
 
-       if (cx->entry_method == ACPI_CSTATE_FFH) {
-               if (current_set_polling_and_test())
-                       return -EINVAL;
-       }
-
        acpi_unlazy_tlb(smp_processor_id());
 
        /* Tell the scheduler that we are going deep-idle: */
index 14f1e95063380a5e2a315428fc8a4d5e8bcc39d3..e3a92a6da39ae258cf9a4094f4293799e378271b 100644 (file)
@@ -427,6 +427,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9128 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
+                        PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9170 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
@@ -1238,15 +1241,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       /* AHCI controllers often implement SFF compatible interface.
-        * Grab all PCI BARs just in case.
-        */
-       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
-       if (rc == -EBUSY)
-               pcim_pin_device(pdev);
-       if (rc)
-               return rc;
-
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
            (pdev->device == 0x2652 || pdev->device == 0x2653)) {
                u8 map;
@@ -1263,6 +1257,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
+       /* AHCI controllers often implement SFF compatible interface.
+        * Grab all PCI BARs just in case.
+        */
+       rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME);
+       if (rc == -EBUSY)
+               pcim_pin_device(pdev);
+       if (rc)
+               return rc;
+
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        if (!hpriv)
                return -ENOMEM;
index ae2d73fe321e2f2c62d8e5709a788905edfd5a89..3e23e9941dad0080d629581723243c6550d4d476 100644 (file)
@@ -113,7 +113,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
        /*
         * set PHY Paremeters, two steps to configure the GPR13,
         * one write for rest of parameters, mask of first write
-        * is 0x07fffffd, and the other one write for setting
+        * is 0x07ffffff, and the other one write for setting
         * the mpll_clk_en.
         */
        regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
@@ -124,6 +124,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
                        | 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
index 75b93678bbcd7f4231e0c2028995795487db671c..1393a5890ed5356e5ef36965ea74e49e226c0a29 100644 (file)
@@ -2149,9 +2149,16 @@ static int ata_dev_config_ncq(struct ata_device *dev,
                                    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
                                    err_mask);
                } else {
+                       u8 *cmds = dev->ncq_send_recv_cmds;
+
                        dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
-                       memcpy(dev->ncq_send_recv_cmds, ap->sector_buf,
-                               ATA_LOG_NCQ_SEND_RECV_SIZE);
+                       memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+
+                       if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
+                               ata_dev_dbg(dev, "disabling queued TRIM support\n");
+                               cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
+                                       ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
+                       }
                }
        }
 
@@ -4156,6 +4163,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
+       /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+       { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
@@ -4202,6 +4212,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
+       /* 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, },
+
        /* End Marker */
        { }
 };
@@ -6519,6 +6533,7 @@ static int __init ata_parse_force_one(char **cur,
                { "norst",      .lflags         = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
                { "rstonce",    .lflags         = ATA_LFLAG_RST_ONCE },
                { "atapi_dmadir", .horkage_on   = ATA_HORKAGE_ATAPI_DMADIR },
+               { "disable",    .horkage_on     = ATA_HORKAGE_DISABLE },
        };
        char *start = *cur, *p = *cur;
        char *id, *val, *endp;
index db6dfcfa3e2ee932190069290814f2a71bc8f3f6..377eb889f555dd2029c46a01254a3a204744ac81 100644 (file)
@@ -3625,6 +3625,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                shost->max_lun = 1;
                shost->max_channel = 1;
                shost->max_cmd_len = 16;
+               shost->no_write_same = 1;
 
                /* Schedule policy is determined by ->qc_defer()
                 * callback and it needs to see every deferred qc.
@@ -3871,6 +3872,27 @@ void ata_scsi_hotplug(struct work_struct *work)
                return;
        }
 
+       /*
+        * XXX - UGLY HACK
+        *
+        * The block layer suspend/resume path is fundamentally broken due
+        * to freezable kthreads and workqueue and may deadlock if a block
+        * device gets removed while resume is in progress.  I don't know
+        * what the solution is short of removing freezable kthreads and
+        * workqueues altogether.
+        *
+        * The following is an ugly hack to avoid kicking off device
+        * removal while freezer is active.  This is a joke but does avoid
+        * this particular deadlock scenario.
+        *
+        * https://bugzilla.kernel.org/show_bug.cgi?id=62801
+        * http://marc.info/?l=linux-kernel&m=138695698516487
+        */
+#ifdef CONFIG_FREEZER
+       while (pm_freezing)
+               msleep(10);
+#endif
+
        DPRINTK("ENTER\n");
        mutex_lock(&ap->scsi_scan_mutex);
 
index fe3ca0989b14cac2e712ef2778f2a1b7e528c85b..1ad2f62d34b98fd0b41be9a239827e1634327c54 100644 (file)
@@ -83,6 +83,10 @@ static struct pci_driver sis_pci_driver = {
        .id_table               = sis_pci_tbl,
        .probe                  = sis_init_one,
        .remove                 = ata_pci_remove_one,
+#ifdef CONFIG_PM
+       .suspend                = ata_pci_device_suspend,
+       .resume                 = ata_pci_device_resume,
+#endif
 };
 
 static struct scsi_host_template sis_sht = {
index 98745dd77e8ccfb75080d47fb099448d81d1eaa8..81f977510775460fa2bf8b0bd500c69027c02274 100644 (file)
@@ -40,7 +40,7 @@ static int regmap_mmio_gather_write(void *context,
 
        BUG_ON(reg_size != 4);
 
-       if (ctx->clk) {
+       if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
@@ -73,7 +73,7 @@ static int regmap_mmio_gather_write(void *context,
                offset += ctx->val_bytes;
        }
 
-       if (ctx->clk)
+       if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
 
        return 0;
@@ -96,7 +96,7 @@ static int regmap_mmio_read(void *context,
 
        BUG_ON(reg_size != 4);
 
-       if (ctx->clk) {
+       if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
@@ -129,7 +129,7 @@ static int regmap_mmio_read(void *context,
                offset += ctx->val_bytes;
        }
 
-       if (ctx->clk)
+       if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
 
        return 0;
@@ -139,7 +139,7 @@ static void regmap_mmio_free_context(void *context)
 {
        struct regmap_mmio_context *ctx = context;
 
-       if (ctx->clk) {
+       if (!IS_ERR(ctx->clk)) {
                clk_unprepare(ctx->clk);
                clk_put(ctx->clk);
        }
@@ -209,6 +209,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
 
        ctx->regs = regs;
        ctx->val_bytes = config->val_bits / 8;
+       ctx->clk = ERR_PTR(-ENODEV);
 
        if (clk_id == NULL)
                return ctx;
index 9c021d9cace0fcc74080ccec7b5a2b3933c65f2a..c2e00210094995fde1cc69998d03f98e01c75fb1 100644 (file)
@@ -1549,7 +1549,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
                                                val + (i * val_bytes),
                                                val_bytes);
                        if (ret != 0)
-                               return ret;
+                               goto out;
                }
        } else {
                ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
@@ -1743,7 +1743,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
 /**
  * regmap_read(): Read a value from a single register
  *
- * @map: Register map to write to
+ * @map: Register map to read from
  * @reg: Register to be read from
  * @val: Pointer to store read value
  *
@@ -1770,7 +1770,7 @@ EXPORT_SYMBOL_GPL(regmap_read);
 /**
  * regmap_raw_read(): Read raw data from the device
  *
- * @map: Register map to write to
+ * @map: Register map to read from
  * @reg: First register to be read from
  * @val: Pointer to store read value
  * @val_len: Size of data to read
@@ -1882,7 +1882,7 @@ EXPORT_SYMBOL_GPL(regmap_fields_read);
 /**
  * regmap_bulk_read(): Read multiple registers from the device
  *
- * @map: Register map to write to
+ * @map: Register map to read from
  * @reg: First register to be read from
  * @val: Pointer to store read value, in native register size for device
  * @val_count: Number of registers to read
index ea192ec029c45bf7354d8184b44e1eb460cdbf77..83a598ebb65a4ab7699d1dcebe1b44b42ea8ae5a 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+
 #include <linux/moduleparam.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -65,7 +66,7 @@ enum {
        NULL_Q_MQ               = 2,
 };
 
-static int submit_queues = 1;
+static int submit_queues;
 module_param(submit_queues, int, S_IRUGO);
 MODULE_PARM_DESC(submit_queues, "Number of submission queues");
 
@@ -101,9 +102,9 @@ static int hw_queue_depth = 64;
 module_param(hw_queue_depth, int, S_IRUGO);
 MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: 64");
 
-static bool use_per_node_hctx = true;
+static bool use_per_node_hctx = false;
 module_param(use_per_node_hctx, bool, S_IRUGO);
-MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: true");
+MODULE_PARM_DESC(use_per_node_hctx, "Use per-node allocation for hardware context queues. Default: false");
 
 static void put_tag(struct nullb_queue *nq, unsigned int tag)
 {
@@ -346,8 +347,37 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq)
 
 static struct blk_mq_hw_ctx *null_alloc_hctx(struct blk_mq_reg *reg, unsigned int hctx_index)
 {
-       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL,
-                               hctx_index);
+       int b_size = DIV_ROUND_UP(reg->nr_hw_queues, nr_online_nodes);
+       int tip = (reg->nr_hw_queues % nr_online_nodes);
+       int node = 0, i, n;
+
+       /*
+        * Split submit queues evenly wrt to the number of nodes. If uneven,
+        * fill the first buckets with one extra, until the rest is filled with
+        * no extra.
+        */
+       for (i = 0, n = 1; i < hctx_index; i++, n++) {
+               if (n % b_size == 0) {
+                       n = 0;
+                       node++;
+
+                       tip--;
+                       if (!tip)
+                               b_size = reg->nr_hw_queues / nr_online_nodes;
+               }
+       }
+
+       /*
+        * A node might not be online, therefore map the relative node id to the
+        * real node id.
+        */
+       for_each_online_node(n) {
+               if (!node)
+                       break;
+               node--;
+       }
+
+       return kzalloc_node(sizeof(struct blk_mq_hw_ctx), GFP_KERNEL, n);
 }
 
 static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
@@ -355,16 +385,24 @@ static void null_free_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_index)
        kfree(hctx);
 }
 
+static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq)
+{
+       BUG_ON(!nullb);
+       BUG_ON(!nq);
+
+       init_waitqueue_head(&nq->wait);
+       nq->queue_depth = nullb->queue_depth;
+}
+
 static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
                          unsigned int index)
 {
        struct nullb *nullb = data;
        struct nullb_queue *nq = &nullb->queues[index];
 
-       init_waitqueue_head(&nq->wait);
-       nq->queue_depth = nullb->queue_depth;
-       nullb->nr_queues++;
        hctx->driver_data = nq;
+       null_init_queue(nullb, nq);
+       nullb->nr_queues++;
 
        return 0;
 }
@@ -387,10 +425,7 @@ static void null_del_dev(struct nullb *nullb)
        list_del_init(&nullb->list);
 
        del_gendisk(nullb->disk);
-       if (queue_mode == NULL_Q_MQ)
-               blk_mq_free_queue(nullb->q);
-       else
-               blk_cleanup_queue(nullb->q);
+       blk_cleanup_queue(nullb->q);
        put_disk(nullb->disk);
        kfree(nullb);
 }
@@ -417,13 +452,13 @@ static int setup_commands(struct nullb_queue *nq)
 
        nq->cmds = kzalloc(nq->queue_depth * sizeof(*cmd), GFP_KERNEL);
        if (!nq->cmds)
-               return 1;
+               return -ENOMEM;
 
        tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG;
        nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL);
        if (!nq->tag_map) {
                kfree(nq->cmds);
-               return 1;
+               return -ENOMEM;
        }
 
        for (i = 0; i < nq->queue_depth; i++) {
@@ -454,33 +489,37 @@ static void cleanup_queues(struct nullb *nullb)
 
 static int setup_queues(struct nullb *nullb)
 {
-       struct nullb_queue *nq;
-       int i;
-
-       nullb->queues = kzalloc(submit_queues * sizeof(*nq), GFP_KERNEL);
+       nullb->queues = kzalloc(submit_queues * sizeof(struct nullb_queue),
+                                                               GFP_KERNEL);
        if (!nullb->queues)
-               return 1;
+               return -ENOMEM;
 
        nullb->nr_queues = 0;
        nullb->queue_depth = hw_queue_depth;
 
-       if (queue_mode == NULL_Q_MQ)
-               return 0;
+       return 0;
+}
+
+static int init_driver_queues(struct nullb *nullb)
+{
+       struct nullb_queue *nq;
+       int i, ret = 0;
 
        for (i = 0; i < submit_queues; i++) {
                nq = &nullb->queues[i];
-               init_waitqueue_head(&nq->wait);
-               nq->queue_depth = hw_queue_depth;
-               if (setup_commands(nq))
-                       break;
+
+               null_init_queue(nullb, nq);
+
+               ret = setup_commands(nq);
+               if (ret)
+                       goto err_queue;
                nullb->nr_queues++;
        }
 
-       if (i == submit_queues)
-               return 0;
-
+       return 0;
+err_queue:
        cleanup_queues(nullb);
-       return 1;
+       return ret;
 }
 
 static int null_add_dev(void)
@@ -495,34 +534,36 @@ static int null_add_dev(void)
 
        spin_lock_init(&nullb->lock);
 
+       if (queue_mode == NULL_Q_MQ && use_per_node_hctx)
+               submit_queues = nr_online_nodes;
+
        if (setup_queues(nullb))
                goto err;
 
        if (queue_mode == NULL_Q_MQ) {
                null_mq_reg.numa_node = home_node;
                null_mq_reg.queue_depth = hw_queue_depth;
+               null_mq_reg.nr_hw_queues = submit_queues;
 
                if (use_per_node_hctx) {
                        null_mq_reg.ops->alloc_hctx = null_alloc_hctx;
                        null_mq_reg.ops->free_hctx = null_free_hctx;
-
-                       null_mq_reg.nr_hw_queues = nr_online_nodes;
                } else {
                        null_mq_reg.ops->alloc_hctx = blk_mq_alloc_single_hw_queue;
                        null_mq_reg.ops->free_hctx = blk_mq_free_single_hw_queue;
-
-                       null_mq_reg.nr_hw_queues = submit_queues;
                }
 
                nullb->q = blk_mq_init_queue(&null_mq_reg, nullb);
        } else if (queue_mode == NULL_Q_BIO) {
                nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
                blk_queue_make_request(nullb->q, null_queue_bio);
+               init_driver_queues(nullb);
        } else {
                nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
                blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
                if (nullb->q)
                        blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
+               init_driver_queues(nullb);
        }
 
        if (!nullb->q)
@@ -534,10 +575,7 @@ static int null_add_dev(void)
        disk = nullb->disk = alloc_disk_node(1, home_node);
        if (!disk) {
 queue_fail:
-               if (queue_mode == NULL_Q_MQ)
-                       blk_mq_free_queue(nullb->q);
-               else
-                       blk_cleanup_queue(nullb->q);
+               blk_cleanup_queue(nullb->q);
                cleanup_queues(nullb);
 err:
                kfree(nullb);
@@ -579,7 +617,13 @@ static int __init null_init(void)
        }
 #endif
 
-       if (submit_queues > nr_cpu_ids)
+       if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
+               if (submit_queues < nr_online_nodes) {
+                       pr_warn("null_blk: submit_queues param is set to %u.",
+                                                       nr_online_nodes);
+                       submit_queues = nr_online_nodes;
+               }
+       } else if (submit_queues > nr_cpu_ids)
                submit_queues = nr_cpu_ids;
        else if (!submit_queues)
                submit_queues = 1;
index 9199c93be926ed97f33eaa95fc9ce4ec0549cea7..eb6e1e0e8db25f78f2d2407e0d54dafc2a2b9583 100644 (file)
@@ -5269,7 +5269,7 @@ const char *skd_skdev_state_to_str(enum skd_drvr_state state)
        }
 }
 
-const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
+static const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
 {
        switch (state) {
        case SKD_MSG_STATE_IDLE:
@@ -5281,7 +5281,7 @@ const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
        }
 }
 
-const char *skd_skreq_state_to_str(enum skd_req_state state)
+static const char *skd_skreq_state_to_str(enum skd_req_state state)
 {
        switch (state) {
        case SKD_REQ_STATE_IDLE:
index 432db1b59b003a837679cd187c4743f98ca9b152..c4a4c900628891c31fec541277cb7ffea9a3e68b 100644 (file)
@@ -489,7 +489,7 @@ static int blkif_queue_request(struct request *req)
 
                        if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
                            (i % SEGS_PER_INDIRECT_FRAME == 0)) {
-                               unsigned long pfn;
+                               unsigned long uninitialized_var(pfn);
 
                                if (segments)
                                        kunmap_atomic(segments);
@@ -2011,6 +2011,10 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
 
        bdev = bdget_disk(disk, 0);
 
+       if (!bdev) {
+               WARN(1, "Block device %s yanked out from us!\n", disk->disk_name);
+               goto out_mutex;
+       }
        if (bdev->bd_openers)
                goto out;
 
@@ -2041,6 +2045,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
 
 out:
        bdput(bdev);
+out_mutex:
        mutex_unlock(&blkfront_mutex);
 }
 
index 5a95baf4b104e4c2dc559534867effa53e6327a2..27de5046708a233cbc99e42a4349387f9f5157cb 100644 (file)
@@ -43,9 +43,6 @@
 #include <linux/zorro.h>
 
 
-extern int m68k_realnum_memory;
-extern struct mem_info m68k_memory[NUM_MEMINFO];
-
 #define Z2MINOR_COMBINED      (0)
 #define Z2MINOR_Z2ONLY        (1)
 #define Z2MINOR_CHIPONLY      (2)
@@ -116,8 +113,8 @@ get_z2ram( void )
        if ( test_bit( i, zorro_unused_z2ram ) )
        {
            z2_count++;
-           z2ram_map[ z2ram_size++ ] = 
-               ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT );
+           z2ram_map[z2ram_size++] = (unsigned long)ZTWO_VADDR(Z2RAM_START) +
+                                     (i << Z2RAM_CHUNKSHIFT);
            clear_bit( i, zorro_unused_z2ram );
        }
     }
index 6bfc1bb318f6399397ca8f169cc07fd98b46256d..dceb85f8d9a8251ed115e06af348692898f6a400 100644 (file)
@@ -87,6 +87,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
        { USB_DEVICE(0x0930, 0x0219) },
+       { USB_DEVICE(0x0930, 0x0220) },
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x13d3, 0x3393) },
        { USB_DEVICE(0x0489, 0xe04e) },
@@ -129,6 +130,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index c0ff34f2d2df577efffe902562f9578690ea4e39..3980fd18f6eaeeb129fe543728f19231df80bd59 100644 (file)
@@ -154,6 +154,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
index 40cc0cf2ded639f6b4e3f28cfb1b093660c19ae1..e6939e13e3388e0b05132f72320d8eec0c757a57 100644 (file)
@@ -664,6 +664,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
                },
        },
+       {
+               .ident = "Dell XPS421",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+               },
+       },
         { }
 };
 
index 8e562dc656016cd9c4dbeaaa3dac0a96a02d0f26..e1f3337a0cf9f7d7fa223a86e84282765d915108 100644 (file)
@@ -27,15 +27,18 @@ static char *tpm_device_name = "TPM";
 static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
                                void **return_value)
 {
-       acpi_status status;
+       acpi_status status = AE_OK;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-       if (strstr(buffer.pointer, context) != NULL) {
-               *return_value = handle;
+
+       if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) {
+               if (strstr(buffer.pointer, context) != NULL) {
+                       *return_value = handle;
+                       status = AE_CTRL_TERMINATE;
+               }
                kfree(buffer.pointer);
-               return AE_CTRL_TERMINATE;
        }
-       return AE_OK;
+
+       return status;
 }
 
 static inline void ppi_assign_params(union acpi_object params[4],
index 8d3009e44fba40d4fba82825bd59d98febf53984..5543b7df8e16c736c210407a5d837ffb32ab3beb 100644 (file)
@@ -87,7 +87,7 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
        return 0;
 }
 
-static unsigned int _get_val(struct clk_divider *divider, u8 div)
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return div;
index 7be41e676a6470ab02b0bfd52867f54561a7960d..00a3abe103a5ac472dfb352a1bb0cec42cd29ddb 100644 (file)
@@ -60,7 +60,7 @@ static int s2mps11_clk_prepare(struct clk_hw *hw)
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
        int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap,
+       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic,
                                S2MPS11_REG_RTC_CTRL,
                                 s2mps11->mask, s2mps11->mask);
        if (!ret)
@@ -74,7 +74,7 @@ static void s2mps11_clk_unprepare(struct clk_hw *hw)
        struct s2mps11_clk *s2mps11 = to_s2mps11_clk(hw);
        int ret;
 
-       ret = regmap_update_bits(s2mps11->iodev->regmap, S2MPS11_REG_RTC_CTRL,
+       ret = regmap_update_bits(s2mps11->iodev->regmap_pmic, S2MPS11_REG_RTC_CTRL,
                           s2mps11->mask, ~s2mps11->mask);
 
        if (!ret)
@@ -174,7 +174,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                s2mps11_clk->hw.init = &s2mps11_clks_init[i];
                s2mps11_clk->mask = 1 << i;
 
-               ret = regmap_read(s2mps11_clk->iodev->regmap,
+               ret = regmap_read(s2mps11_clk->iodev->regmap_pmic,
                                  S2MPS11_REG_RTC_CTRL, &val);
                if (ret < 0)
                        goto err_reg;
index 39b40aaede2b36a3bd92546ff344420b480fb569..68e515d093d864ca9cc704d6f90a441695e67a6d 100644 (file)
@@ -26,17 +26,17 @@ static struct clk_onecell_data clk_data;
 #define ASS_CLK_DIV 0x4
 #define ASS_CLK_GATE 0x8
 
+/* list of all parent clock list */
+static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
+static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
+
+#ifdef CONFIG_PM_SLEEP
 static unsigned long reg_save[][2] = {
        {ASS_CLK_SRC,  0},
        {ASS_CLK_DIV,  0},
        {ASS_CLK_GATE, 0},
 };
 
-/* list of all parent clock list */
-static const char *mout_audss_p[] = { "fin_pll", "fout_epll" };
-static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" };
-
-#ifdef CONFIG_PM_SLEEP
 static int exynos_audss_clk_suspend(void)
 {
        int i;
index ad5ff50c5f281a5e1c31c498c78c5a717aa464de..1a7c1b929c690b03b2b24a1423da55a97b66aa00 100644 (file)
@@ -39,7 +39,7 @@
 #define SRC_TOP1               0xc214
 #define SRC_CAM                        0xc220
 #define SRC_TV                 0xc224
-#define SRC_MFC                        0xcc28
+#define SRC_MFC                        0xc228
 #define SRC_G3D                        0xc22c
 #define E4210_SRC_IMAGE                0xc230
 #define SRC_LCD0               0xc234
index adf32343c9f9c408f5b8bc7c78a6ce3bc66c27a7..e52359cf9b6fe76db63b787717f003454d89e12e 100644 (file)
@@ -25,6 +25,7 @@
 #define MPLL_LOCK              0x4000
 #define MPLL_CON0              0x4100
 #define SRC_CORE1              0x4204
+#define GATE_IP_ACP            0x8800
 #define CPLL_LOCK              0x10020
 #define EPLL_LOCK              0x10030
 #define VPLL_LOCK              0x10040
@@ -75,7 +76,6 @@
 #define SRC_CDREX              0x20200
 #define PLL_DIV2_SEL           0x20a24
 #define GATE_IP_DISP1          0x10928
-#define GATE_IP_ACP            0x10000
 
 /* list of PLLs to be registered */
 enum exynos5250_plls {
@@ -120,7 +120,8 @@ enum exynos5250_clks {
        spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
        hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
        tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
-       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, mdma0,
+       smmu_mdma0,
 
        /* mux clocks */
        mout_hdmi = 1024,
@@ -354,8 +355,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
        GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
        GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
-       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
-       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 1, 0, 0),
        GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
        GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
        GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -406,7 +407,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
        GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
        GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
-       GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+       GATE(sysreg, "sysreg", "aclk66",
+                       GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
        GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0),
        GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
        GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
@@ -492,6 +494,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
        GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
        GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
        GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+       GATE(mdma0, "mdma0", "aclk266", GATE_IP_ACP, 1, 0, 0),
+       GATE(smmu_mdma0, "smmu_mdma0", "aclk266", GATE_IP_ACP, 5, 0, 0),
 };
 
 static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
index bdb953e15d2a88d201c3997ca86e80f15a00e5cf..cd6950fd8caf063417f6717db581f39d69100ed4 100644 (file)
@@ -37,6 +37,10 @@ config SUN4I_TIMER
        select CLKSRC_MMIO
        bool
 
+config SUN5I_HSTIMER
+       select CLKSRC_MMIO
+       bool
+
 config VT8500_TIMER
        bool
 
@@ -75,6 +79,7 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 config CLKSRC_EFM32
        bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32
        depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
+       select CLKSRC_MMIO
        default ARCH_EFM32
        help
          Support to use the timers of EFM32 SoCs as clock source and clock
@@ -87,6 +92,7 @@ config ARM_ARCH_TIMER
 config ARM_ARCH_TIMER_EVTSTREAM
        bool "Support for ARM architected timer event stream generation"
        default y if ARM_ARCH_TIMER
+       depends on ARM_ARCH_TIMER
        help
          This option enables support for event stream generation based on
          the ARM architected timer. It is used for waking up CPUs executing
index 33621efb91489693a2e1f7cd2e5b3ab423fc8939..358358d87b6dc4f9fe384c9af5158ab43ab3f8ea 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_MOXART)     += moxart_timer.o
 obj-$(CONFIG_ARCH_MXS)         += mxs_timer.o
 obj-$(CONFIG_ARCH_PRIMA2)      += timer-prima2.o
 obj-$(CONFIG_SUN4I_TIMER)      += sun4i_timer.o
+obj-$(CONFIG_SUN5I_HSTIMER)    += timer-sun5i.o
 obj-$(CONFIG_ARCH_TEGRA)       += tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)     += vt8500_timer.o
 obj-$(CONFIG_ARCH_NSPIRE)      += zevio-timer.o
index c639b1a9e99686fb3333fc825c65d84e3cc52bae..0fc31d029e52224391dc419d96e9391aa38fff77 100644 (file)
@@ -202,7 +202,7 @@ static struct clocksource gt_clocksource = {
 };
 
 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
-static u32 notrace gt_sched_clock_read(void)
+static u64 notrace gt_sched_clock_read(void)
 {
        return gt_counter_read();
 }
@@ -217,7 +217,7 @@ static void __init gt_clocksource_init(void)
        writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
 
 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
-       setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate);
+       sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate);
 #endif
        clocksource_register_hz(&gt_clocksource, gt_clk_rate);
 }
index 0d7d8c3ed6b2221cded6206291cbb4fa6c453efc..5176e761166b27a0730341ec1688ae5157cf6258 100644 (file)
@@ -98,12 +98,6 @@ kona_timer_get_counter(void *timer_base, uint32_t *msw, uint32_t *lsw)
        return;
 }
 
-static const struct of_device_id bcm_timer_ids[] __initconst = {
-       {.compatible = "brcm,kona-timer"},
-       {.compatible = "bcm,kona-timer"}, /* deprecated name */
-       {},
-};
-
 static void __init kona_timers_init(struct device_node *node)
 {
        u32 freq;
index b2bb3a4bc20542199cb4a3eab1bc71bcc5022dfa..63f176de0d0228c63ba58f606d21afd98cdc5e9e 100644 (file)
  * struct ttc_timer - This definition defines local timer structure
  *
  * @base_addr: Base address of timer
+ * @freq:      Timer input clock frequency
  * @clk:       Associated clock source
  * @clk_rate_change_nb Notifier block for clock rate changes
  */
 struct ttc_timer {
        void __iomem *base_addr;
+       unsigned long freq;
        struct clk *clk;
        struct notifier_block clk_rate_change_nb;
 };
@@ -158,7 +160,7 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs)
                                TTC_COUNT_VAL_OFFSET);
 }
 
-static u32 notrace ttc_sched_clock_read(void)
+static u64 notrace ttc_sched_clock_read(void)
 {
        return __raw_readl(ttc_sched_clock_val_reg);
 }
@@ -196,9 +198,8 @@ static void ttc_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               ttc_set_interval(timer,
-                               DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk),
-                                       PRESCALE * HZ));
+               ttc_set_interval(timer, DIV_ROUND_CLOSEST(ttce->ttc.freq,
+                                               PRESCALE * HZ));
                break;
        case CLOCK_EVT_MODE_ONESHOT:
        case CLOCK_EVT_MODE_UNUSED:
@@ -273,6 +274,8 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
                return;
        }
 
+       ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk);
+
        ttccs->ttc.clk_rate_change_nb.notifier_call =
                ttc_rate_change_clocksource_cb;
        ttccs->ttc.clk_rate_change_nb.next = NULL;
@@ -298,16 +301,14 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
        __raw_writel(CNT_CNTRL_RESET,
                     ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
 
-       err = clocksource_register_hz(&ttccs->cs,
-                       clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+       err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE);
        if (WARN_ON(err)) {
                kfree(ttccs);
                return;
        }
 
        ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET;
-       setup_sched_clock(ttc_sched_clock_read, 16,
-                       clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+       sched_clock_register(ttc_sched_clock_read, 16, ttccs->ttc.freq / PRESCALE);
 }
 
 static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
@@ -334,6 +335,9 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
                                ndata->new_rate / PRESCALE);
                local_irq_restore(flags);
 
+               /* update cached frequency */
+               ttc->freq = ndata->new_rate;
+
                /* fall through */
        }
        case PRE_RATE_CHANGE:
@@ -367,6 +371,7 @@ static void __init ttc_setup_clockevent(struct clk *clk,
        if (clk_notifier_register(ttcce->ttc.clk,
                                &ttcce->ttc.clk_rate_change_nb))
                pr_warn("Unable to register clock notifier.\n");
+       ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk);
 
        ttcce->ttc.base_addr = base;
        ttcce->ce.name = "ttc_clockevent";
@@ -388,15 +393,14 @@ static void __init ttc_setup_clockevent(struct clk *clk,
        __raw_writel(0x1,  ttcce->ttc.base_addr + TTC_IER_OFFSET);
 
        err = request_irq(irq, ttc_clock_event_interrupt,
-                         IRQF_DISABLED | IRQF_TIMER,
-                         ttcce->ce.name, ttcce);
+                         IRQF_TIMER, ttcce->ce.name, ttcce);
        if (WARN_ON(err)) {
                kfree(ttcce);
                return;
        }
 
        clockevents_config_and_register(&ttcce->ce,
-                       clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe);
+                       ttcce->ttc.freq / PRESCALE, 1, 0xfffe);
 }
 
 /**
index 35639cf4e5a208af89c9b692eae32227bcefc5d3..ae2e4278c42abd75358279e937e991497097a2e6 100644 (file)
@@ -28,6 +28,7 @@ void __init clocksource_of_init(void)
        struct device_node *np;
        const struct of_device_id *match;
        clocksource_of_init_fn init_func;
+       unsigned clocksources = 0;
 
        for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
                if (!of_device_is_available(np))
@@ -35,6 +36,8 @@ void __init clocksource_of_init(void)
 
                init_func = match->data;
                init_func(np);
-               of_node_put(np);
+               clocksources++;
        }
+       if (!clocksources)
+               pr_crit("%s: no matching clocksources found\n", __func__);
 }
index ea210482dd2099af6ce35e31bd234fcc18a4d970..db21052908984c96aa86950d976784a078043374 100644 (file)
@@ -131,7 +131,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
 
 static struct irqaction mfgptirq  = {
        .handler = mfgpt_tick,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED,
+       .flags = IRQF_NOBALANCING | IRQF_TIMER | IRQF_SHARED,
        .name = DRV_NAME,
 };
 
index e54ca1062d8e6a827a998591b0b5d58dc59eee76..f3656a6b0382c9982563e0abe84054e98a67dc98 100644 (file)
@@ -243,8 +243,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
        dw_ced->irqaction.dev_id        = &dw_ced->ced;
        dw_ced->irqaction.irq           = irq;
        dw_ced->irqaction.flags         = IRQF_TIMER | IRQF_IRQPOLL |
-                                         IRQF_NOBALANCING |
-                                         IRQF_DISABLED;
+                                         IRQF_NOBALANCING;
 
        dw_ced->eoi = apbt_eoi;
        err = setup_irq(irq, &dw_ced->irqaction);
index 45ba8aecc7298428016dd6d5601482362cce0c4e..2a2ea2717f3ac94dfba2fdd6a986c4630556e7da 100644 (file)
@@ -108,12 +108,11 @@ static void __init add_clocksource(struct device_node *source_timer)
 
 static u64 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base);
 }
 
 static const struct of_device_id sptimer_ids[] __initconst = {
        { .compatible = "picochip,pc3x2-rtc" },
-       { .compatible = "snps,dw-apb-timer-sp" },
        { /* Sentinel */ },
 };
 
@@ -151,4 +150,6 @@ static void __init dw_apb_timer_init(struct device_node *timer)
        num_called++;
 }
 CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
index ed7b73b508e096bb06a3e87a1843aa813f835430..152a3f3875eeab3223a68f4cddc509e5b378a515 100644 (file)
@@ -187,7 +187,7 @@ static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction nmdk_timer_irq = {
        .name           = "Nomadik Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_TIMER,
        .handler        = nmdk_timer_interrupt,
        .dev_id         = &nmdk_clkevt,
 };
index 85082e8d305298ac41b085df4bdb493aca95c682..5645cfc90c415ecd6108291304610e683579962f 100644 (file)
@@ -264,7 +264,7 @@ static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
 
 static struct irqaction samsung_clock_event_irq = {
        .name           = "samsung_time_irq",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = samsung_clock_event_isr,
        .dev_id         = &time_event_device,
 };
index 0965e9848b3d1893df4511f4ed70e1d39ffcbc96..0b1836a6c53975aade352b7f56b815d6c7ce1cb5 100644 (file)
@@ -634,12 +634,18 @@ static int sh_cmt_clock_event_next(unsigned long delta,
 
 static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
 {
-       pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev);
+       struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+
+       pm_genpd_syscore_poweroff(&p->pdev->dev);
+       clk_unprepare(p->clk);
 }
 
 static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
 {
-       pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev);
+       struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+
+       clk_prepare(p->clk);
+       pm_genpd_syscore_poweron(&p->pdev->dev);
 }
 
 static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
@@ -726,8 +732,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
        p->irqaction.name = dev_name(&p->pdev->dev);
        p->irqaction.handler = sh_cmt_interrupt;
        p->irqaction.dev_id = p;
-       p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \
-                            IRQF_IRQPOLL  | IRQF_NOBALANCING;
+       p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
 
        /* get hold of clock */
        p->clk = clk_get(&p->pdev->dev, "cmt_fck");
@@ -737,6 +742,10 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
                goto err2;
        }
 
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err3;
+
        if (res2 && (resource_size(res2) == 4)) {
                /* assume both CMSTR and CMCSR to be 32-bit */
                p->read_control = sh_cmt_read32;
@@ -773,19 +782,21 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
                              cfg->clocksource_rating);
        if (ret) {
                dev_err(&p->pdev->dev, "registration failed\n");
-               goto err3;
+               goto err4;
        }
        p->cs_enabled = false;
 
        ret = setup_irq(irq, &p->irqaction);
        if (ret) {
                dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
-               goto err3;
+               goto err4;
        }
 
        platform_set_drvdata(pdev, p);
 
        return 0;
+err4:
+       clk_unprepare(p->clk);
 err3:
        clk_put(p->clk);
 err2:
index 4aac9ee0d0c054a7ba953b17ac3272946af7b47d..e30d76e0a6fae9dab56a1b4ebc15ee769dd2fca3 100644 (file)
@@ -302,8 +302,7 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
        p->irqaction.handler = sh_mtu2_interrupt;
        p->irqaction.dev_id = p;
        p->irqaction.irq = irq;
-       p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \
-                            IRQF_IRQPOLL  | IRQF_NOBALANCING;
+       p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
 
        /* get hold of clock */
        p->clk = clk_get(&p->pdev->dev, "mtu2_fck");
@@ -313,8 +312,20 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
                goto err1;
        }
 
-       return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
-                               cfg->clockevent_rating);
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err2;
+
+       ret = sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
+                              cfg->clockevent_rating);
+       if (ret < 0)
+               goto err3;
+
+       return 0;
+ err3:
+       clk_unprepare(p->clk);
+ err2:
+       clk_put(p->clk);
  err1:
        iounmap(p->mapbase);
  err0:
@@ -346,7 +357,6 @@ static int sh_mtu2_probe(struct platform_device *pdev)
        ret = sh_mtu2_setup(p, pdev);
        if (ret) {
                kfree(p);
-               platform_set_drvdata(pdev, NULL);
                pm_runtime_idle(&pdev->dev);
                return ret;
        }
index 78b8dae49628cce42fb45ebdff2b32ece5045a52..ecd7b60bfdfa9d2323053f325b8f9d4447988c9d 100644 (file)
@@ -462,8 +462,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
        p->irqaction.handler = sh_tmu_interrupt;
        p->irqaction.dev_id = p;
        p->irqaction.irq = irq;
-       p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \
-                            IRQF_IRQPOLL  | IRQF_NOBALANCING;
+       p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
 
        /* get hold of clock */
        p->clk = clk_get(&p->pdev->dev, "tmu_fck");
@@ -472,12 +471,26 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
                ret = PTR_ERR(p->clk);
                goto err1;
        }
+
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err2;
+
        p->cs_enabled = false;
        p->enable_count = 0;
 
-       return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
-                              cfg->clockevent_rating,
-                              cfg->clocksource_rating);
+       ret = sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
+                             cfg->clockevent_rating,
+                             cfg->clocksource_rating);
+       if (ret < 0)
+               goto err3;
+
+       return 0;
+
+ err3:
+       clk_unprepare(p->clk);
+ err2:
+       clk_put(p->clk);
  err1:
        iounmap(p->mapbase);
  err0:
@@ -509,7 +522,6 @@ static int sh_tmu_probe(struct platform_device *pdev)
        ret = sh_tmu_setup(p, pdev);
        if (ret) {
                kfree(p);
-               platform_set_drvdata(pdev, NULL);
                pm_runtime_idle(&pdev->dev);
                return ret;
        }
index 2fb4695a28d83e2e0f26c1e787b0c575612c650c..bf497afba9ad1ef0c6c8ec57c9761f05d3acf799 100644 (file)
@@ -114,7 +114,7 @@ static int sun4i_clkevt_next_event(unsigned long evt,
 
 static struct clock_event_device sun4i_clockevent = {
        .name = "sun4i_tick",
-       .rating = 300,
+       .rating = 350,
        .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode = sun4i_clkevt_mode,
        .set_next_event = sun4i_clkevt_next_event,
@@ -138,7 +138,7 @@ static struct irqaction sun4i_timer_irq = {
        .dev_id = &sun4i_clockevent,
 };
 
-static u32 sun4i_timer_sched_read(void)
+static u64 notrace sun4i_timer_sched_read(void)
 {
        return ~readl(timer_base + TIMER_CNTVAL_REG(1));
 }
@@ -170,15 +170,18 @@ static void __init sun4i_timer_init(struct device_node *node)
               TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
               timer_base + TIMER_CTL_REG(1));
 
-       setup_sched_clock(sun4i_timer_sched_read, 32, rate);
+       sched_clock_register(sun4i_timer_sched_read, 32, rate);
        clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name,
-                             rate, 300, 32, clocksource_mmio_readl_down);
+                             rate, 350, 32, clocksource_mmio_readl_down);
 
        ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
 
        writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
               timer_base + TIMER_CTL_REG(0));
 
+       /* Make sure timer is stopped before playing with interrupts */
+       sun4i_clkevt_time_stop(0);
+
        ret = setup_irq(irq, &sun4i_timer_irq);
        if (ret)
                pr_warn("failed to setup irq %d\n", irq);
@@ -187,7 +190,8 @@ static void __init sun4i_timer_init(struct device_node *node)
        val = readl(timer_base + TIMER_IRQ_EN_REG);
        writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
 
-       sun4i_clockevent.cpumask = cpumask_of(0);
+       sun4i_clockevent.cpumask = cpu_possible_mask;
+       sun4i_clockevent.irq = irq;
 
        clockevents_config_and_register(&sun4i_clockevent, rate,
                                        TIMER_SYNC_TICKS, 0xffffffff);
index 642849256d82ecabd0d7222d8a960280ce3f3e24..d1869f02051cbe9ccfa23a0dec7d235d5d0d3f02 100644 (file)
@@ -149,7 +149,7 @@ static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction tegra_timer_irq = {
        .name           = "timer0",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
+       .flags          = IRQF_TIMER | IRQF_TRIGGER_HIGH,
        .handler        = tegra_timer_interrupt,
        .dev_id         = &tegra_clockevent,
 };
index d8e47e5027858faf9f99c0b3ad99883bd7bc9cc2..ee8691b89944e3fcbc3dbf7eeaadf00ec38ffd93 100644 (file)
@@ -76,6 +76,7 @@
 static void __iomem *timer_base, *local_base;
 static unsigned int timer_clk;
 static bool timer25Mhz = true;
+static u32 enable_mask;
 
 /*
  * Number of timer ticks per jiffy.
@@ -121,8 +122,7 @@ armada_370_xp_clkevt_next_event(unsigned long delta,
        /*
         * Enable the timer.
         */
-       local_timer_ctrl_clrset(TIMER0_RELOAD_EN,
-                               TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+       local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask);
        return 0;
 }
 
@@ -141,9 +141,7 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode,
                /*
                 * Enable timer.
                 */
-               local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN |
-                                          TIMER0_EN |
-                                          TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+               local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
        } else {
                /*
                 * Disable timer.
@@ -240,10 +238,13 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
        WARN_ON(!timer_base);
        local_base = of_iomap(np, 1);
 
-       if (timer25Mhz)
+       if (timer25Mhz) {
                set = TIMER0_25MHZ;             
-       else
+               enable_mask = TIMER0_EN;
+       } else {
                clr = TIMER0_25MHZ;
+               enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT);
+       }
        timer_ctrl_clrset(clr, set);
        local_timer_ctrl_clrset(clr, set);
 
@@ -255,11 +256,6 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
 
        ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
 
-       /*
-        * Set scale and timer for sched_clock.
-        */
-       sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
-
        /*
         * Setup free-running clocksource timer (interrupts
         * disabled).
@@ -267,8 +263,12 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
        writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
        writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
 
-       timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN |
-                            TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+       timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
+
+       /*
+        * Set scale and timer for sched_clock.
+        */
+       sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
 
        clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
                              "armada_370_xp_clocksource",
index 9c7f018a67cad356a2e85cfe270117a6404ac547..20066222f3f29cdb052c2282eafd1dadb8519d8b 100644 (file)
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(orion_timer_ctrl_clrset);
 /*
  * Free-running clocksource handling.
  */
-static u32 notrace orion_read_sched_clock(void)
+static u64 notrace orion_read_sched_clock(void)
 {
        return ~readl(timer_base + TIMER0_VAL);
 }
@@ -135,7 +135,7 @@ static void __init orion_timer_init(struct device_node *np)
        clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource",
                              clk_get_rate(clk), 300, 32,
                              clocksource_mmio_readl_down);
-       setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk));
+       sched_clock_register(orion_read_sched_clock, 32, clk_get_rate(clk));
 
        /* setup timer1 as clockevent timer */
        if (setup_irq(irq, &orion_clkevt_irq))
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
new file mode 100644 (file)
index 0000000..deebcd6
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Allwinner SoCs hstimer driver.
+ *
+ * Copyright (C) 2013 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqreturn.h>
+#include <linux/sched_clock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define TIMER_IRQ_EN_REG               0x00
+#define TIMER_IRQ_EN(val)                      BIT(val)
+#define TIMER_IRQ_ST_REG               0x04
+#define TIMER_CTL_REG(val)             (0x20 * (val) + 0x10)
+#define TIMER_CTL_ENABLE                       BIT(0)
+#define TIMER_CTL_RELOAD                       BIT(1)
+#define TIMER_CTL_CLK_PRES(val)                        (((val) & 0x7) << 4)
+#define TIMER_CTL_ONESHOT                      BIT(7)
+#define TIMER_INTVAL_LO_REG(val)       (0x20 * (val) + 0x14)
+#define TIMER_INTVAL_HI_REG(val)       (0x20 * (val) + 0x18)
+#define TIMER_CNTVAL_LO_REG(val)       (0x20 * (val) + 0x1c)
+#define TIMER_CNTVAL_HI_REG(val)       (0x20 * (val) + 0x20)
+
+#define TIMER_SYNC_TICKS       3
+
+static void __iomem *timer_base;
+static u32 ticks_per_jiffy;
+
+/*
+ * When we disable a timer, we need to wait at least for 2 cycles of
+ * the timer source clock. We will use for that the clocksource timer
+ * that is already setup and runs at the same frequency than the other
+ * timers, and we never will be disabled.
+ */
+static void sun5i_clkevt_sync(void)
+{
+       u32 old = readl(timer_base + TIMER_CNTVAL_LO_REG(1));
+
+       while ((old - readl(timer_base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
+               cpu_relax();
+}
+
+static void sun5i_clkevt_time_stop(u8 timer)
+{
+       u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+       writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer));
+
+       sun5i_clkevt_sync();
+}
+
+static void sun5i_clkevt_time_setup(u8 timer, u32 delay)
+{
+       writel(delay, timer_base + TIMER_INTVAL_LO_REG(timer));
+}
+
+static void sun5i_clkevt_time_start(u8 timer, bool periodic)
+{
+       u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+
+       if (periodic)
+               val &= ~TIMER_CTL_ONESHOT;
+       else
+               val |= TIMER_CTL_ONESHOT;
+
+       writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
+              timer_base + TIMER_CTL_REG(timer));
+}
+
+static void sun5i_clkevt_mode(enum clock_event_mode mode,
+                             struct clock_event_device *clk)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               sun5i_clkevt_time_stop(0);
+               sun5i_clkevt_time_setup(0, ticks_per_jiffy);
+               sun5i_clkevt_time_start(0, true);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               sun5i_clkevt_time_stop(0);
+               sun5i_clkevt_time_start(0, false);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       default:
+               sun5i_clkevt_time_stop(0);
+               break;
+       }
+}
+
+static int sun5i_clkevt_next_event(unsigned long evt,
+                                  struct clock_event_device *unused)
+{
+       sun5i_clkevt_time_stop(0);
+       sun5i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS);
+       sun5i_clkevt_time_start(0, false);
+
+       return 0;
+}
+
+static struct clock_event_device sun5i_clockevent = {
+       .name = "sun5i_tick",
+       .rating = 340,
+       .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode = sun5i_clkevt_mode,
+       .set_next_event = sun5i_clkevt_next_event,
+};
+
+
+static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+
+       writel(0x1, timer_base + TIMER_IRQ_ST_REG);
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction sun5i_timer_irq = {
+       .name = "sun5i_timer0",
+       .flags = IRQF_TIMER | IRQF_IRQPOLL,
+       .handler = sun5i_timer_interrupt,
+       .dev_id = &sun5i_clockevent,
+};
+
+static u64 sun5i_timer_sched_read(void)
+{
+       return ~readl(timer_base + TIMER_CNTVAL_LO_REG(1));
+}
+
+static void __init sun5i_timer_init(struct device_node *node)
+{
+       unsigned long rate;
+       struct clk *clk;
+       int ret, irq;
+       u32 val;
+
+       timer_base = of_iomap(node, 0);
+       if (!timer_base)
+               panic("Can't map registers");
+
+       irq = irq_of_parse_and_map(node, 0);
+       if (irq <= 0)
+               panic("Can't parse IRQ");
+
+       clk = of_clk_get(node, 0);
+       if (IS_ERR(clk))
+               panic("Can't get timer clock");
+       clk_prepare_enable(clk);
+       rate = clk_get_rate(clk);
+
+       writel(~0, timer_base + TIMER_INTVAL_LO_REG(1));
+       writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
+              timer_base + TIMER_CTL_REG(1));
+
+       sched_clock_register(sun5i_timer_sched_read, 32, rate);
+       clocksource_mmio_init(timer_base + TIMER_CNTVAL_LO_REG(1), node->name,
+                             rate, 340, 32, clocksource_mmio_readl_down);
+
+       ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
+
+       ret = setup_irq(irq, &sun5i_timer_irq);
+       if (ret)
+               pr_warn("failed to setup irq %d\n", irq);
+
+       /* Enable timer0 interrupt */
+       val = readl(timer_base + TIMER_IRQ_EN_REG);
+       writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
+
+       sun5i_clockevent.cpumask = cpu_possible_mask;
+       sun5i_clockevent.irq = irq;
+
+       clockevents_config_and_register(&sun5i_clockevent, rate,
+                                       TIMER_SYNC_TICKS, 0xffffffff);
+}
+CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
+                      sun5i_timer_init);
+CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
+                      sun5i_timer_init);
index ad3c0e83a77956431541315108b093f2ca282b52..1098ed3b9b89f2663fbf8a989017d0a7621a9504 100644 (file)
@@ -124,7 +124,7 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction irq = {
        .name    = "vt8500_timer",
-       .flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .flags   = IRQF_TIMER | IRQF_IRQPOLL,
        .handler = vt8500_timer_interrupt,
        .dev_id  = &clockevent,
 };
index 856ad80418ae5b92610e23e98922f0ff6505d34e..7c03dd84f66a35cabbde683eece8e23f73585743 100644 (file)
@@ -58,7 +58,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
        return 0;
 }
 
-static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
+static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
        unsigned int frequency, rate, min_freq;
        int retval, steps, i;
index 02d534da22dda0bb22277c4f80f7c1d27f24cd65..8d19f7c06010c364ff6ee758c15096c252f9f4bd 100644 (file)
@@ -828,14 +828,17 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
        int ret = 0;
 
        memcpy(&new_policy, policy, sizeof(*policy));
+
+       /* Use the default policy if its valid. */
+       if (cpufreq_driver->setpolicy)
+               cpufreq_parse_governor(policy->governor->name,
+                                       &new_policy.policy, NULL);
+
        /* assure that the starting sequence is run in cpufreq_set_policy */
        policy->governor = NULL;
 
        /* set default policy */
        ret = cpufreq_set_policy(policy, &new_policy);
-       policy->user_policy.policy = policy->policy;
-       policy->user_policy.governor = policy->governor;
-
        if (ret) {
                pr_debug("setting policy failed\n");
                if (cpufreq_driver->exit)
@@ -845,8 +848,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
 
 #ifdef CONFIG_HOTPLUG_CPU
 static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
-                                 unsigned int cpu, struct device *dev,
-                                 bool frozen)
+                                 unsigned int cpu, struct device *dev)
 {
        int ret = 0;
        unsigned long flags;
@@ -877,11 +879,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy,
                }
        }
 
-       /* Don't touch sysfs links during light-weight init */
-       if (!frozen)
-               ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
-
-       return ret;
+       return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
 }
 #endif
 
@@ -926,6 +924,27 @@ err_free_policy:
        return NULL;
 }
 
+static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
+{
+       struct kobject *kobj;
+       struct completion *cmp;
+
+       down_read(&policy->rwsem);
+       kobj = &policy->kobj;
+       cmp = &policy->kobj_unregister;
+       up_read(&policy->rwsem);
+       kobject_put(kobj);
+
+       /*
+        * We need to make sure that the underlying kobj is
+        * actually not referenced anymore by anybody before we
+        * proceed with unloading.
+        */
+       pr_debug("waiting for dropping of refcount\n");
+       wait_for_completion(cmp);
+       pr_debug("wait complete\n");
+}
+
 static void cpufreq_policy_free(struct cpufreq_policy *policy)
 {
        free_cpumask_var(policy->related_cpus);
@@ -986,7 +1005,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) {
                if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) {
                        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
-                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen);
+                       ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev);
                        up_read(&cpufreq_rwsem);
                        return ret;
                }
@@ -994,15 +1013,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-       if (frozen)
-               /* Restore the saved policy when doing light-weight init */
-               policy = cpufreq_policy_restore(cpu);
-       else
+       /*
+        * Restore the saved policy when doing light-weight init and fall back
+        * to the full init if that fails.
+        */
+       policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
+       if (!policy) {
+               frozen = false;
                policy = cpufreq_policy_alloc();
-
-       if (!policy)
-               goto nomem_out;
-
+               if (!policy)
+                       goto nomem_out;
+       }
 
        /*
         * In the resume path, since we restore a saved policy, the assignment
@@ -1047,8 +1068,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
         */
        cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 
-       policy->user_policy.min = policy->min;
-       policy->user_policy.max = policy->max;
+       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);
@@ -1079,6 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 
        cpufreq_init_policy(policy);
 
+       if (!frozen) {
+               policy->user_policy.policy = policy->policy;
+               policy->user_policy.governor = policy->governor;
+       }
+
        kobject_uevent(&policy->kobj, KOBJ_ADD);
        up_read(&cpufreq_rwsem);
 
@@ -1096,7 +1124,13 @@ err_get_freq:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 err_set_policy_cpu:
+       if (frozen) {
+               /* Do not leave stale fallback data behind. */
+               per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
+               cpufreq_policy_put_kobj(policy);
+       }
        cpufreq_policy_free(policy);
+
 nomem_out:
        up_read(&cpufreq_rwsem);
 
@@ -1118,7 +1152,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 }
 
 static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
-                                          unsigned int old_cpu, bool frozen)
+                                          unsigned int old_cpu)
 {
        struct device *cpu_dev;
        int ret;
@@ -1126,10 +1160,6 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        /* first sibling now owns the new sysfs dir */
        cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
 
-       /* Don't touch sysfs files during light-weight tear-down */
-       if (frozen)
-               return cpu_dev->id;
-
        sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
        ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
        if (ret) {
@@ -1196,7 +1226,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                if (!frozen)
                        sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
-               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
+               new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
                if (new_cpu >= 0) {
                        update_policy_cpu(policy, new_cpu);
 
@@ -1218,8 +1248,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
        int ret;
        unsigned long flags;
        struct cpufreq_policy *policy;
-       struct kobject *kobj;
-       struct completion *cmp;
 
        read_lock_irqsave(&cpufreq_driver_lock, flags);
        policy = per_cpu(cpufreq_cpu_data, cpu);
@@ -1249,22 +1277,8 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                        }
                }
 
-               if (!frozen) {
-                       down_read(&policy->rwsem);
-                       kobj = &policy->kobj;
-                       cmp = &policy->kobj_unregister;
-                       up_read(&policy->rwsem);
-                       kobject_put(kobj);
-
-                       /*
-                        * We need to make sure that the underlying kobj is
-                        * actually not referenced anymore by anybody before we
-                        * proceed with unloading.
-                        */
-                       pr_debug("waiting for dropping of refcount\n");
-                       wait_for_completion(cmp);
-                       pr_debug("wait complete\n");
-               }
+               if (!frozen)
+                       cpufreq_policy_put_kobj(policy);
 
                /*
                 * Perform the ->exit() even during light-weight tear-down,
index 5f1cbae369611062c18ee50982ffa5c6f724d30f..d51f17ed691e023196bbd7e56a3341d4025ce092 100644 (file)
@@ -581,7 +581,8 @@ static void intel_pstate_timer_func(unsigned long __data)
 }
 
 #define ICPU(model, policy) \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy }
+       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\
+                       (unsigned long)&policy }
 
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x2a, core_params),
@@ -614,6 +615,11 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu = all_cpu_data[cpunum];
 
        intel_pstate_get_cpu_pstates(cpu);
+       if (!cpu->pstate.current_pstate) {
+               all_cpu_data[cpunum] = NULL;
+               kfree(cpu);
+               return -ENODATA;
+       }
 
        cpu->cpu = cpunum;
 
index 36795639df0da2d828c784b61c82a728037f6e1c..6e51114057d0963605ef1dfc80b231946e1b88f7 100644 (file)
@@ -65,7 +65,7 @@ static struct cpuidle_driver calxeda_idle_driver = {
        .state_count = 2,
 };
 
-static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
+static int calxeda_cpuidle_probe(struct platform_device *pdev)
 {
        return cpuidle_register(&calxeda_idle_driver, NULL);
 }
index 2a991e468f78190e1dfab933225d33cfef69d710..a55e68f2cfc8bfad02a85957c9d9ddc55823c6fe 100644 (file)
@@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-       if (dev->registered == 0)
+       if (!dev || dev->registered == 0)
                return;
 
        cpuidle_pause_and_lock();
index 4f44b71b9e24a14a6bc5f99c37e4184970dbb035..4cf5dec826e1e283aa8b5991cd1a4b80a0dbdba6 100644 (file)
@@ -818,7 +818,7 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
                       ivsize, 1);
        print_hex_dump(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
-                      req->cryptlen, 1);
+                      req->cryptlen - ctx->authsize, 1);
 #endif
 
        if (err) {
@@ -972,12 +972,9 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
                                 (edesc->src_nents ? : 1);
                in_options = LDST_SGF;
        }
-       if (encrypt)
-               append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                                 req->cryptlen - authsize, in_options);
-       else
-               append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                                 req->cryptlen, in_options);
+
+       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+                         in_options);
 
        if (likely(req->src == req->dst)) {
                if (all_contig) {
@@ -998,7 +995,8 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
                }
        }
        if (encrypt)
-               append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+               append_seq_out_ptr(desc, dst_dma, req->cryptlen + authsize,
+                                  out_options);
        else
                append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
                                   out_options);
@@ -1048,8 +1046,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
                sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents;
                in_options = LDST_SGF;
        }
-       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                         req->cryptlen - authsize, in_options);
+       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+                         in_options);
 
        if (contig & GIV_DST_CONTIG) {
                dst_dma = edesc->iv_dma;
@@ -1066,7 +1064,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
                }
        }
 
-       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options);
+       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen + authsize,
+                          out_options);
 }
 
 /*
@@ -1130,7 +1129,8 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
  * allocate and map the aead extended descriptor
  */
 static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
-                                          int desc_bytes, bool *all_contig_ptr)
+                                          int desc_bytes, bool *all_contig_ptr,
+                                          bool encrypt)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
        struct caam_ctx *ctx = crypto_aead_ctx(aead);
@@ -1145,12 +1145,22 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
        bool assoc_chained = false, src_chained = false, dst_chained = false;
        int ivsize = crypto_aead_ivsize(aead);
        int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
+       unsigned int authsize = ctx->authsize;
 
        assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
-       src_nents = sg_count(req->src, req->cryptlen, &src_chained);
 
-       if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+       if (unlikely(req->dst != req->src)) {
+               src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+               dst_nents = sg_count(req->dst,
+                                    req->cryptlen +
+                                       (encrypt ? authsize : (-authsize)),
+                                    &dst_chained);
+       } else {
+               src_nents = sg_count(req->src,
+                                    req->cryptlen +
+                                       (encrypt ? authsize : 0),
+                                    &src_chained);
+       }
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
                                 DMA_TO_DEVICE, assoc_chained);
@@ -1234,11 +1244,9 @@ static int aead_encrypt(struct aead_request *req)
        u32 *desc;
        int ret = 0;
 
-       req->cryptlen += ctx->authsize;
-
        /* allocate extended descriptor */
        edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                CAAM_CMD_SZ, &all_contig);
+                                CAAM_CMD_SZ, &all_contig, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1275,7 +1283,7 @@ static int aead_decrypt(struct aead_request *req)
 
        /* allocate extended descriptor */
        edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                CAAM_CMD_SZ, &all_contig);
+                                CAAM_CMD_SZ, &all_contig, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1332,7 +1340,8 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
        src_nents = sg_count(req->src, req->cryptlen, &src_chained);
 
        if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+               dst_nents = sg_count(req->dst, req->cryptlen + ctx->authsize,
+                                    &dst_chained);
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
                                 DMA_TO_DEVICE, assoc_chained);
@@ -1426,8 +1435,6 @@ static int aead_givencrypt(struct aead_givcrypt_request *areq)
        u32 *desc;
        int ret = 0;
 
-       req->cryptlen += ctx->authsize;
-
        /* allocate extended descriptor */
        edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
                                     CAAM_CMD_SZ, &contig);
index d23356d20e1ca430e5993aaf77b88b39b82fe651..1d80bd3636c5b1f2cf4dc078d4934e64befc7f68 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #include "compat.h"
 #include "regs.h"
index 9dd6e01eac33050b8304c5f8758440e7286606f2..f757a0f428bde807a8e5402af8404e98314c2bf8 100644 (file)
@@ -1410,14 +1410,12 @@ static const struct platform_device_info ixp_dev_info __initdata = {
 static int __init ixp_module_init(void)
 {
        int num = ARRAY_SIZE(ixp4xx_algos);
-       int i, err ;
+       int i, err;
 
        pdev = platform_device_register_full(&ixp_dev_info);
        if (IS_ERR(pdev))
                return PTR_ERR(pdev);
 
-       dev = &pdev->dev;
-
        spin_lock_init(&desc_lock);
        spin_lock_init(&emerg_lock);
 
index 905de4427e7c4d1630604db45ffa2ba158983918..b44f4ddc565c3bb7cd32b84c08a0b286543681e5 100644 (file)
@@ -790,7 +790,7 @@ static void ipsec_esp_unmap(struct device *dev,
 
        if (edesc->assoc_chained)
                talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
-       else
+       else if (areq->assoclen)
                /* assoc_nents counts also for IV in non-contiguous cases */
                dma_unmap_sg(dev, areq->assoc,
                             edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
@@ -973,7 +973,11 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
                dma_sync_single_for_device(dev, edesc->dma_link_tbl,
                                           edesc->dma_len, DMA_BIDIRECTIONAL);
        } else {
-               to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->assoc));
+               if (areq->assoclen)
+                       to_talitos_ptr(&desc->ptr[1],
+                                      sg_dma_address(areq->assoc));
+               else
+                       to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
                desc->ptr[1].j_extent = 0;
        }
 
@@ -1108,7 +1112,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                 unsigned int authsize,
                                                 unsigned int ivsize,
                                                 int icv_stashing,
-                                                u32 cryptoflags)
+                                                u32 cryptoflags,
+                                                bool encrypt)
 {
        struct talitos_edesc *edesc;
        int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
@@ -1122,10 +1127,10 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       if (iv)
+       if (ivsize)
                iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
 
-       if (assoc) {
+       if (assoclen) {
                /*
                 * Currently it is assumed that iv is provided whenever assoc
                 * is.
@@ -1141,19 +1146,17 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                        assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
        }
 
-       src_nents = sg_count(src, cryptlen + authsize, &src_chained);
-       src_nents = (src_nents == 1) ? 0 : src_nents;
-
-       if (!dst) {
-               dst_nents = 0;
-       } else {
-               if (dst == src) {
-                       dst_nents = src_nents;
-               } else {
-                       dst_nents = sg_count(dst, cryptlen + authsize,
-                                            &dst_chained);
-                       dst_nents = (dst_nents == 1) ? 0 : dst_nents;
-               }
+       if (!dst || dst == src) {
+               src_nents = sg_count(src, cryptlen + authsize, &src_chained);
+               src_nents = (src_nents == 1) ? 0 : src_nents;
+               dst_nents = dst ? src_nents : 0;
+       } else { /* dst && dst != src*/
+               src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
+                                    &src_chained);
+               src_nents = (src_nents == 1) ? 0 : src_nents;
+               dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
+                                    &dst_chained);
+               dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
 
        /*
@@ -1173,9 +1176,16 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
        if (!edesc) {
-               talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+               if (assoc_chained)
+                       talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+               else if (assoclen)
+                       dma_unmap_sg(dev, assoc,
+                                    assoc_nents ? assoc_nents - 1 : 1,
+                                    DMA_TO_DEVICE);
+
                if (iv_dma)
                        dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+
                dev_err(dev, "could not allocate edescriptor\n");
                return ERR_PTR(-ENOMEM);
        }
@@ -1197,7 +1207,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
-                                             int icv_stashing)
+                                             int icv_stashing, bool encrypt)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
@@ -1206,7 +1216,7 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
        return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
                                   iv, areq->assoclen, areq->cryptlen,
                                   ctx->authsize, ivsize, icv_stashing,
-                                  areq->base.flags);
+                                  areq->base.flags, encrypt);
 }
 
 static int aead_encrypt(struct aead_request *req)
@@ -1216,7 +1226,7 @@ static int aead_encrypt(struct aead_request *req)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(req, req->iv, 0);
+       edesc = aead_edesc_alloc(req, req->iv, 0, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1239,7 +1249,7 @@ static int aead_decrypt(struct aead_request *req)
        req->cryptlen -= authsize;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(req, req->iv, 1);
+       edesc = aead_edesc_alloc(req, req->iv, 1, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1285,7 +1295,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(areq, req->giv, 0);
+       edesc = aead_edesc_alloc(areq, req->giv, 0, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1441,7 +1451,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 }
 
 static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
-                                                   areq)
+                                                   areq, bool encrypt)
 {
        struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
        struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
@@ -1449,7 +1459,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
 
        return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
                                   areq->info, 0, areq->nbytes, 0, ivsize, 0,
-                                  areq->base.flags);
+                                  areq->base.flags, encrypt);
 }
 
 static int ablkcipher_encrypt(struct ablkcipher_request *areq)
@@ -1459,7 +1469,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(areq);
+       edesc = ablkcipher_edesc_alloc(areq, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1476,7 +1486,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(areq);
+       edesc = ablkcipher_edesc_alloc(areq, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1628,7 +1638,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
        struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 
        return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
-                                  nbytes, 0, 0, 0, areq->base.flags);
+                                  nbytes, 0, 0, 0, areq->base.flags, false);
 }
 
 static int ahash_init(struct ahash_request *areq)
index 446687cc2334ed2f60a0b6f0170382fe733aae01..c823daaf90430bb501ff9bc168e88adbcecf87ef 100644 (file)
@@ -62,6 +62,7 @@ config INTEL_IOATDMA
        tristate "Intel I/OAT DMA support"
        depends on PCI && X86
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select DCA
        help
          Enable support for the Intel(R) I/OAT DMA engine present
@@ -112,6 +113,7 @@ config MV_XOR
        bool "Marvell XOR engine support"
        depends on PLAT_ORION
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        ---help---
          Enable support for the Marvell XOR engine.
@@ -187,6 +189,7 @@ config AMCC_PPC440SPE_ADMA
        tristate "AMCC PPC440SPe ADMA support"
        depends on 440SPe || 440SP
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        help
@@ -352,6 +355,7 @@ config NET_DMA
        bool "Network: TCP receive copy offload"
        depends on DMA_ENGINE && NET
        default (INTEL_IOATDMA || FSL_DMA)
+       depends on BROKEN
        help
          This enables the use of DMA engines in the network stack to
          offload receive copy-to-user operations, freeing CPU cycles.
@@ -377,4 +381,7 @@ config DMATEST
          Simple DMA test client. Say N unless you're debugging a
          DMA Device driver.
 
+config DMA_ENGINE_RAID
+       bool
+
 endif
index 16a2aa28f85672689f66c37039a8e72230e71b02..ec4ee5c1fe9dc2115e029d0c472bd32f48cb281c 100644 (file)
@@ -1169,7 +1169,7 @@ static void pl08x_desc_free(struct virt_dma_desc *vd)
        struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
        struct pl08x_dma_chan *plchan = to_pl08x_chan(vd->tx.chan);
 
-       dma_descriptor_unmap(txd);
+       dma_descriptor_unmap(&vd->tx);
        if (!txd->done)
                pl08x_release_mux(plchan);
 
index f31d647acdfaac3730371e1366ff964e245435ac..2787aba60c6bdee8ed0489cb932338d6a81528ac 100644 (file)
@@ -347,10 +347,6 @@ static struct device *chan2dev(struct dma_chan *chan)
 {
        return &chan->dev->device;
 }
-static struct device *chan2parent(struct dma_chan *chan)
-{
-       return chan->dev->device.parent;
-}
 
 #if defined(VERBOSE_DEBUG)
 static void vdbg_dump_regs(struct at_dma_chan *atchan)
index ea806bdc12ef92418c528be0b950758de59c3ee7..ef63b9058f3c09d9d9dea56096bc5edda6d3b125 100644 (file)
@@ -912,7 +912,7 @@ struct dmaengine_unmap_pool {
 #define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) }
 static struct dmaengine_unmap_pool unmap_pool[] = {
        __UNMAP_POOL(2),
-       #if IS_ENABLED(CONFIG_ASYNC_TX_DMA)
+       #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID)
        __UNMAP_POOL(16),
        __UNMAP_POOL(128),
        __UNMAP_POOL(256),
@@ -1054,7 +1054,7 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
        dma_cookie_t cookie;
        unsigned long flags;
 
-       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOIO);
+       unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOWAIT);
        if (!unmap)
                return -ENOMEM;
 
index 20f9a3aaf9266ea6daa71a18f08d258afa8a1a1e..9dfcaf5c12888d3de80483329ffccc7fbbacd02a 100644 (file)
@@ -539,9 +539,9 @@ static int dmatest_func(void *data)
 
                um->len = params->buf_size;
                for (i = 0; i < src_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->srcs[i];
+                       void *buf = thread->srcs[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
                                                   um->len, DMA_TO_DEVICE);
@@ -559,9 +559,9 @@ static int dmatest_func(void *data)
                /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
                dsts = &um->addr[src_cnt];
                for (i = 0; i < dst_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->dsts[i];
+                       void *buf = thread->dsts[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
                                               DMA_BIDIRECTIONAL);
index 7086a16a55f2ed488573e475e615600c80be767e..f157c6f76b32b8c98dce28eed6253db033acc258 100644 (file)
@@ -86,11 +86,6 @@ static void set_desc_cnt(struct fsldma_chan *chan,
        hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
-static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
-{
-       return DMA_TO_CPU(chan, desc->hw.count, 32);
-}
-
 static void set_desc_src(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
@@ -101,16 +96,6 @@ static void set_desc_src(struct fsldma_chan *chan,
        hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
-static dma_addr_t get_desc_src(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_dst(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
@@ -121,16 +106,6 @@ static void set_desc_dst(struct fsldma_chan *chan,
        hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
-static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_next(struct fsldma_chan *chan,
                          struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
@@ -408,7 +383,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
        struct fsl_desc_sw *child;
        unsigned long flags;
-       dma_cookie_t cookie;
+       dma_cookie_t cookie = -EINVAL;
 
        spin_lock_irqsave(&chan->desc_lock, flags);
 
@@ -854,10 +829,6 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
                                      struct fsl_desc_sw *desc)
 {
        struct dma_async_tx_descriptor *txd = &desc->async_tx;
-       struct device *dev = chan->common.device->dev;
-       dma_addr_t src = get_desc_src(chan, desc);
-       dma_addr_t dst = get_desc_dst(chan, desc);
-       u32 len = get_desc_cnt(chan, desc);
 
        /* Run the link descriptor callback function */
        if (txd->callback) {
index 1a49c777607c50d313482f3ead21c19572a1cf8d..87529181efccb9851467cc04be04bd91fecb15b3 100644 (file)
@@ -817,7 +817,15 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
        dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, dma_src)) {
+               dev_err(dev, "mapping src buffer failed\n");
+               goto free_resources;
+       }
        dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+       if (dma_mapping_error(dev, dma_dest)) {
+               dev_err(dev, "mapping dest buffer failed\n");
+               goto unmap_src;
+       }
        flags = DMA_PREP_INTERRUPT;
        tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
                                                   IOAT_TEST_SIZE, flags);
@@ -855,8 +863,9 @@ int ioat_dma_self_test(struct ioatdma_device *device)
        }
 
 unmap_dma:
-       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
        dma_unmap_single(dev, dma_dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
+unmap_src:
+       dma_unmap_single(dev, dma_src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
 free_resources:
        dma->device_free_chan_resources(dma_chan);
 out:
index dcb1e05149a7664c6e65a214d783080d540aaafd..8869500ab92b84a4b93f4111f8936e6722d4911c 100644 (file)
@@ -1017,6 +1017,7 @@ static int mmp_pdma_probe(struct platform_device *op)
                }
        }
 
+       platform_set_drvdata(op, pdev);
        dev_info(pdev->device.dev, "initialized %d channels\n", dma_channels);
        return 0;
 }
index 7807f0ef4e209c25ad90db9d32f7bc13955391cf..53fb0c8365b0b27f29a893a3072103c9fb2360e9 100644 (file)
@@ -54,12 +54,6 @@ static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
        hw_desc->desc_command = (1 << 31);
 }
 
-static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
-{
-       struct mv_xor_desc *hw_desc = desc->hw_desc;
-       return hw_desc->phy_dest_addr;
-}
-
 static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
                                   u32 byte_count)
 {
@@ -787,7 +781,6 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
 /*
  * Perform a transaction to verify the HW works.
  */
-#define MV_XOR_TEST_SIZE 2000
 
 static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
 {
@@ -797,20 +790,21 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        int err = 0;
 
-       src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!src)
                return -ENOMEM;
 
-       dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+       dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
        if (!dest) {
                kfree(src);
                return -ENOMEM;
        }
 
        /* Fill in src buffer */
-       for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+       for (i = 0; i < PAGE_SIZE; i++)
                ((u8 *) src)[i] = (u8)i;
 
        dma_chan = &mv_chan->dmachan;
@@ -819,14 +813,26 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
-       dest_dma = dma_map_single(dma_chan->device->dev, dest,
-                                 MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, 2, GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
+       src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
+                                PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->to_cnt = 1;
+       unmap->addr[0] = src_dma;
 
-       src_dma = dma_map_single(dma_chan->device->dev, src,
-                                MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+       dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
+                                 PAGE_SIZE, DMA_FROM_DEVICE);
+       unmap->from_cnt = 1;
+       unmap->addr[1] = dest_dma;
+
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
-                                   MV_XOR_TEST_SIZE, 0);
+                                   PAGE_SIZE, 0);
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
        async_tx_ack(tx);
@@ -841,8 +847,8 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
        dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
-                               MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
-       if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+                               PAGE_SIZE, DMA_FROM_DEVICE);
+       if (memcmp(src, dest, PAGE_SIZE)) {
                dev_err(dma_chan->device->dev,
                        "Self-test copy failed compare, disabling\n");
                err = -ENODEV;
@@ -850,6 +856,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
        kfree(src);
@@ -867,13 +874,15 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
        dma_addr_t dest_dma;
        struct dma_async_tx_descriptor *tx;
+       struct dmaengine_unmap_data *unmap;
        struct dma_chan *dma_chan;
        dma_cookie_t cookie;
        u8 cmp_byte = 0;
        u32 cmp_word;
        int err = 0;
+       int src_count = MV_XOR_NUM_SRC_TEST;
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
                if (!xor_srcs[src_idx]) {
                        while (src_idx--)
@@ -890,13 +899,13 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
        /* Fill in src buffers */
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+       for (src_idx = 0; src_idx < src_count; src_idx++) {
                u8 *ptr = page_address(xor_srcs[src_idx]);
                for (i = 0; i < PAGE_SIZE; i++)
                        ptr[i] = (1 << src_idx);
        }
 
-       for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+       for (src_idx = 0; src_idx < src_count; src_idx++)
                cmp_byte ^= (u8) (1 << src_idx);
 
        cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
@@ -910,16 +919,29 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
                goto out;
        }
 
+       unmap = dmaengine_get_unmap_data(dma_chan->device->dev, src_count + 1,
+                                        GFP_KERNEL);
+       if (!unmap) {
+               err = -ENOMEM;
+               goto free_resources;
+       }
+
        /* test xor */
-       dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
-                               DMA_FROM_DEVICE);
+       for (i = 0; i < src_count; i++) {
+               unmap->addr[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+                                             0, PAGE_SIZE, DMA_TO_DEVICE);
+               dma_srcs[i] = unmap->addr[i];
+               unmap->to_cnt++;
+       }
 
-       for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
-               dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
-                                          0, PAGE_SIZE, DMA_TO_DEVICE);
+       unmap->addr[src_count] = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+                                     DMA_FROM_DEVICE);
+       dest_dma = unmap->addr[src_count];
+       unmap->from_cnt = 1;
+       unmap->len = PAGE_SIZE;
 
        tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
-                                MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+                                src_count, PAGE_SIZE, 0);
 
        cookie = mv_xor_tx_submit(tx);
        mv_xor_issue_pending(dma_chan);
@@ -948,9 +970,10 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
        }
 
 free_resources:
+       dmaengine_unmap_put(unmap);
        mv_xor_free_chan_resources(dma_chan);
 out:
-       src_idx = MV_XOR_NUM_SRC_TEST;
+       src_idx = src_count;
        while (src_idx--)
                __free_page(xor_srcs[src_idx]);
        __free_page(dest);
@@ -1176,6 +1199,7 @@ static int mv_xor_probe(struct platform_device *pdev)
                int i = 0;
 
                for_each_child_of_node(pdev->dev.of_node, np) {
+                       struct mv_xor_chan *chan;
                        dma_cap_mask_t cap_mask;
                        int irq;
 
@@ -1193,21 +1217,21 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
-                               xordev->channels[i] = NULL;
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                irq_dispose_mapping(irq);
                                goto err_channel_add;
                        }
 
+                       xordev->channels[i] = chan;
                        i++;
                }
        } else if (pdata && pdata->channels) {
                for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
                        struct mv_xor_channel_data *cd;
+                       struct mv_xor_chan *chan;
                        int irq;
 
                        cd = &pdata->channels[i];
@@ -1222,13 +1246,14 @@ static int mv_xor_probe(struct platform_device *pdev)
                                goto err_channel_add;
                        }
 
-                       xordev->channels[i] =
-                               mv_xor_channel_add(xordev, pdev, i,
-                                                  cd->cap_mask, irq);
-                       if (IS_ERR(xordev->channels[i])) {
-                               ret = PTR_ERR(xordev->channels[i]);
+                       chan = mv_xor_channel_add(xordev, pdev, i,
+                                                 cd->cap_mask, irq);
+                       if (IS_ERR(chan)) {
+                               ret = PTR_ERR(chan);
                                goto err_channel_add;
                        }
+
+                       xordev->channels[i] = chan;
                }
        }
 
index cdf0483b8f2dfb8f746b786fd6bf84b0d5f6657b..536632f6479c6966029022614f2bf863974256b4 100644 (file)
@@ -2492,12 +2492,9 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
 
 static inline void _init_desc(struct dma_pl330_desc *desc)
 {
-       desc->pchan = NULL;
        desc->req.x = &desc->px;
        desc->req.token = desc;
        desc->rqcfg.swap = SWAP_NO;
-       desc->rqcfg.privileged = 0;
-       desc->rqcfg.insnaccess = 0;
        desc->rqcfg.scctl = SCCTRL0;
        desc->rqcfg.dcctl = DCCTRL0;
        desc->req.cfg = &desc->rqcfg;
@@ -2517,7 +2514,7 @@ static int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count)
        if (!pdmac)
                return 0;
 
-       desc = kmalloc(count * sizeof(*desc), flg);
+       desc = kcalloc(count, sizeof(*desc), flg);
        if (!desc)
                return 0;
 
index 8da48c6b2a38ccd76f3e127d53e4be5ab7be425c..8bba298535b0984e241793403af6920399d7366d 100644 (file)
@@ -532,29 +532,6 @@ static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc,
        hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
 }
 
-/**
- * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation
- */
-static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc,
-                                       int value, unsigned long flags)
-{
-       struct dma_cdb *hw_desc = desc->hw_desc;
-
-       memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
-       desc->hw_next = NULL;
-       desc->src_cnt = 1;
-       desc->dst_cnt = 1;
-
-       if (flags & DMA_PREP_INTERRUPT)
-               set_bit(PPC440SPE_DESC_INT, &desc->flags);
-       else
-               clear_bit(PPC440SPE_DESC_INT, &desc->flags);
-
-       hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value);
-       hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value);
-       hw_desc->opc = DMA_CDB_OPC_DFILL128;
-}
-
 /**
  * ppc440spe_desc_set_src_addr - set source address into the descriptor
  */
@@ -1504,8 +1481,6 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
                struct ppc440spe_adma_chan *chan,
                dma_cookie_t cookie)
 {
-       int i;
-
        BUG_ON(desc->async_tx.cookie < 0);
        if (desc->async_tx.cookie > 0) {
                cookie = desc->async_tx.cookie;
@@ -3898,7 +3873,7 @@ static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev)
                        ppc440spe_adma_prep_dma_interrupt;
        }
        pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: "
-         "( %s%s%s%s%s%s%s)\n",
+         "( %s%s%s%s%s%s)\n",
          dev_name(adev->dev),
          dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "",
          dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "",
index 4cb12797863678be86af66017ec2cffb54f5dd16..4eddedb6eb7dd3deb68550c1b8065e8b9d882278 100644 (file)
@@ -628,42 +628,13 @@ retry:
        s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
 }
 
-static void s3c24xx_dma_unmap_buffers(struct s3c24xx_txd *txd)
-{
-       struct device *dev = txd->vd.tx.chan->device->dev;
-       struct s3c24xx_sg *dsg;
-
-       if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
-               if (txd->vd.tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_single(dev, dsg->src_addr, dsg->len,
-                                               DMA_TO_DEVICE);
-               else {
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_page(dev, dsg->src_addr, dsg->len,
-                                               DMA_TO_DEVICE);
-               }
-       }
-
-       if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
-               if (txd->vd.tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_single(dev, dsg->dst_addr, dsg->len,
-                                               DMA_FROM_DEVICE);
-               else
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_page(dev, dsg->dst_addr, dsg->len,
-                                               DMA_FROM_DEVICE);
-       }
-}
-
 static void s3c24xx_dma_desc_free(struct virt_dma_desc *vd)
 {
        struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
        struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(vd->tx.chan);
 
        if (!s3cchan->slave)
-               s3c24xx_dma_unmap_buffers(txd);
+               dma_descriptor_unmap(&vd->tx);
 
        s3c24xx_dma_free_txd(txd);
 }
@@ -795,7 +766,7 @@ static enum dma_status s3c24xx_dma_tx_status(struct dma_chan *chan,
 
        spin_lock_irqsave(&s3cchan->vc.lock, flags);
        ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret == DMA_SUCCESS) {
+       if (ret == DMA_COMPLETE) {
                spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
                return ret;
        }
index ebad84591a6e22bd1f28866c3f0b1946eba3dff0..3083d901a414f000a54e0337e02973a4586399bf 100644 (file)
@@ -60,6 +60,7 @@
 #define HPB_DMAE_DSTPR_DMSTP   BIT(0)
 
 /* DMA status register (DSTSR) bits */
+#define HPB_DMAE_DSTSR_DQSTS   BIT(2)
 #define HPB_DMAE_DSTSR_DMSTS   BIT(0)
 
 /* DMA common registers */
@@ -286,6 +287,9 @@ static void hpb_dmae_halt(struct shdma_chan *schan)
 
        ch_reg_write(chan, HPB_DMAE_DCMDR_DQEND, HPB_DMAE_DCMDR);
        ch_reg_write(chan, HPB_DMAE_DSTPR_DMSTP, HPB_DMAE_DSTPR);
+
+       chan->plane_idx = 0;
+       chan->first_desc = true;
 }
 
 static const struct hpb_dmae_slave_config *
@@ -385,7 +389,10 @@ static bool hpb_dmae_channel_busy(struct shdma_chan *schan)
        struct hpb_dmae_chan *chan = to_chan(schan);
        u32 dstsr = ch_reg_read(chan, HPB_DMAE_DSTSR);
 
-       return (dstsr & HPB_DMAE_DSTSR_DMSTS) == HPB_DMAE_DSTSR_DMSTS;
+       if (chan->xfer_mode == XFER_DOUBLE)
+               return dstsr & HPB_DMAE_DSTSR_DQSTS;
+       else
+               return dstsr & HPB_DMAE_DSTSR_DMSTS;
 }
 
 static int
@@ -510,6 +517,8 @@ static int hpb_dmae_chan_probe(struct hpb_dmae_device *hpbdev, int id)
        }
 
        schan = &new_hpb_chan->shdma_chan;
+       schan->max_xfer_len = HPB_DMA_TCR_MAX;
+
        shdma_chan_probe(sdev, schan, id);
 
        if (pdev->id >= 0)
index bae6c29f5502ab951f7926bdf621977703bc96b1..17686caf64d5c4beedd0d189dd4487a57acb1254 100644 (file)
@@ -406,7 +406,6 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
        dma_async_tx_callback callback;
        void *param;
        struct dma_async_tx_descriptor *txd = &desc->txd;
-       struct txx9dmac_slave *ds = dc->chan.private;
 
        dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
                 txd->cookie, desc);
index b53d0de17e155290294238c0add6aec7dea9cbff..98e14ee4833c4d26b805843bcbe30daf29f99bb3 100644 (file)
@@ -1,7 +1,7 @@
 #include "amd64_edac.h"
 #include <asm/amd_nb.h>
 
-static struct edac_pci_ctl_info *amd64_ctl_pci;
+static struct edac_pci_ctl_info *pci_ctl;
 
 static int report_gart_errors;
 module_param(report_gart_errors, int, 0644);
@@ -162,7 +162,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
  * scan the scrub rate mapping table for a close or matching bandwidth value to
  * issue. If requested is too big, then use last maximum value found.
  */
-static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
+static int __set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 {
        u32 scrubval;
        int i;
@@ -198,7 +198,7 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
        return 0;
 }
 
-static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
+static int set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
        u32 min_scrubrate = 0x5;
@@ -210,10 +210,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
        if (pvt->fam == 0x15 && pvt->model < 0x10)
                f15h_select_dct(pvt, 0);
 
-       return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
+       return __set_scrub_rate(pvt->F3, bw, min_scrubrate);
 }
 
-static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
+static int get_scrub_rate(struct mem_ctl_info *mci)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
        u32 scrubval = 0;
@@ -240,8 +240,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
  * returns true if the SysAddr given by sys_addr matches the
  * DRAM base/limit associated with node_id
  */
-static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr,
-                                  u8 nid)
+static bool base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, u8 nid)
 {
        u64 addr;
 
@@ -285,7 +284,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
 
        if (intlv_en == 0) {
                for (node_id = 0; node_id < DRAM_RANGES; node_id++) {
-                       if (amd64_base_limit_match(pvt, sys_addr, node_id))
+                       if (base_limit_match(pvt, sys_addr, node_id))
                                goto found;
                }
                goto err_no_match;
@@ -309,7 +308,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
        }
 
        /* sanity test for sys_addr */
-       if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) {
+       if (unlikely(!base_limit_match(pvt, sys_addr, node_id))) {
                amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address"
                           "range for node %d with node interleaving enabled.\n",
                           __func__, sys_addr, node_id);
@@ -660,7 +659,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
  * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
  * are ECC capable.
  */
-static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
+static unsigned long determine_edac_cap(struct amd64_pvt *pvt)
 {
        u8 bit;
        unsigned long edac_cap = EDAC_FLAG_NONE;
@@ -675,9 +674,9 @@ static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt)
        return edac_cap;
 }
 
-static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8);
+static void debug_display_dimm_sizes(struct amd64_pvt *, u8);
 
-static void amd64_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
+static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 {
        edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr);
 
@@ -711,7 +710,7 @@ static void dump_misc_regs(struct amd64_pvt *pvt)
                 (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no",
                 (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no");
 
-       amd64_dump_dramcfg_low(pvt, pvt->dclr0, 0);
+       debug_dump_dramcfg_low(pvt, pvt->dclr0, 0);
 
        edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare);
 
@@ -722,19 +721,19 @@ static void dump_misc_regs(struct amd64_pvt *pvt)
 
        edac_dbg(1, "  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
 
-       amd64_debug_display_dimm_sizes(pvt, 0);
+       debug_display_dimm_sizes(pvt, 0);
 
        /* everything below this point is Fam10h and above */
        if (pvt->fam == 0xf)
                return;
 
-       amd64_debug_display_dimm_sizes(pvt, 1);
+       debug_display_dimm_sizes(pvt, 1);
 
        amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
 
        /* Only if NOT ganged does dclr1 have valid info */
        if (!dct_ganging_enabled(pvt))
-               amd64_dump_dramcfg_low(pvt, pvt->dclr1, 1);
+               debug_dump_dramcfg_low(pvt, pvt->dclr1, 1);
 }
 
 /*
@@ -800,7 +799,7 @@ static void read_dct_base_mask(struct amd64_pvt *pvt)
        }
 }
 
-static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs)
+static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs)
 {
        enum mem_type type;
 
@@ -1578,7 +1577,7 @@ static int f15_m30h_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
                                             num_dcts_intlv, dct_sel);
 
        /* Verify we stay within the MAX number of channels allowed */
-       if (channel > 4 || channel < 0)
+       if (channel > 3)
                return -EINVAL;
 
        leg_mmio_hole = (u8) (dct_cont_base_reg >> 1 & BIT(0));
@@ -1702,7 +1701,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
  * debug routine to display the memory sizes of all logical DIMMs and its
  * CSROWs
  */
-static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
+static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 {
        int dimm, size0, size1;
        u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
@@ -1744,7 +1743,7 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
        }
 }
 
-static struct amd64_family_type amd64_family_types[] = {
+static struct amd64_family_type family_types[] = {
        [K8_CPUS] = {
                .ctl_name = "K8",
                .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
@@ -2005,9 +2004,9 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
                             string, "");
 }
 
-static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
-                                           struct mce *m)
+static inline void decode_bus_error(int node_id, struct mce *m)
 {
+       struct mem_ctl_info *mci = mcis[node_id];
        struct amd64_pvt *pvt = mci->pvt_info;
        u8 ecc_type = (m->status >> 45) & 0x3;
        u8 xec = XEC(m->status, 0x1f);
@@ -2035,11 +2034,6 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
        __log_bus_error(mci, &err, ecc_type);
 }
 
-void amd64_decode_bus_error(int node_id, struct mce *m)
-{
-       __amd64_decode_bus_error(mcis[node_id], m);
-}
-
 /*
  * Use pvt->F2 which contains the F2 CPU PCI device to get the related
  * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error.
@@ -2196,7 +2190,7 @@ static void read_mc_regs(struct amd64_pvt *pvt)
  *     encompasses
  *
  */
-static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
 {
        u32 cs_mode, nr_pages;
        u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
@@ -2263,19 +2257,19 @@ static int init_csrows(struct mem_ctl_info *mci)
                            pvt->mc_node_id, i);
 
                if (row_dct0) {
-                       nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
+                       nr_pages = get_csrow_nr_pages(pvt, 0, i);
                        csrow->channels[0]->dimm->nr_pages = nr_pages;
                }
 
                /* K8 has only one DCT */
                if (pvt->fam != 0xf && row_dct1) {
-                       int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i);
+                       int row_dct1_pages = get_csrow_nr_pages(pvt, 1, i);
 
                        csrow->channels[1]->dimm->nr_pages = row_dct1_pages;
                        nr_pages += row_dct1_pages;
                }
 
-               mtype = amd64_determine_memory_type(pvt, i);
+               mtype = determine_memory_type(pvt, i);
 
                edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
 
@@ -2309,7 +2303,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid)
 }
 
 /* check MCG_CTL on all the cpus on this node */
-static bool amd64_nb_mce_bank_enabled_on_node(u16 nid)
+static bool nb_mce_bank_enabled_on_node(u16 nid)
 {
        cpumask_var_t mask;
        int cpu, nbe;
@@ -2482,7 +2476,7 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid)
        ecc_en = !!(value & NBCFG_ECC_ENABLE);
        amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
 
-       nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid);
+       nb_mce_en = nb_mce_bank_enabled_on_node(nid);
        if (!nb_mce_en)
                amd64_notice("NB MCE bank disabled, set MSR "
                             "0x%08x[4] on node %d to enable.\n",
@@ -2537,7 +2531,7 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
        if (pvt->nbcap & NBCAP_CHIPKILL)
                mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
 
-       mci->edac_cap           = amd64_determine_edac_cap(pvt);
+       mci->edac_cap           = determine_edac_cap(pvt);
        mci->mod_name           = EDAC_MOD_STR;
        mci->mod_ver            = EDAC_AMD64_VERSION;
        mci->ctl_name           = fam->ctl_name;
@@ -2545,14 +2539,14 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
        mci->ctl_page_to_phys   = NULL;
 
        /* memory scrubber interface */
-       mci->set_sdram_scrub_rate = amd64_set_scrub_rate;
-       mci->get_sdram_scrub_rate = amd64_get_scrub_rate;
+       mci->set_sdram_scrub_rate = set_scrub_rate;
+       mci->get_sdram_scrub_rate = get_scrub_rate;
 }
 
 /*
  * returns a pointer to the family descriptor on success, NULL otherwise.
  */
-static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
+static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
 {
        struct amd64_family_type *fam_type = NULL;
 
@@ -2563,29 +2557,29 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
 
        switch (pvt->fam) {
        case 0xf:
-               fam_type                = &amd64_family_types[K8_CPUS];
-               pvt->ops                = &amd64_family_types[K8_CPUS].ops;
+               fam_type        = &family_types[K8_CPUS];
+               pvt->ops        = &family_types[K8_CPUS].ops;
                break;
 
        case 0x10:
-               fam_type                = &amd64_family_types[F10_CPUS];
-               pvt->ops                = &amd64_family_types[F10_CPUS].ops;
+               fam_type        = &family_types[F10_CPUS];
+               pvt->ops        = &family_types[F10_CPUS].ops;
                break;
 
        case 0x15:
                if (pvt->model == 0x30) {
-                       fam_type        = &amd64_family_types[F15_M30H_CPUS];
-                       pvt->ops        = &amd64_family_types[F15_M30H_CPUS].ops;
+                       fam_type = &family_types[F15_M30H_CPUS];
+                       pvt->ops = &family_types[F15_M30H_CPUS].ops;
                        break;
                }
 
-               fam_type                = &amd64_family_types[F15_CPUS];
-               pvt->ops                = &amd64_family_types[F15_CPUS].ops;
+               fam_type        = &family_types[F15_CPUS];
+               pvt->ops        = &family_types[F15_CPUS].ops;
                break;
 
        case 0x16:
-               fam_type                = &amd64_family_types[F16_CPUS];
-               pvt->ops                = &amd64_family_types[F16_CPUS].ops;
+               fam_type        = &family_types[F16_CPUS];
+               pvt->ops        = &family_types[F16_CPUS].ops;
                break;
 
        default:
@@ -2601,7 +2595,7 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
        return fam_type;
 }
 
-static int amd64_init_one_instance(struct pci_dev *F2)
+static int init_one_instance(struct pci_dev *F2)
 {
        struct amd64_pvt *pvt = NULL;
        struct amd64_family_type *fam_type = NULL;
@@ -2619,7 +2613,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
        pvt->F2 = F2;
 
        ret = -EINVAL;
-       fam_type = amd64_per_family_init(pvt);
+       fam_type = per_family_init(pvt);
        if (!fam_type)
                goto err_free;
 
@@ -2680,7 +2674,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
        if (report_gart_errors)
                amd_report_gart_errors(true);
 
-       amd_register_ecc_decoder(amd64_decode_bus_error);
+       amd_register_ecc_decoder(decode_bus_error);
 
        mcis[nid] = mci;
 
@@ -2703,8 +2697,8 @@ err_ret:
        return ret;
 }
 
-static int amd64_probe_one_instance(struct pci_dev *pdev,
-                                   const struct pci_device_id *mc_type)
+static int probe_one_instance(struct pci_dev *pdev,
+                             const struct pci_device_id *mc_type)
 {
        u16 nid = amd_get_node_id(pdev);
        struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
@@ -2736,7 +2730,7 @@ static int amd64_probe_one_instance(struct pci_dev *pdev,
                        goto err_enable;
        }
 
-       ret = amd64_init_one_instance(pdev);
+       ret = init_one_instance(pdev);
        if (ret < 0) {
                amd64_err("Error probing instance: %d\n", nid);
                restore_ecc_error_reporting(s, nid, F3);
@@ -2752,7 +2746,7 @@ err_out:
        return ret;
 }
 
-static void amd64_remove_one_instance(struct pci_dev *pdev)
+static void remove_one_instance(struct pci_dev *pdev)
 {
        struct mem_ctl_info *mci;
        struct amd64_pvt *pvt;
@@ -2777,7 +2771,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev)
 
        /* unregister from EDAC MCE */
        amd_report_gart_errors(false);
-       amd_unregister_ecc_decoder(amd64_decode_bus_error);
+       amd_unregister_ecc_decoder(decode_bus_error);
 
        kfree(ecc_stngs[nid]);
        ecc_stngs[nid] = NULL;
@@ -2795,7 +2789,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev)
  * PCI core identifies what devices are on a system during boot, and then
  * inquiry this table to see if this driver is for a given device found.
  */
-static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = {
+static const struct pci_device_id amd64_pci_table[] = {
        {
                .vendor         = PCI_VENDOR_ID_AMD,
                .device         = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
@@ -2843,8 +2837,8 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table);
 
 static struct pci_driver amd64_pci_driver = {
        .name           = EDAC_MOD_STR,
-       .probe          = amd64_probe_one_instance,
-       .remove         = amd64_remove_one_instance,
+       .probe          = probe_one_instance,
+       .remove         = remove_one_instance,
        .id_table       = amd64_pci_table,
 };
 
@@ -2853,23 +2847,18 @@ static void setup_pci_device(void)
        struct mem_ctl_info *mci;
        struct amd64_pvt *pvt;
 
-       if (amd64_ctl_pci)
+       if (pci_ctl)
                return;
 
        mci = mcis[0];
-       if (mci) {
-
-               pvt = mci->pvt_info;
-               amd64_ctl_pci =
-                       edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
-
-               if (!amd64_ctl_pci) {
-                       pr_warning("%s(): Unable to create PCI control\n",
-                                  __func__);
+       if (!mci)
+               return;
 
-                       pr_warning("%s(): PCI error report via EDAC not set\n",
-                                  __func__);
-                       }
+       pvt = mci->pvt_info;
+       pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
+       if (!pci_ctl) {
+               pr_warn("%s(): Unable to create PCI control\n", __func__);
+               pr_warn("%s(): PCI error report via EDAC not set\n", __func__);
        }
 }
 
@@ -2925,8 +2914,8 @@ err_ret:
 
 static void __exit amd64_edac_exit(void)
 {
-       if (amd64_ctl_pci)
-               edac_pci_release_generic_ctl(amd64_ctl_pci);
+       if (pci_ctl)
+               edac_pci_release_generic_ctl(pci_ctl);
 
        pci_unregister_driver(&amd64_pci_driver);
 
index 96e3ee3460a566a96928eb45b332ced184902fe8..3a501b530e11347c8b3d918b470b255464e42dab 100644 (file)
@@ -333,7 +333,7 @@ static void amd76x_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(amd76x_pci_tbl) = {
+static const struct pci_device_id amd76x_pci_tbl[] = {
        {
         PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         AMD762},
index 644fec54681fcb5c56bac57a5ced18505ee4da46..92d54fa65f939d57f7f18332bed3f6d55a03d33d 100644 (file)
@@ -1182,9 +1182,11 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
        pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
                                pvt->dev_info->err_dev, pvt->bridge_ck);
 
-       if (pvt->bridge_ck == NULL)
+       if (pvt->bridge_ck == NULL) {
                pvt->bridge_ck = pci_scan_single_device(pdev->bus,
                                                        PCI_DEVFN(0, 1));
+               pci_dev_get(pvt->bridge_ck);
+       }
 
        if (pvt->bridge_ck == NULL) {
                e752x_printk(KERN_ERR, "error reporting device not found:"
@@ -1421,7 +1423,7 @@ static void e752x_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(e752x_pci_tbl) = {
+static const struct pci_device_id e752x_pci_tbl[] = {
        {
         PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         E7520},
index 1c4056a5038396e11c10945d695de060d00ad47c..3cda79bc8b0034d9917f6cafe457bfb67ba3815b 100644 (file)
@@ -555,7 +555,7 @@ static void e7xxx_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(e7xxx_pci_tbl) = {
+static const struct pci_device_id e7xxx_pci_tbl[] = {
        {
         PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         E7205},
index 102674346035e13bc28d6f3f001ea0d4a5e57e29..592af5f0cf391d292e05fd5c3a94b5589c7cb684 100644 (file)
@@ -437,6 +437,9 @@ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
 {
        int status;
 
+       if (!edac_dev->edac_check)
+               return;
+
        status = cancel_delayed_work(&edac_dev->work);
        if (status == 0) {
                /* workq instance might be running, wait for it */
index 9f7e0e609516c536ae9a7366f8e1c23e1c6cf32c..51c0362acf5c456db84eb0786722c284849b30b9 100644 (file)
@@ -914,7 +914,7 @@ void __exit edac_debugfs_exit(void)
        debugfs_remove(edac_debugfs);
 }
 
-int edac_create_debug_nodes(struct mem_ctl_info *mci)
+static int edac_create_debug_nodes(struct mem_ctl_info *mci)
 {
        struct dentry *d, *parent;
        char name[80];
index 351945fa2ecdca3f59a691db38206a0f13795797..9d9e18aefaaa491e2020d55b503bcbbe862a9032 100644 (file)
@@ -29,6 +29,25 @@ EXPORT_SYMBOL_GPL(edac_err_assert);
 
 static atomic_t edac_subsys_valid = ATOMIC_INIT(0);
 
+int edac_report_status = EDAC_REPORTING_ENABLED;
+EXPORT_SYMBOL_GPL(edac_report_status);
+
+static int __init edac_report_setup(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!strncmp(str, "on", 2))
+               set_edac_report_status(EDAC_REPORTING_ENABLED);
+       else if (!strncmp(str, "off", 3))
+               set_edac_report_status(EDAC_REPORTING_DISABLED);
+       else if (!strncmp(str, "force", 5))
+               set_edac_report_status(EDAC_REPORTING_FORCE);
+
+       return 0;
+}
+__setup("edac_report=", edac_report_setup);
+
 /*
  * called to determine if there is an EDAC driver interested in
  * knowing an event (such as NMI) occurred
index 694efcbf19c097d45f715c06eda1f234bc89788c..cd28b968e5c7a19e21105a1a2252e84a26f70074 100644 (file)
@@ -487,7 +487,7 @@ static void i3000_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(i3000_pci_tbl) = {
+static const struct pci_device_id i3000_pci_tbl[] = {
        {
         PCI_VEND_DEV(INTEL, 3000_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         I3000},
index be10a74b16ea7132cf895acaf51a03eaec5ae9d5..fa1326e5a4b06d61c2c5fc7756121acc4a8f44bc 100644 (file)
@@ -466,7 +466,7 @@ static void i3200_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(i3200_pci_tbl) = {
+static const struct pci_device_id i3200_pci_tbl[] = {
        {
                PCI_VEND_DEV(INTEL, 3200_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                I3200},
index 63b2194e8c20683b38570d269300c82e96d8a3bf..72e07e3cf718fb760c62cda09023b199857bcb13 100644 (file)
@@ -1530,7 +1530,7 @@ static void i5000_remove_one(struct pci_dev *pdev)
  *
  *     The "E500P" device is the first device supported.
  */
-static DEFINE_PCI_DEVICE_TABLE(i5000_pci_tbl) = {
+static const struct pci_device_id i5000_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I5000_DEV16),
         .driver_data = I5000P},
 
index 157b934e8ce3a528468e45a735ab41dee6043cea..36a38ee94fa8a5236a27d9899b5c1481ac7fb981 100644 (file)
@@ -1213,7 +1213,7 @@ static void i5100_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(i5100_pci_tbl) = {
+static const struct pci_device_id i5100_pci_tbl[] = {
        /* Device 16, Function 0, Channel 0 Memory Map, Error Flag/Mask, ... */
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_16) },
        { 0, }
index 0a05bbceb08f4e870eb97f50443f6c7e6447676a..e080cbfa8fc9d0e4c8c255ac1165306be716c336 100644 (file)
@@ -1416,7 +1416,7 @@ static void i5400_remove_one(struct pci_dev *pdev)
  *
  *     The "E500P" device is the first device supported.
  */
-static DEFINE_PCI_DEVICE_TABLE(i5400_pci_tbl) = {
+static const struct pci_device_id i5400_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)},
        {0,}                    /* 0 terminated list. */
 };
index 9004c64b169e05c37394bd742ae0f1042b8a2eb1..d63f4798f7d09127872f97ed925a5af64a75f81f 100644 (file)
@@ -1160,7 +1160,7 @@ static void i7300_remove_one(struct pci_dev *pdev)
  *
  * Has only 8086:360c PCI ID
  */
-static DEFINE_PCI_DEVICE_TABLE(i7300_pci_tbl) = {
+static const struct pci_device_id i7300_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)},
        {0,}                    /* 0 terminated list. */
 };
index 80a963d64e58c143db789743d664e998c9e1ee66..87533ca7752e0105683210913f83731a9b988aab 100644 (file)
@@ -394,7 +394,7 @@ static const struct pci_id_table pci_dev_table[] = {
 /*
  *     pci_device_id   table for which devices we are looking for
  */
-static DEFINE_PCI_DEVICE_TABLE(i7core_pci_tbl) = {
+static const struct pci_device_id i7core_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)},
        {0,}                    /* 0 terminated list. */
index 57fdb77903ba9a142513a94cabd7b5775defed1a..d730e276d1a8437526f168e83f503c1d5c236473 100644 (file)
@@ -386,7 +386,7 @@ static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
 
 EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_remove_one);
 
-static DEFINE_PCI_DEVICE_TABLE(i82443bxgx_pci_tbl) = {
+static const struct pci_device_id i82443bxgx_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0)},
index 3e3e431c83011313dadc901afe8347501a23e911..3382f6344e428b31a4659660140a7ea90e5cab28 100644 (file)
@@ -288,7 +288,7 @@ static void i82860_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(i82860_pci_tbl) = {
+static const struct pci_device_id i82860_pci_tbl[] = {
        {
         PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         I82860},
index 2f8535fc451e64745be644b6a685b6be414005ed..80573df0a4d77d9e083af858735f619addef8948 100644 (file)
@@ -527,7 +527,7 @@ static void i82875p_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(i82875p_pci_tbl) = {
+static const struct pci_device_id i82875p_pci_tbl[] = {
        {
         PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         I82875P},
index 0c8d4b0eaa32876c1eecc8f83b708242244855a1..10b10521f62e19a550479755ad41247683d336e6 100644 (file)
@@ -628,7 +628,7 @@ static void i82975x_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(i82975x_pci_tbl) = {
+static const struct pci_device_id i82975x_pci_tbl[] = {
        {
                PCI_VEND_DEV(INTEL, 82975_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                I82975X
index fd46b0bd5f2ae273cec5cad4a42b621613b307da..8f9182179a7c804088d1889ac96c7f90a28d804e 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Freescale MPC85xx Memory Controller kenel module
  *
+ * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.
+ *
  * Author: Dave Jiang <djiang@mvista.com>
  *
  * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
@@ -196,6 +198,42 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
                edac_pci_handle_npe(pci, pci->ctl_name);
 }
 
+static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
+{
+       struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+       u32 err_detect;
+
+       err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
+
+       pr_err("PCIe error(s) detected\n");
+       pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect);
+       pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n",
+                       in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR));
+       pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n",
+                       in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
+       pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n",
+                       in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
+       pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n",
+                       in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
+       pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n",
+                       in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
+
+       /* clear error bits */
+       out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
+}
+
+static int mpc85xx_pcie_find_capability(struct device_node *np)
+{
+       struct pci_controller *hose;
+
+       if (!np)
+               return -EINVAL;
+
+       hose = pci_find_hose_for_OF_device(np);
+
+       return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
+}
+
 static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
 {
        struct edac_pci_ctl_info *pci = dev_id;
@@ -207,7 +245,10 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
        if (!err_detect)
                return IRQ_NONE;
 
-       mpc85xx_pci_check(pci);
+       if (pdata->is_pcie)
+               mpc85xx_pcie_check(pci);
+       else
+               mpc85xx_pci_check(pci);
 
        return IRQ_HANDLED;
 }
@@ -239,14 +280,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
        pdata = pci->pvt_info;
        pdata->name = "mpc85xx_pci_err";
        pdata->irq = NO_IRQ;
+
+       if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
+               pdata->is_pcie = true;
+
        dev_set_drvdata(&op->dev, pci);
        pci->dev = &op->dev;
        pci->mod_name = EDAC_MOD_STR;
        pci->ctl_name = pdata->name;
        pci->dev_name = dev_name(&op->dev);
 
-       if (edac_op_state == EDAC_OPSTATE_POLL)
-               pci->edac_check = mpc85xx_pci_check;
+       if (edac_op_state == EDAC_OPSTATE_POLL) {
+               if (pdata->is_pcie)
+                       pci->edac_check = mpc85xx_pcie_check;
+               else
+                       pci->edac_check = mpc85xx_pci_check;
+       }
 
        pdata->edac_idx = edac_pci_idx++;
 
@@ -275,16 +324,26 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
                goto err;
        }
 
-       orig_pci_err_cap_dr =
-           in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
+       if (pdata->is_pcie) {
+               orig_pci_err_cap_dr =
+                   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);
+               out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);
+               orig_pci_err_en =
+                   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+               out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);
+       } else {
+               orig_pci_err_cap_dr =
+                   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
 
-       /* PCI master abort is expected during config cycles */
-       out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
+               /* PCI master abort is expected during config cycles */
+               out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
 
-       orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+               orig_pci_err_en =
+                   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
 
-       /* disable master abort reporting */
-       out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+               /* disable master abort reporting */
+               out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+       }
 
        /* clear error bits */
        out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
@@ -297,7 +356,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
        if (edac_op_state == EDAC_OPSTATE_INT) {
                pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
-                                      mpc85xx_pci_isr, IRQF_DISABLED,
+                                      mpc85xx_pci_isr,
+                                      IRQF_DISABLED | IRQF_SHARED,
                                       "[EDAC] PCI err", pci);
                if (res < 0) {
                        printk(KERN_ERR
@@ -312,6 +372,22 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
                       pdata->irq);
        }
 
+       if (pdata->is_pcie) {
+               /*
+                * Enable all PCIe error interrupt & error detect except invalid
+                * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation
+                * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access
+                * detection enable bit. Because PCIe bus code to initialize and
+                * configure these PCIe devices on booting will use some invalid
+                * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much
+                * notice information. So disable this detect to fix ugly print.
+                */
+               out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0
+                        & ~PEX_ERR_ICCAIE_EN_BIT);
+               out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0
+                        | PEX_ERR_ICCAD_DISR_BIT);
+       }
+
        devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
        edac_dbg(3, "success\n");
        printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
index 932016f2cf06032a78f48297899a9a9c8b3c8eb2..8c6256436227be68d90ddd5ca8ebd3667857086c 100644 (file)
 #define MPC85XX_PCI_ERR_DR             0x0000
 #define MPC85XX_PCI_ERR_CAP_DR         0x0004
 #define MPC85XX_PCI_ERR_EN             0x0008
+#define   PEX_ERR_ICCAIE_EN_BIT                0x00020000
 #define MPC85XX_PCI_ERR_ATTRIB         0x000c
 #define MPC85XX_PCI_ERR_ADDR           0x0010
+#define   PEX_ERR_ICCAD_DISR_BIT       0x00020000
 #define MPC85XX_PCI_ERR_EXT_ADDR       0x0014
 #define MPC85XX_PCI_ERR_DL             0x0018
 #define MPC85XX_PCI_ERR_DH             0x001c
 #define MPC85XX_PCI_GAS_TIMR           0x0020
 #define MPC85XX_PCI_PCIX_TIMR          0x0024
+#define MPC85XX_PCIE_ERR_CAP_R0                0x0028
+#define MPC85XX_PCIE_ERR_CAP_R1                0x002c
+#define MPC85XX_PCIE_ERR_CAP_R2                0x0030
+#define MPC85XX_PCIE_ERR_CAP_R3                0x0034
 
 struct mpc85xx_mc_pdata {
        char *name;
@@ -158,6 +164,7 @@ struct mpc85xx_l2_pdata {
 
 struct mpc85xx_pci_pdata {
        char *name;
+       bool is_pcie;
        int edac_idx;
        void __iomem *pci_vbase;
        int irq;
index 2fd6a549090584b8ac69848acfd30750a9f68e0b..8f936bc7a010cb448b9e99c1a675eed6347f9ccd 100644 (file)
@@ -383,7 +383,7 @@ static void r82600_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(r82600_pci_tbl) = {
+static const struct pci_device_id r82600_pci_tbl[] = {
        {
         PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)
         },
index 8472405c558612e949e5be4caa6a6ac7c889c335..54e2abe671f70acef2965ec5f74cd8b877ac7089 100644 (file)
@@ -461,7 +461,7 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
 /*
  *     pci_device_id   table for which devices we are looking for
  */
-static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = {
+static const struct pci_device_id sbridge_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
        {0,}                    /* 0 terminated list. */
@@ -915,7 +915,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
        }
 }
 
-struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
+static struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
 {
        struct sbridge_dev *sbridge_dev;
 
@@ -945,7 +945,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        u32                     tad_offset;
        u32                     rir_way;
        u32                     mb, kb;
-       u64                     ch_addr, offset, limit, prv = 0;
+       u64                     ch_addr, offset, limit = 0, prv = 0;
 
 
        /*
@@ -1829,6 +1829,9 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
        struct mem_ctl_info *mci;
        struct sbridge_pvt *pvt;
 
+       if (get_edac_report_status() == EDAC_REPORTING_DISABLED)
+               return NOTIFY_DONE;
+
        mci = get_mci_for_node_id(mce->socketid);
        if (!mci)
                return NOTIFY_BAD;
@@ -2142,9 +2145,10 @@ static int __init sbridge_init(void)
        opstate_init();
 
        pci_rc = pci_register_driver(&sbridge_driver);
-
        if (pci_rc >= 0) {
                mce_register_decode_chain(&sbridge_mce_dec);
+               if (get_edac_report_status() == EDAC_REPORTING_DISABLED)
+                       sbridge_printk(KERN_WARNING, "Loading driver, error reporting disabled.\n");
                return 0;
        }
 
index 1a4df82376ba425236f569905a589125c72ccf2a..4891b450830bdd742076927957819da9b666c445 100644 (file)
@@ -448,7 +448,7 @@ static void x38_remove_one(struct pci_dev *pdev)
        edac_mc_free(mci);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(x38_pci_tbl) = {
+static const struct pci_device_id x38_pci_tbl[] = {
        {
         PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         X38},
index 3c55ec856e39c714e7b474f081c01180b9aa9e2d..a287cece0593c327c53e8961b70a0dde8b1af2ce 100644 (file)
@@ -1082,7 +1082,7 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
 static int arizona_extcon_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
-       struct arizona_pdata *pdata;
+       struct arizona_pdata *pdata = &arizona->pdata;
        struct arizona_extcon_info *info;
        unsigned int val;
        int jack_irq_fall, jack_irq_rise;
@@ -1091,8 +1091,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
        if (!arizona->dapm || !arizona->dapm->card)
                return -EPROBE_DEFER;
 
-       pdata = dev_get_platdata(arizona->dev);
-
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (!info) {
                dev_err(&pdev->dev, "Failed to allocate memory\n");
index 15443d3b6be18049ddddbb7ec035eb05ce7dc409..76322330cbd7a10b427ff5d011b83abbd0abb0e8 100644 (file)
@@ -792,6 +792,8 @@ void extcon_dev_unregister(struct extcon_dev *edev)
                return;
        }
 
+       device_unregister(&edev->dev);
+
        if (edev->mutually_exclusive && edev->max_supported) {
                for (index = 0; edev->mutually_exclusive[index];
                                index++)
@@ -812,7 +814,6 @@ void extcon_dev_unregister(struct extcon_dev *edev)
        if (switch_class)
                class_compat_remove_link(switch_class, &edev->dev, NULL);
 #endif
-       device_unregister(&edev->dev);
        put_device(&edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
index 299fad6b5867287f0869648e4a99eaa9b581d872..5373dc5b60114f31af5cf66cdbb923bdc6b0f973 100644 (file)
@@ -14,3 +14,4 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
 obj-$(CONFIG_EFI)              += efi/
+obj-$(CONFIG_UEFI_CPER)                += efi/
index 3150aa4874e8f67e4360635934acdcb11bac6fef..1e75f48b61f8a1ca92991873e27e69479862bcbb 100644 (file)
@@ -36,7 +36,18 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE
          backend for pstore by default. This setting can be overridden
          using the efivars module's pstore_disable parameter.
 
-config UEFI_CPER
-       def_bool n
+config EFI_RUNTIME_MAP
+       bool "Export efi runtime maps to sysfs"
+       depends on X86 && EFI && KEXEC
+       default y
+       help
+         Export efi runtime memory maps to /sys/firmware/efi/runtime-map.
+         That memory map is used for example by kexec to set up efi virtual
+         mapping the 2nd kernel, but can also be used for debugging purposes.
+
+         See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
 
 endmenu
+
+config UEFI_CPER
+       bool
index 9ba156d3c7755e6854595b9983fc23db20fa2111..9553496b0f43ed9cffd2826b99df2fbb60655fb9 100644 (file)
@@ -1,7 +1,8 @@
 #
 # Makefile for linux kernel
 #
-obj-y                                  += efi.o vars.o
+obj-$(CONFIG_EFI)                      += efi.o vars.o
 obj-$(CONFIG_EFI_VARS)                 += efivars.o
 obj-$(CONFIG_EFI_VARS_PSTORE)          += efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)                        += cper.o
+obj-$(CONFIG_EFI_RUNTIME_MAP)          += runtime-map.o
index 5002d50e37817314d1fe3e449ad991ade1969f6b..4b9dc836dcf956e86c3800398946d40b0d1cf6dc 100644 (file)
@@ -18,14 +18,12 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
-       efivar_entry_iter_begin();
        psi->data = NULL;
        return 0;
 }
 
 static int efi_pstore_close(struct pstore_info *psi)
 {
-       efivar_entry_iter_end();
        psi->data = NULL;
        return 0;
 }
@@ -39,6 +37,12 @@ struct pstore_read_data {
        char **buf;
 };
 
+static inline u64 generic_id(unsigned long timestamp,
+                            unsigned int part, int count)
+{
+       return (timestamp * 100 + part) * 1000 + count;
+}
+
 static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 {
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
@@ -57,7 +61,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 
        if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
                   cb_data->type, &part, &cnt, &time, &data_type) == 5) {
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, cnt);
                *cb_data->count = cnt;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -67,7 +71,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
                        *cb_data->compressed = false;
        } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
                   cb_data->type, &part, &cnt, &time) == 4) {
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, cnt);
                *cb_data->count = cnt;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -79,7 +83,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
                 * which doesn't support holding
                 * multiple logs, remains.
                 */
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, 0);
                *cb_data->count = 0;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -91,19 +95,125 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
        __efivar_entry_get(entry, &entry->var.Attributes,
                           &entry->var.DataSize, entry->var.Data);
        size = entry->var.DataSize;
+       memcpy(*cb_data->buf, entry->var.Data,
+              (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
 
-       *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL);
-       if (*cb_data->buf == NULL)
-               return -ENOMEM;
        return size;
 }
 
+/**
+ * efi_pstore_scan_sysfs_enter
+ * @entry: scanning entry
+ * @next: next entry
+ * @head: list head
+ */
+static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos,
+                                       struct efivar_entry *next,
+                                       struct list_head *head)
+{
+       pos->scanning = true;
+       if (&next->list != head)
+               next->scanning = true;
+}
+
+/**
+ * __efi_pstore_scan_sysfs_exit
+ * @entry: deleting entry
+ * @turn_off_scanning: Check if a scanning flag should be turned off
+ */
+static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
+                                               bool turn_off_scanning)
+{
+       if (entry->deleting) {
+               list_del(&entry->list);
+               efivar_entry_iter_end();
+               efivar_unregister(entry);
+               efivar_entry_iter_begin();
+       } else if (turn_off_scanning)
+               entry->scanning = false;
+}
+
+/**
+ * efi_pstore_scan_sysfs_exit
+ * @pos: scanning entry
+ * @next: next entry
+ * @head: list head
+ * @stop: a flag checking if scanning will stop
+ */
+static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
+                                      struct efivar_entry *next,
+                                      struct list_head *head, bool stop)
+{
+       __efi_pstore_scan_sysfs_exit(pos, true);
+       if (stop)
+               __efi_pstore_scan_sysfs_exit(next, &next->list != head);
+}
+
+/**
+ * efi_pstore_sysfs_entry_iter
+ *
+ * @data: function-specific data to pass to callback
+ * @pos: entry to begin iterating from
+ *
+ * You MUST call efivar_enter_iter_begin() before this function, and
+ * efivar_entry_iter_end() afterwards.
+ *
+ * It is possible to begin iteration from an arbitrary entry within
+ * the list by passing @pos. @pos is updated on return to point to
+ * the next entry of the last one passed to efi_pstore_read_func().
+ * To begin iterating from the beginning of the list @pos must be %NULL.
+ */
+static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
+{
+       struct efivar_entry *entry, *n;
+       struct list_head *head = &efivar_sysfs_list;
+       int size = 0;
+
+       if (!*pos) {
+               list_for_each_entry_safe(entry, n, head, list) {
+                       efi_pstore_scan_sysfs_enter(entry, n, head);
+
+                       size = efi_pstore_read_func(entry, data);
+                       efi_pstore_scan_sysfs_exit(entry, n, head, size < 0);
+                       if (size)
+                               break;
+               }
+               *pos = n;
+               return size;
+       }
+
+       list_for_each_entry_safe_from((*pos), n, head, list) {
+               efi_pstore_scan_sysfs_enter((*pos), n, head);
+
+               size = efi_pstore_read_func((*pos), data);
+               efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
+               if (size)
+                       break;
+       }
+       *pos = n;
+       return size;
+}
+
+/**
+ * efi_pstore_read
+ *
+ * This function returns a size of NVRAM entry logged via efi_pstore_write().
+ * The meaning and behavior of efi_pstore/pstore are as below.
+ *
+ * size > 0: Got data of an entry logged via efi_pstore_write() successfully,
+ *           and pstore filesystem will continue reading subsequent entries.
+ * size == 0: Entry was not logged via efi_pstore_write(),
+ *            and efi_pstore driver will continue reading subsequent entries.
+ * size < 0: Failed to get data of entry logging via efi_pstore_write(),
+ *           and pstore will stop reading entry.
+ */
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
                               int *count, struct timespec *timespec,
                               char **buf, bool *compressed,
                               struct pstore_info *psi)
 {
        struct pstore_read_data data;
+       ssize_t size;
 
        data.id = id;
        data.type = type;
@@ -112,8 +222,17 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
        data.compressed = compressed;
        data.buf = buf;
 
-       return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data,
-                                  (struct efivar_entry **)&psi->data);
+       *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
+       if (!*data.buf)
+               return -ENOMEM;
+
+       efivar_entry_iter_begin();
+       size = efi_pstore_sysfs_entry_iter(&data,
+                                          (struct efivar_entry **)&psi->data);
+       efivar_entry_iter_end();
+       if (size <= 0)
+               kfree(*data.buf);
+       return size;
 }
 
 static int efi_pstore_write(enum pstore_type_id type,
@@ -184,9 +303,17 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
                        return 0;
        }
 
+       if (entry->scanning) {
+               /*
+                * Skip deletion because this entry will be deleted
+                * after scanning is completed.
+                */
+               entry->deleting = true;
+       } else
+               list_del(&entry->list);
+
        /* found */
        __efivar_entry_delete(entry);
-       list_del(&entry->list);
 
        return 1;
 }
@@ -199,14 +326,16 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
        char name[DUMP_NAME_LEN];
        efi_char16_t efi_name[DUMP_NAME_LEN];
        int found, i;
+       unsigned int part;
 
-       sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
-               time.tv_sec);
+       do_div(id, 1000);
+       part = do_div(id, 100);
+       sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec);
 
        for (i = 0; i < DUMP_NAME_LEN; i++)
                efi_name[i] = name[i];
 
-       edata.id = id;
+       edata.id = part;
        edata.type = type;
        edata.count = count;
        edata.time = time;
@@ -214,10 +343,12 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 
        efivar_entry_iter_begin();
        found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry);
-       efivar_entry_iter_end();
 
-       if (found)
+       if (found && !entry->scanning) {
+               efivar_entry_iter_end();
                efivar_unregister(entry);
+       } else
+               efivar_entry_iter_end();
 
        return 0;
 }
@@ -225,6 +356,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 static struct pstore_info efi_pstore_info = {
        .owner          = THIS_MODULE,
        .name           = "efi",
+       .flags          = PSTORE_FLAGS_FRAGILE,
        .open           = efi_pstore_open,
        .close          = efi_pstore_close,
        .read           = efi_pstore_read,
index 2e2fbdec0845414df2f32a8c0f862b4149ce3198..4753bac652798501cc79caeb50bd6c9ebd2b2dd3 100644 (file)
@@ -32,6 +32,9 @@ struct efi __read_mostly efi = {
        .hcdp       = EFI_INVALID_TABLE_ADDR,
        .uga        = EFI_INVALID_TABLE_ADDR,
        .uv_systab  = EFI_INVALID_TABLE_ADDR,
+       .fw_vendor  = EFI_INVALID_TABLE_ADDR,
+       .runtime    = EFI_INVALID_TABLE_ADDR,
+       .config_table  = EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
 
@@ -71,13 +74,49 @@ static ssize_t systab_show(struct kobject *kobj,
 static struct kobj_attribute efi_attr_systab =
                        __ATTR(systab, 0400, systab_show, NULL);
 
+#define EFI_FIELD(var) efi.var
+
+#define EFI_ATTR_SHOW(name) \
+static ssize_t name##_show(struct kobject *kobj, \
+                               struct kobj_attribute *attr, char *buf) \
+{ \
+       return sprintf(buf, "0x%lx\n", EFI_FIELD(name)); \
+}
+
+EFI_ATTR_SHOW(fw_vendor);
+EFI_ATTR_SHOW(runtime);
+EFI_ATTR_SHOW(config_table);
+
+static struct kobj_attribute efi_attr_fw_vendor = __ATTR_RO(fw_vendor);
+static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
+static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
+
 static struct attribute *efi_subsys_attrs[] = {
        &efi_attr_systab.attr,
-       NULL,   /* maybe more in the future? */
+       &efi_attr_fw_vendor.attr,
+       &efi_attr_runtime.attr,
+       &efi_attr_config_table.attr,
+       NULL,
 };
 
+static umode_t efi_attr_is_visible(struct kobject *kobj,
+                                  struct attribute *attr, int n)
+{
+       umode_t mode = attr->mode;
+
+       if (attr == &efi_attr_fw_vendor.attr)
+               return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
+       else if (attr == &efi_attr_runtime.attr)
+               return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
+       else if (attr == &efi_attr_config_table.attr)
+               return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode;
+
+       return mode;
+}
+
 static struct attribute_group efi_subsys_attr_group = {
        .attrs = efi_subsys_attrs,
+       .is_visible = efi_attr_is_visible,
 };
 
 static struct efivars generic_efivars;
@@ -128,6 +167,10 @@ static int __init efisubsys_init(void)
                goto err_unregister;
        }
 
+       error = efi_runtime_map_init(efi_kobj);
+       if (error)
+               goto err_remove_group;
+
        /* and the standard mountpoint for efivarfs */
        efivars_kobj = kobject_create_and_add("efivars", efi_kobj);
        if (!efivars_kobj) {
index 933eb027d527d53aa8fb275b84c5d9b6e2ce3602..3dc24823919749ebb110f62b9ca5696cdaf67511 100644 (file)
@@ -383,12 +383,16 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
        else if (__efivar_entry_delete(entry))
                err = -EIO;
 
-       efivar_entry_iter_end();
-
-       if (err)
+       if (err) {
+               efivar_entry_iter_end();
                return err;
+       }
 
-       efivar_unregister(entry);
+       if (!entry->scanning) {
+               efivar_entry_iter_end();
+               efivar_unregister(entry);
+       } else
+               efivar_entry_iter_end();
 
        /* It's dead Jim.... */
        return count;
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
new file mode 100644 (file)
index 0000000..97cdd16
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * linux/drivers/efi/runtime-map.c
+ * Copyright (C) 2013 Red Hat, Inc., Dave Young <dyoung@redhat.com>
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/efi.h>
+#include <linux/slab.h>
+
+#include <asm/setup.h>
+
+static void *efi_runtime_map;
+static int nr_efi_runtime_map;
+static u32 efi_memdesc_size;
+
+struct efi_runtime_map_entry {
+       efi_memory_desc_t md;
+       struct kobject kobj;   /* kobject for each entry */
+};
+
+static struct efi_runtime_map_entry **map_entries;
+
+struct map_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct efi_runtime_map_entry *entry, char *buf);
+};
+
+static inline struct map_attribute *to_map_attr(struct attribute *attr)
+{
+       return container_of(attr, struct map_attribute, attr);
+}
+
+static ssize_t type_show(struct efi_runtime_map_entry *entry, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "0x%x\n", entry->md.type);
+}
+
+#define EFI_RUNTIME_FIELD(var) entry->md.var
+
+#define EFI_RUNTIME_U64_ATTR_SHOW(name) \
+static ssize_t name##_show(struct efi_runtime_map_entry *entry, char *buf) \
+{ \
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n", EFI_RUNTIME_FIELD(name)); \
+}
+
+EFI_RUNTIME_U64_ATTR_SHOW(phys_addr);
+EFI_RUNTIME_U64_ATTR_SHOW(virt_addr);
+EFI_RUNTIME_U64_ATTR_SHOW(num_pages);
+EFI_RUNTIME_U64_ATTR_SHOW(attribute);
+
+static inline struct efi_runtime_map_entry *to_map_entry(struct kobject *kobj)
+{
+       return container_of(kobj, struct efi_runtime_map_entry, kobj);
+}
+
+static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,
+                             char *buf)
+{
+       struct efi_runtime_map_entry *entry = to_map_entry(kobj);
+       struct map_attribute *map_attr = to_map_attr(attr);
+
+       return map_attr->show(entry, buf);
+}
+
+static struct map_attribute map_type_attr = __ATTR_RO(type);
+static struct map_attribute map_phys_addr_attr   = __ATTR_RO(phys_addr);
+static struct map_attribute map_virt_addr_attr  = __ATTR_RO(virt_addr);
+static struct map_attribute map_num_pages_attr  = __ATTR_RO(num_pages);
+static struct map_attribute map_attribute_attr  = __ATTR_RO(attribute);
+
+/*
+ * These are default attributes that are added for every memmap entry.
+ */
+static struct attribute *def_attrs[] = {
+       &map_type_attr.attr,
+       &map_phys_addr_attr.attr,
+       &map_virt_addr_attr.attr,
+       &map_num_pages_attr.attr,
+       &map_attribute_attr.attr,
+       NULL
+};
+
+static const struct sysfs_ops map_attr_ops = {
+       .show = map_attr_show,
+};
+
+static void map_release(struct kobject *kobj)
+{
+       struct efi_runtime_map_entry *entry;
+
+       entry = to_map_entry(kobj);
+       kfree(entry);
+}
+
+static struct kobj_type __refdata map_ktype = {
+       .sysfs_ops      = &map_attr_ops,
+       .default_attrs  = def_attrs,
+       .release        = map_release,
+};
+
+static struct kset *map_kset;
+
+static struct efi_runtime_map_entry *
+add_sysfs_runtime_map_entry(struct kobject *kobj, int nr)
+{
+       int ret;
+       struct efi_runtime_map_entry *entry;
+
+       if (!map_kset) {
+               map_kset = kset_create_and_add("runtime-map", NULL, kobj);
+               if (!map_kset)
+                       return ERR_PTR(-ENOMEM);
+       }
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry) {
+               kset_unregister(map_kset);
+               return entry;
+       }
+
+       memcpy(&entry->md, efi_runtime_map + nr * efi_memdesc_size,
+              sizeof(efi_memory_desc_t));
+
+       kobject_init(&entry->kobj, &map_ktype);
+       entry->kobj.kset = map_kset;
+       ret = kobject_add(&entry->kobj, NULL, "%d", nr);
+       if (ret) {
+               kobject_put(&entry->kobj);
+               kset_unregister(map_kset);
+               return ERR_PTR(ret);
+       }
+
+       return entry;
+}
+
+void efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size)
+{
+       efi_runtime_map = map;
+       nr_efi_runtime_map = nr_entries;
+       efi_memdesc_size = desc_size;
+}
+
+int __init efi_runtime_map_init(struct kobject *efi_kobj)
+{
+       int i, j, ret = 0;
+       struct efi_runtime_map_entry *entry;
+
+       if (!efi_runtime_map)
+               return 0;
+
+       map_entries = kzalloc(nr_efi_runtime_map * sizeof(entry), GFP_KERNEL);
+       if (!map_entries) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       for (i = 0; i < nr_efi_runtime_map; i++) {
+               entry = add_sysfs_runtime_map_entry(efi_kobj, i);
+               if (IS_ERR(entry)) {
+                       ret = PTR_ERR(entry);
+                       goto out_add_entry;
+               }
+               *(map_entries + i) = entry;
+       }
+
+       return 0;
+out_add_entry:
+       for (j = i - 1; j > 0; j--) {
+               entry = *(map_entries + j);
+               kobject_put(&entry->kobj);
+       }
+       if (map_kset)
+               kset_unregister(map_kset);
+out:
+       return ret;
+}
index 391c67b182d9b282681890cd04b98c0183023abc..b22659cccca42ebf85e3b54e52249b581b786409 100644 (file)
@@ -683,8 +683,16 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
        if (!found)
                return NULL;
 
-       if (remove)
-               list_del(&entry->list);
+       if (remove) {
+               if (entry->scanning) {
+                       /*
+                        * The entry will be deleted
+                        * after scanning is completed.
+                        */
+                       entry->deleting = true;
+               } else
+                       list_del(&entry->list);
+       }
 
        return entry;
 }
index 8847adf392b7ecf823f9f603314c76001367203f..84be70157ad6b6e9809bd007c422e223c359d429 100644 (file)
@@ -327,7 +327,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
         * NOTE:  we assume for now that only irqs in the first gpio_chip
         * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
         */
-       if (offset < d->irq_base)
+       if (offset < d->gpio_unbanked)
                return d->gpio_irq + offset;
        else
                return -ENODEV;
@@ -419,6 +419,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 
                /* pass "bank 0" GPIO IRQs to AINTC */
                chips[0].chip.to_irq = gpio_to_irq_unbanked;
+               chips[0].gpio_irq = bank_irq;
+               chips[0].gpio_unbanked = pdata->gpio_unbanked;
                binten = BIT(0);
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
index 914e859e3eda38724642a8bdf60ea8bb7d4adcd6..d7d6d72eba33e89306168a16f16f487e445bb183 100644 (file)
@@ -70,10 +70,14 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
        u32 val;
        struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+       u32 out_mask, out_shadow;
 
-       val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+       out_mask = in_be32(mm->regs + GPIO_DIR);
 
-       return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+       val = in_be32(mm->regs + GPIO_DAT) & ~out_mask;
+       out_shadow = mpc8xxx_gc->data & out_mask;
+
+       return (val | out_shadow) & mpc8xxx_gpio2mask(gpio);
 }
 
 static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
index 7b37300973dbc15d1a424448d932867b4d10d06d..2baf0ddf7e0230f2b334fc9e25dfca3bbe0205c9 100644 (file)
@@ -252,7 +252,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
-       clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+       clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
        __clear_bit(gpio, msm_gpio.enabled_irqs);
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
@@ -264,7 +264,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        __set_bit(gpio, msm_gpio.enabled_irqs);
-       set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+       set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
        writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
        spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
index fe088a30567ac63325fd02be82b8e682aa2323eb..8b7e719a68c3662f454c76b3e82b9569abeb22f8 100644 (file)
@@ -169,7 +169,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
        u32 pending;
        unsigned int offset, irqs_handled = 0;
 
-       while ((pending = gpio_rcar_read(p, INTDT))) {
+       while ((pending = gpio_rcar_read(p, INTDT) &
+                         gpio_rcar_read(p, INTMSK))) {
                offset = __ffs(pending);
                gpio_rcar_write(p, INTCLR, BIT(offset));
                generic_handle_irq(irq_find_mapping(p->irq_domain, offset));
index b97d6a6577b961d379a977e14a3c5c693cce5049..f9996899c1f29cd26e7267cbeb349378c6e26bb4 100644 (file)
@@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
        if (offset < TWL4030_GPIO_MAX)
                ret = twl4030_set_gpio_direction(offset, 1);
        else
-               ret = -EINVAL;
+               ret = -EINVAL;  /* LED outputs can't be set as input */
 
        if (!ret)
                priv->direction &= ~BIT(offset);
@@ -354,11 +354,20 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
 static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
-       int ret = -EINVAL;
+       int ret = 0;
 
        mutex_lock(&priv->mutex);
-       if (offset < TWL4030_GPIO_MAX)
+       if (offset < TWL4030_GPIO_MAX) {
                ret = twl4030_set_gpio_direction(offset, 0);
+               if (ret) {
+                       mutex_unlock(&priv->mutex);
+                       return ret;
+               }
+       }
+
+       /*
+        *  LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output
+        */
 
        priv->direction |= BIT(offset);
        mutex_unlock(&priv->mutex);
index ac53a95936626800143d1ad30320329f0f3ec050..85f772c0b26a619ec9c563f77f35c22fb8975e7f 100644 (file)
@@ -2368,7 +2368,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
                                continue;
                        }
 
-                       if (chip->ngpio >= p->chip_hwnum) {
+                       if (chip->ngpio <= p->chip_hwnum) {
                                dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
                                         chip->label, chip->ngpio);
                                continue;
@@ -2418,7 +2418,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx)
 {
-       struct gpio_desc *desc;
+       struct gpio_desc *desc = NULL;
        int status;
        enum gpio_lookup_flags flags = 0;
 
@@ -2431,13 +2431,23 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
        } else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
                dev_dbg(dev, "using ACPI for GPIO lookup\n");
                desc = acpi_find_gpio(dev, con_id, idx, &flags);
-       } else {
+       }
+
+       /*
+        * Either we are not using DT or ACPI, or their lookup did not return
+        * a result. In that case, use platform lookup as a fallback.
+        */
+       if (!desc || IS_ERR(desc)) {
+               struct gpio_desc *pdesc;
                dev_dbg(dev, "using lookup tables for GPIO lookup");
-               desc = gpiod_find(dev, con_id, idx, &flags);
+               pdesc = gpiod_find(dev, con_id, idx, &flags);
+               /* If used as fallback, do not replace the previous error */
+               if (!IS_ERR(pdesc) || !desc)
+                       desc = pdesc;
        }
 
        if (IS_ERR(desc)) {
-               dev_warn(dev, "lookup for GPIO %s failed\n", con_id);
+               dev_dbg(dev, "lookup for GPIO %s failed\n", con_id);
                return desc;
        }
 
index eef09ec9a5ff03691f259031d6b0dc5337e4fb02..a72cae03b99b781d7becf0987c91317c3777a65c 100644 (file)
@@ -103,6 +103,7 @@ void armada_drm_queue_unref_work(struct drm_device *,
 extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs;
 
 int armada_fbdev_init(struct drm_device *);
+void armada_fbdev_lastclose(struct drm_device *);
 void armada_fbdev_fini(struct drm_device *);
 
 int armada_overlay_plane_create(struct drm_device *, unsigned long);
index 4f2b28354915c68fcbc730af9ef8b50142ef26bb..62d0ff3efddf9bb5a08e1b209b5a40c6b8148e47 100644 (file)
@@ -321,6 +321,11 @@ static struct drm_ioctl_desc armada_ioctls[] = {
                DRM_UNLOCKED),
 };
 
+static void armada_drm_lastclose(struct drm_device *dev)
+{
+       armada_fbdev_lastclose(dev);
+}
+
 static const struct file_operations armada_drm_fops = {
        .owner                  = THIS_MODULE,
        .llseek                 = no_llseek,
@@ -337,7 +342,7 @@ static struct drm_driver armada_drm_driver = {
        .open                   = NULL,
        .preclose               = NULL,
        .postclose              = NULL,
-       .lastclose              = NULL,
+       .lastclose              = armada_drm_lastclose,
        .unload                 = armada_drm_unload,
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = armada_drm_enable_vblank,
index dd5ea77dac960c916fd5d8169c625a572a897e05..948cb14c561ec501e10bae0f89adb043dc0b2808 100644 (file)
@@ -105,9 +105,9 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
        drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
        drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
 
-       DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n",
-               dfb->fb.width, dfb->fb.height,
-               dfb->fb.bits_per_pixel, obj->phys_addr);
+       DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n",
+               dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel,
+               (unsigned long long)obj->phys_addr);
 
        return 0;
 
@@ -177,6 +177,16 @@ int armada_fbdev_init(struct drm_device *dev)
        return ret;
 }
 
+void armada_fbdev_lastclose(struct drm_device *dev)
+{
+       struct armada_private *priv = dev->dev_private;
+
+       drm_modeset_lock_all(dev);
+       if (priv->fbdev)
+               drm_fb_helper_restore_fbdev_mode(priv->fbdev);
+       drm_modeset_unlock_all(dev);
+}
+
 void armada_fbdev_fini(struct drm_device *dev)
 {
        struct armada_private *priv = dev->dev_private;
@@ -192,11 +202,11 @@ void armada_fbdev_fini(struct drm_device *dev)
                        framebuffer_release(info);
                }
 
+               drm_fb_helper_fini(fbh);
+
                if (fbh->fb)
                        fbh->fb->funcs->destroy(fbh->fb);
 
-               drm_fb_helper_fini(fbh);
-
                priv->fbdev = NULL;
        }
 }
index 9f2356bae7fdafb5318b172d47535b6b32408e07..887816f43476937fcfbceed5207025b63eccb132 100644 (file)
@@ -172,8 +172,9 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
                obj->dev_addr = obj->linear->start;
        }
 
-       DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n",
-                        obj, obj->phys_addr, obj->dev_addr);
+       DRM_DEBUG_DRIVER("obj %p phys %#llx dev %#llx\n", obj,
+                        (unsigned long long)obj->phys_addr,
+                        (unsigned long long)obj->dev_addr);
 
        return 0;
 }
@@ -557,7 +558,6 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
                         * refcount on the gem object itself.
                         */
                        drm_gem_object_reference(obj);
-                       dma_buf_put(buf);
                        return obj;
                }
        }
@@ -573,6 +573,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
        }
 
        dobj->obj.import_attach = attach;
+       get_dma_buf(buf);
 
        /*
         * Don't call dma_buf_map_attachment() here - it maps the
index fb7cf0e796f668328e7a923dbcada92ba8c2f1c7..8835dcddfac3ab7c3ee1a4ba72360443e730aa74 100644 (file)
@@ -68,6 +68,8 @@
 #define EDID_QUIRK_DETAILED_SYNC_PP            (1 << 6)
 /* Force reduced-blanking timings for detailed modes */
 #define EDID_QUIRK_FORCE_REDUCED_BLANKING      (1 << 7)
+/* Force 8bpc */
+#define EDID_QUIRK_FORCE_8BPC                  (1 << 8)
 
 struct detailed_mode_closure {
        struct drm_connector *connector;
@@ -128,6 +130,9 @@ static struct edid_quirk {
 
        /* Medion MD 30217 PG */
        { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
+
+       /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
+       { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
 };
 
 /*
@@ -2674,7 +2679,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
        int modes = 0;
        u8 cea_mode;
 
-       if (video_db == NULL || video_index > video_len)
+       if (video_db == NULL || video_index >= video_len)
                return 0;
 
        /* CEA modes are numbered 1..127 */
@@ -2701,7 +2706,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
        if (structure & (1 << 8)) {
                newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
                if (newmode) {
-                       newmode->flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
+                       newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
                        drm_mode_probed_add(connector, newmode);
                        modes++;
                }
@@ -3435,6 +3440,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 
        drm_add_display_info(edid, &connector->display_info);
 
+       if (quirks & EDID_QUIRK_FORCE_8BPC)
+               connector->display_info.bpc = 8;
+
        return num_modes;
 }
 EXPORT_SYMBOL(drm_add_edid_modes);
index 85071a1c4547921f53fd5372c2664a3066d00ef4..b0733153dfd294f178ff1818618fadbe63a1d144 100644 (file)
@@ -1041,7 +1041,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
                                /* if equal delete the probed mode */
                                mode->status = pmode->status;
                                /* Merge type bits together */
-                               mode->type = pmode->type;
+                               mode->type |= pmode->type;
                                list_del(&pmode->head);
                                drm_mode_destroy(connector->dev, pmode);
                                break;
index f53d5246979c386ed632b21c08decb3ab1296f9e..66dd3a001cf1b5ee43ec75f190b03146e7bbe46d 100644 (file)
@@ -566,11 +566,11 @@ err_unload:
        if (dev->driver->unload)
                dev->driver->unload(dev);
 err_primary_node:
-       drm_put_minor(dev->primary);
+       drm_unplug_minor(dev->primary);
 err_render_node:
-       drm_put_minor(dev->render);
+       drm_unplug_minor(dev->render);
 err_control_node:
-       drm_put_minor(dev->control);
+       drm_unplug_minor(dev->control);
 err_agp:
        if (dev->driver->bus->agp_destroy)
                dev->driver->bus->agp_destroy(dev);
index b676006a95a0118951f8e12d04f8a6fff0c49fb0..22b8f5eced80f3407b0fa9fc365c1d9e349d7e54 100644 (file)
@@ -172,29 +172,38 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 
 static void exynos_drm_preclose(struct drm_device *dev,
                                        struct drm_file *file)
+{
+       exynos_drm_subdrv_close(dev, file);
+}
+
+static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct exynos_drm_private *private = dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
+       struct drm_pending_vblank_event *v, *vt;
+       struct drm_pending_event *e, *et;
        unsigned long flags;
 
-       /* release events of current file */
+       if (!file->driver_priv)
+               return;
+
+       /* Release all events not unhandled by page flip handler. */
        spin_lock_irqsave(&dev->event_lock, flags);
-       list_for_each_entry_safe(e, t, &private->pageflip_event_list,
+       list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
                        base.link) {
-               if (e->base.file_priv == file) {
-                       list_del(&e->base.link);
-                       e->base.destroy(&e->base);
+               if (v->base.file_priv == file) {
+                       list_del(&v->base.link);
+                       drm_vblank_put(dev, v->pipe);
+                       v->base.destroy(&v->base);
                }
        }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       exynos_drm_subdrv_close(dev, file);
-}
+       /* Release all events handled by page flip handler but not freed. */
+       list_for_each_entry_safe(e, et, &file->event_list, link) {
+               list_del(&e->link);
+               e->destroy(e);
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
-{
-       if (!file->driver_priv)
-               return;
 
        kfree(file->driver_priv);
        file->driver_priv = NULL;
index 23da72b5eae98b0bae1e400ea28d74ed5ee7e472..a61878bf5dcd091cf31ed64a8374d230b580dc1e 100644 (file)
@@ -31,7 +31,7 @@
 #include "exynos_drm_iommu.h"
 
 /*
- * FIMD is stand for Fully Interactive Mobile Display and
+ * FIMD stands for Fully Interactive Mobile Display and
  * as a display controller, it transfers contents drawn on memory
  * to a LCD Panel through Display Interfaces such as RGB or
  * CPU Interface.
index 0cab2d045135b66d0462c88d390e43eff3df7b20..5c648425c1e053616801b3e1e545791a5fe111c0 100644 (file)
@@ -83,6 +83,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
 
+       /*
+        * The dri breadcrumb update races against the drm master disappearing.
+        * Instead of trying to fix this (this is by far not the only ums issue)
+        * just don't do the update in kms mode.
+        */
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
        if (dev->primary->master) {
                master_priv = dev->primary->master->driver_priv;
                if (master_priv->sarea_priv)
@@ -1490,16 +1498,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        mutex_init(&dev_priv->dpio_lock);
-       mutex_init(&dev_priv->rps.hw_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
 
-       mutex_init(&dev_priv->pc8.lock);
-       dev_priv->pc8.requirements_met = false;
-       dev_priv->pc8.gpu_idle = false;
-       dev_priv->pc8.irqs_disabled = false;
-       dev_priv->pc8.enabled = false;
-       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
-       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
+       intel_pm_setup(dev);
 
        intel_display_crc_init(dev);
 
@@ -1603,7 +1604,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        intel_irq_init(dev);
-       intel_pm_init(dev);
        intel_uncore_sanitize(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
@@ -1848,8 +1848,10 @@ void i915_driver_lastclose(struct drm_device * dev)
 
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
+       mutex_lock(&dev->struct_mutex);
        i915_gem_context_close(dev, file_priv);
        i915_gem_release(dev, file_priv);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
index 989be12cdd6e962e625b8376734f101ace947d1c..5b7b7e06cb3a09caec1cd7d5ab90401389df7a40 100644 (file)
@@ -534,8 +534,10 @@ static int i915_drm_freeze(struct drm_device *dev)
                 * Disable CRTCs directly since we want to preserve sw state
                 * for _thaw.
                 */
+               mutex_lock(&dev->mode_config.mutex);
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                        dev_priv->display.crtc_disable(crtc);
+               mutex_unlock(&dev->mode_config.mutex);
 
                intel_modeset_suspend_hw(dev);
        }
@@ -649,6 +651,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
                intel_modeset_init_hw(dev);
 
                drm_modeset_lock_all(dev);
+               drm_mode_config_reset(dev);
                intel_modeset_setup_hw_state(dev, true);
                drm_modeset_unlock_all(dev);
 
index ccdbecca070d2340919d5499f80824ddb84db4ac..90fcccba17b00da4a91ea2556b53a81e877356f0 100644 (file)
@@ -1755,8 +1755,13 @@ struct drm_i915_file_private {
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev)  (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0C00)
-#define IS_ULT(dev)            (IS_HASWELL(dev) && \
+#define IS_BDW_ULT(dev)                (IS_BROADWELL(dev) && \
+                                (((dev)->pdev->device & 0xf) == 0x2  || \
+                                ((dev)->pdev->device & 0xf) == 0x6 || \
+                                ((dev)->pdev->device & 0xf) == 0xe))
+#define IS_HSW_ULT(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0A00)
+#define IS_ULT(dev)            (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
 #define IS_HSW_GT3(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0x00F0) == 0x0020)
 #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
@@ -1901,9 +1906,7 @@ void i915_queue_hangcheck(struct drm_device *dev);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 
 extern void intel_uncore_sanitize(struct drm_device *dev);
 extern void intel_uncore_early_sanitize(struct drm_device *dev);
index 12bbd5eac70db7a22a291dfc5c2e01624803c816..76d3d1ab73c6965063eba62527594dce82dc41d4 100644 (file)
@@ -2343,15 +2343,24 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
        kfree(request);
 }
 
-static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
-                                     struct intel_ring_buffer *ring)
+static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
+                                      struct intel_ring_buffer *ring)
 {
-       u32 completed_seqno;
-       u32 acthd;
+       u32 completed_seqno = ring->get_seqno(ring, false);
+       u32 acthd = intel_ring_get_active_head(ring);
+       struct drm_i915_gem_request *request;
+
+       list_for_each_entry(request, &ring->request_list, list) {
+               if (i915_seqno_passed(completed_seqno, request->seqno))
+                       continue;
 
-       acthd = intel_ring_get_active_head(ring);
-       completed_seqno = ring->get_seqno(ring, false);
+               i915_set_reset_status(ring, request, acthd);
+       }
+}
 
+static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
+                                       struct intel_ring_buffer *ring)
+{
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
 
@@ -2359,9 +2368,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
                                           struct drm_i915_gem_request,
                                           list);
 
-               if (request->seqno > completed_seqno)
-                       i915_set_reset_status(ring, request, acthd);
-
                i915_gem_free_request(request);
        }
 
@@ -2403,8 +2409,16 @@ void i915_gem_reset(struct drm_device *dev)
        struct intel_ring_buffer *ring;
        int i;
 
+       /*
+        * Before we free the objects from the requests, we need to inspect
+        * them for finding the guilty party. As the requests only borrow
+        * their reference to the objects, the inspection must be done first.
+        */
+       for_each_ring(ring, dev_priv, i)
+               i915_gem_reset_ring_status(dev_priv, ring);
+
        for_each_ring(ring, dev_priv, i)
-               i915_gem_reset_ring_lists(dev_priv, ring);
+               i915_gem_reset_ring_cleanup(dev_priv, ring);
 
        i915_gem_cleanup_ringbuffer(dev);
 
@@ -4442,10 +4456,9 @@ i915_gem_init_hw(struct drm_device *dev)
        if (dev_priv->ellc_size)
                I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
 
-       if (IS_HSW_GT3(dev))
-               I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_ENABLED);
-       else
-               I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_DISABLED);
+       if (IS_HASWELL(dev))
+               I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ?
+                          LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
 
        if (HAS_PCH_NOP(dev)) {
                u32 temp = I915_READ(GEN7_MSG_CTL);
index 72a3df32292f79d88d1ba17dc8d620a24ad435ca..b0f42b9ca037ed472e1a0dd4cd663df6ffd70f06 100644 (file)
@@ -347,10 +347,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
 
-       mutex_lock(&dev->struct_mutex);
        idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
        idr_destroy(&file_priv->context_idr);
-       mutex_unlock(&dev->struct_mutex);
 }
 
 static struct i915_hw_context *
@@ -423,11 +421,21 @@ static int do_switch(struct i915_hw_context *to)
        if (ret)
                return ret;
 
-       /* Clear this page out of any CPU caches for coherent swap-in/out. Note
+       /*
+        * Pin can switch back to the default context if we end up calling into
+        * evict_everything - as a last ditch gtt defrag effort that also
+        * switches to the default context. Hence we need to reload from here.
+        */
+       from = ring->last_context;
+
+       /*
+        * Clear this page out of any CPU caches for coherent swap-in/out. Note
         * that thanks to write = false in this call and us not setting any gpu
         * write domains when putting a context object onto the active list
         * (when switching away from it), this won't block.
-        * XXX: We need a real interface to do this instead of trickery. */
+        *
+        * XXX: We need a real interface to do this instead of trickery.
+        */
        ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
        if (ret) {
                i915_gem_object_unpin(to->obj);
index 7d5752fda5f18b7850beeed588a6f1b3a85cd79a..9bb533e0d76234cdc14ec6d9da31a310114080a5 100644 (file)
@@ -125,13 +125,15 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 
        ret = i915_gem_object_get_pages(obj);
        if (ret)
-               goto error;
+               goto err;
+
+       i915_gem_object_pin_pages(obj);
 
        ret = -ENOMEM;
 
        pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
        if (pages == NULL)
-               goto error;
+               goto err_unpin;
 
        i = 0;
        for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
@@ -141,15 +143,16 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
        drm_free_large(pages);
 
        if (!obj->dma_buf_vmapping)
-               goto error;
+               goto err_unpin;
 
        obj->vmapping_count = 1;
-       i915_gem_object_pin_pages(obj);
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
        return obj->dma_buf_vmapping;
 
-error:
+err_unpin:
+       i915_gem_object_unpin_pages(obj);
+err:
        mutex_unlock(&dev->struct_mutex);
        return ERR_PTR(ret);
 }
index b7376533633d2cd74eeae8442a49588cf1af1cdc..8f3adc7d0dc823bd5e7848f013bda20d1d133cbc 100644 (file)
@@ -88,6 +88,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
        } else
                drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level);
 
+search_again:
        /* First see if there is a large enough contiguous idle region... */
        list_for_each_entry(vma, &vm->inactive_list, mm_list) {
                if (mark_free(vma, &unwind_list))
@@ -115,10 +116,17 @@ none:
                list_del_init(&vma->exec_list);
        }
 
-       /* We expect the caller to unpin, evict all and try again, or give up.
-        * So calling i915_gem_evict_vm() is unnecessary.
+       /* Can we unpin some objects such as idle hw contents,
+        * or pending flips?
         */
-       return -ENOSPC;
+       ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev);
+       if (ret)
+               return ret;
+
+       /* Only idle the GPU and repeat the search once */
+       i915_gem_retire_requests(dev);
+       nonblocking = true;
+       goto search_again;
 
 found:
        /* drm_mm doesn't allow any other other operations while
index 885d595e0e02255e30fbff181247b70df1af5363..a3ba9a8cd68794bbfd163c9236c91c7be9d15965 100644 (file)
@@ -33,6 +33,9 @@
 #include "intel_drv.h"
 #include <linux/dma_remapping.h>
 
+#define  __EXEC_OBJECT_HAS_PIN (1<<31)
+#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
+
 struct eb_vmas {
        struct list_head vmas;
        int and;
@@ -90,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 {
        struct drm_i915_gem_object *obj;
        struct list_head objects;
-       int i, ret = 0;
+       int i, ret;
 
        INIT_LIST_HEAD(&objects);
        spin_lock(&file->table_lock);
@@ -103,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Invalid object handle %d at index %d\n",
                                   exec[i].handle, i);
                        ret = -ENOENT;
-                       goto out;
+                       goto err;
                }
 
                if (!list_empty(&obj->obj_exec_link)) {
@@ -111,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
                                   obj, exec[i].handle, i);
                        ret = -EINVAL;
-                       goto out;
+                       goto err;
                }
 
                drm_gem_object_reference(&obj->base);
@@ -120,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb,
        spin_unlock(&file->table_lock);
 
        i = 0;
-       list_for_each_entry(obj, &objects, obj_exec_link) {
+       while (!list_empty(&objects)) {
                struct i915_vma *vma;
 
+               obj = list_first_entry(&objects,
+                                      struct drm_i915_gem_object,
+                                      obj_exec_link);
+
                /*
                 * NOTE: We can leak any vmas created here when something fails
                 * later on. But that's no issue since vma_unbind can deal with
@@ -135,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb,
                if (IS_ERR(vma)) {
                        DRM_DEBUG("Failed to lookup VMA\n");
                        ret = PTR_ERR(vma);
-                       goto out;
+                       goto err;
                }
 
+               /* Transfer ownership from the objects list to the vmas list. */
                list_add_tail(&vma->exec_list, &eb->vmas);
+               list_del_init(&obj->obj_exec_link);
 
                vma->exec_entry = &exec[i];
                if (eb->and < 0) {
@@ -152,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb,
                ++i;
        }
 
+       return 0;
 
-out:
+
+err:
        while (!list_empty(&objects)) {
                obj = list_first_entry(&objects,
                                       struct drm_i915_gem_object,
                                       obj_exec_link);
                list_del_init(&obj->obj_exec_link);
-               if (ret)
-                       drm_gem_object_unreference(&obj->base);
+               drm_gem_object_unreference(&obj->base);
        }
+       /*
+        * Objects already transfered to the vmas list will be unreferenced by
+        * eb_destroy.
+        */
+
        return ret;
 }
 
@@ -187,7 +202,28 @@ static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle)
        }
 }
 
-static void eb_destroy(struct eb_vmas *eb) {
+static void
+i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
+{
+       struct drm_i915_gem_exec_object2 *entry;
+       struct drm_i915_gem_object *obj = vma->obj;
+
+       if (!drm_mm_node_allocated(&vma->node))
+               return;
+
+       entry = vma->exec_entry;
+
+       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
+               i915_gem_object_unpin_fence(obj);
+
+       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
+               i915_gem_object_unpin(obj);
+
+       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
+}
+
+static void eb_destroy(struct eb_vmas *eb)
+{
        while (!list_empty(&eb->vmas)) {
                struct i915_vma *vma;
 
@@ -195,6 +231,7 @@ static void eb_destroy(struct eb_vmas *eb) {
                                       struct i915_vma,
                                       exec_list);
                list_del_init(&vma->exec_list);
+               i915_gem_execbuffer_unreserve_vma(vma);
                drm_gem_object_unreference(&vma->obj->base);
        }
        kfree(eb);
@@ -478,9 +515,6 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb,
        return ret;
 }
 
-#define  __EXEC_OBJECT_HAS_PIN (1<<31)
-#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
-
 static int
 need_reloc_mappable(struct i915_vma *vma)
 {
@@ -552,26 +586,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
        return 0;
 }
 
-static void
-i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
-{
-       struct drm_i915_gem_exec_object2 *entry;
-       struct drm_i915_gem_object *obj = vma->obj;
-
-       if (!drm_mm_node_allocated(&vma->node))
-               return;
-
-       entry = vma->exec_entry;
-
-       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
-               i915_gem_object_unpin_fence(obj);
-
-       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
-               i915_gem_object_unpin(obj);
-
-       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
-}
-
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                            struct list_head *vmas,
@@ -670,13 +684,14 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                                goto err;
                }
 
-err:           /* Decrement pin count for bound objects */
-               list_for_each_entry(vma, vmas, exec_list)
-                       i915_gem_execbuffer_unreserve_vma(vma);
-
+err:
                if (ret != -ENOSPC || retry++)
                        return ret;
 
+               /* Decrement pin count for bound objects */
+               list_for_each_entry(vma, vmas, exec_list)
+                       i915_gem_execbuffer_unreserve_vma(vma);
+
                ret = i915_gem_evict_vm(vm, true);
                if (ret)
                        return ret;
@@ -708,6 +723,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
        while (!list_empty(&eb->vmas)) {
                vma = list_first_entry(&eb->vmas, struct i915_vma, exec_list);
                list_del_init(&vma->exec_list);
+               i915_gem_execbuffer_unreserve_vma(vma);
                drm_gem_object_unreference(&vma->obj->base);
        }
 
index 3620a1b0a73cbcea019cbd5503250410e51f2807..d3c3b5b15824ee8bb927a7b1a382582309b31376 100644 (file)
@@ -57,7 +57,9 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
 #define HSW_WB_LLC_AGE3                        HSW_CACHEABILITY_CONTROL(0x2)
 #define HSW_WB_LLC_AGE0                        HSW_CACHEABILITY_CONTROL(0x3)
 #define HSW_WB_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0xb)
+#define HSW_WB_ELLC_LLC_AGE3           HSW_CACHEABILITY_CONTROL(0x8)
 #define HSW_WT_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0x6)
+#define HSW_WT_ELLC_LLC_AGE3           HSW_CACHEABILITY_CONTROL(0x7)
 
 #define GEN8_PTES_PER_PAGE             (PAGE_SIZE / sizeof(gen8_gtt_pte_t))
 #define GEN8_PDES_PER_PAGE             (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
@@ -185,10 +187,10 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
        case I915_CACHE_NONE:
                break;
        case I915_CACHE_WT:
-               pte |= HSW_WT_ELLC_LLC_AGE0;
+               pte |= HSW_WT_ELLC_LLC_AGE3;
                break;
        default:
-               pte |= HSW_WB_ELLC_LLC_AGE0;
+               pte |= HSW_WB_ELLC_LLC_AGE3;
                break;
        }
 
@@ -335,8 +337,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                kfree(ppgtt->gen8_pt_dma_addr[i]);
        }
 
-       __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT);
-       __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT);
+       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
 }
 
 /**
@@ -904,14 +906,12 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
                WARN_ON(readq(&gtt_entries[i-1])
                        != gen8_pte_encode(addr, level, true));
 
-#if 0 /* TODO: Still needed on GEN8? */
        /* This next bit makes the above posting read even more important. We
         * want to flush the TLBs only after we're certain all the PTE updates
         * have finished.
         */
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-#endif
 }
 
 /*
@@ -1239,6 +1239,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
        bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
        if (bdw_gmch_ctl)
                bdw_gmch_ctl = 1 << bdw_gmch_ctl;
+       if (bdw_gmch_ctl > 4) {
+               WARN_ON(!i915_preliminary_hw_support);
+               return 4<<20;
+       }
+
        return bdw_gmch_ctl << 20;
 }
 
index 5d1dedc02f159c8b7a21d23a940df9c5bf0c2bd2..f13d5edc39d56c9bdfe3091a9218872ef59be071 100644 (file)
@@ -2713,6 +2713,8 @@ static void gen8_irq_preinstall(struct drm_device *dev)
 #undef GEN8_IRQ_INIT_NDX
 
        POSTING_READ(GEN8_PCU_IIR);
+
+       ibx_irq_preinstall(dev);
 }
 
 static void ibx_hpd_irq_setup(struct drm_device *dev)
index f9eafb6ed523a2d0f8fbd2ff981705c644733790..ee2742122a02561f910b6d9d5383418794234eff 100644 (file)
  */
 #define MI_LOAD_REGISTER_IMM(x)        MI_INSTR(0x22, 2*x-1)
 #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1)
+#define  MI_SRM_LRM_GLOBAL_GTT         (1<<22)
 #define MI_FLUSH_DW            MI_INSTR(0x26, 1) /* for GEN6 */
 #define   MI_FLUSH_DW_STORE_INDEX      (1<<21)
 #define   MI_INVALIDATE_TLB            (1<<18)
index 330077bcd0bddb22ecf056766dd88cd7ed70bfaf..b69dc3e66c165ac77782943450d98602ef75c205 100644 (file)
@@ -173,7 +173,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
                ddi_translations = ddi_translations_dp;
                break;
        case PORT_D:
-               if (intel_dpd_is_edp(dev))
+               if (intel_dp_is_edp(dev, PORT_D))
                        ddi_translations = ddi_translations_edp;
                else
                        ddi_translations = ddi_translations_dp;
@@ -1057,12 +1057,18 @@ void intel_ddi_setup_hw_pll_state(struct drm_device *dev)
        enum pipe pipe;
        struct intel_crtc *intel_crtc;
 
+       dev_priv->ddi_plls.spll_refcount = 0;
+       dev_priv->ddi_plls.wrpll1_refcount = 0;
+       dev_priv->ddi_plls.wrpll2_refcount = 0;
+
        for_each_pipe(pipe) {
                intel_crtc =
                        to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 
-               if (!intel_crtc->active)
+               if (!intel_crtc->active) {
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
                        continue;
+               }
 
                intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
                                                                 pipe);
@@ -1158,9 +1164,10 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
        if (wait)
                intel_wait_ddi_buf_idle(dev_priv, port);
 
-       if (type == INTEL_OUTPUT_EDP) {
+       if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
                ironlake_edp_panel_vdd_on(intel_dp);
+               intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
                ironlake_edp_panel_off(intel_dp);
        }
 
index 7ec8b488bb1d30b6b950a23eecc833b574ab4db0..2bde35d34eb99d121aee6a51bfff5e2c8f75524a 100644 (file)
@@ -5815,7 +5815,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)
                uint16_t postoff = 0;
 
                if (intel_crtc->config.limited_color_range)
-                       postoff = (16 * (1 << 13) / 255) & 0x1fff;
+                       postoff = (16 * (1 << 12) / 255) & 0x1fff;
 
                I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
                I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
@@ -6303,7 +6303,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        uint32_t val;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-               WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+               WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
 
        WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -6402,7 +6402,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
        /* Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine! */
-       dev_priv->uncore.funcs.force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6436,7 +6436,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
 
-       dev_priv->uncore.funcs.force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
@@ -8354,7 +8354,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
                intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
                                        DERRMR_PIPEB_PRI_FLIP_DONE |
                                        DERRMR_PIPEC_PRI_FLIP_DONE));
-               intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1));
+               intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
+                               MI_SRM_LRM_GLOBAL_GTT);
                intel_ring_emit(ring, DERRMR);
                intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
        }
@@ -9134,7 +9135,7 @@ intel_pipe_config_compare(struct drm_device *dev,
        if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
                PIPE_CONF_CHECK_I(pipe_bpp);
 
-       if (!IS_HASWELL(dev)) {
+       if (!HAS_DDI(dev)) {
                PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
                PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
        }
@@ -10049,7 +10050,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_ddi_init(dev, PORT_D);
        } else if (HAS_PCH_SPLIT(dev)) {
                int found;
-               dpd_is_edp = intel_dpd_is_edp(dev);
+               dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
 
                if (has_edp_a(dev))
                        intel_dp_init(dev, DP_A, PORT_A);
@@ -10086,8 +10087,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
                                        PORT_C);
                        if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
-                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C,
-                                             PORT_C);
+                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
                }
 
                intel_dsi_init(dev);
@@ -10541,11 +10541,20 @@ static struct intel_quirk intel_quirks[] = {
        /* Sony Vaio Y cannot use SSC on LVDS */
        { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
 
-       /*
-        * All GM45 Acer (and its brands eMachines and Packard Bell) laptops
-        * seem to use inverted backlight PWM.
-        */
-       { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness },
+       /* Acer Aspire 5734Z must invert backlight brightness */
+       { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
+
+       /* Acer/eMachines G725 */
+       { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
+
+       /* Acer/eMachines e725 */
+       { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
+
+       /* Acer/Packard Bell NCL20 */
+       { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
+
+       /* Acer Aspire 4736Z */
+       { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
 
        /* Dell XPS13 HD Sandy Bridge */
        { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
@@ -11036,8 +11045,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        intel_modeset_check_state(dev);
-
-       drm_mode_config_reset(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
@@ -11046,7 +11053,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
        intel_setup_overlay(dev);
 
+       mutex_lock(&dev->mode_config.mutex);
+       drm_mode_config_reset(dev);
        intel_modeset_setup_hw_state(dev, false);
+       mutex_unlock(&dev->mode_config.mutex);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11125,14 +11135,15 @@ void intel_connector_attach_encoder(struct intel_connector *connector,
 int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
        u16 gmch_ctrl;
 
-       pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
+       pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
        if (state)
                gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
        else
                gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-       pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
+       pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
        return 0;
 }
 
index 0b2e842fef0151070b09af535d54fdcee2215602..30c627c7b7ba18a0dbd546859b047a769cad1d64 100644 (file)
@@ -3326,11 +3326,19 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
 }
 
 /* check the VBT to see whether the eDP is on DP-D port */
-bool intel_dpd_is_edp(struct drm_device *dev)
+bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        union child_device_config *p_child;
        int i;
+       static const short port_mapping[] = {
+               [PORT_B] = PORT_IDPB,
+               [PORT_C] = PORT_IDPC,
+               [PORT_D] = PORT_IDPD,
+       };
+
+       if (port == PORT_A)
+               return true;
 
        if (!dev_priv->vbt.child_dev_num)
                return false;
@@ -3338,7 +3346,7 @@ bool intel_dpd_is_edp(struct drm_device *dev)
        for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
                p_child = dev_priv->vbt.child_dev + i;
 
-               if (p_child->common.dvo_port == PORT_IDPD &&
+               if (p_child->common.dvo_port == port_mapping[port] &&
                    (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
                    (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
                        return true;
@@ -3616,26 +3624,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        intel_dp->DP = I915_READ(intel_dp->output_reg);
        intel_dp->attached_connector = intel_connector;
 
-       type = DRM_MODE_CONNECTOR_DisplayPort;
-       /*
-        * FIXME : We need to initialize built-in panels before external panels.
-        * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
-        */
-       switch (port) {
-       case PORT_A:
+       if (intel_dp_is_edp(dev, port))
                type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       case PORT_C:
-               if (IS_VALLEYVIEW(dev))
-                       type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       case PORT_D:
-               if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
-                       type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       default:        /* silence GCC warning */
-               break;
-       }
+       else
+               type = DRM_MODE_CONNECTOR_DisplayPort;
 
        /*
         * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
index 1e49aa8f5377395c8803d5a55765199bd38af037..79f91f26e288d4bf2ae7815cb82cfc3271745bd5 100644 (file)
@@ -708,7 +708,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder);
 void intel_dp_check_link_status(struct intel_dp *intel_dp);
 bool intel_dp_compute_config(struct intel_encoder *encoder,
                             struct intel_crtc_config *pipe_config);
-bool intel_dpd_is_edp(struct drm_device *dev);
+bool intel_dp_is_edp(struct drm_device *dev, enum port port);
 void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
 void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
 void ironlake_edp_panel_on(struct intel_dp *intel_dp);
@@ -821,6 +821,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane,
                                    uint32_t sprite_width, int pixel_size,
                                    bool enabled, bool scaled);
 void intel_init_pm(struct drm_device *dev);
+void intel_pm_setup(struct drm_device *dev);
 bool intel_fbc_enabled(struct drm_device *dev);
 void intel_update_fbc(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
index f161ac02c4f6e613efbfc7f763cbb3566dc75248..e6f782d1c6696d94fe4d4a80cf7f4d6ee6b5c7d7 100644 (file)
@@ -451,7 +451,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev,
 
        spin_lock_irqsave(&dev_priv->backlight.lock, flags);
 
-       if (HAS_PCH_SPLIT(dev)) {
+       if (IS_BROADWELL(dev)) {
+               val = I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
+       } else if (HAS_PCH_SPLIT(dev)) {
                val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
        } else {
                if (IS_VALLEYVIEW(dev))
@@ -479,6 +481,13 @@ static u32 intel_panel_get_backlight(struct drm_device *dev,
        return val;
 }
 
+static void intel_bdw_panel_set_backlight(struct drm_device *dev, u32 level)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
+}
+
 static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -496,7 +505,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev,
        DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
        level = intel_panel_compute_brightness(dev, pipe, level);
 
-       if (HAS_PCH_SPLIT(dev))
+       if (IS_BROADWELL(dev))
+               return intel_bdw_panel_set_backlight(dev, level);
+       else if (HAS_PCH_SPLIT(dev))
                return intel_pch_panel_set_backlight(dev, level);
 
        if (is_backlight_combination_mode(dev)) {
@@ -666,7 +677,16 @@ void intel_panel_enable_backlight(struct intel_connector *connector)
                POSTING_READ(reg);
                I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
 
-               if (HAS_PCH_SPLIT(dev) &&
+               if (IS_BROADWELL(dev)) {
+                       /*
+                        * Broadwell requires PCH override to drive the PCH
+                        * backlight pin. The above will configure the CPU
+                        * backlight pin, which we don't plan to use.
+                        */
+                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
+                       tmp |= BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE;
+                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
+               } else if (HAS_PCH_SPLIT(dev) &&
                    !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
                        tmp = I915_READ(BLC_PWM_PCH_CTL1);
                        tmp |= BLM_PCH_PWM_ENABLE;
index caf2ee4e5441426527234453dbb43ed4c4c7273f..26c29c173221058aeeaa9a3c0d889500b8db9fec 100644 (file)
@@ -1180,7 +1180,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
 
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -1267,7 +1267,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
        crtc = intel_get_crtc_for_plane(dev, plane);
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -1498,7 +1498,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
                const struct drm_display_mode *adjusted_mode =
                        &to_intel_crtc(crtc)->config.adjusted_mode;
                int clock = adjusted_mode->crtc_clock;
-               int htotal = adjusted_mode->htotal;
+               int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
                int pixel_size = crtc->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
@@ -1624,7 +1624,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                const struct drm_display_mode *adjusted_mode =
                        &to_intel_crtc(enabled)->config.adjusted_mode;
                int clock = adjusted_mode->crtc_clock;
-               int htotal = adjusted_mode->htotal;
+               int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
                int pixel_size = enabled->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
@@ -1776,7 +1776,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
        crtc = intel_get_crtc_for_plane(dev, plane);
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -2469,8 +2469,9 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
        /* The WM are computed with base on how long it takes to fill a single
         * row at the given clock rate, multiplied by 8.
         * */
-       linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
-       ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
+       linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
+                                    mode->crtc_clock);
+       ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
                                         intel_ddi_get_cdclk_freq(dev_priv));
 
        return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
@@ -5684,8 +5685,11 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool is_enabled, enable_requested;
+       unsigned long irqflags;
        uint32_t tmp;
 
+       WARN_ON(dev_priv->pc8.enabled);
+
        tmp = I915_READ(HSW_PWR_WELL_DRIVER);
        is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
        enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5701,9 +5705,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
                                      HSW_PWR_WELL_STATE_ENABLED), 20))
                                DRM_ERROR("Timeout enabling power well\n");
                }
+
+               if (IS_BROADWELL(dev)) {
+                       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
+                                  dev_priv->de_irq_mask[PIPE_B]);
+                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
+                                  ~dev_priv->de_irq_mask[PIPE_B] |
+                                  GEN8_PIPE_VBLANK);
+                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
+                                  dev_priv->de_irq_mask[PIPE_C]);
+                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
+                                  ~dev_priv->de_irq_mask[PIPE_C] |
+                                  GEN8_PIPE_VBLANK);
+                       POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
+                       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+               }
        } else {
                if (enable_requested) {
-                       unsigned long irqflags;
                        enum pipe p;
 
                        I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
@@ -5730,16 +5749,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 static void __intel_power_well_get(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
-       if (!power_well->count++)
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!power_well->count++) {
+               hsw_disable_package_c8(dev_priv);
                __intel_set_power_well(dev, true);
+       }
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        WARN_ON(!power_well->count);
-       if (!--power_well->count && i915_disable_power_well)
+       if (!--power_well->count && i915_disable_power_well) {
                __intel_set_power_well(dev, false);
+               hsw_enable_package_c8(dev_priv);
+       }
 }
 
 void intel_display_power_get(struct drm_device *dev,
@@ -6129,10 +6156,19 @@ int vlv_freq_opcode(int ddr_freq, int val)
        return val;
 }
 
-void intel_pm_init(struct drm_device *dev)
+void intel_pm_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       mutex_init(&dev_priv->rps.hw_lock);
+
+       mutex_init(&dev_priv->pc8.lock);
+       dev_priv->pc8.requirements_met = false;
+       dev_priv->pc8.gpu_idle = false;
+       dev_priv->pc8.irqs_disabled = false;
+       dev_priv->pc8.enabled = false;
+       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
+       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
 }
index b620337e6d672c164448090016a27d1b713a2a24..c2f09d4563008ff7e32238675dab1b4da02ec967 100644 (file)
@@ -965,6 +965,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
        } else if (IS_GEN6(ring->dev)) {
                mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
        } else {
+               /* XXX: gen8 returns to sanity */
                mmio = RING_HWS_PGA(ring->mmio_base);
        }
 
index 0b02078a0b848c4127385b1d3b5d3ab6be755c80..25cbe073c388a3185d1a32afeb805993e43d12d3 100644 (file)
@@ -784,6 +784,7 @@ static int gen6_do_reset(struct drm_device *dev)
 int intel_gpu_reset(struct drm_device *dev)
 {
        switch (INTEL_INFO(dev)->gen) {
+       case 8:
        case 7:
        case 6: return gen6_do_reset(dev);
        case 5: return ironlake_do_reset(dev);
index edcf801613e66ea5c34665eafe1147d39cda62db..b3fa1ba191b7115be412894936c3633bf9221188 100644 (file)
@@ -59,6 +59,7 @@ nouveau-y += core/subdev/clock/nv40.o
 nouveau-y += core/subdev/clock/nv50.o
 nouveau-y += core/subdev/clock/nv84.o
 nouveau-y += core/subdev/clock/nva3.o
+nouveau-y += core/subdev/clock/nvaa.o
 nouveau-y += core/subdev/clock/nvc0.o
 nouveau-y += core/subdev/clock/nve0.o
 nouveau-y += core/subdev/clock/pllnv04.o
index 48f06378d3f9d5f9e09e03291a11d6e26527f674..2ea5568b6cf59be811fa6777612eca8b8180736b 100644 (file)
@@ -104,11 +104,8 @@ nouveau_subdev_create_(struct nouveau_object *parent,
 
        if (parent) {
                struct nouveau_device *device = nv_device(parent);
-               int subidx = nv_hclass(subdev) & 0xff;
-
                subdev->debug = nouveau_dbgopt(device->dbgopt, subname);
                subdev->mmio  = nv_subdev(device)->mmio;
-               device->subdev[subidx] = *pobject;
        }
 
        return 0;
index 9135b25a29d09a4e82e57e1c9a1a27608eee6a99..dd01c6c435d6e2e01ecb92ccbd57cf09e7346660 100644 (file)
@@ -268,6 +268,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
                if (ret)
                        return ret;
 
+               device->subdev[i] = devobj->subdev[i];
+
                /* note: can't init *any* subdevs until devinit has been run
                 * due to not knowing exactly what the vbios init tables will
                 * mess with.  devinit also can't be run until all of its
index db139827047cf4a6b103a2d98cc7fe5c208721db..db3fc7be856a733d07f8431a182326e3f20b4182 100644 (file)
@@ -283,7 +283,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
@@ -311,7 +311,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
index 8d06eef2b9ee02f7b3d895c8d7a37bfd6e022924..dbc5e33de94f8b6caebbab7319d3bfb7117c57f2 100644 (file)
@@ -161,7 +161,7 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass;
-               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass;
                device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass;
index 5f555788121c9ff8c63a7e66da794011b67f237e..e6352bd5b4ff53c066b587bf51595b8ca54ac3af 100644 (file)
@@ -33,6 +33,7 @@
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+#include "nv04.h"
 #include "nv50.h"
 
 /*******************************************************************************
@@ -460,6 +461,8 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        nv_subdev(priv)->intr = nv04_fifo_intr;
        nv_engine(priv)->cclass = &nv50_fifo_cclass;
        nv_engine(priv)->sclass = nv50_fifo_sclass;
+       priv->base.pause = nv04_fifo_pause;
+       priv->base.start = nv04_fifo_start;
        return 0;
 }
 
index 0908dc834c84c48ac34f91afde1984ed593531bd..fe0f41e65d9b9c6ab6abfa5b1d5f7b3031fe5557 100644 (file)
@@ -35,6 +35,7 @@
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+#include "nv04.h"
 #include "nv50.h"
 
 /*******************************************************************************
@@ -432,6 +433,8 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        nv_subdev(priv)->intr = nv04_fifo_intr;
        nv_engine(priv)->cclass = &nv84_fifo_cclass;
        nv_engine(priv)->sclass = nv84_fifo_sclass;
+       priv->base.pause = nv04_fifo_pause;
+       priv->base.start = nv04_fifo_start;
        return 0;
 }
 
index 434bb4b0fa2e650a130a98cc940f5ca7727cfeac..5c8a63dc506aafcfbbe5088ede75ed635d0ba8a4 100644 (file)
@@ -334,7 +334,7 @@ nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds)
        while ((mthd = &mthds[i++]) && (init = mthd->init)) {
                u32  addr = 0x80000000 | mthd->oclass;
                for (data = 0; init->count; init++) {
-                       if (data != init->data) {
+                       if (init == mthd->init || data != init->data) {
                                nv_wr32(priv, 0x40448c, init->data);
                                data = init->data;
                        }
index b574dd4bb8285e65ccdbcf23db7b6f139e1cb73c..5ce686ee729ea5d937164d55892a9aebd2312b77 100644 (file)
@@ -176,7 +176,7 @@ nv50_software_context_ctor(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       chan->vblank.nr_event = pdisp->vblank->index_nr;
+       chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0;
        chan->vblank.event = kzalloc(chan->vblank.nr_event *
                                     sizeof(*chan->vblank.event), GFP_KERNEL);
        if (!chan->vblank.event)
index e2675bc0edba5f9baefc5d514750d151a2ce23a7..8f4ced75444a95478887b4be5791fc99dd3499dc 100644 (file)
@@ -14,6 +14,9 @@ enum nv_clk_src {
        nv_clk_src_hclk,
        nv_clk_src_hclkm3,
        nv_clk_src_hclkm3d2,
+       nv_clk_src_hclkm2d3, /* NVAA */
+       nv_clk_src_hclkm4, /* NVAA */
+       nv_clk_src_cclk, /* NVAA */
 
        nv_clk_src_host,
 
@@ -127,6 +130,7 @@ extern struct nouveau_oclass nv04_clock_oclass;
 extern struct nouveau_oclass nv40_clock_oclass;
 extern struct nouveau_oclass *nv50_clock_oclass;
 extern struct nouveau_oclass *nv84_clock_oclass;
+extern struct nouveau_oclass *nvaa_clock_oclass;
 extern struct nouveau_oclass nva3_clock_oclass;
 extern struct nouveau_oclass nvc0_clock_oclass;
 extern struct nouveau_oclass nve0_clock_oclass;
index 8541aa382ff224136d8c1cedff00db0595a753c2..d89dbdf39b0db501159a873eeb5ada0612a3ba35 100644 (file)
@@ -75,6 +75,11 @@ struct nouveau_fb {
 static inline struct nouveau_fb *
 nouveau_fb(void *obj)
 {
+       /* fbram uses this before device subdev pointer is valid */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_FB)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB];
 }
 
index 9fa5da72387192467ba80c9f9f9a7f2a0adbe339..7f50a858b16f68395a3fe0b84c5bd9f275e8849f 100644 (file)
@@ -73,7 +73,7 @@ struct nouveau_i2c {
        int (*identify)(struct nouveau_i2c *, int index,
                        const char *what, struct nouveau_i2c_board_info *,
                        bool (*match)(struct nouveau_i2c_port *,
-                                     struct i2c_board_info *));
+                                     struct i2c_board_info *, void *), void *);
        struct list_head ports;
 };
 
index ec7a54e91a087cdea900dd1f94947adc0f6f395c..4aca33887aaa639e4ad738065bfa775319d75afc 100644 (file)
@@ -50,6 +50,13 @@ struct nouveau_instmem {
 static inline struct nouveau_instmem *
 nouveau_instmem(void *obj)
 {
+       /* nv04/nv40 impls need to create objects in their constructor,
+        * which is before the subdev pointer is valid
+        */
+       if (nv_iclass(obj, NV_SUBDEV_CLASS) &&
+           nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM)
+               return obj;
+
        return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM];
 }
 
index 420908cb82b613bbc97fbccb9b123f3449926100..df1b1b42309337cb14c79b503497e49bf80ee49b 100644 (file)
@@ -365,13 +365,13 @@ static u16
 init_script(struct nouveau_bios *bios, int index)
 {
        struct nvbios_init init = { .bios = bios };
-       u16 data;
+       u16 bmp_ver = bmp_version(bios), data;
 
-       if (bmp_version(bios) && bmp_version(bios) < 0x0510) {
-               if (index > 1)
+       if (bmp_ver && bmp_ver < 0x0510) {
+               if (index > 1 || bmp_ver < 0x0100)
                        return 0x0000;
 
-               data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18);
+               data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);
                return nv_ro16(bios, data + (index * 2));
        }
 
@@ -1294,7 +1294,11 @@ init_jump(struct nvbios_init *init)
        u16 offset = nv_ro16(bios, init->offset + 1);
 
        trace("JUMP\t0x%04x\n", offset);
-       init->offset = offset;
+
+       if (init_exec(init))
+               init->offset = offset;
+       else
+               init->offset += 3;
 }
 
 /**
index da50c1b129283923f841eef8c4192df09131f935..30c1f3a4158e3de87fd2bfb24592b9ea685b2d88 100644 (file)
@@ -69,6 +69,11 @@ nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1,
        return 0;
 }
 
+static struct nouveau_clocks
+nv04_domain[] = {
+       { nv_clk_src_max }
+};
+
 static int
 nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,7 +82,7 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, NULL, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
new file mode 100644 (file)
index 0000000..7a723b4
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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: Ben Skeggs
+ */
+
+#include <engine/fifo.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/timer.h>
+#include <subdev/clock.h>
+
+#include "pll.h"
+
+struct nvaa_clock_priv {
+       struct nouveau_clock base;
+       enum nv_clk_src csrc, ssrc, vsrc;
+       u32 cctrl, sctrl;
+       u32 ccoef, scoef;
+       u32 cpost, spost;
+       u32 vdiv;
+};
+
+static u32
+read_div(struct nouveau_clock *clk)
+{
+       return nv_rd32(clk, 0x004600);
+}
+
+static u32
+read_pll(struct nouveau_clock *clk, u32 base)
+{
+       u32 ctrl = nv_rd32(clk, base + 0);
+       u32 coef = nv_rd32(clk, base + 4);
+       u32 ref = clk->read(clk, nv_clk_src_href);
+       u32 post_div = 0;
+       u32 clock = 0;
+       int N1, M1;
+
+       switch (base){
+       case 0x4020:
+               post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16);
+               break;
+       case 0x4028:
+               post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16;
+               break;
+       default:
+               break;
+       }
+
+       N1 = (coef & 0x0000ff00) >> 8;
+       M1 = (coef & 0x000000ff);
+       if ((ctrl & 0x80000000) && M1) {
+               clock = ref * N1 / M1;
+               clock = clock / post_div;
+       }
+
+       return clock;
+}
+
+static int
+nvaa_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       u32 mast = nv_rd32(clk, 0x00c054);
+       u32 P = 0;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_href:
+               return 100000; /* PCIE reference clock */
+       case nv_clk_src_hclkm4:
+               return clk->read(clk, nv_clk_src_href) * 4;
+       case nv_clk_src_hclkm2d3:
+               return clk->read(clk, nv_clk_src_href) * 2 / 3;
+       case nv_clk_src_host:
+               switch (mast & 0x000c0000) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3);
+               case 0x00040000: break;
+               case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x000c0000: return clk->read(clk, nv_clk_src_cclk);
+               }
+               break;
+       case nv_clk_src_core:
+               P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16;
+
+               switch (mast & 0x00000003) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000001: return 0;
+               case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P;
+               case 0x00000003: return read_pll(clk, 0x004028) >> P;
+               }
+               break;
+       case nv_clk_src_cclk:
+               if ((mast & 0x03000000) != 0x03000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               if ((mast & 0x00000200) == 0x00000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               switch (mast & 0x00000c00) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_href);
+               case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3);
+               default: return 0;
+               }
+       case nv_clk_src_shader:
+               P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16;
+               switch (mast & 0x00000030) {
+               case 0x00000000:
+                       if (mast & 0x00000040)
+                               return clk->read(clk, nv_clk_src_href) >> P;
+                       return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000010: break;
+               case 0x00000020: return read_pll(clk, 0x004028) >> P;
+               case 0x00000030: return read_pll(clk, 0x004020) >> P;
+               }
+               break;
+       case nv_clk_src_mem:
+               return 0;
+               break;
+       case nv_clk_src_vdec:
+               P = (read_div(clk) & 0x00000700) >> 8;
+
+               switch (mast & 0x00400000) {
+               case 0x00400000:
+                       return clk->read(clk, nv_clk_src_core) >> P;
+                       break;
+               default:
+                       return 500000 >> P;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
+       return 0;
+}
+
+static u32
+calc_pll(struct nvaa_clock_priv *priv, u32 reg,
+        u32 clock, int *N, int *M, int *P)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll pll;
+       struct nouveau_clock *clk = &priv->base;
+       int ret;
+
+       ret = nvbios_pll_parse(bios, reg, &pll);
+       if (ret)
+               return 0;
+
+       pll.vco2.max_freq = 0;
+       pll.refclk = clk->read(clk, nv_clk_src_href);
+       if (!pll.refclk)
+               return 0;
+
+       return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P);
+}
+
+static inline u32
+calc_P(u32 src, u32 target, int *div)
+{
+       u32 clk0 = src, clk1 = src;
+       for (*div = 0; *div <= 7; (*div)++) {
+               if (clk0 <= target) {
+                       clk1 = clk0 << (*div ? 1 : 0);
+                       break;
+               }
+               clk0 >>= 1;
+       }
+
+       if (target - clk0 <= clk1 - target)
+               return clk0;
+       (*div)--;
+       return clk1;
+}
+
+static int
+nvaa_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       const int shader = cstate->domain[nv_clk_src_shader];
+       const int core = cstate->domain[nv_clk_src_core];
+       const int vdec = cstate->domain[nv_clk_src_vdec];
+       u32 out = 0, clock = 0;
+       int N, M, P1, P2 = 0;
+       int divs = 0;
+
+       /* cclk: find suitable source, disable PLL if we can */
+       if (core < clk->read(clk, nv_clk_src_hclkm4))
+               out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs);
+
+       /* Calculate clock * 2, so shader clock can use it too */
+       clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1);
+
+       if (abs(core - out) <=
+           abs(core - (clock >> 1))) {
+               priv->csrc = nv_clk_src_hclkm4;
+               priv->cctrl = divs << 16;
+       } else {
+               /* NVCTRL is actually used _after_ NVPOST, and after what we
+                * call NVPLL. To make matters worse, NVPOST is an integer
+                * divider instead of a right-shift number. */
+               if(P1 > 2) {
+                       P2 = P1 - 2;
+                       P1 = 2;
+               }
+
+               priv->csrc = nv_clk_src_core;
+               priv->ccoef = (N << 8) | M;
+
+               priv->cctrl = (P2 + 1) << 16;
+               priv->cpost = (1 << P1) << 16;
+       }
+
+       /* sclk: nvpll + divisor, href or spll */
+       out = 0;
+       if (shader == clk->read(clk, nv_clk_src_href)) {
+               priv->ssrc = nv_clk_src_href;
+       } else {
+               clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
+               if (priv->csrc == nv_clk_src_core) {
+                       out = calc_P((core << 1), shader, &divs);
+               }
+
+               if (abs(shader - out) <=
+                   abs(shader - clock) &&
+                  (divs + P2) <= 7) {
+                       priv->ssrc = nv_clk_src_core;
+                       priv->sctrl = (divs + P2) << 16;
+               } else {
+                       priv->ssrc = nv_clk_src_shader;
+                       priv->scoef = (N << 8) | M;
+                       priv->sctrl = P1 << 16;
+               }
+       }
+
+       /* vclk */
+       out = calc_P(core, vdec, &divs);
+       clock = calc_P(500000, vdec, &P1);
+       if(abs(vdec - out) <=
+          abs(vdec - clock)) {
+               priv->vsrc = nv_clk_src_cclk;
+               priv->vdiv = divs << 16;
+       } else {
+               priv->vsrc = nv_clk_src_vdec;
+               priv->vdiv = P1 << 16;
+       }
+
+       /* Print strategy! */
+       nv_debug(priv, "nvpll: %08x %08x %08x\n",
+                       priv->ccoef, priv->cpost, priv->cctrl);
+       nv_debug(priv, " spll: %08x %08x %08x\n",
+                       priv->scoef, priv->spost, priv->sctrl);
+       nv_debug(priv, " vdiv: %08x\n", priv->vdiv);
+       if (priv->csrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "core: hrefm4\n");
+       else
+               nv_debug(priv, "core: nvpll\n");
+
+       if (priv->ssrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "shader: hrefm4\n");
+       else if (priv->ssrc == nv_clk_src_core)
+               nv_debug(priv, "shader: nvpll\n");
+       else
+               nv_debug(priv, "shader: spll\n");
+
+       if (priv->vsrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "vdec: 500MHz\n");
+       else
+               nv_debug(priv, "vdec: core\n");
+
+       return 0;
+}
+
+static int
+nvaa_clock_prog(struct nouveau_clock *clk)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+       unsigned long flags;
+       u32 pllmask = 0, mast, ptherm_gate;
+       int ret = -EBUSY;
+
+       /* halt and idle execution engines */
+       ptherm_gate = nv_mask(clk, 0x020060, 0x00070000, 0x00000000);
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000001);
+       /* Wait until the interrupt handler is finished */
+       if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000))
+               goto resume;
+
+       if (pfifo)
+               pfifo->pause(pfifo, &flags);
+
+       if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010))
+               goto resume;
+       if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f))
+               goto resume;
+
+       /* First switch to safe clocks: href */
+       mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640);
+       mast &= ~0x00400e73;
+       mast |= 0x03000000;
+
+       switch (priv->csrc) {
+       case nv_clk_src_hclkm4:
+               nv_mask(clk, 0x4028, 0x00070000, priv->cctrl);
+               mast |= 0x00000002;
+               break;
+       case nv_clk_src_core:
+               nv_wr32(clk, 0x402c, priv->ccoef);
+               nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl);
+               nv_wr32(clk, 0x4040, priv->cpost);
+               pllmask |= (0x3 << 8);
+               mast |= 0x00000003;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown core clock\n");
+               goto resume;
+       }
+
+       switch (priv->ssrc) {
+       case nv_clk_src_href:
+               nv_mask(clk, 0x4020, 0x00070000, 0x00000000);
+               /* mast |= 0x00000000; */
+               break;
+       case nv_clk_src_core:
+               nv_mask(clk, 0x4020, 0x00070000, priv->sctrl);
+               mast |= 0x00000020;
+               break;
+       case nv_clk_src_shader:
+               nv_wr32(clk, 0x4024, priv->scoef);
+               nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl);
+               nv_wr32(clk, 0x4070, priv->spost);
+               pllmask |= (0x3 << 12);
+               mast |= 0x00000030;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown sclk clock\n");
+               goto resume;
+       }
+
+       if (!nv_wait(clk, 0x004080, pllmask, pllmask)) {
+               nv_warn(priv,"Reclocking failed: unstable PLLs\n");
+               goto resume;
+       }
+
+       switch (priv->vsrc) {
+       case nv_clk_src_cclk:
+               mast |= 0x00400000;
+       default:
+               nv_wr32(clk, 0x4600, priv->vdiv);
+       }
+
+       nv_wr32(clk, 0xc054, mast);
+       ret = 0;
+
+resume:
+       if (pfifo)
+               pfifo->start(pfifo, &flags);
+
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000000);
+       nv_wr32(clk, 0x020060, ptherm_gate);
+
+       /* Disable some PLLs and dividers when unused */
+       if (priv->csrc != nv_clk_src_core) {
+               nv_wr32(clk, 0x4040, 0x00000000);
+               nv_mask(clk, 0x4028, 0x80000000, 0x00000000);
+       }
+
+       if (priv->ssrc != nv_clk_src_shader) {
+               nv_wr32(clk, 0x4070, 0x00000000);
+               nv_mask(clk, 0x4020, 0x80000000, 0x00000000);
+       }
+
+       return ret;
+}
+
+static void
+nvaa_clock_tidy(struct nouveau_clock *clk)
+{
+}
+
+static struct nouveau_clocks
+nvaa_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_vdec   , 0xff, 0, "vdec", 1000 },
+       { nv_clk_src_max }
+};
+
+static int
+nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nvaa_clock_priv *priv;
+       int ret;
+
+       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nvaa_clock_read;
+       priv->base.calc = nvaa_clock_calc;
+       priv->base.prog = nvaa_clock_prog;
+       priv->base.tidy = nvaa_clock_tidy;
+       return 0;
+}
+
+struct nouveau_oclass *
+nvaa_clock_oclass = &(struct nouveau_oclass) {
+       .handle = NV_SUBDEV(CLOCK, 0xaa),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvaa_clock_ctor,
+               .dtor = _nouveau_clock_dtor,
+               .init = _nouveau_clock_init,
+               .fini = _nouveau_clock_fini,
+       },
+};
index 041fd5edaebf7de988206ec6440bdf1950edc938..c33c03d2f4af2f695e50e92078ea18c800d07eec 100644 (file)
@@ -197,7 +197,7 @@ static int
 nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
                     struct nouveau_i2c_board_info *info,
                     bool (*match)(struct nouveau_i2c_port *,
-                                  struct i2c_board_info *))
+                                  struct i2c_board_info *, void *), void *data)
 {
        struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index);
        int i;
@@ -221,7 +221,7 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
                }
 
                if (nv_probe_i2c(port, info[i].dev.addr) &&
-                   (!match || match(port, &info[i].dev))) {
+                   (!match || match(port, &info[i].dev, data))) {
                        nv_info(i2c, "detected %s: %s\n", what,
                                info[i].dev.type);
                        return i;
index af129c2e811388adbb3129a0f76f9648eb669658..64f8b4702bf7272c3edf7950e16bf46b07d5457a 100644 (file)
@@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info)
 static int
 mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)
 {
-       struct nouveau_mxm *mxm = nouveau_mxm(bios);
+       struct nouveau_mxm *mxm = data;
        struct context ctx = { .outp = (u32 *)(bios->data + pdcb) };
        u8 type, i2cidx, link, ver, len;
        u8 *conn;
@@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm)
                return;
        }
 
-       dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry);
+       dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry);
        mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL);
 }
 
index e44ed7b93c6d88db3826a6c6dcb13efd5429385a..7610fc5f8fa256de8038e3770ca227a3d0150c64 100644 (file)
@@ -29,9 +29,9 @@
 
 static bool
 probe_monitoring_device(struct nouveau_i2c_port *i2c,
-                       struct i2c_board_info *info)
+                       struct i2c_board_info *info, void *data)
 {
-       struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
+       struct nouveau_therm_priv *priv = data;
        struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
        struct i2c_client *client;
 
@@ -96,7 +96,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
                };
 
                i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                                 board, probe_monitoring_device);
+                             board, probe_monitoring_device, therm);
                if (priv->ic)
                        return;
        }
@@ -108,7 +108,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
                };
 
                i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                                 board, probe_monitoring_device);
+                             board, probe_monitoring_device, therm);
                if (priv->ic)
                        return;
        }
@@ -117,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
           device. Let's try our static list.
         */
        i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
-                     nv_board_infos, probe_monitoring_device);
+                     nv_board_infos, probe_monitoring_device, therm);
 }
index 936a71c5908076814a4aa8ffc5c2a3757e745ea5..7fdc51e2a571bee85b6fcf707890c8e4138ca8d9 100644 (file)
@@ -643,7 +643,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
            get_tmds_slave(encoder))
                return;
 
-       type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL);
+       type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL);
        if (type < 0)
                return;
 
index 3618ac6b6316416797a36e474bf613a12cf032ab..32e7064b819b6df4f9e5847beba7a826eaaed726 100644 (file)
@@ -58,8 +58,8 @@ struct nouveau_plane {
 };
 
 static uint32_t formats[] = {
-       DRM_FORMAT_NV12,
        DRM_FORMAT_UYVY,
+       DRM_FORMAT_NV12,
 };
 
 /* Sine can be approximated with
@@ -99,13 +99,28 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_bo *cur = nv_plane->cur;
        bool flip = nv_plane->flip;
-       int format = ALIGN(src_w * 4, 0x100);
        int soff = NV_PCRTC0_SIZE * nv_crtc->index;
        int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
-       int ret;
+       int format, ret;
+
+       /* Source parameters given in 16.16 fixed point, ignore fractional. */
+       src_x >>= 16;
+       src_y >>= 16;
+       src_w >>= 16;
+       src_h >>= 16;
+
+       format = ALIGN(src_w * 4, 0x100);
 
        if (format > 0xffff)
-               return -EINVAL;
+               return -ERANGE;
+
+       if (dev->chipset >= 0x30) {
+               if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
+                       return -ERANGE;
+       } else {
+               if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3))
+                       return -ERANGE;
+       }
 
        ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
        if (ret)
@@ -113,12 +128,6 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
        nv_plane->cur = nv_fb->nvbo;
 
-       /* Source parameters given in 16.16 fixed point, ignore fractional. */
-       src_x = src_x >> 16;
-       src_y = src_y >> 16;
-       src_w = src_w >> 16;
-       src_h = src_h >> 16;
-
        nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
        nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
 
@@ -245,14 +254,25 @@ nv10_overlay_init(struct drm_device *device)
 {
        struct nouveau_device *dev = nouveau_dev(device);
        struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
+       int num_formats = ARRAY_SIZE(formats);
        int ret;
 
        if (!plane)
                return;
 
+       switch (dev->chipset) {
+       case 0x10:
+       case 0x11:
+       case 0x15:
+       case 0x1a:
+       case 0x20:
+               num_formats = 1;
+               break;
+       }
+
        ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */,
                             &nv10_plane_funcs,
-                            formats, ARRAY_SIZE(formats), false);
+                            formats, num_formats, false);
        if (ret)
                goto err;
 
index cc4b208ce546d50aad1813810981099fe6d81935..244822df8ffc73d1e9f15075c7ee6faa54368a84 100644 (file)
@@ -59,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index)
        struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
 
        return i2c->identify(i2c, i2c_index, "TV encoder",
-                            nv04_tv_encoder_info, NULL);
+                            nv04_tv_encoder_info, NULL, NULL);
 }
 
 
index 6828d81ed7b99daea875ffd06c4dd399d4aa05dd..900fae01793e7884ee8033a11d6c247cbeb36678 100644 (file)
@@ -447,6 +447,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        if (ret)
                goto done;
 
+       info->offset = ntfy->node->offset;
+
 done:
        if (ret)
                nouveau_abi16_ntfy_fini(chan, ntfy);
index 95c740454049ad1b4a4cf23c2bc63d7038c7a362..ba0183fb84f3b871a4815552021174e870f780e8 100644 (file)
@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
        bool dsm_detected;
        bool optimus_detected;
        acpi_handle dhandle;
+       acpi_handle other_handle;
        acpi_handle rom_handle;
 } nouveau_dsm_priv;
 
@@ -260,9 +261,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
        if (!dhandle)
                return false;
 
-       if (!acpi_has_method(dhandle, "_DSM"))
+       if (!acpi_has_method(dhandle, "_DSM")) {
+               nouveau_dsm_priv.other_handle = dhandle;
                return false;
-
+       }
        if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
@@ -338,6 +340,16 @@ static bool nouveau_dsm_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
                        acpi_method_name);
                nouveau_dsm_priv.dsm_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when _DSM is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
+               acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
                ret = true;
        }
 
index 7809d92183c4236c9f1f937ea6cde6a39e780063..25ea82f8def3cb883a06aef6e9da59ea4cbffaf7 100644 (file)
@@ -608,8 +608,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        fence = nouveau_fence_ref(new_bo->bo.sync_obj);
        spin_unlock(&new_bo->bo.bdev->fence_lock);
        ret = nouveau_fence_sync(fence, chan);
+       nouveau_fence_unref(&fence);
        if (ret)
-               return ret;
+               goto fail_free;
 
        if (new_bo != old_bo) {
                ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);
@@ -701,7 +702,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
 
        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
        if (s->event)
-               drm_send_vblank_event(dev, -1, s->event);
+               drm_send_vblank_event(dev, s->crtc, s->event);
 
        list_del(&s->head);
        if (ps)
index 7a3759f1c41a67bac6b48cdcfd5b10b5ac30ae39..98a22e6e27a11f73045fdbab161452309f2416ab 100644 (file)
@@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        if (nouveau_runtime_pm == 0)
                return -EINVAL;
 
+       /* 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;
+       }
+
        nv_debug_level(SILENT);
        drm_kms_helper_poll_disable(drm_dev);
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
index f8e66c08b11a292545a29e327966d3d4256e5f09..4e384a2f99c3627ea0fc6e31f5f0e34ac95e71e8 100644 (file)
@@ -1265,7 +1265,7 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
                    uint32_t start, uint32_t size)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-       u32 end = max(start + size, (u32)256);
+       u32 end = min_t(u32, start + size, 256);
        u32 i;
 
        for (i = start; i < end; i++) {
index 037d324bf58f6ccfda14ff471f3c98b4405981a0..66ac0ff95f5a30408bf722b43e49e76138e74546 100644 (file)
@@ -8,5 +8,6 @@ config DRM_QXL
         select DRM_KMS_HELPER
        select DRM_KMS_FB_HELPER
         select DRM_TTM
+       select CRC32
        help
                QXL virtual GPU for Spice virtualization desktop integration. Do not enable this driver unless your distro ships a corresponding X.org QXL driver that can handle kernel modesetting.
index 5e827c29d1948a658cf61205b7607ff5a53263d7..d70aafb83307d2a085afdbba6a2d4762309667ea 100644 (file)
@@ -24,7 +24,7 @@
  */
 
 
-#include "linux/crc32.h"
+#include <linux/crc32.h>
 
 #include "qxl_drv.h"
 #include "qxl_object.h"
index 80a20120e6253590d07e9ec4b0085b6ea9d31437..0b9621c9aeea3b25da6bad8b121bfc3c3236ddcc 100644 (file)
@@ -1143,31 +1143,53 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
        }
 
        if (tiling_flags & RADEON_TILING_MACRO) {
-               if (rdev->family >= CHIP_BONAIRE)
-                       tmp = rdev->config.cik.tile_config;
-               else if (rdev->family >= CHIP_TAHITI)
-                       tmp = rdev->config.si.tile_config;
-               else if (rdev->family >= CHIP_CAYMAN)
-                       tmp = rdev->config.cayman.tile_config;
-               else
-                       tmp = rdev->config.evergreen.tile_config;
+               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
 
-               switch ((tmp & 0xf0) >> 4) {
-               case 0: /* 4 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
-                       break;
-               case 1: /* 8 banks */
-               default:
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
-                       break;
-               case 2: /* 16 banks */
-                       fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
-                       break;
+               /* Set NUM_BANKS. */
+               if (rdev->family >= CHIP_BONAIRE) {
+                       unsigned tileb, index, num_banks, tile_split_bytes;
+
+                       /* Calculate the macrotile mode index. */
+                       tile_split_bytes = 64 << tile_split;
+                       tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+                       tileb = min(tile_split_bytes, tileb);
+
+                       for (index = 0; tileb > 64; index++) {
+                               tileb >>= 1;
+                       }
+
+                       if (index >= 16) {
+                               DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+                                         target_fb->bits_per_pixel, tile_split);
+                               return -EINVAL;
+                       }
+
+                       num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 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)
+                               tmp = rdev->config.cayman.tile_config;
+                       else
+                               tmp = rdev->config.evergreen.tile_config;
+
+                       switch ((tmp & 0xf0) >> 4) {
+                       case 0: /* 4 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+                               break;
+                       case 1: /* 8 banks */
+                       default:
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+                               break;
+                       case 2: /* 16 banks */
+                               fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+                               break;
+                       }
                }
 
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-
-               evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
                fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
                fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
                fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
@@ -1180,23 +1202,18 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
                fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
 
        if (rdev->family >= CHIP_BONAIRE) {
-               u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
-               u32 num_rb = rdev->config.cik.max_backends_per_se;
-               if (num_pipe_configs > 8)
-                       num_pipe_configs = 8;
-               if (num_pipe_configs == 8)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
-               else if (num_pipe_configs == 4) {
-                       if (num_rb == 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
-                       else if (num_rb < 4)
-                               fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
-               } else if (num_pipe_configs == 2)
-                       fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
+               /* Read the pipe config from the 2D TILED SCANOUT mode.
+                * It should be the same for the other modes too, but not all
+                * modes set the pipe config field. */
+               u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
+
+               fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
        } else if ((rdev->family == CHIP_TAHITI) ||
                   (rdev->family == CHIP_PITCAIRN))
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
-       else if (rdev->family == CHIP_VERDE)
+       else if ((rdev->family == CHIP_VERDE) ||
+                (rdev->family == CHIP_OLAND) ||
+                (rdev->family == CHIP_HAINAN)) /* for completeness.  HAINAN has no display hw */
                fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
 
        switch (radeon_crtc->crtc_id) {
index 0652ee0a20989db0b69f816d45e17f9354e5ca8a..f685035dbe39a7d7ad48e63a9b4ca2ea717701fe 100644 (file)
@@ -44,7 +44,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
        PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
        unsigned char *base;
-       u16 out;
+       u16 out = cpu_to_le16(0);
 
        memset(&args, 0, sizeof(args));
 
@@ -55,11 +55,14 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
                        DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
                        return -EINVAL;
                }
-               args.ucRegIndex = buf[0];
-               if (num > 1) {
+               if (buf == NULL)
+                       args.ucRegIndex = 0;
+               else
+                       args.ucRegIndex = buf[0];
+               if (num)
                        num--;
+               if (num)
                        memcpy(&out, &buf[1], num);
-               }
                args.lpI2CDataOut = cpu_to_le16(out);
        } else {
                if (num > ATOM_MAX_HW_I2C_READ) {
@@ -96,14 +99,14 @@ int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
        struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
        struct i2c_msg *p;
        int i, remaining, current_count, buffer_offset, max_bytes, ret;
-       u8 buf = 0, flags;
+       u8 flags;
 
        /* check for bus probe */
        p = &msgs[0];
        if ((num == 1) && (p->len == 0)) {
                ret = radeon_process_i2c_ch(i2c,
                                            p->addr, HW_I2C_WRITE,
-                                           &buf, 1);
+                                           NULL, 0);
                if (ret)
                        return ret;
                else
index b43a3a3c90671911a4eaa0a7c5a260c42118df41..e950fabd7f5e474ab3e60371f669e31805077785 100644 (file)
@@ -3057,7 +3057,7 @@ static u32 cik_create_bitmask(u32 bit_width)
  * Returns the disabled RB bitmask.
  */
 static u32 cik_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -3071,7 +3071,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
@@ -3088,7 +3088,7 @@ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
  */
 static void cik_setup_rb(struct radeon_device *rdev,
                         u32 se_num, u32 sh_per_se,
-                        u32 max_rb_num)
+                        u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -3098,7 +3098,7 @@ static void cik_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        cik_select_se_sh(rdev, i, j);
-                       data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        if (rdev->family == CHIP_HAWAII)
                                disabled_rbs |= data << ((i * sh_per_se + j) * HAWAII_RB_BITMAP_WIDTH_PER_SH);
                        else
@@ -3108,12 +3108,14 @@ static void cik_setup_rb(struct radeon_device *rdev,
        cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.cik.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                cik_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
index 0300727a4f70d52c71e24931bbec8335ce6ba6d3..d08b83c6267b4cde4ff5ce0ad71754c1e5e446a1 100644 (file)
@@ -458,7 +458,7 @@ int cik_copy_dma(struct radeon_device *rdev,
                radeon_ring_write(ring, 0); /* src/dst endian swap */
                radeon_ring_write(ring, src_offset & 0xffffffff);
                radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff);
-               radeon_ring_write(ring, dst_offset & 0xfffffffc);
+               radeon_ring_write(ring, dst_offset & 0xffffffff);
                radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff);
                src_offset += cur_size_in_bytes;
                dst_offset += cur_size_in_bytes;
index 009f46e0ce72db47534d2b7667bcd0119607d91b..713a5d35990102ea315fa078a93c11d6c1aae1f5 100644 (file)
@@ -93,11 +93,13 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
        struct radeon_device *rdev = encoder->dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       u32 offset = dig->afmt->offset;
+       u32 offset;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
+       offset = dig->afmt->offset;
+
        WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
               AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
 }
@@ -112,7 +114,7 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
        struct radeon_connector *radeon_connector = NULL;
        u32 tmp = 0, offset;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -156,7 +158,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -172,7 +174,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -217,7 +219,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
                { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
        };
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -233,7 +235,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
@@ -306,7 +308,9 @@ int dce6_audio_init(struct radeon_device *rdev)
        rdev->audio.enabled = true;
 
        if (ASIC_IS_DCE8(rdev))
-               rdev->audio.num_pins = 7;
+               rdev->audio.num_pins = 6;
+       else if (ASIC_IS_DCE61(rdev))
+               rdev->audio.num_pins = 4;
        else
                rdev->audio.num_pins = 6;
 
index aa695c4feb3d00d393c2e9b74e2395a3a7395164..0c6d5cef4cf121770c63fcb559bf6cc187640292 100644 (file)
@@ -118,7 +118,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
        }
@@ -173,7 +173,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
-       if (sad_count < 0) {
+       if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
        }
index 11aab2ab54ce27fb5c0279cbaaad797e95bea42f..f59a9e9fccf8a803ce6097e4e185d8824ad5f714 100644 (file)
@@ -895,6 +895,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                    (rdev->pdev->device == 0x999C)) {
                        rdev->config.cayman.max_simds_per_se = 6;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9903) ||
                           (rdev->pdev->device == 0x9904) ||
                           (rdev->pdev->device == 0x990A) ||
@@ -905,6 +909,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x999D)) {
                        rdev->config.cayman.max_simds_per_se = 4;
                        rdev->config.cayman.max_backends_per_se = 2;
+                       rdev->config.cayman.max_hw_contexts = 8;
+                       rdev->config.cayman.sx_max_export_size = 256;
+                       rdev->config.cayman.sx_max_export_pos_size = 64;
+                       rdev->config.cayman.sx_max_export_smx_size = 192;
                } else if ((rdev->pdev->device == 0x9919) ||
                           (rdev->pdev->device == 0x9990) ||
                           (rdev->pdev->device == 0x9991) ||
@@ -915,9 +923,17 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x99A0)) {
                        rdev->config.cayman.max_simds_per_se = 3;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                } else {
                        rdev->config.cayman.max_simds_per_se = 2;
                        rdev->config.cayman.max_backends_per_se = 1;
+                       rdev->config.cayman.max_hw_contexts = 4;
+                       rdev->config.cayman.sx_max_export_size = 128;
+                       rdev->config.cayman.sx_max_export_pos_size = 32;
+                       rdev->config.cayman.sx_max_export_smx_size = 96;
                }
                rdev->config.cayman.max_texture_channel_caches = 2;
                rdev->config.cayman.max_gprs = 256;
@@ -925,10 +941,6 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                rdev->config.cayman.max_gs_threads = 32;
                rdev->config.cayman.max_stack_entries = 512;
                rdev->config.cayman.sx_num_of_sets = 8;
-               rdev->config.cayman.sx_max_export_size = 256;
-               rdev->config.cayman.sx_max_export_pos_size = 64;
-               rdev->config.cayman.sx_max_export_smx_size = 192;
-               rdev->config.cayman.max_hw_contexts = 8;
                rdev->config.cayman.sq_num_cf_insts = 2;
 
                rdev->config.cayman.sc_prim_fifo_size = 0x40;
index cdc003085a76b802eddba1d1ba1a9df5e739dc26..49c4d48f54d616b49b7af261d8fa2d71586ab8fd 100644 (file)
@@ -785,8 +785,8 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
        struct ni_ps *ps = ni_get_ps(rps);
        struct radeon_clock_and_voltage_limits *max_limits;
        bool disable_mclk_switching;
-       u32 mclk, sclk;
-       u16 vddc, vddci;
+       u32 mclk;
+       u16 vddci;
        u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
@@ -839,24 +839,14 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
 
        /* XXX validate the min clocks required for display */
 
+       /* adjust low state */
        if (disable_mclk_switching) {
-               mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
-               sclk = ps->performance_levels[0].sclk;
-               vddc = ps->performance_levels[0].vddc;
-               vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
-       } else {
-               sclk = ps->performance_levels[0].sclk;
-               mclk = ps->performance_levels[0].mclk;
-               vddc = ps->performance_levels[0].vddc;
-               vddci = ps->performance_levels[0].vddci;
+               ps->performance_levels[0].mclk =
+                       ps->performance_levels[ps->performance_level_count - 1].mclk;
+               ps->performance_levels[0].vddci =
+                       ps->performance_levels[ps->performance_level_count - 1].vddci;
        }
 
-       /* adjusted low state */
-       ps->performance_levels[0].sclk = sclk;
-       ps->performance_levels[0].mclk = mclk;
-       ps->performance_levels[0].vddc = vddc;
-       ps->performance_levels[0].vddci = vddci;
-
        btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
                                  &ps->performance_levels[0].sclk,
                                  &ps->performance_levels[0].mclk);
@@ -868,11 +858,15 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
                        ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
        }
 
+       /* adjust remaining states */
        if (disable_mclk_switching) {
                mclk = ps->performance_levels[0].mclk;
+               vddci = ps->performance_levels[0].vddci;
                for (i = 1; i < ps->performance_level_count; i++) {
                        if (mclk < ps->performance_levels[i].mclk)
                                mclk = ps->performance_levels[i].mclk;
+                       if (vddci < ps->performance_levels[i].vddci)
+                               vddci = ps->performance_levels[i].vddci;
                }
                for (i = 0; i < ps->performance_level_count; i++) {
                        ps->performance_levels[i].mclk = mclk;
index 4b89262f3f0e37242de23b7b6ea2fc555d141da3..b7d3ecba43e34d3b559ee072800101532150c631 100644 (file)
@@ -304,9 +304,9 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
-       } else if (ASIC_IS_DCE3(rdev)) {
+       } else {
                /* according to the reg specs, this should DCE3.2 only, but in
-                * practice it seems to cover DCE3.0/3.1 as well.
+                * practice it seems to cover DCE2.0/3.0/3.1 as well.
                 */
                if (dig->dig_encoder == 0) {
                        WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
@@ -317,10 +317,6 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
-       } else {
-               /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */
-               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
-                      AUDIO_DTO_MODULE(clock / 10));
        }
 }
 
index ecf2a3960c0786ca02fc3aef84afab61e0e6303f..45e1f447bc794c677a8e83830fd318585c2d7f7e 100644 (file)
@@ -1940,7 +1940,7 @@ struct si_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -1970,7 +1970,7 @@ struct cik_asic {
        unsigned sc_earlyz_tile_fifo_size;
 
        unsigned num_tile_pipes;
-       unsigned num_backends_per_se;
+       unsigned backend_enable_mask;
        unsigned backend_disable_mask_per_asic;
        unsigned backend_map;
        unsigned num_texture_channel_caches;
@@ -2710,10 +2710,10 @@ void radeon_vm_fence(struct radeon_device *rdev,
                     struct radeon_vm *vm,
                     struct radeon_fence *fence);
 uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr);
-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
-                           struct radeon_vm *vm,
-                           struct radeon_bo *bo,
-                           struct ttm_mem_reg *mem);
+int radeon_vm_bo_update(struct radeon_device *rdev,
+                       struct radeon_vm *vm,
+                       struct radeon_bo *bo,
+                       struct ttm_mem_reg *mem);
 void radeon_vm_bo_invalidate(struct radeon_device *rdev,
                             struct radeon_bo *bo);
 struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm,
index e354ce94cdd17492030e2bd85ef1406810e9e5df..c0425bb6223a99fae5eab07a069ab73ace19eec7 100644 (file)
@@ -2021,7 +2021,7 @@ static struct radeon_asic ci_asic = {
                .hdmi_setmode = &evergreen_hdmi_setmode,
        },
        .copy = {
-               .blit = NULL,
+               .blit = &cik_copy_cpdma,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
@@ -2122,7 +2122,7 @@ static struct radeon_asic kv_asic = {
                .hdmi_setmode = &evergreen_hdmi_setmode,
        },
        .copy = {
-               .blit = NULL,
+               .blit = &cik_copy_cpdma,
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
index f79ee184ffd5849f4d0e0ec1b87b0d94d0f1f131..5c39bf7c3d88668bad65ef9667de82a0a145f196 100644 (file)
@@ -2918,7 +2918,7 @@ int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev,
                        mpll_param->dll_speed = args.ucDllSpeed;
                        mpll_param->bwcntl = args.ucBWCntl;
                        mpll_param->vco_mode =
-                               (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0;
+                               (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK);
                        mpll_param->yclk_sel =
                                (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0;
                        mpll_param->qdr =
index 9d302eaeea1587b6fdb5439119b6f45c0de961db..485848f889f55c9f4b86bf61bd8c019e2ad96a27 100644 (file)
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv {
        bool atpx_detected;
        /* handle for device - and atpx */
        acpi_handle dhandle;
+       acpi_handle other_handle;
        struct radeon_atpx atpx;
 } radeon_atpx_priv;
 
@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
                return false;
 
        status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
-       if (ACPI_FAILURE(status))
+       if (ACPI_FAILURE(status)) {
+               radeon_atpx_priv.other_handle = dhandle;
                return false;
-
+       }
        radeon_atpx_priv.dhandle = dhandle;
        radeon_atpx_priv.atpx.handle = atpx_handle;
        return true;
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void)
                printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
                       acpi_method_name);
                radeon_atpx_priv.atpx_detected = true;
+               /*
+                * On some systems hotplug events are generated for the device
+                * being switched off when ATPX is executed.  They cause ACPI
+                * hotplug to trigger and attempt to remove the device from
+                * the system, which causes it to break down.  Prevent that from
+                * happening by setting the no_hotplug flag for the involved
+                * ACPI device objects.
+                */
+               acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
+               acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
                return true;
        }
        return false;
index f41594b2eeac775794f3d2b2d050a06e387d9025..0b366169d64de55c52e4c2d9c26d1c3b9db19b2d 100644 (file)
@@ -360,13 +360,13 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser,
        struct radeon_bo *bo;
        int r;
 
-       r = radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
+       r = radeon_vm_bo_update(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
        if (r) {
                return r;
        }
        list_for_each_entry(lobj, &parser->validated, tv.head) {
                bo = lobj->bo;
-               r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem);
+               r = radeon_vm_bo_update(parser->rdev, vm, bo, &bo->tbo.mem);
                if (r) {
                        return r;
                }
index 9f5ff28864f6e3ccf4f4736cc55307735d87a70a..db39ea36bf22fc396da63e5a157adf42e752e712 100644 (file)
  *   2.33.0 - Add SI tiling mode array query
  *   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
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       35
+#define KMS_DRIVER_MINOR       36
 #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);
@@ -508,15 +509,6 @@ static const struct file_operations radeon_driver_kms_fops = {
 #endif
 };
 
-
-static void
-radeon_pci_shutdown(struct pci_dev *pdev)
-{
-       struct drm_device *dev = pci_get_drvdata(pdev);
-
-       radeon_driver_unload_kms(dev);
-}
-
 static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP |
@@ -586,7 +578,6 @@ static struct pci_driver radeon_kms_pci_driver = {
        .probe = radeon_pci_probe,
        .remove = radeon_pci_remove,
        .driver.pm = &radeon_pm_ops,
-       .shutdown = radeon_pci_shutdown,
 };
 
 static int __init radeon_init(void)
index 543dcfae7e6f5f9a01797a9bb90455be5fef88c5..00e0d449021c343015540ea3baf1028b85a10090 100644 (file)
  * 1.31- Add support for num Z pipes from GET_PARAM
  * 1.32- fixes for rv740 setup
  * 1.33- Add r6xx/r7xx const buffer support
+ * 1.34- fix evergreen/cayman GS register
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           33
+#define DRIVER_MINOR           34
 #define DRIVER_PATCHLEVEL      0
 
 long radeon_drm_ioctl(struct file *filp,
index 3044e504f4ec9a8a4cbf6ef18bbd009fe7672c01..96e440061bdbf5b65a6213047f62bbeb89aea77f 100644 (file)
@@ -29,6 +29,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_reg.h"
+#include "radeon_trace.h"
 
 /*
  * GART
@@ -737,6 +738,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
        for (i = 0; i < 2; ++i) {
                if (choices[i]) {
                        vm->id = choices[i];
+                       trace_radeon_vm_grab_id(vm->id, ring);
                        return rdev->vm_manager.active[choices[i]];
                }
        }
@@ -1116,7 +1118,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
 }
 
 /**
- * radeon_vm_bo_update_pte - map a bo into the vm page table
+ * radeon_vm_bo_update - map a bo into the vm page table
  *
  * @rdev: radeon_device pointer
  * @vm: requested vm
@@ -1128,10 +1130,10 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
  *
  * Object have to be reserved & global and local mutex must be locked!
  */
-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
-                           struct radeon_vm *vm,
-                           struct radeon_bo *bo,
-                           struct ttm_mem_reg *mem)
+int radeon_vm_bo_update(struct radeon_device *rdev,
+                       struct radeon_vm *vm,
+                       struct radeon_bo *bo,
+                       struct ttm_mem_reg *mem)
 {
        struct radeon_ib ib;
        struct radeon_bo_va *bo_va;
@@ -1176,6 +1178,8 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                bo_va->valid = false;
        }
 
+       trace_radeon_vm_bo_update(bo_va);
+
        nptes = radeon_bo_ngpu_pages(bo);
 
        /* assume two extra pdes in case the mapping overlaps the borders */
@@ -1257,7 +1261,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
        mutex_lock(&rdev->vm_manager.lock);
        mutex_lock(&bo_va->vm->mutex);
        if (bo_va->soffset) {
-               r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL);
+               r = radeon_vm_bo_update(rdev, bo_va->vm, bo_va->bo, NULL);
        }
        mutex_unlock(&rdev->vm_manager.lock);
        list_del(&bo_va->vm_list);
index 55d0b474bd371ae83f1cea0ec08d30504b371816..21d593c0ecaf4e7e0ec85ab9b7bf53fafd0f2a87 100644 (file)
@@ -461,6 +461,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_SI_CP_DMA_COMPUTE:
                *value = 1;
                break;
+       case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
+               if (rdev->family >= CHIP_BONAIRE) {
+                       *value = rdev->config.cik.backend_enable_mask;
+               } else if (rdev->family >= CHIP_TAHITI) {
+                       *value = rdev->config.si.backend_enable_mask;
+               } else {
+                       DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+               }
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
index d1385ccc672c4976aff90d9150fb221f98c29441..984097b907ef5ee67c8e59faf4198ccf8add5f1b 100644 (file)
@@ -537,8 +537,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf)
 {
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
        int temp;
 
        if (rdev->asic->pm.get_temperature)
@@ -553,8 +552,7 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
                                             struct device_attribute *attr,
                                             char *buf)
 {
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
        int hyst = to_sensor_dev_attr(attr)->index;
        int temp;
 
@@ -566,23 +564,14 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
 
-static ssize_t radeon_hwmon_show_name(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "radeon\n");
-}
-
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1);
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_crit.dev_attr.attr,
        &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
-       &sensor_dev_attr_name.dev_attr.attr,
        NULL
 };
 
@@ -590,8 +579,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
                                        struct attribute *attr, int index)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
 
        /* Skip limit attributes if DPM is not enabled */
        if (rdev->pm.pm_method != PM_METHOD_DPM &&
@@ -607,11 +595,15 @@ static const struct attribute_group hwmon_attrgroup = {
        .is_visible = hwmon_attributes_visible,
 };
 
+static const struct attribute_group *hwmon_groups[] = {
+       &hwmon_attrgroup,
+       NULL
+};
+
 static int radeon_hwmon_init(struct radeon_device *rdev)
 {
        int err = 0;
-
-       rdev->pm.int_hwmon_dev = NULL;
+       struct device *hwmon_dev;
 
        switch (rdev->pm.int_thermal_type) {
        case THERMAL_TYPE_RV6XX:
@@ -624,20 +616,13 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        case THERMAL_TYPE_KV:
                if (rdev->asic->pm.get_temperature == NULL)
                        return err;
-               rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
-               if (IS_ERR(rdev->pm.int_hwmon_dev)) {
-                       err = PTR_ERR(rdev->pm.int_hwmon_dev);
+               hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
+                                                             "radeon", rdev,
+                                                             hwmon_groups);
+               if (IS_ERR(hwmon_dev)) {
+                       err = PTR_ERR(hwmon_dev);
                        dev_err(rdev->dev,
                                "Unable to register hwmon device: %d\n", err);
-                       break;
-               }
-               dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev);
-               err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj,
-                                        &hwmon_attrgroup);
-               if (err) {
-                       dev_err(rdev->dev,
-                               "Unable to create hwmon sysfs file: %d\n", err);
-                       hwmon_device_unregister(rdev->dev);
                }
                break;
        default:
@@ -647,14 +632,6 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        return err;
 }
 
-static void radeon_hwmon_fini(struct radeon_device *rdev)
-{
-       if (rdev->pm.int_hwmon_dev) {
-               sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup);
-               hwmon_device_unregister(rdev->pm.int_hwmon_dev);
-       }
-}
-
 static void radeon_dpm_thermal_work_handler(struct work_struct *work)
 {
        struct radeon_device *rdev =
@@ -1337,8 +1314,6 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
 
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
-
-       radeon_hwmon_fini(rdev);
 }
 
 static void radeon_pm_fini_dpm(struct radeon_device *rdev)
@@ -1358,8 +1333,6 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
 
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
-
-       radeon_hwmon_fini(rdev);
 }
 
 void radeon_pm_fini(struct radeon_device *rdev)
index 9f0e18172b6e8074bf865e93902d67f1584141bd..0473257d407886e175f77347078b2de54c61cfc3 100644 (file)
@@ -47,6 +47,39 @@ TRACE_EVENT(radeon_cs,
                      __entry->fences)
 );
 
+TRACE_EVENT(radeon_vm_grab_id,
+           TP_PROTO(unsigned vmid, int ring),
+           TP_ARGS(vmid, ring),
+           TP_STRUCT__entry(
+                            __field(u32, vmid)
+                            __field(u32, ring)
+                            ),
+
+           TP_fast_assign(
+                          __entry->vmid = vmid;
+                          __entry->ring = ring;
+                          ),
+           TP_printk("vmid=%u, ring=%u", __entry->vmid, __entry->ring)
+);
+
+TRACE_EVENT(radeon_vm_bo_update,
+           TP_PROTO(struct radeon_bo_va *bo_va),
+           TP_ARGS(bo_va),
+           TP_STRUCT__entry(
+                            __field(u64, soffset)
+                            __field(u64, eoffset)
+                            __field(u32, flags)
+                            ),
+
+           TP_fast_assign(
+                          __entry->soffset = bo_va->soffset;
+                          __entry->eoffset = bo_va->eoffset;
+                          __entry->flags = bo_va->flags;
+                          ),
+           TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x",
+                     __entry->soffset, __entry->eoffset, __entry->flags)
+);
+
 TRACE_EVENT(radeon_vm_set_page,
            TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
                     uint32_t incr, uint32_t flags),
index 373d088bac66db910291045424e075921d39d202..b9c0529b4a2e1e9d8f69e51f6742d023492a0040 100644 (file)
@@ -473,7 +473,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                return -EINVAL;
        }
 
-       if ((start >> 28) != (end >> 28)) {
+       if ((start >> 28) != ((end - 1) >> 28)) {
                DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
                          start, end);
                return -EINVAL;
index a072fa8c46b04a00a9c78886b20a29615f7ad86c..d46b58d078aad94eaca7050eb3deb9c1375583a7 100644 (file)
@@ -21,7 +21,7 @@ cayman 0x9400
 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
 0x000089B0 VGT_HS_OFFCHIP_PARAM
 0x00008A14 PA_CL_ENHANCE
-0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008A60 PA_SU_LINE_STIPPLE_VALUE
 0x00008B10 PA_SC_LINE_STIPPLE_STATE
 0x00008BF0 PA_SC_ENHANCE
 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
@@ -532,7 +532,7 @@ cayman 0x9400
 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
-0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028B90 VGT_GS_INSTANCE_CNT
 0x00028BD4 PA_SC_CENTROID_PRIORITY_0
 0x00028BD8 PA_SC_CENTROID_PRIORITY_1
 0x00028BDC PA_SC_LINE_CNTL
index b912a37689bf818a0fccd576f6436f71e4e936ff..57745c8761c863714abe07ba2ff73324980ea18e 100644 (file)
@@ -22,7 +22,7 @@ evergreen 0x9400
 0x000089A4 VGT_COMPUTE_START_Z
 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
 0x00008A14 PA_CL_ENHANCE
-0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008A60 PA_SU_LINE_STIPPLE_VALUE
 0x00008B10 PA_SC_LINE_STIPPLE_STATE
 0x00008BF0 PA_SC_ENHANCE
 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
@@ -545,7 +545,7 @@ evergreen 0x9400
 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
-0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028B90 VGT_GS_INSTANCE_CNT
 0x00028C00 PA_SC_LINE_CNTL
 0x00028C08 PA_SU_VTX_CNTL
 0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
index 1c560629575a8906fb74e006285096f07eac7f19..e7dab069cccf48a05e19cfd7caf27bd65d38c53d 100644 (file)
@@ -162,6 +162,16 @@ static void rs690_mc_init(struct radeon_device *rdev)
        base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
        base = G_000100_MC_FB_START(base) << 16;
        rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+       /* Some boards seem to be configured for 128MB of sideport memory,
+        * but really only have 64MB.  Just skip the sideport and use
+        * UMA memory.
+        */
+       if (rdev->mc.igp_sideport_enabled &&
+           (rdev->mc.real_vram_size == (384 * 1024 * 1024))) {
+               base += 128 * 1024 * 1024;
+               rdev->mc.real_vram_size -= 128 * 1024 * 1024;
+               rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+       }
 
        /* Use K8 direct mapping for fast fb access. */ 
        rdev->fastfb_working = false;
index 913b025ae9b399695bed47af97cccf08fe68caf7..374499db20c7e59b55d956b066a30bdc42b4f71f 100644 (file)
@@ -2328,6 +2328,12 @@ void rv770_get_engine_memory_ss(struct radeon_device *rdev)
        pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
                                                       ASIC_INTERNAL_MEMORY_SS, 0);
 
+       /* disable ss, causes hangs on some cayman boards */
+       if (rdev->family == CHIP_CAYMAN) {
+               pi->sclk_ss = false;
+               pi->mclk_ss = false;
+       }
+
        if (pi->sclk_ss || pi->mclk_ss)
                pi->dynamic_ss = true;
        else
index 6a64ccaa0695643add9ee7e6b3f383202d35a988..85e1edfaa3bed0814e262378ae0a7558834936d3 100644 (file)
@@ -2811,7 +2811,7 @@ static void si_setup_spi(struct radeon_device *rdev,
 }
 
 static u32 si_get_rb_disabled(struct radeon_device *rdev,
-                             u32 max_rb_num, u32 se_num,
+                             u32 max_rb_num_per_se,
                              u32 sh_per_se)
 {
        u32 data, mask;
@@ -2825,14 +2825,14 @@ static u32 si_get_rb_disabled(struct radeon_device *rdev,
 
        data >>= BACKEND_DISABLE_SHIFT;
 
-       mask = si_create_bitmask(max_rb_num / se_num / sh_per_se);
+       mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
 
        return data & mask;
 }
 
 static void si_setup_rb(struct radeon_device *rdev,
                        u32 se_num, u32 sh_per_se,
-                       u32 max_rb_num)
+                       u32 max_rb_num_per_se)
 {
        int i, j;
        u32 data, mask;
@@ -2842,19 +2842,21 @@ static void si_setup_rb(struct radeon_device *rdev,
        for (i = 0; i < se_num; i++) {
                for (j = 0; j < sh_per_se; j++) {
                        si_select_se_sh(rdev, i, j);
-                       data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+                       data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
                        disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
                }
        }
        si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
 
        mask = 1;
-       for (i = 0; i < max_rb_num; i++) {
+       for (i = 0; i < max_rb_num_per_se * se_num; i++) {
                if (!(disabled_rbs & mask))
                        enabled_rbs |= mask;
                mask <<= 1;
        }
 
+       rdev->config.si.backend_enable_mask = enabled_rbs;
+
        for (i = 0; i < se_num; i++) {
                si_select_se_sh(rdev, i, 0xffffffff);
                data = 0;
@@ -3882,8 +3884,15 @@ static int si_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        /* size in MB on si */
-       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
-       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+       tmp = RREG32(CONFIG_MEMSIZE);
+       /* some boards may have garbage in the upper 16 bits */
+       if (tmp & 0xffff0000) {
+               DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
+               if (tmp & 0xffff)
+                       tmp &= 0xffff;
+       }
+       rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL;
+       rdev->mc.real_vram_size = rdev->mc.mc_vram_size;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        si_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
index 28e178137718090f317c8884da071458900cce65..07eba596d458d22b63bc9f0a731d6ca3befae036 100644 (file)
@@ -135,11 +135,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
        unsigned int num_relocs = args->num_relocs;
        unsigned int num_waitchks = args->num_waitchks;
        struct drm_tegra_cmdbuf __user *cmdbufs =
-               (void * __user)(uintptr_t)args->cmdbufs;
+               (void __user *)(uintptr_t)args->cmdbufs;
        struct drm_tegra_reloc __user *relocs =
-               (void * __user)(uintptr_t)args->relocs;
+               (void __user *)(uintptr_t)args->relocs;
        struct drm_tegra_waitchk __user *waitchks =
-               (void * __user)(uintptr_t)args->waitchks;
+               (void __user *)(uintptr_t)args->waitchks;
        struct drm_tegra_syncpt syncpt;
        struct host1x_job *job;
        int err;
@@ -163,9 +163,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                struct drm_tegra_cmdbuf cmdbuf;
                struct host1x_bo *bo;
 
-               err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
-               if (err)
+               if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) {
+                       err = -EFAULT;
                        goto fail;
+               }
 
                bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
                if (!bo) {
@@ -178,10 +179,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                cmdbufs++;
        }
 
-       err = copy_from_user(job->relocarray, relocs,
-                            sizeof(*relocs) * num_relocs);
-       if (err)
+       if (copy_from_user(job->relocarray, relocs,
+                          sizeof(*relocs) * num_relocs)) {
+               err = -EFAULT;
                goto fail;
+       }
 
        while (num_relocs--) {
                struct host1x_reloc *reloc = &job->relocarray[num_relocs];
@@ -199,15 +201,17 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                }
        }
 
-       err = copy_from_user(job->waitchk, waitchks,
-                            sizeof(*waitchks) * num_waitchks);
-       if (err)
+       if (copy_from_user(job->waitchk, waitchks,
+                          sizeof(*waitchks) * num_waitchks)) {
+               err = -EFAULT;
                goto fail;
+       }
 
-       err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
-                            sizeof(syncpt));
-       if (err)
+       if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts,
+                          sizeof(syncpt))) {
+               err = -EFAULT;
                goto fail;
+       }
 
        job->is_addr_reg = context->client->ops->is_addr_reg;
        job->syncpt_incrs = syncpt.incrs;
@@ -573,7 +577,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
 }
 #endif
 
-struct drm_driver tegra_drm_driver = {
+static struct drm_driver tegra_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
index fdfe259ed7f8e5e403f984d533b54a3257128aef..7da0b923131f05ca5f67fb8113f2fd9754023a15 100644 (file)
@@ -116,7 +116,7 @@ host1x_client_to_dc(struct host1x_client *client)
 
 static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
 {
-       return container_of(crtc, struct tegra_dc, base);
+       return crtc ? container_of(crtc, struct tegra_dc, base) : NULL;
 }
 
 static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
index 490f7719e317ed80319f4961a69d3e349d1ad333..a3835e7de1842b84145e52c40ef15ed21e183323 100644 (file)
@@ -247,7 +247,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
                 info->var.yoffset * fb->pitches[0];
 
        drm->mode_config.fb_base = (resource_size_t)bo->paddr;
-       info->screen_base = bo->vaddr + offset;
+       info->screen_base = (void __iomem *)bo->vaddr + offset;
        info->screen_size = size;
        info->fix.smem_start = (unsigned long)(bo->paddr + offset);
        info->fix.smem_len = size;
index ba47ca4fb880cc239a9b5c454b3b6c5b5adcddc8..3b29018913a5f2bb9da1a2ae2f57ddc89280bbe8 100644 (file)
@@ -14,6 +14,8 @@
 
 struct tegra_rgb {
        struct tegra_output output;
+       struct tegra_dc *dc;
+
        struct clk *clk_parent;
        struct clk *clk;
 };
@@ -84,18 +86,18 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
 
 static int tegra_output_rgb_enable(struct tegra_output *output)
 {
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_rgb *rgb = to_rgb(output);
 
-       tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
+       tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
        return 0;
 }
 
 static int tegra_output_rgb_disable(struct tegra_output *output)
 {
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_rgb *rgb = to_rgb(output);
 
-       tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
+       tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
        return 0;
 }
@@ -146,6 +148,7 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
 
        rgb->output.dev = dc->dev;
        rgb->output.of_node = np;
+       rgb->dc = dc;
 
        err = tegra_output_probe(&rgb->output);
        if (err < 0)
index 15b86a94949dcb875d3cd716322875ad8c763e88..4061521523154e0fbc102623b6a9d348e03d0313 100644 (file)
@@ -353,7 +353,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
         * Don't move nonexistent data. Clear destination instead.
         */
        if (old_iomap == NULL &&
-           (ttm == NULL || ttm->state == tt_unpopulated)) {
+           (ttm == NULL || (ttm->state == tt_unpopulated &&
+                            !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) {
                memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE);
                goto out2;
        }
index b249ab9b1eb29c402d407049a42c2fda83b3ffb1..6440eeac22d250844d2203018258654e54483cd3 100644 (file)
@@ -169,9 +169,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
-           drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
-       page_last = vma_pages(vma) +
-           drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
+               vma->vm_pgoff - drm_vma_node_start(&bo->vma_node);
+       page_last = vma_pages(vma) + vma->vm_pgoff -
+               drm_vma_node_start(&bo->vma_node);
 
        if (unlikely(page_offset >= bo->num_pages)) {
                retval = VM_FAULT_SIGBUS;
index 24ffbe990736e3e0751609e78d113d08c952b69f..8d67b943ac05ce2d1dd44597d00a1e5a07fd9bdb 100644 (file)
@@ -125,6 +125,12 @@ static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask)
 
 static void udl_gem_put_pages(struct udl_gem_object *obj)
 {
+       if (obj->base.import_attach) {
+               drm_free_large(obj->pages);
+               obj->pages = NULL;
+               return;
+       }
+
        drm_gem_put_pages(&obj->base, obj->pages, false, false);
        obj->pages = NULL;
 }
index 7776e6f0aef650d475e39640b3d781b42f8d7036..0489c61524826f2e2b673628783393639f0c591e 100644 (file)
@@ -150,6 +150,8 @@ struct vmw_ttm_tt {
        bool mapped;
 };
 
+const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
+
 /**
  * Helper functions to advance a struct vmw_piter iterator.
  *
index db85985c7086f04648b6a4bb89b83f352c393ec2..20890ad8408bb5ef377c4ff54c80397c3105efaf 100644 (file)
@@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
  * TTM buffer object driver - vmwgfx_buffer.c
  */
 
+extern const size_t vmw_tt_size;
 extern struct ttm_placement vmw_vram_placement;
 extern struct ttm_placement vmw_vram_ne_placement;
 extern struct ttm_placement vmw_vram_sys_placement;
index a51f48e3e917e0d3f5d4c73202be335df6f6919b..45d5b5ab6ca9d8788fe80f0fbfd9f164203c026a 100644 (file)
@@ -68,6 +68,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
                                  SVGA_FIFO_3D_HWVERSION));
                break;
        }
+       case DRM_VMW_PARAM_MAX_SURF_MEMORY:
+               param->value = dev_priv->memory_size;
+               break;
        default:
                DRM_ERROR("Illegal vmwgfx get param request: %d\n",
                          param->param);
index ecb3d867b4260d9c9ada27438fb252dac1fc77e9..03f1c203863193621d9941af3051169ea2f79afb 100644 (file)
@@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du)
                vmw_surface_unreference(&du->cursor_surface);
        if (du->cursor_dmabuf)
                vmw_dmabuf_unreference(&du->cursor_dmabuf);
+       drm_sysfs_connector_remove(&du->connector);
        drm_crtc_cleanup(&du->crtc);
        drm_encoder_cleanup(&du->encoder);
        drm_connector_cleanup(&du->connector);
index 79f7e8e605296902bb4355b78e2e78d1792f89fa..a055a26819c2b6b7963d6d245576e17b8d9a7500 100644 (file)
@@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
                connector->encoder = NULL;
                encoder->crtc = NULL;
                crtc->fb = NULL;
+               crtc->enabled = false;
 
                vmw_ldu_del_active(dev_priv, ldu);
 
@@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
        crtc->x = set->x;
        crtc->y = set->y;
        crtc->mode = *mode;
+       crtc->enabled = true;
 
        vmw_ldu_add_active(dev_priv, ldu, vfb);
 
@@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
+       (void) drm_sysfs_connector_add(connector);
+
        drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
        drm_mode_crtc_set_gamma_size(crtc, 256);
index efe2b74c5eb17f1f86b12048be5884c9aabf50b2..9b5ea2ac7ddff21562aa7ef52a2f96872c623116 100644 (file)
@@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
 /**
  * Buffer management.
  */
+
+/**
+ * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers
+ *
+ * @dev_priv: Pointer to a struct vmw_private identifying the device.
+ * @size: The requested buffer size.
+ * @user: Whether this is an ordinary dma buffer or a user dma buffer.
+ */
+static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size,
+                                 bool user)
+{
+       static size_t struct_size, user_struct_size;
+       size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+       size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *));
+
+       if (unlikely(struct_size == 0)) {
+               size_t backend_size = ttm_round_pot(vmw_tt_size);
+
+               struct_size = backend_size +
+                       ttm_round_pot(sizeof(struct vmw_dma_buffer));
+               user_struct_size = backend_size +
+                       ttm_round_pot(sizeof(struct vmw_user_dma_buffer));
+       }
+
+       if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+               page_array_size +=
+                       ttm_round_pot(num_pages * sizeof(dma_addr_t));
+
+       return ((user) ? user_struct_size : struct_size) +
+               page_array_size;
+}
+
 void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
 {
        struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
@@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
        kfree(vmw_bo);
 }
 
+static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
+{
+       struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
+
+       ttm_prime_object_kfree(vmw_user_bo, prime);
+}
+
 int vmw_dmabuf_init(struct vmw_private *dev_priv,
                    struct vmw_dma_buffer *vmw_bo,
                    size_t size, struct ttm_placement *placement,
@@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
        struct ttm_bo_device *bdev = &dev_priv->bdev;
        size_t acc_size;
        int ret;
+       bool user = (bo_free == &vmw_user_dmabuf_destroy);
 
-       BUG_ON(!bo_free);
+       BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free)));
 
-       acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer));
+       acc_size = vmw_dmabuf_acc_size(dev_priv, size, user);
        memset(vmw_bo, 0, sizeof(*vmw_bo));
 
        INIT_LIST_HEAD(&vmw_bo->res_list);
 
        ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-                         ttm_bo_type_device, placement,
+                         (user) ? ttm_bo_type_device :
+                         ttm_bo_type_kernel, placement,
                          0, interruptible,
                          NULL, acc_size, NULL, bo_free);
        return ret;
 }
 
-static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
-{
-       struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
-
-       ttm_prime_object_kfree(vmw_user_bo, prime);
-}
-
 static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
 {
        struct vmw_user_dma_buffer *vmw_user_bo;
@@ -781,54 +815,55 @@ err_ref:
 }
 
 
+/**
+ * vmw_dumb_create - Create a dumb kms buffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @args: Pointer to a struct drm_mode_create_dumb structure
+ *
+ * This is a driver callback for the core drm create_dumb functionality.
+ * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except
+ * that the arguments have a different format.
+ */
 int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
                    struct drm_mode_create_dumb *args)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct vmw_master *vmaster = vmw_master(file_priv->master);
-       struct vmw_user_dma_buffer *vmw_user_bo;
-       struct ttm_buffer_object *tmp;
+       struct vmw_dma_buffer *dma_buf;
        int ret;
 
        args->pitch = args->width * ((args->bpp + 7) / 8);
        args->size = args->pitch * args->height;
 
-       vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
-       if (vmw_user_bo == NULL)
-               return -ENOMEM;
-
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (ret != 0) {
-               kfree(vmw_user_bo);
+       if (unlikely(ret != 0))
                return ret;
-       }
 
-       ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size,
-                             &vmw_vram_sys_placement, true,
-                             &vmw_user_dmabuf_destroy);
-       if (ret != 0)
-               goto out_no_dmabuf;
-
-       tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
-       ret = ttm_prime_object_init(vmw_fpriv(file_priv)->tfile,
-                                   args->size,
-                                   &vmw_user_bo->prime,
-                                   false,
-                                   ttm_buffer_type,
-                                   &vmw_user_dmabuf_release, NULL);
+       ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
+                                   args->size, false, &args->handle,
+                                   &dma_buf);
        if (unlikely(ret != 0))
-               goto out_no_base_object;
-
-       args->handle = vmw_user_bo->prime.base.hash.key;
+               goto out_no_dmabuf;
 
-out_no_base_object:
-       ttm_bo_unref(&tmp);
+       vmw_dmabuf_unreference(&dma_buf);
 out_no_dmabuf:
        ttm_read_unlock(&vmaster->lock);
        return ret;
 }
 
+/**
+ * vmw_dumb_map_offset - Return the address space offset of a dumb buffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @handle: Handle identifying the dumb buffer.
+ * @offset: The address space offset returned.
+ *
+ * This is a driver callback for the core drm dumb_map_offset functionality.
+ */
 int vmw_dumb_map_offset(struct drm_file *file_priv,
                        struct drm_device *dev, uint32_t handle,
                        uint64_t *offset)
@@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
        return 0;
 }
 
+/**
+ * vmw_dumb_destroy - Destroy a dumb boffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @handle: Handle identifying the dumb buffer.
+ *
+ * This is a driver callback for the core drm dumb_destroy functionality.
+ */
 int vmw_dumb_destroy(struct drm_file *file_priv,
                     struct drm_device *dev,
                     uint32_t handle)
index 26387c3d5a21f01c51d844c228f26a6232b84453..22406c8651ead6caa629ce6ae2de963bdd0a35d7 100644 (file)
@@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
                crtc->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
+               crtc->enabled = false;
 
                vmw_sou_del_active(dev_priv, sou);
 
@@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
                crtc->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
+               crtc->enabled = false;
 
                return ret;
        }
@@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
        crtc->fb = fb;
        crtc->x = set->x;
        crtc->y = set->y;
+       crtc->enabled = true;
 
        return 0;
 }
@@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
+       (void) drm_sysfs_connector_add(connector);
+
        drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
 
        drm_mode_crtc_set_gamma_size(crtc, 256);
index 509383f8be034ec3512c95b1c2100818bad5d71e..6a929591aa73801df1126433bc514980e80d1465 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
+#include "bus.h"
 #include "dev.h"
 
 static DEFINE_MUTEX(clients_lock);
@@ -257,7 +258,7 @@ static int host1x_unregister_client(struct host1x *host1x,
        return -ENODEV;
 }
 
-struct bus_type host1x_bus_type = {
+static struct bus_type host1x_bus_type = {
        .name = "host1x",
 };
 
@@ -301,7 +302,7 @@ static int host1x_device_add(struct host1x *host1x,
        device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
        device->dev.dma_mask = &device->dev.coherent_dma_mask;
        device->dev.release = host1x_device_release;
-       dev_set_name(&device->dev, driver->name);
+       dev_set_name(&device->dev, "%s", driver->name);
        device->dev.bus = &host1x_bus_type;
        device->dev.parent = host1x->dev;
 
index 37e2a63241a9d6150b1554896fde15ac0294c157..6b09b71940c2d5df0251ec2b3cd417ec2eb93e2d 100644 (file)
@@ -54,8 +54,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,
                u32 *p = (u32 *)((u32)pb->mapped + getptr);
                *(p++) = HOST1X_OPCODE_NOP;
                *(p++) = HOST1X_OPCODE_NOP;
-               dev_dbg(host1x->dev, "%s: NOP at 0x%x\n", __func__,
-                       pb->phys + getptr);
+               dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__,
+                       (u64)pb->phys + getptr);
                getptr = (getptr + 8) & (pb->size_bytes - 1);
        }
        wmb();
index 640c75ca5a8bbc465dcc9f1350d4f5efdd928d5d..f72c873eff819f831202a742cf02ec70e94753f2 100644 (file)
@@ -163,8 +163,8 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
                                continue;
                        }
 
-                       host1x_debug_output(o, "    GATHER at %08x+%04x, %d words\n",
-                                           g->base, g->offset, g->words);
+                       host1x_debug_output(o, "    GATHER at %#llx+%04x, %d words\n",
+                                           (u64)g->base, g->offset, g->words);
 
                        show_gather(o, g->base + g->offset, g->words, cdma,
                                    g->base, mapped);
index ecb5ca669e97615cb47cbb9d31381bf76e33f367..e7769636759129f2540c5c670f1cc332180191fe 100644 (file)
@@ -341,6 +341,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        case USB_DEVICE_ID_GENIUS_GX_IMPERATOR:
                rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
                                        "Genius Gx Imperator Keyboard");
+               break;
        case USB_DEVICE_ID_GENIUS_MANTICORE:
                rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
                                        "Genius Manticore Keyboard");
index a184e1921c11190ffce1033e5b7d4f512d55f798..8fab82829f8b11321f957059837e8f50feb71828 100644 (file)
@@ -112,13 +112,15 @@ static int sensor_hub_get_physical_device_count(
 
 static void sensor_hub_fill_attr_info(
                struct hid_sensor_hub_attribute_info *info,
-               s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size)
+               s32 index, s32 report_id, struct hid_field *field)
 {
        info->index = index;
        info->report_id = report_id;
-       info->units = units;
-       info->unit_expo = unit_expo;
-       info->size = size/8;
+       info->units = field->unit;
+       info->unit_expo = field->unit_exponent;
+       info->size = (field->report_size * field->report_count)/8;
+       info->logical_minimum = field->logical_minimum;
+       info->logical_maximum = field->logical_maximum;
 }
 
 static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
@@ -325,9 +327,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                        if (field->physical == usage_id &&
                                field->logical == attr_usage_id) {
                                sensor_hub_fill_attr_info(info, i, report->id,
-                                       field->unit, field->unit_exponent,
-                                       field->report_size *
-                                                       field->report_count);
+                                                         field);
                                ret = 0;
                        } else {
                                for (j = 0; j < field->maxusage; ++j) {
@@ -336,11 +336,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                                        field->usage[j].collection_index ==
                                        collection_index) {
                                                sensor_hub_fill_attr_info(info,
-                                                       i, report->id,
-                                                       field->unit,
-                                                       field->unit_exponent,
-                                                       field->report_size *
-                                                       field->report_count);
+                                                         i, report->id, field);
                                                ret = 0;
                                                break;
                                        }
@@ -572,6 +568,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
                                        ret = -ENOMEM;
                                        goto err_free_names;
                        }
+                       sd->hid_sensor_hub_client_devs[
+                               sd->hid_sensor_client_cnt].id = PLATFORM_DEVID_AUTO;
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].name = name;
                        sd->hid_sensor_hub_client_devs[
index 78be66176840d1c6abdf29dd632d7a107f6ad2d3..bbb0b0d463f7e0c7cf489a3b30ff2057563d1749 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/moduleparam.h>
+#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpu_device_id.h>
@@ -52,7 +53,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
 
 #define BASE_SYSFS_ATTR_NO     2       /* Sysfs Base attr no for coretemp */
 #define NUM_REAL_CORES         32      /* Number of Real cores per cpu */
-#define CORETEMP_NAME_LENGTH   17      /* String Length of attrs */
+#define CORETEMP_NAME_LENGTH   19      /* String Length of attrs */
 #define MAX_CORE_ATTRS         4       /* Maximum no of basic attrs */
 #define TOTAL_ATTRS            (MAX_CORE_ATTRS + 1)
 #define MAX_CORE_DATA          (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
@@ -176,20 +177,33 @@ static ssize_t show_temp(struct device *dev,
        /* Check whether the time interval has elapsed */
        if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) {
                rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
-               tdata->valid = 0;
-               /* Check whether the data is valid */
-               if (eax & 0x80000000) {
-                       tdata->temp = tdata->tjmax -
-                                       ((eax >> 16) & 0x7f) * 1000;
-                       tdata->valid = 1;
-               }
+               /*
+                * Ignore the valid bit. In all observed cases the register
+                * value is either low or zero if the valid bit is 0.
+                * Return it instead of reporting an error which doesn't
+                * really help at all.
+                */
+               tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
+               tdata->valid = 1;
                tdata->last_updated = jiffies;
        }
 
        mutex_unlock(&tdata->update_lock);
-       return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
+       return sprintf(buf, "%d\n", tdata->temp);
 }
 
+struct tjmax_pci {
+       unsigned int device;
+       int tjmax;
+};
+
+static const struct tjmax_pci tjmax_pci_table[] = {
+       { 0x0708, 110000 },     /* CE41x0 (Sodaville ) */
+       { 0x0c72, 102000 },     /* Atom S1240 (Centerton) */
+       { 0x0c73, 95000 },      /* Atom S1220 (Centerton) */
+       { 0x0c75, 95000 },      /* Atom S1260 (Centerton) */
+};
+
 struct tjmax {
        char const *id;
        int tjmax;
@@ -198,9 +212,6 @@ struct tjmax {
 static const struct tjmax tjmax_table[] = {
        { "CPU  230", 100000 },         /* Model 0x1c, stepping 2       */
        { "CPU  330", 125000 },         /* Model 0x1c, stepping 2       */
-       { "CPU CE4110", 110000 },       /* Model 0x1c, stepping 10 Sodaville */
-       { "CPU CE4150", 110000 },       /* Model 0x1c, stepping 10      */
-       { "CPU CE4170", 110000 },       /* Model 0x1c, stepping 10      */
 };
 
 struct tjmax_model {
@@ -222,8 +233,11 @@ static const struct tjmax_model tjmax_model_table[] = {
                                 * is undetectable by software
                                 */
        { 0x27, ANY, 90000 },   /* Atom Medfield (Z2460) */
-       { 0x35, ANY, 90000 },   /* Atom Clover Trail/Cloverview (Z2760) */
-       { 0x36, ANY, 100000 },  /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */
+       { 0x35, ANY, 90000 },   /* Atom Clover Trail/Cloverview (Z27x0) */
+       { 0x36, ANY, 100000 },  /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx)
+                                * Also matches S12x0 (stepping 9), covered by
+                                * PCI table
+                                */
 };
 
 static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
@@ -236,8 +250,20 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
        int err;
        u32 eax, edx;
        int i;
+       struct pci_dev *host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+
+       /*
+        * Explicit tjmax table entries override heuristics.
+        * First try PCI host bridge IDs, followed by model ID strings
+        * and model/stepping information.
+        */
+       if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) {
+               for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) {
+                       if (host_bridge->device == tjmax_pci_table[i].device)
+                               return tjmax_pci_table[i].tjmax;
+               }
+       }
 
-       /* explicit tjmax table entries override heuristics */
        for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
                if (strstr(c->x86_model_id, tjmax_table[i].id))
                        return tjmax_table[i].tjmax;
@@ -343,12 +369,12 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
                if (cpu_has_tjmax(c))
                        dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
        } else {
-               val = (eax >> 16) & 0xff;
+               val = (eax >> 16) & 0x7f;
                /*
                 * If the TjMax is not plausible, an assumption
                 * will be used
                 */
-               if (val) {
+               if (val >= 85) {
                        dev_dbg(dev, "TjMax is %d degrees C\n", val);
                        return val * 1000;
                }
index 960fac3fb16648ce327eabf2d84018e42c871cb0..afd31042b452073e50c1227a5e9d3cde5086b8ff 100644 (file)
@@ -45,7 +45,7 @@ static const char * const input_names[] = {
 /* Conversion function for VDDOUT and VBAT */
 static inline int volt_reg_to_mv(int value)
 {
-       return DIV_ROUND_CLOSEST(value * 1000, 512) + 2500;
+       return DIV_ROUND_CLOSEST(value * 2000, 1023) + 2500;
 }
 
 /* Conversion function for ADC channels 4, 5 and 6 */
@@ -57,7 +57,7 @@ static inline int input_reg_to_mv(int value)
 /* Conversion function for VBBAT */
 static inline int vbbat_reg_to_mv(int value)
 {
-       return DIV_ROUND_CLOSEST(value * 2500, 512);
+       return DIV_ROUND_CLOSEST(value * 5000, 1023);
 }
 
 static inline int da9052_enable_vddout_channel(struct da9052 *da9052)
index dff841085bafc9bb170c81309c3f75c8a0d92f4b..6040121a405a2c124cf1e9ef5fbbd357f60f6075 100644 (file)
@@ -249,7 +249,7 @@ static void fam15h_power_remove(struct pci_dev *pdev)
        sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = {
+static const struct pci_device_id fam15h_power_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        {}
index 2dc37c7c6947cfa6dd5fde0e72ff5701f7162dd0..7d68a08baaa83eb42366e17c29b4ff88bda68152 100644 (file)
@@ -43,6 +43,7 @@
  * @last_update: time of last update (jiffies)
  * @temperature: cached temperature measurement value
  * @humidity: cached humidity measurement value
+ * @write_length: length for I2C measurement request
  */
 struct hih6130 {
        struct device *hwmon_dev;
@@ -51,6 +52,7 @@ struct hih6130 {
        unsigned long last_update;
        int temperature;
        int humidity;
+       size_t write_length;
 };
 
 /**
@@ -121,8 +123,15 @@ static int hih6130_update_measurements(struct i2c_client *client)
         */
        if (time_after(jiffies, hih6130->last_update + HZ) || !hih6130->valid) {
 
-               /* write to slave address, no data, to request a measurement */
-               ret = i2c_master_send(client, tmp, 0);
+               /*
+                * Write to slave address to request a measurement.
+                * According with the datasheet it should be with no data, but
+                * for systems with I2C bus drivers that do not allow zero
+                * length packets we write one dummy byte to allow sensor
+                * measurements on them.
+                */
+               tmp[0] = 0;
+               ret = i2c_master_send(client, tmp, hih6130->write_length);
                if (ret < 0)
                        goto out;
 
@@ -252,6 +261,9 @@ static int hih6130_probe(struct i2c_client *client,
                goto fail_remove_sysfs;
        }
 
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
+               hih6130->write_length = 1;
+
        return 0;
 
 fail_remove_sysfs:
index d65f3fd895ddda22d23164f1a0c94c870b77e2ce..baf375b5ab0db67dad2cefd20f1e27a73a96183d 100644 (file)
@@ -204,12 +204,13 @@ static void k10temp_remove(struct pci_dev *pdev)
                           &sensor_dev_attr_temp1_crit_hyst.dev_attr);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
+static const struct pci_device_id k10temp_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        {}
 };
index 5b50e9e4f96bb2ebf7e6630c846d591afca36248..734d55d48cc88fcf1cb3ededba02cb6cb80961ae 100644 (file)
@@ -135,7 +135,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
+static const struct pci_device_id k8temp_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { 0 },
 };
index 6cf6bff790033756a70d1d57ebe9f8f1096899f8..a2f3b4a365e4bbafa17385df4fdca298a7ece0e5 100644 (file)
@@ -94,6 +94,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm <= 0)
                return 255;
+       if (rpm > 1350000)
+               return 1;
        return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
index 4c4c1421bf28f66462d8d0bf5f2ee70947005ac0..8b8f3aa49726873b89267ebe45f4e145eab2c7bb 100644 (file)
@@ -1610,12 +1610,14 @@ static int lm90_probe(struct i2c_client *client,
                                                "lm90", client);
                if (err < 0) {
                        dev_err(dev, "cannot request IRQ %d\n", client->irq);
-                       goto exit_remove_files;
+                       goto exit_unregister;
                }
        }
 
        return 0;
 
+exit_unregister:
+       hwmon_device_unregister(data->hwmon_dev);
 exit_remove_files:
        lm90_remove_files(client, data);
 exit_restore:
index cf811c1a14756f3180e4b91243f1c10c85a800e1..8686e966fa28e20d267ddf597580ff62e4faf231 100644 (file)
@@ -3936,6 +3936,18 @@ static int nct6775_probe(struct platform_device *pdev)
        return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
+static void nct6791_enable_io_mapping(int sioaddr)
+{
+       int val;
+
+       val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
+       if (val & 0x10) {
+               pr_info("Enabling hardware monitor logical device mappings.\n");
+               superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
+                            val & ~0x10);
+       }
+}
+
 #ifdef CONFIG_PM
 static int nct6775_suspend(struct device *dev)
 {
@@ -3955,11 +3967,20 @@ static int nct6775_suspend(struct device *dev)
 static int nct6775_resume(struct device *dev)
 {
        struct nct6775_data *data = dev_get_drvdata(dev);
-       int i, j;
+       int i, j, err = 0;
 
        mutex_lock(&data->update_lock);
        data->bank = 0xff;              /* Force initial bank selection */
 
+       if (data->kind == nct6791) {
+               err = superio_enter(data->sioreg);
+               if (err)
+                       goto abort;
+
+               nct6791_enable_io_mapping(data->sioreg);
+               superio_exit(data->sioreg);
+       }
+
        /* Restore limits */
        for (i = 0; i < data->in_num; i++) {
                if (!(data->have_in & (1 << i)))
@@ -3996,11 +4017,12 @@ static int nct6775_resume(struct device *dev)
                nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
        }
 
+abort:
        /* Force re-reading all values */
        data->valid = false;
        mutex_unlock(&data->update_lock);
 
-       return 0;
+       return err;
 }
 
 static const struct dev_pm_ops nct6775_dev_pm_ops = {
@@ -4088,15 +4110,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
                pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
                superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
        }
-       if (sio_data->kind == nct6791) {
-               val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);
-               if (val & 0x10) {
-                       pr_info("Enabling hardware monitor logical device mappings.\n");
-                       superio_outb(sioaddr,
-                                    NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,
-                                    val & ~0x10);
-               }
-       }
+
+       if (sio_data->kind == nct6791)
+               nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
        pr_info("Found %s or compatible chip at %#x:%#x\n",
index 1404e6319deb3cf918c1874f1be8b09b85902d65..e74bd7e620e8140a44a3917ef701ff22223b8a62 100644 (file)
@@ -141,6 +141,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm <= 0)
                return 255;
+       if (rpm > 1350000)
+               return 1;
        return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
@@ -752,7 +754,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
        return data;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = {
+static const struct pci_device_id sis5595_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
        { 0, }
 };
index c9dcce8c3dc34fa7ec8e7eeb0c8ee6812dc159ce..babd732b4e184303d071149e98ae4651b71403e4 100644 (file)
@@ -824,7 +824,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
        return data;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = {
+static const struct pci_device_id via686a_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
        { }
 };
index 0e7017841f7dacb9b1341e4313f4acaf009349a6..b3babe3326fb2d41b68ce3712f8dd00871c33508 100644 (file)
@@ -145,7 +145,7 @@ static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
  */
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
-       if (rpm == 0)
+       if (rpm <= 0 || rpm > 1310720)
                return 0;
        return clamp_val(1310720 / (rpm * div), 1, 255);
 }
@@ -766,7 +766,7 @@ static struct platform_driver vt8231_driver = {
        .remove = vt8231_remove,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
+static const struct pci_device_id vt8231_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
        { 0, }
 };
index edb06cda5a689a4be87046b138051f5b4b42e3ca..6ed76ceb92709078497571ad4cb6f8740d3490bb 100644 (file)
@@ -481,9 +481,11 @@ store_pwm(struct device *dev, struct device_attribute *attr,
        if (err)
                return err;
        val = clamp_val(val, 0, 255);
+       val = DIV_ROUND_CLOSEST(val, 0x11);
 
        mutex_lock(&data->update_lock);
-       data->pwm[nr] = val;
+       data->pwm[nr] = val * 0x11;
+       val |= w83l786ng_read_value(client, W83L786NG_REG_PWM[nr]) & 0xf0;
        w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val);
        mutex_unlock(&data->update_lock);
        return count;
@@ -510,7 +512,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
        mutex_lock(&data->update_lock);
        reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
        data->pwm_enable[nr] = val;
-       reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
+       reg &= ~(0x03 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
        reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr];
        w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg);
        mutex_unlock(&data->update_lock);
@@ -776,9 +778,10 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
                            ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
                            ? 0 : 1;
                        data->pwm_enable[i] =
-                           ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1;
-                       data->pwm[i] = w83l786ng_read_value(client,
-                           W83L786NG_REG_PWM[i]);
+                           ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
+                       data->pwm[i] =
+                           (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
+                            & 0x0f) * 0x11;
                }
 
 
index 1d7efa3169cd772ed2ba580b0c8cfd149eee09d5..d0cfbb4cb9643498540799281399cd1b314b91e3 100644 (file)
@@ -312,7 +312,9 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
-       clk_prepare_enable(i2c_imx->clk);
+       result = clk_prepare_enable(i2c_imx->clk);
+       if (result)
+               return result;
        imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
        /* Enable I2C controller */
        imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
index 797e3117bef7437ef2d6f734431a16e43acaed34..2d0847b6be626d00ee642daab806aeb259f6eb0b 100644 (file)
@@ -139,6 +139,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
        priv->adap.algo = &priv->algo;
        priv->adap.algo_data = priv;
        priv->adap.dev.parent = &parent->dev;
+       priv->adap.retries = parent->retries;
+       priv->adap.timeout = parent->timeout;
 
        /* Sanity check on class */
        if (i2c_mux_parent_classes(parent) & class)
index b1d38590ac0196f1da49d4d67e411b3741175b9f..46eaf58d881b4e31032327e7c248979d693d9c11 100644 (file)
@@ -198,7 +198,7 @@ fail_base2:
                                continue;
                        }
                }         
-               buddha_board = ZTWO_VADDR(board);
+               buddha_board = (unsigned long)ZTWO_VADDR(board);
                
                /* write to BUDDHA_IRQ_MR to enable the board IRQ */
                /* X-Surf doesn't have this.  IRQs are always on */
index cbd4e9abc47e8f47f512915d224f916166921110..6c0e0452dd9b48c8ea0541d393c4f42e6d4efde4 100644 (file)
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[] __initdata = {
+static struct cpuidle_state nehalem_cstates[] = {
        {
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[] __initdata = {
+static struct cpuidle_state snb_cstates[] = {
        {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[] __initdata = {
+static struct cpuidle_state ivb_cstates[] = {
        {
                .name = "C1-IVB",
                .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[] __initdata = {
+static struct cpuidle_state hsw_cstates[] = {
        {
                .name = "C1-HSW",
                .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[] __initdata = {
+static struct cpuidle_state atom_cstates[] = {
        {
                .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .enter = NULL }
 };
-static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state avn_cstates[] = {
        {
                .name = "C1-AVN",
                .desc = "MWAIT 0x00",
@@ -340,10 +340,12 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
        {
                .name = "C6-AVN",
                .desc = "MWAIT 0x51",
-               .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 15,
                .target_residency = 45,
                .enter = &intel_idle },
+       {
+               .enter = NULL }
 };
 
 /**
@@ -375,13 +377,7 @@ static int intel_idle(struct cpuidle_device *dev,
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
-       if (!current_set_polling_and_test()) {
-
-               __monitor((void *)&current_thread_info()->flags, 0, 0);
-               smp_mb();
-               if (!need_resched())
-                       __mwait(eax, ecx);
-       }
+       mwait_idle_with_hints(eax, ecx);
 
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
index acb7f90359a3460371c9d1e8a00cd15c3a77a26d..749a6cadab8b3708d9a9e2d50f9d086f6f17e80e 100644 (file)
@@ -200,7 +200,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 1,
                        .scan_index = 1,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[1] = {
                        .type = IIO_VOLTAGE,
@@ -210,7 +216,13 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
                        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                        .address = 0,
                        .scan_index = 0,
-                       .scan_type = IIO_ST('u', 12, 16, 0),
+                       .scan_type = {
+                               .sign = 'u',
+                               .realbits = 12,
+                               .storagebits = 16,
+                               .shift = 0,
+                               .endianness = IIO_BE,
+                       },
                },
                .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
                .int_vref_mv = 2500,
index 1178121b55b032989257e3167c6724815458ec26..39188b72cd3b2865a763e5a0b3c4715ad3d93570 100644 (file)
@@ -25,13 +25,4 @@ config HID_SENSOR_IIO_TRIGGER
          If this driver is compiled as a module, it will be named
          hid-sensor-trigger.
 
-config HID_SENSOR_ENUM_BASE_QUIRKS
-       bool "ENUM base quirks for HID Sensor IIO drivers"
-       depends on HID_SENSOR_IIO_COMMON
-       help
-         Say yes here to build support for sensor hub FW using
-         enumeration, which is using 1 as base instead of 0.
-         Since logical minimum is still set 0 instead of 1,
-         there is no easy way to differentiate.
-
 endmenu
index bbd6426c9726d8f4e0bf36f1e138901c19ff99e8..7dcf83998e6f7fc58de8c5c3a894207abcd06bab 100644 (file)
@@ -33,24 +33,34 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 {
        struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
        int state_val;
+       int report_val;
 
        if (state) {
                if (sensor_hub_device_open(st->hsdev))
                        return -EIO;
-       } else
+               state_val =
+               HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
+               report_val =
+               HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
+
+       } else {
                sensor_hub_device_close(st->hsdev);
+               state_val =
+               HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
+               report_val =
+               HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
+       }
 
-       state_val = state ? 1 : 0;
-       if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
-               ++state_val;
        st->data_ready = state;
+       state_val += st->power_state.logical_minimum;
+       report_val += st->report_state.logical_minimum;
        sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
                                        st->power_state.index,
                                        (s32)state_val);
 
        sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
                                        st->report_state.index,
-                                       (s32)state_val);
+                                       (s32)report_val);
 
        return 0;
 }
index 3fb7757a10287b1991b4ef23676a8e4d2b315dad..368660dfe135a51c3cac05dd90d7dcb75dacb7c2 100644 (file)
@@ -651,7 +651,12 @@ static const struct iio_chan_spec adis16448_channels[] = {
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = ADIS16448_BARO_OUT,
                .scan_index = ADIS16400_SCAN_BARO,
-               .scan_type = IIO_ST('s', 16, 16, 0),
+               .scan_type = {
+                       .sign = 's',
+                       .realbits = 16,
+                       .storagebits = 16,
+                       .endianness = IIO_BE,
+               },
        },
        ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
        IIO_CHAN_SOFT_TIMESTAMP(11)
index b0d65df3ede2050d4c9944e819b45917ef945c87..a022f27c6690d56ba9c70caaa3953919b15c492e 100644 (file)
@@ -43,6 +43,7 @@ config GP2AP020A00F
        depends on I2C
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
+       select IRQ_WORK
        help
          Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip
          hooked to an I2C bus.
index 21df5713001831f91f5dbd592df94837bf612186..0922e39b0ea979a8355ac5da395d527ab871d269 100644 (file)
@@ -387,7 +387,7 @@ static int cm36651_read_int_time(struct cm36651_data *cm36651,
                return -EINVAL;
        }
 
-       return IIO_VAL_INT_PLUS_MICRO;
+       return IIO_VAL_INT;
 }
 
 static int cm36651_write_int_time(struct cm36651_data *cm36651,
index c47c2034ca71f9a95f3153fbc31756fc34b1fde0..0717940ec3b5080083cb53e8d8526bdf692c829a 100644 (file)
@@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id)
 static void rem_ref(struct iw_cm_id *cm_id)
 {
        struct iwcm_id_private *cm_id_priv;
+       int cb_destroy;
+
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-       if (iwcm_deref_id(cm_id_priv) &&
-           test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
+
+       /*
+        * Test bit before deref in case the cm_id gets freed on another
+        * thread.
+        */
+       cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
+       if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
                BUG_ON(!list_empty(&cm_id_priv->work_list));
                free_cm_id(cm_id_priv);
        }
index bdc842e9faefe4ba477b96c479975643bfdc6366..a283274a5a09fa17b0dede8f5819ef9dfaf4458b 100644 (file)
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
        do {                                                            \
-               (udata)->inbuf  = (void __user *) (ibuf);               \
+               (udata)->inbuf  = (const void __user *) (ibuf);         \
                (udata)->outbuf = (void __user *) (obuf);               \
                (udata)->inlen  = (ilen);                               \
                (udata)->outlen = (olen);                               \
        } while (0)
 
+#define INIT_UDATA_BUF_OR_NULL(udata, ibuf, obuf, ilen, olen)                  \
+       do {                                                                    \
+               (udata)->inbuf  = (ilen) ? (const void __user *) (ibuf) : NULL; \
+               (udata)->outbuf = (olen) ? (void __user *) (obuf) : NULL;       \
+               (udata)->inlen  = (ilen);                                       \
+               (udata)->outlen = (olen);                                       \
+       } while (0)
+
 /*
  * Our lifetime rules for these structs are the following:
  *
index 65f6e7dc380c382cc0335e495fb2f583a4eef7b7..f1cc83855af65dd334a21d7c82a94f252413e42a 100644 (file)
@@ -2593,6 +2593,9 @@ out_put:
 static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
                                union ib_flow_spec *ib_spec)
 {
+       if (kern_spec->reserved)
+               return -EINVAL;
+
        ib_spec->type = kern_spec->type;
 
        switch (ib_spec->type) {
@@ -2646,6 +2649,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        void *ib_spec;
        int i;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        if (ucore->outlen < sizeof(resp))
                return -ENOSPC;
 
@@ -2671,6 +2677,10 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
            (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
                return -EINVAL;
 
+       if (cmd.flow_attr.reserved[0] ||
+           cmd.flow_attr.reserved[1])
+               return -EINVAL;
+
        if (cmd.flow_attr.num_of_specs) {
                kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
                                         GFP_KERNEL);
@@ -2731,6 +2741,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
        if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
                pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
                        i, cmd.flow_attr.size);
+               err = -EINVAL;
                goto err_free;
        }
        flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
@@ -2791,10 +2802,16 @@ int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
        struct ib_uobject               *uobj;
        int                             ret;
 
+       if (ucore->inlen < sizeof(cmd))
+               return -EINVAL;
+
        ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
        if (ret)
                return ret;
 
+       if (cmd.comp_mask)
+               return -EINVAL;
+
        uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
                              file->ucontext);
        if (!uobj)
index 34386943ebcff4cf18849082add568f5fc73bc5a..08219fb3338b0652f350da1af864b4cfb355ff3c 100644 (file)
@@ -668,25 +668,30 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
                if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
                        return -EINVAL;
 
+               if (ex_hdr.cmd_hdr_reserved)
+                       return -EINVAL;
+
                if (ex_hdr.response) {
                        if (!hdr.out_words && !ex_hdr.provider_out_words)
                                return -EINVAL;
+
+                       if (!access_ok(VERIFY_WRITE,
+                                      (void __user *) (unsigned long) ex_hdr.response,
+                                      (hdr.out_words + ex_hdr.provider_out_words) * 8))
+                               return -EFAULT;
                } else {
                        if (hdr.out_words || ex_hdr.provider_out_words)
                                return -EINVAL;
                }
 
-               INIT_UDATA(&ucore,
-                          (hdr.in_words) ? buf : 0,
-                          (unsigned long)ex_hdr.response,
-                          hdr.in_words * 8,
-                          hdr.out_words * 8);
-
-               INIT_UDATA(&uhw,
-                          (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
-                          (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
-                          ex_hdr.provider_in_words * 8,
-                          ex_hdr.provider_out_words * 8);
+               INIT_UDATA_BUF_OR_NULL(&ucore, buf, (unsigned long) ex_hdr.response,
+                                      hdr.in_words * 8, hdr.out_words * 8);
+
+               INIT_UDATA_BUF_OR_NULL(&uhw,
+                                      buf + ucore.inlen,
+                                      (unsigned long) ex_hdr.response + ucore.outlen,
+                                      ex_hdr.provider_in_words * 8,
+                                      ex_hdr.provider_out_words * 8);
 
                err = uverbs_ex_cmd_table[command](file,
                                                   &ucore,
index 12fef76c791c524454bd9a0c48d5b4a967ac19af..45126879ad28a2149351232a1f9c4a2551f06c09 100644 (file)
@@ -524,50 +524,6 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
        return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
-#define VLAN_NONE 0xfff
-#define FILTER_SEL_VLAN_NONE 0xffff
-#define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */
-#define FILTER_SEL_WIDTH_VIN_P_FC \
-       (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/
-#define FILTER_SEL_WIDTH_TAG_P_FC \
-       (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */
-#define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC)
-
-static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst,
-                                 struct l2t_entry *l2t)
-{
-       unsigned int ntuple = 0;
-       u32 viid;
-
-       switch (dev->rdev.lldi.filt_mode) {
-
-       /* default filter mode */
-       case HW_TPL_FR_MT_PR_IV_P_FC:
-               if (l2t->vlan == VLAN_NONE)
-                       ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC;
-               else {
-                       ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC;
-                       ntuple |= 1 << FILTER_SEL_WIDTH_TAG_P_FC;
-               }
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       case HW_TPL_FR_MT_PR_OV_P_FC: {
-               viid = cxgb4_port_viid(l2t->neigh->dev);
-
-               ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC;
-               ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC;
-               ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC;
-               ntuple |= l2t->lport << S_PORT | IPPROTO_TCP <<
-                         FILTER_SEL_WIDTH_VLD_TAG_P_FC;
-               break;
-       }
-       default:
-               break;
-       }
-       return ntuple;
-}
-
 static int send_connect(struct c4iw_ep *ep)
 {
        struct cpl_act_open_req *req;
@@ -641,8 +597,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req->local_ip = la->sin_addr.s_addr;
                        req->peer_ip = ra->sin_addr.s_addr;
                        req->opt0 = cpu_to_be64(opt0);
-                       req->params = cpu_to_be32(select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t));
+                       req->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req->opt2 = cpu_to_be32(opt2);
                } else {
                        req6 = (struct cpl_act_open_req6 *)skb_put(skb, wrlen);
@@ -662,9 +619,9 @@ static int send_connect(struct c4iw_ep *ep)
                        req6->peer_ip_lo = *((__be64 *)
                                                (ra6->sin6_addr.s6_addr + 8));
                        req6->opt0 = cpu_to_be64(opt0);
-                       req6->params = cpu_to_be32(
-                                       select_ntuple(ep->com.dev, ep->dst,
-                                                     ep->l2t));
+                       req6->params = cpu_to_be32(cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        req6->opt2 = cpu_to_be32(opt2);
                }
        } else {
@@ -681,8 +638,9 @@ static int send_connect(struct c4iw_ep *ep)
                        t5_req->peer_ip = ra->sin_addr.s_addr;
                        t5_req->opt0 = cpu_to_be64(opt0);
                        t5_req->params = cpu_to_be64(V_FILTER_TUPLE(
-                                               select_ntuple(ep->com.dev,
-                                               ep->dst, ep->l2t)));
+                                                    cxgb4_select_ntuple(
+                                            ep->com.dev->rdev.lldi.ports[0],
+                                            ep->l2t)));
                        t5_req->opt2 = cpu_to_be32(opt2);
                } else {
                        t5_req6 = (struct cpl_t5_act_open_req6 *)
@@ -703,7 +661,9 @@ static int send_connect(struct c4iw_ep *ep)
                                                (ra6->sin6_addr.s6_addr + 8));
                        t5_req6->opt0 = cpu_to_be64(opt0);
                        t5_req6->params = (__force __be64)cpu_to_be32(
-                               select_ntuple(ep->com.dev, ep->dst, ep->l2t));
+                                                       cxgb4_select_ntuple(
+                                               ep->com.dev->rdev.lldi.ports[0],
+                                               ep->l2t));
                        t5_req6->opt2 = cpu_to_be32(opt2);
                }
        }
@@ -1630,7 +1590,8 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
        memset(req, 0, sizeof(*req));
        req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR));
        req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16)));
-       req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst,
+       req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
+                                    ep->com.dev->rdev.lldi.ports[0],
                                     ep->l2t));
        sin = (struct sockaddr_in *)&ep->com.local_addr;
        req->le.lport = sin->sin_port;
@@ -2938,7 +2899,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        /*
         * Allocate a server TID.
         */
-       if (dev->rdev.lldi.enable_fw_ofld_conn)
+       if (dev->rdev.lldi.enable_fw_ofld_conn &&
+           ep->com.local_addr.ss_family == AF_INET)
                ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids,
                                             cm_id->local_addr.ss_family, ep);
        else
@@ -3323,9 +3285,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        /*
         * Calculate the server tid from filter hit index from cpl_rx_pkt.
         */
-       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val)
-                                         - dev->rdev.lldi.tids->sftid_base
-                                         + dev->rdev.lldi.tids->nstids;
+       stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
 
        lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
        if (!lep) {
@@ -3397,7 +3357,9 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        window = (__force u16) htons((__force u16)tcph->window);
 
        /* Calcuate filter portion for LE region. */
-       filter = (__force unsigned int) cpu_to_be32(select_ntuple(dev, dst, e));
+       filter = (__force unsigned int) cpu_to_be32(cxgb4_select_ntuple(
+                                                   dev->rdev.lldi.ports[0],
+                                                   e));
 
        /*
         * Synthesize the cpl_pass_accept_req. We have everything except the
index 4cb8eb24497cfa61821b4863c4026ff5a061405a..84e45006451cd3983cd1b28bfb22d2c0a9c02ef7 100644 (file)
@@ -173,7 +173,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
        return ret;
 }
 
-int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
+static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
 {
        u32 remain = len;
        u32 dmalen;
index c29b5c8388331458bb2a2caf85580d76031f1dcb..cdc7df4fdb8aedea8c9026de82d774e5f5fe502b 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <linux/netdevice.h>
+#include <linux/if_arp.h>      /* For ARPHRD_xxx */
 #include <linux/module.h>
 #include <net/rtnetlink.h>
 #include "ipoib.h"
@@ -103,7 +104,7 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
-       if (!pdev)
+       if (!pdev || pdev->type != ARPHRD_INFINIBAND)
                return -ENODEV;
 
        ppriv = netdev_priv(pdev);
index 6be57c38638d28dd0a39464bffe391c4a093f478..9804fca6bf0605a074c13f470e4bf6cf8413bd66 100644 (file)
@@ -207,7 +207,9 @@ isert_free_rx_descriptors(struct isert_conn *isert_conn)
        isert_conn->conn_rx_descs = NULL;
 }
 
+static void isert_cq_tx_work(struct work_struct *);
 static void isert_cq_tx_callback(struct ib_cq *, void *);
+static void isert_cq_rx_work(struct work_struct *);
 static void isert_cq_rx_callback(struct ib_cq *, void *);
 
 static int
@@ -259,26 +261,36 @@ isert_create_device_ib_res(struct isert_device *device)
                cq_desc[i].device = device;
                cq_desc[i].cq_index = i;
 
+               INIT_WORK(&cq_desc[i].cq_rx_work, isert_cq_rx_work);
                device->dev_rx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_rx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_RX_CQ_LEN, i);
-               if (IS_ERR(device->dev_rx_cq[i]))
+               if (IS_ERR(device->dev_rx_cq[i])) {
+                       ret = PTR_ERR(device->dev_rx_cq[i]);
+                       device->dev_rx_cq[i] = NULL;
                        goto out_cq;
+               }
 
+               INIT_WORK(&cq_desc[i].cq_tx_work, isert_cq_tx_work);
                device->dev_tx_cq[i] = ib_create_cq(device->ib_device,
                                                isert_cq_tx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
                                                ISER_MAX_TX_CQ_LEN, i);
-               if (IS_ERR(device->dev_tx_cq[i]))
+               if (IS_ERR(device->dev_tx_cq[i])) {
+                       ret = PTR_ERR(device->dev_tx_cq[i]);
+                       device->dev_tx_cq[i] = NULL;
                        goto out_cq;
+               }
 
-               if (ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_rx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
 
-               if (ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP))
+               ret = ib_req_notify_cq(device->dev_tx_cq[i], IB_CQ_NEXT_COMP);
+               if (ret)
                        goto out_cq;
        }
 
@@ -1724,7 +1736,6 @@ isert_cq_tx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_tx_work, isert_cq_tx_work);
        queue_work(isert_comp_wq, &cq_desc->cq_tx_work);
 }
 
@@ -1768,7 +1779,6 @@ isert_cq_rx_callback(struct ib_cq *cq, void *context)
 {
        struct isert_cq_desc *cq_desc = (struct isert_cq_desc *)context;
 
-       INIT_WORK(&cq_desc->cq_rx_work, isert_cq_rx_work);
        queue_work(isert_rx_wq, &cq_desc->cq_rx_work);
 }
 
index 846ccdd905b19b66872762fd05db29ea0552a8cb..d2965e4b32243a90f40db55a7722c3229d4edb3a 100644 (file)
@@ -1871,6 +1871,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
                break;
 
        case EV_ABS:
+               input_alloc_absinfo(dev);
+               if (!dev->absinfo)
+                       return;
+
                __set_bit(code, dev->absbit);
                break;
 
index dbd2047f1641f0751340eade88c408f31201f318..3ed23513d881301fa06c1bde1ed14f56546d0147 100644 (file)
@@ -536,7 +536,8 @@ static int adp5588_probe(struct i2c_client *client,
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        if (kpad->gpimapsize)
index 67d12b3427c9ee9bcb5da69d276a6bc814467586..60dafd4fa692e1d41457c471d5a79ef0bcdf21f0 100644 (file)
@@ -992,7 +992,8 @@ static int adp5589_probe(struct i2c_client *client,
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        if (kpad->gpimapsize)
index fc88fb48d70d6740ef96f8fdbe9afc32760218c5..09b91d09308780ceebc25d9f860f88eb56b68183 100644 (file)
@@ -289,7 +289,8 @@ static int bfin_kpad_probe(struct platform_device *pdev)
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (bf54x_kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(bf54x_kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        error = input_register_device(input);
index 0735de3a6468f85cad2c08a1dc601d5a67a67a23..1cb1da2944191cdefbec3c8b910ce16ea994a758 100644 (file)
 
 /* ORIENT ADXL346 only */
 #define ADXL346_2D_VALID               (1 << 6)
-#define ADXL346_2D_ORIENT(x)           (((x) & 0x3) >> 4)
+#define ADXL346_2D_ORIENT(x)           (((x) & 0x30) >> 4)
 #define ADXL346_3D_VALID               (1 << 3)
 #define ADXL346_3D_ORIENT(x)           ((x) & 0x7)
 #define ADXL346_2D_PORTRAIT_POS                0       /* +X */
index e37392976fdd5f3f252ca5f2af2a2477fc8265b7..0deca5a3c87fe1adacdce8259a052738486749cb 100644 (file)
@@ -113,9 +113,12 @@ static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_i
        idev->keycodemax = ARRAY_SIZE(lp->btncode);
 
        for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) {
-               lp->btncode[i] = pcf8574_kp_btncode[i];
-               __set_bit(lp->btncode[i] & KEY_MAX, idev->keybit);
+               if (lp->btncode[i] <= KEY_MAX) {
+                       lp->btncode[i] = pcf8574_kp_btncode[i];
+                       __set_bit(lp->btncode[i], idev->keybit);
+               }
        }
+       __clear_bit(KEY_RESERVED, idev->keybit);
 
        sprintf(lp->name, DRV_NAME);
        sprintf(lp->phys, "kp_data/input0");
index ca7a26f1dce81c37c6cd8524f8c4698effbfd739..5cf62e315218386817972a74aafcca22dc572113 100644 (file)
@@ -70,6 +70,25 @@ static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
        { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
 };
 
+static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
+       { PSMOUSE_CMD_ENABLE,           0x00 }, /* 0 */
+       { PSMOUSE_CMD_SETRATE,          0x0a }, /* 1 */
+       { PSMOUSE_CMD_SETRATE,          0x14 }, /* 2 */
+       { PSMOUSE_CMD_SETRATE,          0x28 }, /* 3 */
+       { PSMOUSE_CMD_SETRATE,          0x3c }, /* 4 */
+       { PSMOUSE_CMD_SETRATE,          0x50 }, /* 5 */
+       { PSMOUSE_CMD_SETRATE,          0x64 }, /* 6 */
+       { PSMOUSE_CMD_SETRATE,          0xc8 }, /* 7 */
+       { PSMOUSE_CMD_GETID,            0x00 }, /* 8 */
+       { PSMOUSE_CMD_GETINFO,          0x00 }, /* 9 */
+       { PSMOUSE_CMD_SETRES,           0x00 }, /* a */
+       { PSMOUSE_CMD_SETRES,           0x01 }, /* b */
+       { PSMOUSE_CMD_SETRES,           0x02 }, /* c */
+       { PSMOUSE_CMD_SETRES,           0x03 }, /* d */
+       { PSMOUSE_CMD_SETSCALE21,       0x00 }, /* e */
+       { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
+};
+
 
 #define ALPS_DUALPOINT         0x02    /* touchpad has trackstick */
 #define ALPS_PASS              0x04    /* device has a pass-through port */
@@ -103,6 +122,7 @@ static const struct alps_model_info alps_model_data[] = {
        /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
        { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf,
                ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
+       { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT },              /* Dell XT2 */
        { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS },           /* Dell Vostro 1400 */
        { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff,
                ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },                            /* Toshiba Tecra A11-11L */
@@ -645,6 +665,76 @@ static void alps_process_packet_v3(struct psmouse *psmouse)
        alps_process_touchpad_packet_v3(psmouse);
 }
 
+static void alps_process_packet_v6(struct psmouse *psmouse)
+{
+       struct alps_data *priv = psmouse->private;
+       unsigned char *packet = psmouse->packet;
+       struct input_dev *dev = psmouse->dev;
+       struct input_dev *dev2 = priv->dev2;
+       int x, y, z, left, right, middle;
+
+       /*
+        * We can use Byte5 to distinguish if the packet is from Touchpad
+        * or Trackpoint.
+        * Touchpad:    0 - 0x7E
+        * Trackpoint:  0x7F
+        */
+       if (packet[5] == 0x7F) {
+               /* It should be a DualPoint when received Trackpoint packet */
+               if (!(priv->flags & ALPS_DUALPOINT))
+                       return;
+
+               /* Trackpoint packet */
+               x = packet[1] | ((packet[3] & 0x20) << 2);
+               y = packet[2] | ((packet[3] & 0x40) << 1);
+               z = packet[4];
+               left = packet[3] & 0x01;
+               right = packet[3] & 0x02;
+               middle = packet[3] & 0x04;
+
+               /* To prevent the cursor jump when finger lifted */
+               if (x == 0x7F && y == 0x7F && z == 0x7F)
+                       x = y = z = 0;
+
+               /* Divide 4 since trackpoint's speed is too fast */
+               input_report_rel(dev2, REL_X, (char)x / 4);
+               input_report_rel(dev2, REL_Y, -((char)y / 4));
+
+               input_report_key(dev2, BTN_LEFT, left);
+               input_report_key(dev2, BTN_RIGHT, right);
+               input_report_key(dev2, BTN_MIDDLE, middle);
+
+               input_sync(dev2);
+               return;
+       }
+
+       /* Touchpad packet */
+       x = packet[1] | ((packet[3] & 0x78) << 4);
+       y = packet[2] | ((packet[4] & 0x78) << 4);
+       z = packet[5];
+       left = packet[3] & 0x01;
+       right = packet[3] & 0x02;
+
+       if (z > 30)
+               input_report_key(dev, BTN_TOUCH, 1);
+       if (z < 25)
+               input_report_key(dev, BTN_TOUCH, 0);
+
+       if (z > 0) {
+               input_report_abs(dev, ABS_X, x);
+               input_report_abs(dev, ABS_Y, y);
+       }
+
+       input_report_abs(dev, ABS_PRESSURE, z);
+       input_report_key(dev, BTN_TOOL_FINGER, z > 0);
+
+       /* v6 touchpad does not have middle button */
+       input_report_key(dev, BTN_LEFT, left);
+       input_report_key(dev, BTN_RIGHT, right);
+
+       input_sync(dev);
+}
+
 static void alps_process_packet_v4(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
@@ -897,7 +987,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
        }
 
        /* Bytes 2 - pktsize should have 0 in the highest bit */
-       if (priv->proto_version != ALPS_PROTO_V5 &&
+       if ((priv->proto_version < ALPS_PROTO_V5) &&
            psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
            (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
                psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
@@ -1085,6 +1175,80 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
        return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
 }
 
+static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
+{
+       int i, nibble;
+
+       /*
+        * b0-b11 are valid bits, send sequence is inverse.
+        * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
+        */
+       for (i = 0; i <= 8; i += 4) {
+               nibble = (word >> i) & 0xf;
+               if (alps_command_mode_send_nibble(psmouse, nibble))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
+                                      u16 addr, u16 value)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+       /* 0x0A0 is the command to write the word */
+       if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
+           alps_monitor_mode_send_word(psmouse, 0x0A0) ||
+           alps_monitor_mode_send_word(psmouse, addr) ||
+           alps_monitor_mode_send_word(psmouse, value) ||
+           ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
+               return -1;
+
+       return 0;
+}
+
+static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+       if (enable) {
+               /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
+               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
+                       return -1;
+       } else {
+               /* EC to exit monitor mode */
+               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alps_absolute_mode_v6(struct psmouse *psmouse)
+{
+       u16 reg_val = 0x181;
+       int ret = -1;
+
+       /* enter monitor mode, to write the register */
+       if (alps_monitor_mode(psmouse, true))
+               return -1;
+
+       ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
+
+       if (alps_monitor_mode(psmouse, false))
+               ret = -1;
+
+       return ret;
+}
+
 static int alps_get_status(struct psmouse *psmouse, char *param)
 {
        /* Get status: 0xF5 0xF5 0xF5 0xE9 */
@@ -1189,6 +1353,32 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse)
        return 0;
 }
 
+static int alps_hw_init_v6(struct psmouse *psmouse)
+{
+       unsigned char param[2] = {0xC8, 0x14};
+
+       /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
+       if (alps_passthrough_mode_v2(psmouse, true))
+               return -1;
+
+       if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+           ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+               return -1;
+
+       if (alps_passthrough_mode_v2(psmouse, false))
+               return -1;
+
+       if (alps_absolute_mode_v6(psmouse)) {
+               psmouse_err(psmouse, "Failed to enable absolute mode\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 /*
  * Enable or disable passthrough mode to the trackstick.
  */
@@ -1553,6 +1743,8 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->hw_init = alps_hw_init_v1_v2;
                priv->process_packet = alps_process_packet_v1_v2;
                priv->set_abs_params = alps_set_abs_params_st;
+               priv->x_max = 1023;
+               priv->y_max = 767;
                break;
        case ALPS_PROTO_V3:
                priv->hw_init = alps_hw_init_v3;
@@ -1584,6 +1776,14 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->x_bits = 23;
                priv->y_bits = 12;
                break;
+       case ALPS_PROTO_V6:
+               priv->hw_init = alps_hw_init_v6;
+               priv->process_packet = alps_process_packet_v6;
+               priv->set_abs_params = alps_set_abs_params_st;
+               priv->nibble_commands = alps_v6_nibble_commands;
+               priv->x_max = 2047;
+               priv->y_max = 1535;
+               break;
        }
 }
 
@@ -1705,8 +1905,8 @@ static void alps_disconnect(struct psmouse *psmouse)
 static void alps_set_abs_params_st(struct alps_data *priv,
                                   struct input_dev *dev1)
 {
-       input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
-       input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
+       input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
+       input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
 }
 
 static void alps_set_abs_params_mt(struct alps_data *priv,
index eee59853b9ce0c21bc755c206430911e15789964..704f0f9243076190213b1c1876ef833348e61c99 100644 (file)
@@ -17,6 +17,7 @@
 #define ALPS_PROTO_V3  3
 #define ALPS_PROTO_V4  4
 #define ALPS_PROTO_V5  5
+#define ALPS_PROTO_V6  6
 
 /**
  * struct alps_model_info - touchpad ID table
index 8551dcaf24dbadc854a7f6a6664128598c99a067..597e9b8fc18db99c5bf1f33b3a274c632b2ba24b 100644 (file)
@@ -1313,6 +1313,7 @@ static int elantech_set_properties(struct elantech_data *etd)
                        break;
                case 6:
                case 7:
+               case 8:
                        etd->hw_version = 4;
                        break;
                default:
index 98707fb2cb5d672b6b5bcdc8b787bb37c90c9989..8f4c4ab04bc2d8c61d5fda2a65696806e61ad6f2 100644 (file)
@@ -455,16 +455,26 @@ static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(proto);
 static DEVICE_ATTR_RO(id);
 static DEVICE_ATTR_RO(extra);
-static DEVICE_ATTR_RO(modalias);
-static DEVICE_ATTR_WO(drvctl);
-static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
-static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
 
 static struct attribute *serio_device_id_attrs[] = {
        &dev_attr_type.attr,
        &dev_attr_proto.attr,
        &dev_attr_id.attr,
        &dev_attr_extra.attr,
+       NULL
+};
+
+static struct attribute_group serio_id_attr_group = {
+       .name   = "id",
+       .attrs  = serio_device_id_attrs,
+};
+
+static DEVICE_ATTR_RO(modalias);
+static DEVICE_ATTR_WO(drvctl);
+static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
+static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
+
+static struct attribute *serio_device_attrs[] = {
        &dev_attr_modalias.attr,
        &dev_attr_description.attr,
        &dev_attr_drvctl.attr,
@@ -472,13 +482,13 @@ static struct attribute *serio_device_id_attrs[] = {
        NULL
 };
 
-static struct attribute_group serio_id_attr_group = {
-       .name   = "id",
-       .attrs  = serio_device_id_attrs,
+static struct attribute_group serio_device_attr_group = {
+       .attrs  = serio_device_attrs,
 };
 
 static const struct attribute_group *serio_device_attr_groups[] = {
        &serio_id_attr_group,
+       &serio_device_attr_group,
        NULL
 };
 
index cfd1b7e8c0014306f09d021756e158ffc67ec728..f1cb05148b46826c7075e238f24e530a6a32720c 100644 (file)
@@ -251,7 +251,7 @@ static void sur40_poll(struct input_polled_dev *polldev)
        struct sur40_state *sur40 = polldev->private;
        struct input_dev *input = polldev->input;
        int result, bulk_read, need_blobs, packet_blobs, i;
-       u32 packet_id;
+       u32 uninitialized_var(packet_id);
 
        struct sur40_header *header = &sur40->bulk_in_buffer->header;
        struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0];
@@ -286,7 +286,7 @@ static void sur40_poll(struct input_polled_dev *polldev)
                if (need_blobs == -1) {
                        need_blobs = le16_to_cpu(header->count);
                        dev_dbg(sur40->dev, "need %d blobs\n", need_blobs);
-                       packet_id = header->packet_id;
+                       packet_id = le32_to_cpu(header->packet_id);
                }
 
                /*
index ae4b6b9036292c23387fafb1124247fc377c3f72..5f87bed054674b487e724d3588806235b5b5f738 100644 (file)
@@ -106,6 +106,7 @@ struct usbtouch_device_info {
 struct usbtouch_usb {
        unsigned char *data;
        dma_addr_t data_dma;
+       int data_size;
        unsigned char *buffer;
        int buf_len;
        struct urb *irq;
@@ -1521,7 +1522,7 @@ static int usbtouch_reset_resume(struct usb_interface *intf)
 static void usbtouch_free_buffers(struct usb_device *udev,
                                  struct usbtouch_usb *usbtouch)
 {
-       usb_free_coherent(udev, usbtouch->type->rept_size,
+       usb_free_coherent(udev, usbtouch->data_size,
                          usbtouch->data, usbtouch->data_dma);
        kfree(usbtouch->buffer);
 }
@@ -1566,7 +1567,20 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (!type->process_pkt)
                type->process_pkt = usbtouch_process_pkt;
 
-       usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
+       usbtouch->data_size = type->rept_size;
+       if (type->get_pkt_len) {
+               /*
+                * When dealing with variable-length packets we should
+                * not request more than wMaxPacketSize bytes at once
+                * as we do not know if there is more data coming or
+                * we filled exactly wMaxPacketSize bytes and there is
+                * nothing else.
+                */
+               usbtouch->data_size = min(usbtouch->data_size,
+                                         usb_endpoint_maxp(endpoint));
+       }
+
+       usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size,
                                            GFP_KERNEL, &usbtouch->data_dma);
        if (!usbtouch->data)
                goto out_free;
@@ -1626,12 +1640,12 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
                usb_fill_int_urb(usbtouch->irq, udev,
                         usb_rcvintpipe(udev, endpoint->bEndpointAddress),
-                        usbtouch->data, type->rept_size,
+                        usbtouch->data, usbtouch->data_size,
                         usbtouch_irq, usbtouch, endpoint->bInterval);
        else
                usb_fill_bulk_urb(usbtouch->irq, udev,
                         usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
-                        usbtouch->data, type->rept_size,
+                        usbtouch->data, usbtouch->data_size,
                         usbtouch_irq, usbtouch);
 
        usbtouch->irq->dev = udev;
index 75762d6ff3ba70934190bb2fe70ef6d6135d49c5..aa127ba392a45cbabe9f95180876543dd6441865 100644 (file)
@@ -455,7 +455,18 @@ static void zforce_complete(struct zforce_ts *ts, int cmd, int result)
        }
 }
 
-static irqreturn_t zforce_interrupt(int irq, void *dev_id)
+static irqreturn_t zforce_irq(int irq, void *dev_id)
+{
+       struct zforce_ts *ts = dev_id;
+       struct i2c_client *client = ts->client;
+
+       if (ts->suspended && device_may_wakeup(&client->dev))
+               pm_wakeup_event(&client->dev, 500);
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 {
        struct zforce_ts *ts = dev_id;
        struct i2c_client *client = ts->client;
@@ -465,12 +476,10 @@ static irqreturn_t zforce_interrupt(int irq, void *dev_id)
        u8 *payload;
 
        /*
-        * When suspended, emit a wakeup signal if necessary and return.
+        * When still suspended, return.
         * Due to the level-interrupt we will get re-triggered later.
         */
        if (ts->suspended) {
-               if (device_may_wakeup(&client->dev))
-                       pm_wakeup_event(&client->dev, 500);
                msleep(20);
                return IRQ_HANDLED;
        }
@@ -763,8 +772,8 @@ static int zforce_probe(struct i2c_client *client,
         * Therefore we can trigger the interrupt anytime it is low and do
         * not need to limit it to the interrupt edge.
         */
-       ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                       zforce_interrupt,
+       ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                       zforce_irq, zforce_irq_thread,
                                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                        input_dev->name, ts);
        if (ret) {
index 1abfb5684ab7ebcb7c735e10c71625439490ca09..e46a88700b6824c735967118281c9f7feb6e41b0 100644 (file)
@@ -392,7 +392,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             root_cfg;
        phys_addr_t                     output_mask;
 
-       spinlock_t                      lock;
+       struct mutex                    lock;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -900,7 +900,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
                goto out_free_domain;
        smmu_domain->root_cfg.pgd = pgd;
 
-       spin_lock_init(&smmu_domain->lock);
+       mutex_init(&smmu_domain->lock);
        domain->priv = smmu_domain;
        return 0;
 
@@ -1137,7 +1137,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.
         */
-       spin_lock(&smmu_domain->lock);
+       mutex_lock(&smmu_domain->lock);
        if (!smmu_domain->leaf_smmu) {
                /* Now that we have a master, we can finalise the domain */
                ret = arm_smmu_init_domain_context(domain, dev);
@@ -1152,7 +1152,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                        dev_name(device_smmu->dev));
                goto err_unlock;
        }
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
 
        /* Looks ok, so add the device to the domain */
        master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1162,7 +1162,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:
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
        return ret;
 }
 
@@ -1394,7 +1394,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        if (paddr & ~output_mask)
                return -ERANGE;
 
-       spin_lock(&smmu_domain->lock);
+       mutex_lock(&smmu_domain->lock);
        pgd += pgd_index(iova);
        end = iova + size;
        do {
@@ -1410,7 +1410,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        } while (pgd++, iova != end);
 
 out_unlock:
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
 
        /* Ensure new page tables are visible to the hardware walker */
        if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
@@ -1423,9 +1423,8 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
                        phys_addr_t paddr, size_t size, int flags)
 {
        struct arm_smmu_domain *smmu_domain = domain->priv;
-       struct arm_smmu_device *smmu = smmu_domain->leaf_smmu;
 
-       if (!smmu_domain || !smmu)
+       if (!smmu_domain)
                return -ENODEV;
 
        /* Check for silent address truncation up the SMMU chain. */
@@ -1449,44 +1448,34 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
                                         dma_addr_t iova)
 {
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
+       pgd_t *pgdp, pgd;
+       pud_t pud;
+       pmd_t pmd;
+       pte_t pte;
        struct arm_smmu_domain *smmu_domain = domain->priv;
        struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-       struct arm_smmu_device *smmu = root_cfg->smmu;
 
-       spin_lock(&smmu_domain->lock);
-       pgd = root_cfg->pgd;
-       if (!pgd)
-               goto err_unlock;
+       pgdp = root_cfg->pgd;
+       if (!pgdp)
+               return 0;
 
-       pgd += pgd_index(iova);
-       if (pgd_none_or_clear_bad(pgd))
-               goto err_unlock;
+       pgd = *(pgdp + pgd_index(iova));
+       if (pgd_none(pgd))
+               return 0;
 
-       pud = pud_offset(pgd, iova);
-       if (pud_none_or_clear_bad(pud))
-               goto err_unlock;
+       pud = *pud_offset(&pgd, iova);
+       if (pud_none(pud))
+               return 0;
 
-       pmd = pmd_offset(pud, iova);
-       if (pmd_none_or_clear_bad(pmd))
-               goto err_unlock;
+       pmd = *pmd_offset(&pud, iova);
+       if (pmd_none(pmd))
+               return 0;
 
-       pte = pmd_page_vaddr(*pmd) + pte_index(iova);
+       pte = *(pmd_page_vaddr(pmd) + pte_index(iova));
        if (pte_none(pte))
-               goto err_unlock;
-
-       spin_unlock(&smmu_domain->lock);
-       return __pfn_to_phys(pte_pfn(*pte)) | (iova & ~PAGE_MASK);
+               return 0;
 
-err_unlock:
-       spin_unlock(&smmu_domain->lock);
-       dev_warn(smmu->dev,
-                "invalid (corrupt?) page tables detected for iova 0x%llx\n",
-                (unsigned long long)iova);
-       return -EINVAL;
+       return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
 }
 
 static int arm_smmu_domain_has_cap(struct iommu_domain *domain,
@@ -1863,6 +1852,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
                dev_err(dev,
                        "found only %d context interrupt(s) but %d required\n",
                        smmu->num_context_irqs, smmu->num_context_banks);
+               err = -ENODEV;
                goto out_put_parent;
        }
 
index 9031171c141b52c5e9175fdbf6eec9bd0c4224b3..341c6016812de0e17fbd4c1601708723409351c5 100644 (file)
@@ -957,12 +957,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
        if (WARN_ON(!gic->domain))
                return;
 
+       if (gic_nr == 0) {
 #ifdef CONFIG_SMP
-       set_smp_cross_call(gic_raise_softirq);
-       register_cpu_notifier(&gic_cpu_notifier);
+               set_smp_cross_call(gic_raise_softirq);
+               register_cpu_notifier(&gic_cpu_notifier);
 #endif
-
-       set_handle_irq(gic_handle_irq);
+               set_handle_irq(gic_handle_irq);
+       }
 
        gic_chip.flags |= gic_arch_extn.flags;
        gic_dist_init(gic);
index 82cec63a90112e184c96a2e21e612df977adf7b7..3ee78f02e5d7d940d531aa6ab03c8dc681c9cb3c 100644 (file)
@@ -149,8 +149,9 @@ static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
 static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
                                         int irq, int do_mask)
 {
-       int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
-       int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+       /* The PRIO register is assumed to be 32-bit with fixed 4-bit fields. */
+       int bitfield_width = 4;
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
                                      shift, bitfield_width,
@@ -159,8 +160,9 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
 
 static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
 {
+       /* The SENSE register is assumed to be 32-bit. */
        int bitfield_width = p->config.sense_bitfield_width;
-       int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
 
index 497bd026c2378eec6e781df68d007c135be4c1f7..4a48255281887e8c03f9dbacccf404f4f9c52476 100644 (file)
@@ -1643,10 +1643,6 @@ setup_hfcpci(struct IsdnCard *card)
        int i;
        struct pci_dev *tmp_hfcpci = NULL;
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, hfcpci_revision);
        printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
 
index f6ab63aa699590278531ba9ae6ceabe75ba90813..33eeb4602c7e7131078d78d97b24f09971b8396e 100644 (file)
@@ -290,10 +290,6 @@ int setup_telespci(struct IsdnCard *card)
        struct IsdnCardState *cs = card->cs;
        char tmp[64];
 
-#ifdef __BIG_ENDIAN
-#error "not running on big endian machines now"
-#endif
-
        strcpy(tmp, telespci_revision);
        printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
        if (cs->typ != ISDN_CTYPE_TELESPCI)
index 05188351711d2d80f5ac8cd0a006159b732b2c90..a97263e902ffc6b927db6b935cb290902909f21e 100644 (file)
@@ -244,18 +244,12 @@ static int lp5521_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5521_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, addr[idx] + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -427,15 +421,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5521_load_engine(chip);
+       ret = lp5521_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5521_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 6b553d9f4266d570eec78a2180eee9b56194d62c..fd9ab5f61441c50716620138bf55b175c2ac1045 100644 (file)
@@ -337,18 +337,12 @@ static int lp5523_update_program_memory(struct lp55xx_chip *chip,
        if (i % 2)
                goto err;
 
-       mutex_lock(&chip->lock);
-
        for (i = 0; i < LP5523_PROGRAM_LENGTH; i++) {
                ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + i, pattern[i]);
-               if (ret) {
-                       mutex_unlock(&chip->lock);
+               if (ret)
                        return -EINVAL;
-               }
        }
 
-       mutex_unlock(&chip->lock);
-
        return size;
 
 err:
@@ -548,15 +542,17 @@ static ssize_t store_engine_load(struct device *dev,
 {
        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
        struct lp55xx_chip *chip = led->chip;
+       int ret;
 
        mutex_lock(&chip->lock);
 
        chip->engine_idx = nr;
        lp5523_load_engine_and_select_page(chip);
+       ret = lp5523_update_program_memory(chip, buf, len);
 
        mutex_unlock(&chip->lock);
 
-       return lp5523_update_program_memory(chip, buf, len);
+       return ret;
 }
 store_load(1)
 store_load(2)
index 2848171b8576f3475c63b0669c5a9788d11e6069..b31d8e99c41992c77610fe5ca1694211035ea592 100644 (file)
@@ -82,22 +82,12 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
                      (sizeof(struct led_pwm_data) * num_leds);
 }
 
-static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+static int led_pwm_create_of(struct platform_device *pdev,
+                            struct led_pwm_priv *priv)
 {
        struct device_node *node = pdev->dev.of_node;
        struct device_node *child;
-       struct led_pwm_priv *priv;
-       int count, ret;
-
-       /* count LEDs in this device, so we know how much to allocate */
-       count = of_get_child_count(node);
-       if (!count)
-               return NULL;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
-                           GFP_KERNEL);
-       if (!priv)
-               return NULL;
+       int ret;
 
        for_each_child_of_node(node, child) {
                struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
@@ -109,6 +99,7 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
                if (IS_ERR(led_dat->pwm)) {
                        dev_err(&pdev->dev, "unable to request PWM for %s\n",
                                led_dat->cdev.name);
+                       ret = PTR_ERR(led_dat->pwm);
                        goto err;
                }
                /* Get the period from PWM core when n*/
@@ -137,28 +128,36 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
                priv->num_leds++;
        }
 
-       return priv;
+       return 0;
 err:
        while (priv->num_leds--)
                led_classdev_unregister(&priv->leds[priv->num_leds].cdev);
 
-       return NULL;
+       return ret;
 }
 
 static int led_pwm_probe(struct platform_device *pdev)
 {
        struct led_pwm_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct led_pwm_priv *priv;
-       int i, ret = 0;
+       int count, i;
+       int ret = 0;
+
+       if (pdata)
+               count = pdata->num_leds;
+       else
+               count = of_get_child_count(pdev->dev.of_node);
+
+       if (!count)
+               return -EINVAL;
 
-       if (pdata && pdata->num_leds) {
-               priv = devm_kzalloc(&pdev->dev,
-                                   sizeof_pwm_leds_priv(pdata->num_leds),
-                                   GFP_KERNEL);
-               if (!priv)
-                       return -ENOMEM;
+       priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               for (i = 0; i < pdata->num_leds; i++) {
+       if (pdata) {
+               for (i = 0; i < count; i++) {
                        struct led_pwm *cur_led = &pdata->leds[i];
                        struct led_pwm_data *led_dat = &priv->leds[i];
 
@@ -188,11 +187,11 @@ static int led_pwm_probe(struct platform_device *pdev)
                        if (ret < 0)
                                goto err;
                }
-               priv->num_leds = pdata->num_leds;
+               priv->num_leds = count;
        } else {
-               priv = led_pwm_create_of(pdev);
-               if (!priv)
-                       return -ENODEV;
+               ret = led_pwm_create_of(pdev, priv);
+               if (ret)
+                       return ret;
        }
 
        platform_set_drvdata(pdev, priv);
index d26a312f117aefbfa41dc8bbff377c5b53db345c..3067d56b11a6b6af70ac980ec42d1e8846dd87ca 100644 (file)
@@ -32,7 +32,7 @@ config ADB_MACII
 
 config ADB_MACIISI
        bool "Include Mac IIsi ADB driver"
-       depends on ADB && MAC
+       depends on ADB && MAC && BROKEN
        help
          Say Y here if want your kernel to support Macintosh systems that use
          the Mac IIsi style ADB.  This includes the IIsi, IIvi, IIvx, Classic
index 2b46bf1d7e40ca7375517ebb97a2225475844a91..4c9852d92b0a909d5b103510ae77d55f4bb05ad0 100644 (file)
@@ -421,9 +421,11 @@ out:
 
        if (watermark <= WATERMARK_METADATA) {
                SET_GC_MARK(b, GC_MARK_METADATA);
+               SET_GC_MOVE(b, 0);
                b->prio = BTREE_PRIO;
        } else {
                SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+               SET_GC_MOVE(b, 0);
                b->prio = INITIAL_PRIO;
        }
 
index 4beb55a0ff30dc9da10c340270e9cbd1c0e1c0b0..754f4317748322e7450d69da9591b6b72aff6dc4 100644 (file)
@@ -197,7 +197,7 @@ struct bucket {
        uint8_t         disk_gen;
        uint8_t         last_gc; /* Most out of date gen in the btree */
        uint8_t         gc_gen;
-       uint16_t        gc_mark;
+       uint16_t        gc_mark; /* Bitfield used by GC. See below for field */
 };
 
 /*
@@ -209,7 +209,8 @@ 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, 14);
+BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 13);
+BITMASK(GC_MOVE, struct bucket, gc_mark, 15, 1);
 
 #include "journal.h"
 #include "stats.h"
@@ -372,14 +373,14 @@ struct cached_dev {
        unsigned char           writeback_percent;
        unsigned                writeback_delay;
 
-       int                     writeback_rate_change;
-       int64_t                 writeback_rate_derivative;
        uint64_t                writeback_rate_target;
+       int64_t                 writeback_rate_proportional;
+       int64_t                 writeback_rate_derivative;
+       int64_t                 writeback_rate_change;
 
        unsigned                writeback_rate_update_seconds;
        unsigned                writeback_rate_d_term;
        unsigned                writeback_rate_p_term_inverse;
-       unsigned                writeback_rate_d_smooth;
 };
 
 enum alloc_watermarks {
@@ -445,7 +446,6 @@ struct cache {
         * call prio_write() to keep gens from wrapping.
         */
        uint8_t                 need_save_prio;
-       unsigned                gc_move_threshold;
 
        /*
         * If nonzero, we know we aren't going to find any buckets to invalidate
index 5e2765aadce174e9b7cffd479667a2c48bcf500f..31bb53fcc67a40806cf73659a596f98297d36128 100644 (file)
@@ -1561,6 +1561,28 @@ size_t bch_btree_gc_finish(struct cache_set *c)
                SET_GC_MARK(PTR_BUCKET(c, &c->uuid_bucket, i),
                            GC_MARK_METADATA);
 
+       /* don't reclaim buckets to which writeback keys point */
+       rcu_read_lock();
+       for (i = 0; i < c->nr_uuids; i++) {
+               struct bcache_device *d = c->devices[i];
+               struct cached_dev *dc;
+               struct keybuf_key *w, *n;
+               unsigned j;
+
+               if (!d || UUID_FLASH_ONLY(&c->uuids[i]))
+                       continue;
+               dc = container_of(d, struct cached_dev, disk);
+
+               spin_lock(&dc->writeback_keys.lock);
+               rbtree_postorder_for_each_entry_safe(w, n,
+                                       &dc->writeback_keys.keys, node)
+                       for (j = 0; j < KEY_PTRS(&w->key); j++)
+                               SET_GC_MARK(PTR_BUCKET(c, &w->key, j),
+                                           GC_MARK_DIRTY);
+               spin_unlock(&dc->writeback_keys.lock);
+       }
+       rcu_read_unlock();
+
        for_each_cache(ca, c, i) {
                uint64_t *i;
 
@@ -1817,7 +1839,8 @@ static bool fix_overlapping_extents(struct btree *b, struct bkey *insert,
                        if (KEY_START(k) > KEY_START(insert) + sectors_found)
                                goto check_failed;
 
-                       if (KEY_PTRS(replace_key) != KEY_PTRS(k))
+                       if (KEY_PTRS(k) != KEY_PTRS(replace_key) ||
+                           KEY_DIRTY(k) != KEY_DIRTY(replace_key))
                                goto check_failed;
 
                        /* skip past gen */
@@ -2217,7 +2240,7 @@ struct btree_insert_op {
        struct bkey     *replace_key;
 };
 
-int btree_insert_fn(struct btree_op *b_op, struct btree *b)
+static int btree_insert_fn(struct btree_op *b_op, struct btree *b)
 {
        struct btree_insert_op *op = container_of(b_op,
                                        struct btree_insert_op, op);
index 7c1275e66025b691ec8ee4896448d46e28a2c5d9..f2f0998c4a91872407dd036a54fe72d243885fed 100644 (file)
@@ -25,10 +25,9 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
        unsigned i;
 
        for (i = 0; i < KEY_PTRS(k); i++) {
-               struct cache *ca = PTR_CACHE(c, k, i);
                struct bucket *g = PTR_BUCKET(c, k, i);
 
-               if (GC_SECTORS_USED(g) < ca->gc_move_threshold)
+               if (GC_MOVE(g))
                        return true;
        }
 
@@ -65,11 +64,16 @@ static void write_moving_finish(struct closure *cl)
 
 static void read_moving_endio(struct bio *bio, int error)
 {
+       struct bbio *b = container_of(bio, struct bbio, bio);
        struct moving_io *io = container_of(bio->bi_private,
                                            struct moving_io, cl);
 
        if (error)
                io->op.error = error;
+       else if (!KEY_DIRTY(&b->key) &&
+                ptr_stale(io->op.c, &b->key, 0)) {
+               io->op.error = -EINTR;
+       }
 
        bch_bbio_endio(io->op.c, bio, error, "reading data to move");
 }
@@ -141,6 +145,11 @@ static void read_moving(struct cache_set *c)
                if (!w)
                        break;
 
+               if (ptr_stale(c, &w->key, 0)) {
+                       bch_keybuf_del(&c->moving_gc_keys, w);
+                       continue;
+               }
+
                io = kzalloc(sizeof(struct moving_io) + sizeof(struct bio_vec)
                             * DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
                             GFP_KERNEL);
@@ -184,7 +193,8 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r)
 
 static unsigned bucket_heap_top(struct cache *ca)
 {
-       return GC_SECTORS_USED(heap_peek(&ca->heap));
+       struct bucket *b;
+       return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0;
 }
 
 void bch_moving_gc(struct cache_set *c)
@@ -226,9 +236,8 @@ void bch_moving_gc(struct cache_set *c)
                        sectors_to_move -= GC_SECTORS_USED(b);
                }
 
-               ca->gc_move_threshold = bucket_heap_top(ca);
-
-               pr_debug("threshold %u", ca->gc_move_threshold);
+               while (heap_pop(&ca->heap, b, bucket_cmp))
+                       SET_GC_MOVE(b, 1);
        }
 
        mutex_unlock(&c->bucket_lock);
index dec15cd2d797eaaa7fa0585abf8867c9f70a4cef..c57bfa071a57c58b06fabeb194cbf98f5f4fbf56 100644 (file)
@@ -1676,7 +1676,7 @@ err:
 static bool can_attach_cache(struct cache *ca, struct cache_set *c)
 {
        return ca->sb.block_size        == c->sb.block_size &&
-               ca->sb.bucket_size      == c->sb.block_size &&
+               ca->sb.bucket_size      == c->sb.bucket_size &&
                ca->sb.nr_in_set        == c->sb.nr_in_set;
 }
 
index 80d4c2bee18aa3fd1af0f58c050145af8e0a1c98..a1f85612f0b3dfc5c90b768aaef48118034c02c7 100644 (file)
@@ -83,7 +83,6 @@ rw_attribute(writeback_rate);
 rw_attribute(writeback_rate_update_seconds);
 rw_attribute(writeback_rate_d_term);
 rw_attribute(writeback_rate_p_term_inverse);
-rw_attribute(writeback_rate_d_smooth);
 read_attribute(writeback_rate_debug);
 
 read_attribute(stripe_size);
@@ -129,31 +128,41 @@ SHOW(__bch_cached_dev)
        var_printf(writeback_running,   "%i");
        var_print(writeback_delay);
        var_print(writeback_percent);
-       sysfs_print(writeback_rate,     dc->writeback_rate.rate);
+       sysfs_hprint(writeback_rate,    dc->writeback_rate.rate << 9);
 
        var_print(writeback_rate_update_seconds);
        var_print(writeback_rate_d_term);
        var_print(writeback_rate_p_term_inverse);
-       var_print(writeback_rate_d_smooth);
 
        if (attr == &sysfs_writeback_rate_debug) {
+               char rate[20];
                char dirty[20];
-               char derivative[20];
                char target[20];
-               bch_hprint(dirty,
-                          bcache_dev_sectors_dirty(&dc->disk) << 9);
-               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               char proportional[20];
+               char derivative[20];
+               char change[20];
+               s64 next_io;
+
+               bch_hprint(rate,        dc->writeback_rate.rate << 9);
+               bch_hprint(dirty,       bcache_dev_sectors_dirty(&dc->disk) << 9);
                bch_hprint(target,      dc->writeback_rate_target << 9);
+               bch_hprint(proportional,dc->writeback_rate_proportional << 9);
+               bch_hprint(derivative,  dc->writeback_rate_derivative << 9);
+               bch_hprint(change,      dc->writeback_rate_change << 9);
+
+               next_io = div64_s64(dc->writeback_rate.next - local_clock(),
+                                   NSEC_PER_MSEC);
 
                return sprintf(buf,
-                              "rate:\t\t%u\n"
-                              "change:\t\t%i\n"
+                              "rate:\t\t%s/sec\n"
                               "dirty:\t\t%s\n"
+                              "target:\t\t%s\n"
+                              "proportional:\t%s\n"
                               "derivative:\t%s\n"
-                              "target:\t\t%s\n",
-                              dc->writeback_rate.rate,
-                              dc->writeback_rate_change,
-                              dirty, derivative, target);
+                              "change:\t\t%s/sec\n"
+                              "next io:\t%llims\n",
+                              rate, dirty, target, proportional,
+                              derivative, change, next_io);
        }
 
        sysfs_hprint(dirty_data,
@@ -189,6 +198,7 @@ STORE(__cached_dev)
        struct kobj_uevent_env *env;
 
 #define d_strtoul(var)         sysfs_strtoul(var, dc->var)
+#define d_strtoul_nonzero(var) sysfs_strtoul_clamp(var, dc->var, 1, INT_MAX)
 #define d_strtoi_h(var)                sysfs_hatoi(var, dc->var)
 
        sysfs_strtoul(data_csum,        dc->disk.data_csum);
@@ -197,16 +207,15 @@ STORE(__cached_dev)
        d_strtoul(writeback_metadata);
        d_strtoul(writeback_running);
        d_strtoul(writeback_delay);
-       sysfs_strtoul_clamp(writeback_rate,
-                           dc->writeback_rate.rate, 1, 1000000);
+
        sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent, 0, 40);
 
-       d_strtoul(writeback_rate_update_seconds);
+       sysfs_strtoul_clamp(writeback_rate,
+                           dc->writeback_rate.rate, 1, INT_MAX);
+
+       d_strtoul_nonzero(writeback_rate_update_seconds);
        d_strtoul(writeback_rate_d_term);
-       d_strtoul(writeback_rate_p_term_inverse);
-       sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
-                           dc->writeback_rate_p_term_inverse, 1, INT_MAX);
-       d_strtoul(writeback_rate_d_smooth);
+       d_strtoul_nonzero(writeback_rate_p_term_inverse);
 
        d_strtoi_h(sequential_cutoff);
        d_strtoi_h(readahead);
@@ -313,7 +322,6 @@ static struct attribute *bch_cached_dev_files[] = {
        &sysfs_writeback_rate_update_seconds,
        &sysfs_writeback_rate_d_term,
        &sysfs_writeback_rate_p_term_inverse,
-       &sysfs_writeback_rate_d_smooth,
        &sysfs_writeback_rate_debug,
        &sysfs_dirty_data,
        &sysfs_stripe_size,
index 462214eeacbedbd9548e725be2e625723cda0d7e..bb37618e76648b7bc3caf99532e4f81b48666dfe 100644 (file)
@@ -209,7 +209,13 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
 {
        uint64_t now = local_clock();
 
-       d->next += div_u64(done, d->rate);
+       d->next += div_u64(done * NSEC_PER_SEC, d->rate);
+
+       if (time_before64(now + NSEC_PER_SEC, d->next))
+               d->next = now + NSEC_PER_SEC;
+
+       if (time_after64(now - NSEC_PER_SEC * 2, d->next))
+               d->next = now - NSEC_PER_SEC * 2;
 
        return time_after64(d->next, now)
                ? div_u64(d->next - now, NSEC_PER_SEC / HZ)
index 362c4b3f8b4a00e70d2e36af9ee7ec8cbe67e39e..1030c6020e986934e21c94628794e5e342271b49 100644 (file)
@@ -110,7 +110,7 @@ do {                                                                        \
        _r;                                                             \
 })
 
-#define heap_peek(h)   ((h)->size ? (h)->data[0] : NULL)
+#define heap_peek(h)   ((h)->used ? (h)->data[0] : NULL)
 
 #define heap_full(h)   ((h)->used == (h)->size)
 
index 99053b1251bea1049c627580f3614d1c18f89b60..6c44fe059c2769a4b2c317f25878596268726f0d 100644 (file)
@@ -30,38 +30,40 @@ static void __update_writeback_rate(struct cached_dev *dc)
 
        /* PD controller */
 
-       int change = 0;
-       int64_t error;
        int64_t dirty = bcache_dev_sectors_dirty(&dc->disk);
        int64_t derivative = dirty - dc->disk.sectors_dirty_last;
+       int64_t proportional = dirty - target;
+       int64_t change;
 
        dc->disk.sectors_dirty_last = dirty;
 
-       derivative *= dc->writeback_rate_d_term;
-       derivative = clamp(derivative, -dirty, dirty);
+       /* Scale to sectors per second */
 
-       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
-                             dc->writeback_rate_d_smooth, 0);
+       proportional *= dc->writeback_rate_update_seconds;
+       proportional = div_s64(proportional, dc->writeback_rate_p_term_inverse);
 
-       /* Avoid divide by zero */
-       if (!target)
-               goto out;
+       derivative = div_s64(derivative, dc->writeback_rate_update_seconds);
 
-       error = div64_s64((dirty + derivative - target) << 8, target);
+       derivative = ewma_add(dc->disk.sectors_dirty_derivative, derivative,
+                             (dc->writeback_rate_d_term /
+                              dc->writeback_rate_update_seconds) ?: 1, 0);
+
+       derivative *= dc->writeback_rate_d_term;
+       derivative = div_s64(derivative, dc->writeback_rate_p_term_inverse);
 
-       change = div_s64((dc->writeback_rate.rate * error) >> 8,
-                        dc->writeback_rate_p_term_inverse);
+       change = proportional + derivative;
 
        /* Don't increase writeback rate if the device isn't keeping up */
        if (change > 0 &&
            time_after64(local_clock(),
-                        dc->writeback_rate.next + 10 * NSEC_PER_MSEC))
+                        dc->writeback_rate.next + NSEC_PER_MSEC))
                change = 0;
 
        dc->writeback_rate.rate =
-               clamp_t(int64_t, dc->writeback_rate.rate + change,
+               clamp_t(int64_t, (int64_t) dc->writeback_rate.rate + change,
                        1, NSEC_PER_MSEC);
-out:
+
+       dc->writeback_rate_proportional = proportional;
        dc->writeback_rate_derivative = derivative;
        dc->writeback_rate_change = change;
        dc->writeback_rate_target = target;
@@ -87,15 +89,11 @@ static void update_writeback_rate(struct work_struct *work)
 
 static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
 {
-       uint64_t ret;
-
        if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
            !dc->writeback_percent)
                return 0;
 
-       ret = bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
-
-       return min_t(uint64_t, ret, HZ);
+       return bch_next_delay(&dc->writeback_rate, sectors);
 }
 
 struct dirty_io {
@@ -241,7 +239,7 @@ static void read_dirty(struct cached_dev *dc)
                if (KEY_START(&w->key) != dc->last_read ||
                    jiffies_to_msecs(delay) > 50)
                        while (!kthread_should_stop() && delay)
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
 
                dc->last_read   = KEY_OFFSET(&w->key);
 
@@ -438,7 +436,7 @@ static int bch_writeback_thread(void *arg)
                        while (delay &&
                               !kthread_should_stop() &&
                               !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
-                               delay = schedule_timeout_interruptible(delay);
+                               delay = schedule_timeout_uninterruptible(delay);
                }
        }
 
@@ -476,6 +474,8 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
 
        bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0),
                           sectors_dirty_init_fn, 0);
+
+       dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
 }
 
 int bch_cached_dev_writeback_init(struct cached_dev *dc)
@@ -490,18 +490,15 @@ int bch_cached_dev_writeback_init(struct cached_dev *dc)
        dc->writeback_delay             = 30;
        dc->writeback_rate.rate         = 1024;
 
-       dc->writeback_rate_update_seconds = 30;
-       dc->writeback_rate_d_term       = 16;
-       dc->writeback_rate_p_term_inverse = 64;
-       dc->writeback_rate_d_smooth     = 8;
+       dc->writeback_rate_update_seconds = 5;
+       dc->writeback_rate_d_term       = 30;
+       dc->writeback_rate_p_term_inverse = 6000;
 
        dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
                                              "bcache_writeback");
        if (IS_ERR(dc->writeback_thread))
                return PTR_ERR(dc->writeback_thread);
 
-       set_task_state(dc->writeback_thread, TASK_INTERRUPTIBLE);
-
        INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
        schedule_delayed_work(&dc->writeback_rate_update,
                              dc->writeback_rate_update_seconds * HZ);
index 173cbb20d10498b21440ada78b27f241b47af2cc..54bdd923316f92818d509f06986c9a9a3b7b1927 100644 (file)
@@ -1717,6 +1717,11 @@ static int __init dm_bufio_init(void)
 {
        __u64 mem;
 
+       dm_bufio_allocated_kmem_cache = 0;
+       dm_bufio_allocated_get_free_pages = 0;
+       dm_bufio_allocated_vmalloc = 0;
+       dm_bufio_current_allocated = 0;
+
        memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
        memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
 
index 416b7b752a6e0018d4a11800606a8be6b8890e22..64780ad73bb01737a957ea9682d016da4dbffa93 100644 (file)
@@ -730,15 +730,18 @@ static int pre_cache_entry_found(struct mq_policy *mq, struct entry *e,
        int r = 0;
        bool updated = updated_this_tick(mq, e);
 
-       requeue_and_update_tick(mq, e);
-
        if ((!discarded_oblock && updated) ||
-           !should_promote(mq, e, discarded_oblock, data_dir))
+           !should_promote(mq, e, discarded_oblock, data_dir)) {
+               requeue_and_update_tick(mq, e);
                result->op = POLICY_MISS;
-       else if (!can_migrate)
+
+       } else if (!can_migrate)
                r = -EWOULDBLOCK;
-       else
+
+       else {
+               requeue_and_update_tick(mq, e);
                r = pre_cache_to_cache(mq, e, result);
+       }
 
        return r;
 }
index 9efcf1059b99e3ae2e6e712eb150c0954646d5d8..1b1469ebe5cbad66af0853e0766ba20dbee63275 100644 (file)
@@ -2755,7 +2755,7 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size)
 {
        int r;
 
-       r = dm_cache_resize(cache->cmd, cache->cache_size);
+       r = dm_cache_resize(cache->cmd, new_size);
        if (r) {
                DMERR("could not resize cache metadata");
                return r;
index 496d5f3646a5df623e6c0a9b22d35ad003c610bc..2f91d6d4a2ccf40023c6bccfe142d7781024c810 100644 (file)
@@ -20,6 +20,7 @@
 struct delay_c {
        struct timer_list delay_timer;
        struct mutex timer_lock;
+       struct workqueue_struct *kdelayd_wq;
        struct work_struct flush_expired_bios;
        struct list_head delayed_bios;
        atomic_t may_delay;
@@ -45,14 +46,13 @@ struct dm_delay_info {
 
 static DEFINE_MUTEX(delayed_bios_lock);
 
-static struct workqueue_struct *kdelayd_wq;
 static struct kmem_cache *delayed_cache;
 
 static void handle_delayed_timer(unsigned long data)
 {
        struct delay_c *dc = (struct delay_c *)data;
 
-       queue_work(kdelayd_wq, &dc->flush_expired_bios);
+       queue_work(dc->kdelayd_wq, &dc->flush_expired_bios);
 }
 
 static void queue_timeout(struct delay_c *dc, unsigned long expires)
@@ -191,6 +191,12 @@ out:
                goto bad_dev_write;
        }
 
+       dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
+       if (!dc->kdelayd_wq) {
+               DMERR("Couldn't start kdelayd");
+               goto bad_queue;
+       }
+
        setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
 
        INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
@@ -203,6 +209,8 @@ out:
        ti->private = dc;
        return 0;
 
+bad_queue:
+       mempool_destroy(dc->delayed_pool);
 bad_dev_write:
        if (dc->dev_write)
                dm_put_device(ti, dc->dev_write);
@@ -217,7 +225,7 @@ static void delay_dtr(struct dm_target *ti)
 {
        struct delay_c *dc = ti->private;
 
-       flush_workqueue(kdelayd_wq);
+       destroy_workqueue(dc->kdelayd_wq);
 
        dm_put_device(ti, dc->dev_read);
 
@@ -350,12 +358,6 @@ static int __init dm_delay_init(void)
 {
        int r = -ENOMEM;
 
-       kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
-       if (!kdelayd_wq) {
-               DMERR("Couldn't start kdelayd");
-               goto bad_queue;
-       }
-
        delayed_cache = KMEM_CACHE(dm_delay_info, 0);
        if (!delayed_cache) {
                DMERR("Couldn't create delayed bio cache.");
@@ -373,8 +375,6 @@ static int __init dm_delay_init(void)
 bad_register:
        kmem_cache_destroy(delayed_cache);
 bad_memcache:
-       destroy_workqueue(kdelayd_wq);
-bad_queue:
        return r;
 }
 
@@ -382,7 +382,6 @@ static void __exit dm_delay_exit(void)
 {
        dm_unregister_target(&delay_target);
        kmem_cache_destroy(delayed_cache);
-       destroy_workqueue(kdelayd_wq);
 }
 
 /* Module hooks */
index aec57d76db5d616c8e692fa95cee58a8f62a0573..944690bafd93241d9348f0a4f1cad7f917ce7d83 100644 (file)
@@ -66,6 +66,18 @@ struct dm_snapshot {
 
        atomic_t pending_exceptions_count;
 
+       /* Protected by "lock" */
+       sector_t exception_start_sequence;
+
+       /* Protected by kcopyd single-threaded callback */
+       sector_t exception_complete_sequence;
+
+       /*
+        * A list of pending exceptions that completed out of order.
+        * Protected by kcopyd single-threaded callback.
+        */
+       struct list_head out_of_order_list;
+
        mempool_t *pending_pool;
 
        struct dm_exception_table pending;
@@ -173,6 +185,14 @@ struct dm_snap_pending_exception {
         */
        int started;
 
+       /* There was copying error. */
+       int copy_error;
+
+       /* A sequence number, it is used for in-order completion. */
+       sector_t exception_sequence;
+
+       struct list_head out_of_order_entry;
+
        /*
         * For writing a complete chunk, bypassing the copy.
         */
@@ -1094,6 +1114,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->valid = 1;
        s->active = 0;
        atomic_set(&s->pending_exceptions_count, 0);
+       s->exception_start_sequence = 0;
+       s->exception_complete_sequence = 0;
+       INIT_LIST_HEAD(&s->out_of_order_list);
        init_rwsem(&s->lock);
        INIT_LIST_HEAD(&s->list);
        spin_lock_init(&s->pe_lock);
@@ -1443,6 +1466,19 @@ static void commit_callback(void *context, int success)
        pending_complete(pe, success);
 }
 
+static void complete_exception(struct dm_snap_pending_exception *pe)
+{
+       struct dm_snapshot *s = pe->snap;
+
+       if (unlikely(pe->copy_error))
+               pending_complete(pe, 0);
+
+       else
+               /* Update the metadata if we are persistent */
+               s->store->type->commit_exception(s->store, &pe->e,
+                                                commit_callback, pe);
+}
+
 /*
  * Called when the copy I/O has finished.  kcopyd actually runs
  * this code so don't block.
@@ -1452,13 +1488,32 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
        struct dm_snap_pending_exception *pe = context;
        struct dm_snapshot *s = pe->snap;
 
-       if (read_err || write_err)
-               pending_complete(pe, 0);
+       pe->copy_error = read_err || write_err;
 
-       else
-               /* Update the metadata if we are persistent */
-               s->store->type->commit_exception(s->store, &pe->e,
-                                                commit_callback, pe);
+       if (pe->exception_sequence == s->exception_complete_sequence) {
+               s->exception_complete_sequence++;
+               complete_exception(pe);
+
+               while (!list_empty(&s->out_of_order_list)) {
+                       pe = list_entry(s->out_of_order_list.next,
+                                       struct dm_snap_pending_exception, out_of_order_entry);
+                       if (pe->exception_sequence != s->exception_complete_sequence)
+                               break;
+                       s->exception_complete_sequence++;
+                       list_del(&pe->out_of_order_entry);
+                       complete_exception(pe);
+               }
+       } else {
+               struct list_head *lh;
+               struct dm_snap_pending_exception *pe2;
+
+               list_for_each_prev(lh, &s->out_of_order_list) {
+                       pe2 = list_entry(lh, struct dm_snap_pending_exception, out_of_order_entry);
+                       if (pe2->exception_sequence < pe->exception_sequence)
+                               break;
+               }
+               list_add(&pe->out_of_order_entry, lh);
+       }
 }
 
 /*
@@ -1553,6 +1608,8 @@ __find_pending_exception(struct dm_snapshot *s,
                return NULL;
        }
 
+       pe->exception_sequence = s->exception_start_sequence++;
+
        dm_insert_exception(&s->pending, &pe->e);
 
        return pe;
@@ -2192,7 +2249,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 11, 1},
+       .version = {1, 12, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
index 3d404c1371ed2d7e6f4fa052fd4379fbc89ec388..28a90122a5a89272f5873ed0911d2de19125c15b 100644 (file)
@@ -964,6 +964,7 @@ int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
 
 int __init dm_statistics_init(void)
 {
+       shared_memory_amount = 0;
        dm_stat_need_rcu_barrier = 0;
        return 0;
 }
index 465f08ca62b1e355f8fd776fac4a6159d79a1a2e..3ba6a3859ce3c4957439ff3afdc4a5133bc2900b 100644 (file)
@@ -200,6 +200,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
 
        num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
 
+       if (!num_targets) {
+               kfree(t);
+               return -ENOMEM;
+       }
+
        if (alloc_targets(t, num_targets)) {
                kfree(t);
                return -ENOMEM;
index 60bce435f4fa1443c2994bd483e70ea096c7aa92..8a30ad54bd46aabc72f4ac1800890b5bd8041e11 100644 (file)
@@ -1697,6 +1697,14 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
        up_write(&pmd->root_lock);
 }
 
+void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd)
+{
+       down_write(&pmd->root_lock);
+       pmd->read_only = false;
+       dm_bm_set_read_write(pmd->bm);
+       up_write(&pmd->root_lock);
+}
+
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_block_t threshold,
                                        dm_sm_threshold_fn fn,
index 845ebbe589a9e0a00505bab0150df48331233928..7bcc0e1d62386768d540c41da8e0a25bf7fe9e78 100644 (file)
@@ -193,6 +193,7 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz
  * that nothing is changing.
  */
 void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
+void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd);
 
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_block_t threshold,
index 2c0cf511ec2385fa5a558b5d2e1e1ed0c874c9f6..ee29037ffc2e74633050b708718ccbe963bf20d1 100644 (file)
@@ -640,7 +640,9 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
        if (r) {
-               DMERR_LIMIT("dm_thin_insert_block() failed");
+               DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d",
+                           dm_device_name(pool->pool_md), r);
+               set_pool_mode(pool, PM_READ_ONLY);
                cell_error(pool, m->cell);
                goto out;
        }
@@ -881,32 +883,23 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
        }
 }
 
-static int commit(struct pool *pool)
-{
-       int r;
-
-       r = dm_pool_commit_metadata(pool->pmd);
-       if (r)
-               DMERR_LIMIT("%s: commit failed: error = %d",
-                           dm_device_name(pool->pool_md), r);
-
-       return r;
-}
-
 /*
  * A non-zero return indicates read_only or fail_io mode.
  * Many callers don't care about the return value.
  */
-static int commit_or_fallback(struct pool *pool)
+static int commit(struct pool *pool)
 {
        int r;
 
        if (get_pool_mode(pool) != PM_WRITE)
                return -EINVAL;
 
-       r = commit(pool);
-       if (r)
+       r = dm_pool_commit_metadata(pool->pmd);
+       if (r) {
+               DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d",
+                           dm_device_name(pool->pool_md), r);
                set_pool_mode(pool, PM_READ_ONLY);
+       }
 
        return r;
 }
@@ -943,7 +936,9 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                 * Try to commit to see if that will free up some
                 * more space.
                 */
-               (void) commit_or_fallback(pool);
+               r = commit(pool);
+               if (r)
+                       return r;
 
                r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
                if (r)
@@ -957,7 +952,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                 * table reload).
                 */
                if (!free_blocks) {
-                       DMWARN("%s: no free space available.",
+                       DMWARN("%s: no free data space available.",
                               dm_device_name(pool->pool_md));
                        spin_lock_irqsave(&pool->lock, flags);
                        pool->no_free_space = 1;
@@ -967,8 +962,16 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
        }
 
        r = dm_pool_alloc_data_block(pool->pmd, result);
-       if (r)
+       if (r) {
+               if (r == -ENOSPC &&
+                   !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
+                   !free_blocks) {
+                       DMWARN("%s: no free metadata space available.",
+                              dm_device_name(pool->pool_md));
+                       set_pool_mode(pool, PM_READ_ONLY);
+               }
                return r;
+       }
 
        return 0;
 }
@@ -1349,7 +1352,7 @@ static void process_deferred_bios(struct pool *pool)
        if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
                return;
 
-       if (commit_or_fallback(pool)) {
+       if (commit(pool)) {
                while ((bio = bio_list_pop(&bios)))
                        bio_io_error(bio);
                return;
@@ -1397,6 +1400,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
        case PM_FAIL:
                DMERR("%s: switching pool to failure mode",
                      dm_device_name(pool->pool_md));
+               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;
@@ -1421,6 +1425,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
                break;
 
        case PM_WRITE:
+               dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
                pool->process_discard = process_discard;
                pool->process_prepared_mapping = process_prepared_mapping;
@@ -1637,12 +1642,19 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
        struct pool_c *pt = ti->private;
 
        /*
-        * We want to make sure that degraded pools are never upgraded.
+        * 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 new_mode = pt->adjusted_pf.mode;
 
-       if (old_mode > new_mode)
+       /*
+        * 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;
 
        pool->ti = ti;
@@ -2266,7 +2278,7 @@ static int pool_preresume(struct dm_target *ti)
                return r;
 
        if (need_commit1 || need_commit2)
-               (void) commit_or_fallback(pool);
+               (void) commit(pool);
 
        return 0;
 }
@@ -2293,7 +2305,7 @@ static void pool_postsuspend(struct dm_target *ti)
 
        cancel_delayed_work(&pool->waker);
        flush_workqueue(pool->wq);
-       (void) commit_or_fallback(pool);
+       (void) commit(pool);
 }
 
 static int check_arg_count(unsigned argc, unsigned args_required)
@@ -2427,7 +2439,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct
        if (r)
                return r;
 
-       (void) commit_or_fallback(pool);
+       (void) commit(pool);
 
        r = dm_pool_reserve_metadata_snap(pool->pmd);
        if (r)
@@ -2489,7 +2501,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
                DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
 
        if (!r)
-               (void) commit_or_fallback(pool);
+               (void) commit(pool);
 
        return r;
 }
@@ -2544,7 +2556,7 @@ static void pool_status(struct dm_target *ti, status_type_t type,
 
                /* Commit to ensure statistics aren't out-of-date */
                if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-                       (void) commit_or_fallback(pool);
+                       (void) commit(pool);
 
                r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id);
                if (r) {
index e60cebf3f519841d81726f1aee6ef97df6e8da6b..369d919bdafef4a6418ff1ff6c328fe2c74933ae 100644 (file)
@@ -776,16 +776,10 @@ void md_super_wait(struct mddev *mddev)
        finish_wait(&mddev->sb_wait, &wq);
 }
 
-static void bi_complete(struct bio *bio, int error)
-{
-       complete((struct completion*)bio->bi_private);
-}
-
 int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
                 struct page *page, int rw, bool metadata_op)
 {
        struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
-       struct completion event;
        int ret;
 
        rw |= REQ_SYNC;
@@ -801,11 +795,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
        else
                bio->bi_sector = sector + rdev->data_offset;
        bio_add_page(bio, page, size, 0);
-       init_completion(&event);
-       bio->bi_private = &event;
-       bio->bi_end_io = bi_complete;
-       submit_bio(rw, bio);
-       wait_for_completion(&event);
+       submit_bio_wait(rw, bio);
 
        ret = test_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_put(bio);
@@ -1087,6 +1077,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
        rdev->raid_disk = -1;
        clear_bit(Faulty, &rdev->flags);
        clear_bit(In_sync, &rdev->flags);
+       clear_bit(Bitmap_sync, &rdev->flags);
        clear_bit(WriteMostly, &rdev->flags);
 
        if (mddev->raid_disks == 0) {
@@ -1165,6 +1156,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
                 */
                if (ev1 < mddev->bitmap->events_cleared)
                        return 0;
+               if (ev1 < mddev->events)
+                       set_bit(Bitmap_sync, &rdev->flags);
        } else {
                if (ev1 < mddev->events)
                        /* just a hot-add of a new device, leave raid_disk at -1 */
@@ -1573,6 +1566,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
        rdev->raid_disk = -1;
        clear_bit(Faulty, &rdev->flags);
        clear_bit(In_sync, &rdev->flags);
+       clear_bit(Bitmap_sync, &rdev->flags);
        clear_bit(WriteMostly, &rdev->flags);
 
        if (mddev->raid_disks == 0) {
@@ -1655,6 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
                 */
                if (ev1 < mddev->bitmap->events_cleared)
                        return 0;
+               if (ev1 < mddev->events)
+                       set_bit(Bitmap_sync, &rdev->flags);
        } else {
                if (ev1 < mddev->events)
                        /* just a hot-add of a new device, leave raid_disk at -1 */
@@ -2798,6 +2794,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
                else
                        rdev->saved_raid_disk = -1;
                clear_bit(In_sync, &rdev->flags);
+               clear_bit(Bitmap_sync, &rdev->flags);
                err = rdev->mddev->pers->
                        hot_add_disk(rdev->mddev, rdev);
                if (err) {
@@ -5770,6 +5767,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
                            info->raid_disk < mddev->raid_disks) {
                                rdev->raid_disk = info->raid_disk;
                                set_bit(In_sync, &rdev->flags);
+                               clear_bit(Bitmap_sync, &rdev->flags);
                        } else
                                rdev->raid_disk = -1;
                } else
@@ -7716,7 +7714,8 @@ static int remove_and_add_spares(struct mddev *mddev,
                if (test_bit(Faulty, &rdev->flags))
                        continue;
                if (mddev->ro &&
-                   rdev->saved_raid_disk < 0)
+                   ! (rdev->saved_raid_disk >= 0 &&
+                      !test_bit(Bitmap_sync, &rdev->flags)))
                        continue;
 
                rdev->recovery_offset = 0;
@@ -7797,9 +7796,12 @@ void md_check_recovery(struct mddev *mddev)
                         * As we only add devices that are already in-sync,
                         * we can activate the spares immediately.
                         */
-                       clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        remove_and_add_spares(mddev, NULL);
-                       mddev->pers->spare_active(mddev);
+                       /* There is no thread, but we need to call
+                        * ->spare_active and clear saved_raid_disk
+                        */
+                       md_reap_sync_thread(mddev);
+                       clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        goto unlock;
                }
 
index 2f5cc8a7ef3ed8e80d957ca48b5de5e775ce1ee7..0095ec84ffc7bec45547f87696770f0685fe62a9 100644 (file)
@@ -129,6 +129,9 @@ struct md_rdev {
 enum flag_bits {
        Faulty,                 /* device is known to have a fault */
        In_sync,                /* device is in_sync with rest of array */
+       Bitmap_sync,            /* ..actually, not quite In_sync.  Need a
+                                * bitmap-based recovery to get fully in sync
+                                */
        Unmerged,               /* device is being added to array and should
                                 * be considerred for bvec_merge_fn but not
                                 * yet for actual IO
index af96e24ec3280ff9c29a7b7f13fde6fc4ba43e52..1d75b1dc1e2e2fcdd24a3be8cf9f0168efacd51e 100644 (file)
@@ -317,8 +317,16 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root,
         * The shadow op will often be a noop.  Only insert if it really
         * copied data.
         */
-       if (dm_block_location(*block) != b)
+       if (dm_block_location(*block) != b) {
+               /*
+                * dm_tm_shadow_block will have already decremented the old
+                * block, but it is still referenced by the btree.  We
+                * increment to stop the insert decrementing it below zero
+                * when overwriting the old value.
+                */
+               dm_tm_inc(info->btree_info.tm, b);
                r = insert_ablock(info, index, *block, root);
+       }
 
        return r;
 }
index a7e8bf2963886dfa349a03644cf33ff1ded748c5..064a3c271baa8843657dca3c374ed89061565ad4 100644 (file)
@@ -626,6 +626,12 @@ void dm_bm_set_read_only(struct dm_block_manager *bm)
 }
 EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
 
+void dm_bm_set_read_write(struct dm_block_manager *bm)
+{
+       bm->read_only = false;
+}
+EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
+
 u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
 {
        return crc32c(~(u32) 0, data, len) ^ init_xor;
index 9a82083a66b6a86833bccc1d2b6d4d43c9de6500..13cd58e1fe69ffb4ed477b10ee6bbbe6d58d9926 100644 (file)
@@ -108,9 +108,9 @@ int dm_bm_unlock(struct dm_block *b);
 int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
                           struct dm_block *superblock);
 
- /*
 * Request data be prefetched into the cache.
 */
+/*
* Request data is prefetched into the cache.
+ */
 void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
 
 /*
@@ -125,6 +125,7 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
  * be returned if you do.
  */
 void dm_bm_set_read_only(struct dm_block_manager *bm);
+void dm_bm_set_read_write(struct dm_block_manager *bm);
 
 u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
 
index 6058569fe86c3dcf862ddc933e234e721dbdc3e6..466a60bbd716f6470d1e4004ac217c3f546f5c81 100644 (file)
@@ -381,7 +381,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
 }
 
 static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
-                       uint32_t (*mutator)(void *context, uint32_t old),
+                       int (*mutator)(void *context, uint32_t old, uint32_t *new),
                        void *context, enum allocation_event *ev)
 {
        int r;
@@ -410,11 +410,17 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
 
        if (old > 2) {
                r = sm_ll_lookup_big_ref_count(ll, b, &old);
-               if (r < 0)
+               if (r < 0) {
+                       dm_tm_unlock(ll->tm, nb);
                        return r;
+               }
        }
 
-       ref_count = mutator(context, old);
+       r = mutator(context, old, &ref_count);
+       if (r) {
+               dm_tm_unlock(ll->tm, nb);
+               return r;
+       }
 
        if (ref_count <= 2) {
                sm_set_bitmap(bm_le, bit, ref_count);
@@ -465,9 +471,10 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
        return ll->save_ie(ll, index, &ie_disk);
 }
 
-static uint32_t set_ref_count(void *context, uint32_t old)
+static int set_ref_count(void *context, uint32_t old, uint32_t *new)
 {
-       return *((uint32_t *) context);
+       *new = *((uint32_t *) context);
+       return 0;
 }
 
 int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
@@ -476,9 +483,10 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
        return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
 }
 
-static uint32_t inc_ref_count(void *context, uint32_t old)
+static int inc_ref_count(void *context, uint32_t old, uint32_t *new)
 {
-       return old + 1;
+       *new = old + 1;
+       return 0;
 }
 
 int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
@@ -486,9 +494,15 @@ int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
        return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
 }
 
-static uint32_t dec_ref_count(void *context, uint32_t old)
+static int dec_ref_count(void *context, uint32_t old, uint32_t *new)
 {
-       return old - 1;
+       if (!old) {
+               DMERR_LIMIT("unable to decrement a reference count below 0");
+               return -EINVAL;
+       }
+
+       *new = old - 1;
+       return 0;
 }
 
 int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
index 1c959684caef7512fafd3c1a5505c29c798a9c11..58fc1eef7499e1923ef00095502c1e1b49f50ffb 100644 (file)
@@ -384,12 +384,16 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
        int r = sm_metadata_new_block_(sm, b);
-       if (r)
+       if (r) {
                DMERR("unable to allocate new metadata block");
+               return r;
+       }
 
        r = sm_metadata_get_nr_free(sm, &count);
-       if (r)
+       if (r) {
                DMERR("couldn't get free block count");
+               return r;
+       }
 
        check_threshold(&smm->threshold, count);
 
index 1e5a540995e932852df5ff484a96bfcc8636a432..a49cfcc7a343188a5579350886795ce6fef35c4f 100644 (file)
@@ -924,9 +924,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
                                conf->next_window_requests++;
                        else
                                conf->current_window_requests++;
-               }
-               if (bio->bi_sector >= conf->start_next_window)
                        sector = conf->start_next_window;
+               }
        }
 
        conf->nr_pending++;
index c504e8389e69e3ab9ad717b9f83d0c19c2008d68..06eeb99ea6fc55cf3f8a51e470a430903769110b 100644 (file)
@@ -1319,7 +1319,7 @@ read_again:
                        /* Could not read all from this device, so we will
                         * need another r10_bio.
                         */
-                       sectors_handled = (r10_bio->sectors + max_sectors
+                       sectors_handled = (r10_bio->sector + max_sectors
                                           - bio->bi_sector);
                        r10_bio->sectors = max_sectors;
                        spin_lock_irq(&conf->device_lock);
@@ -1327,7 +1327,7 @@ read_again:
                                bio->bi_phys_segments = 2;
                        else
                                bio->bi_phys_segments++;
-                       spin_unlock(&conf->device_lock);
+                       spin_unlock_irq(&conf->device_lock);
                        /* Cannot call generic_make_request directly
                         * as that will be queued in __generic_make_request
                         * and subsequent mempool_alloc might block
@@ -3218,10 +3218,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                        if (j == conf->copies) {
                                /* Cannot recover, so abort the recovery or
                                 * record a bad block */
-                               put_buf(r10_bio);
-                               if (rb2)
-                                       atomic_dec(&rb2->remaining);
-                               r10_bio = rb2;
                                if (any_working) {
                                        /* problem is that there are bad blocks
                                         * on other device(s)
@@ -3253,6 +3249,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                                        mirror->recovery_disabled
                                                = mddev->recovery_disabled;
                                }
+                               put_buf(r10_bio);
+                               if (rb2)
+                                       atomic_dec(&rb2->remaining);
+                               r10_bio = rb2;
                                break;
                        }
                }
index cc055da02e2a300706548041dc4d9cf63957978c..cbb15716a5db31cf39a08b6a8a9df45d0bc9e0dc 100644 (file)
@@ -687,7 +687,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
                        } else {
                                if (!test_bit(STRIPE_HANDLE, &sh->state))
                                        atomic_inc(&conf->active_stripes);
-                               BUG_ON(list_empty(&sh->lru));
+                               BUG_ON(list_empty(&sh->lru) &&
+                                      !test_bit(STRIPE_EXPANDING, &sh->state));
                                list_del_init(&sh->lru);
                                if (sh->group) {
                                        sh->group->stripes_cnt--;
@@ -3608,7 +3609,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
                         */
                        set_bit(R5_Insync, &dev->flags);
 
-               if (rdev && test_bit(R5_WriteError, &dev->flags)) {
+               if (test_bit(R5_WriteError, &dev->flags)) {
                        /* This flag does not apply to '.replacement'
                         * only to .rdev, so make sure to check that*/
                        struct md_rdev *rdev2 = rcu_dereference(
@@ -3621,7 +3622,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
                        } else
                                clear_bit(R5_WriteError, &dev->flags);
                }
-               if (rdev && test_bit(R5_MadeGood, &dev->flags)) {
+               if (test_bit(R5_MadeGood, &dev->flags)) {
                        /* This flag does not apply to '.replacement'
                         * only to .rdev, so make sure to check that*/
                        struct md_rdev *rdev2 = rcu_dereference(
index d0799e32336450d967114938fc610b66d4134070..9c9063cd3208909d5840a7c2cc745d1bf124f542 100644 (file)
@@ -955,7 +955,7 @@ struct sms_rx_stats {
        u32 modem_state;                /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
        s32 SNR;                /* dB */
        u32 ber;                /* Post Viterbi ber [1E-5] */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
        u32 ber_bit_count;      /* Total number of SYNC bits. */
        u32 ts_per;             /* Transport stream PER,
        0xFFFFFFFF indicate N/A */
@@ -981,7 +981,7 @@ struct sms_rx_stats_ex {
        u32 modem_state;                /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
        s32 SNR;                /* dB */
        u32 ber;                /* Post Viterbi ber [1E-5] */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
        u32 ber_bit_count;      /* Total number of SYNC bits. */
        u32 ts_per;             /* Transport stream PER,
        0xFFFFFFFF indicate N/A */
index 92c413ba0c7971386f052e2f4c4c00876062a31d..ae36d0ae0fb1991ae0ee2e16e392796ca12d271f 100644 (file)
@@ -95,7 +95,7 @@ struct RECEPTION_STATISTICS_PER_SLICES_S {
        u32 is_demod_locked;    /* 0 - not locked, 1 - locked */
 
        u32 ber_bit_count;      /* Total number of SYNC bits. */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
 
        s32 MRC_SNR;            /* dB */
        s32 mrc_in_band_pwr;    /* In band power in dBM */
index 58de4410c5258a7d6009ae47b5becd7e20fa6208..6c7ff0cdcd32ddd44cae9dcf85e98054a7601052 100644 (file)
@@ -435,7 +435,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                dprintk_tscheck("TEI detected. "
                                "PID=0x%x data1=0x%x\n",
                                pid, buf[1]);
-               /* data in this packet cant be trusted - drop it unless
+               /* data in this packet can't be trusted - drop it unless
                 * module option dvb_demux_feed_err_pkts is set */
                if (!dvb_demux_feed_err_pkts)
                        return;
@@ -1032,8 +1032,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
                return -EINVAL;
        }
 
-       if (feed->is_filtering)
+       if (feed->is_filtering) {
+               /* release dvbdmx->mutex as far as it is
+                  acquired by stop_filtering() itself */
+               mutex_unlock(&dvbdmx->mutex);
                feed->stop_filtering(feed);
+               mutex_lock(&dvbdmx->mutex);
+       }
 
        spin_lock_irq(&dvbdmx->lock);
        f = dvbdmxfeed->filter;
index 30ee59052157815edd50669afe2293ed4e2e8867..65728c25ea05adcd50bd658c96a6c54dd6fb569b 100644 (file)
@@ -170,18 +170,18 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
 static int af9033_wr_reg_val_tab(struct af9033_state *state,
                const struct reg_val *tab, int tab_len)
 {
+#define MAX_TAB_LEN 212
        int ret, i, j;
-       u8 buf[MAX_XFER_SIZE];
+       u8 buf[1 + MAX_TAB_LEN];
+
+       dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
 
        if (tab_len > sizeof(buf)) {
-               dev_warn(&state->i2c->dev,
-                        "%s: i2c wr len=%d is too big!\n",
-                        KBUILD_MODNAME, tab_len);
+               dev_warn(&state->i2c->dev, "%s: tab len %d is too big\n",
+                               KBUILD_MODNAME, tab_len);
                return -EINVAL;
        }
 
-       dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
-
        for (i = 0, j = 0; i < tab_len; i++) {
                buf[j] = tab[i].val;
 
index 125a44041011ca0ed17f99999a2bffaa5c1999a1..5c6ab4921bf11d2004ed77e9240b2452fbbb3974 100644 (file)
@@ -78,7 +78,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x4000;
-       if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+       if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000);
        buf[0] = (if_ctl >> 8) & 0x3f;
        buf[1] = (if_ctl >> 0) & 0xff;
 
index 90536147bf0458c444a59e176b79ddff09471f4f..6dbbee453ee15adb0c4d6b97196beefe6e7d9523 100644 (file)
@@ -3048,7 +3048,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
                        dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
 
                        locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
-                       /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */
+                       /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
                        *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
                        *tune_state = CT_DEMOD_STEP_5;
                        break;
@@ -3115,7 +3115,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
 
        case CT_DEMOD_STEP_9: /* 39 */
                        if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
-                               /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */
+                               /* defines timeout for mpeg lock depending on interleaver length of longest layer */
                                for (i = 0; i < 3; i++) {
                                        if (c->layer[i].interleaving >= deeper_interleaver) {
                                                dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
index d416c15691dadd69b49eda6f26c70892c3a02652..bf29a3f0e6f0ca440990f7b8b61e71e9bd02674a 100644 (file)
@@ -1191,7 +1191,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
                        goto error;
 
                if (state->m_enable_parallel == true) {
-                       /* paralel -> enable MD1 to MD7 */
+                       /* parallel -> enable MD1 to MD7 */
                        status = write16(state, SIO_PDR_MD1_CFG__A,
                                         sio_pdr_mdx_cfg);
                        if (status < 0)
@@ -1428,7 +1428,7 @@ static int mpegts_stop(struct drxk_state *state)
 
        dprintk(1, "\n");
 
-       /* Gracefull shutdown (byte boundaries) */
+       /* Graceful shutdown (byte boundaries) */
        status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
        if (status < 0)
                goto error;
@@ -2021,7 +2021,7 @@ static int mpegts_dto_setup(struct drxk_state *state,
                fec_oc_dto_burst_len = 204;
        }
 
-       /* Check serial or parrallel output */
+       /* Check serial or parallel output */
        fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
        if (state->m_enable_parallel == false) {
                /* MPEG data output is serial -> set ipr_mode[0] */
@@ -2908,7 +2908,7 @@ static int adc_synchronization(struct drxk_state *state)
                goto error;
 
        if (count == 1) {
-               /* Try sampling on a diffrent edge */
+               /* Try sampling on a different edge */
                u16 clk_neg = 0;
 
                status = read16(state, IQM_AF_CLKNEG__A, &clk_neg);
@@ -3306,7 +3306,7 @@ static int dvbt_sc_command(struct drxk_state *state,
        if (status < 0)
                goto error;
 
-       /* Retreive results parameters from SC */
+       /* Retrieve results parameters from SC */
        switch (cmd) {
                /* All commands yielding 5 results */
                /* All commands yielding 4 results */
@@ -3849,7 +3849,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
                break;
        }
 #if 0
-       /* No hierachical channels support in BDA */
+       /* No hierarchical channels support in BDA */
        /* Priority (only for hierarchical channels) */
        switch (channel->priority) {
        case DRX_PRIORITY_LOW:
@@ -4081,7 +4081,7 @@ error:
 /*============================================================================*/
 
 /**
-* \brief Retreive lock status .
+* \brief Retrieve lock status .
 * \param demod    Pointer to demodulator instance.
 * \param lockStat Pointer to lock status structure.
 * \return DRXStatus_t.
@@ -6174,7 +6174,7 @@ static int init_drxk(struct drxk_state *state)
                        goto error;
 
                /* Stamp driver version number in SCU data RAM in BCD code
-                       Done to enable field application engineers to retreive drxdriver version
+                       Done to enable field application engineers to retrieve drxdriver version
                        via I2C from SCU RAM.
                        Not using SCU command interface for SCU register access since no
                        microcode may be present.
@@ -6399,7 +6399,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
        fe->ops.tuner_ops.get_if_frequency(fe, &IF);
        start(state, 0, IF);
 
-       /* After set_frontend, stats aren't avaliable */
+       /* After set_frontend, stats aren't available */
        p->strength.stat[0].scale = FE_SCALE_RELATIVE;
        p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
        p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
index 7efb796c472c475bed62f1a0bb783f5b991a5b1e..50e8b63e5169bad938b1fc8b79e0871a619364d3 100644 (file)
@@ -710,6 +710,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
                sizeof(priv->tuner_i2c_adapter.name));
        priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
        priv->tuner_i2c_adapter.algo_data = NULL;
+       priv->tuner_i2c_adapter.dev.parent = &i2c->dev;
        i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
        if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
                dev_err(&i2c->dev,
index 4a5b7d211d2f14e3810111a7f6399405e5000935..b253d400e8176a8baa3d1ba6928a1911d74bdb9d 100644 (file)
@@ -52,9 +52,9 @@
 #define ADV7183_VS_FIELD_CTRL_1    0x31 /* Vsync field control 1 */
 #define ADV7183_VS_FIELD_CTRL_2    0x32 /* Vsync field control 2 */
 #define ADV7183_VS_FIELD_CTRL_3    0x33 /* Vsync field control 3 */
-#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync positon control 1 */
-#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync positon control 2 */
-#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync positon control 3 */
+#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync position control 1 */
+#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync position control 2 */
+#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync position control 3 */
 #define ADV7183_POLARITY           0x37 /* Polarity */
 #define ADV7183_NTSC_COMB_CTRL     0x38 /* NTSC comb control */
 #define ADV7183_PAL_COMB_CTRL      0x39 /* PAL comb control */
index fbfdd2fc2a367f5b48c67fc41785395508fc473d..a324106b9f11e985c0637c16578cd3922ee6f58b 100644 (file)
@@ -877,7 +877,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                break;
        case ADV7604_MODE_HDMI:
                /* set default prim_mode/vid_std for HDMI
-                  accoring to [REF_03, c. 4.2] */
+                  according to [REF_03, c. 4.2] */
                io_write(sd, 0x00, 0x02); /* video std */
                io_write(sd, 0x01, 0x06); /* prim mode */
                break;
index 22f729d66a9696522e18d42932ae383594cbca5f..b154f36740b49151e2b1e0daeaf307c53032f3e7 100644 (file)
@@ -1013,7 +1013,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                break;
        case ADV7842_MODE_HDMI:
                /* set default prim_mode/vid_std for HDMI
-                  accoring to [REF_03, c. 4.2] */
+                  according to [REF_03, c. 4.2] */
                io_write(sd, 0x00, 0x02); /* video std */
                io_write(sd, 0x01, 0x06); /* prim mode */
                break;
index 82bf5679da3064d5a8ffd9da91c3d9e085d8d8bb..99ee456700f4972ef53888d692aa5f4b19930bce 100644 (file)
@@ -394,7 +394,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        if (!rc) {
                /*
-                * If platform_data doesn't specify rc_dev, initilize it
+                * If platform_data doesn't specify rc_dev, initialize it
                 * internally
                 */
                rc = rc_allocate_device();
index f34429e452abf4e01dfd71d38ceb690d3c5ab021..a60931e66312e1ff3818ff363c0edd920c0d6c04 100644 (file)
@@ -544,7 +544,7 @@ int m5mols_init_controls(struct v4l2_subdev *sd)
        u16 zoom_step;
        int ret;
 
-       /* Determine the firmware dependant control range and step values */
+       /* Determine the firmware dependent control range and step values */
        ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max);
        if (ret < 0)
                return ret;
index 4734836fe5a410c8cf4249d9c455f5ceaf4b627c..1c2303d18bf49db242c00ac0cab8a474843c6db1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/log2.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
index 6fec9384d86e4877d5b750a9f9a9ceec53e06bde..e7f555cc827abb4ddc1eba44bb1526e1d32576e4 100644 (file)
@@ -1460,7 +1460,7 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
        mutex_unlock(&state->lock);
 
        v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n",
-                __func__, ret ? "failed" : "succeded", ret);
+                __func__, ret ? "failed" : "succeeded", ret);
 
        return ret;
 }
index 9d2c0865224609504ab1a9b9302cb99d53086e85..9dfa516f694471660f9de431c948ae279ed07bb9 100644 (file)
@@ -393,7 +393,7 @@ struct s5c73m3 {
 
        /* External master clock frequency */
        u32 mclk_frequency;
-       /* Video bus type - MIPI-CSI2/paralell */
+       /* Video bus type - MIPI-CSI2/parallel */
        enum v4l2_mbus_type bus_type;
 
        const struct s5c73m3_frame_size *sensor_pix_size[2];
index 637d026345271c154f4af2da7a53bde6adbcae94..afdbcb045ceece64685db171dac9699d8a7dfc49 100644 (file)
@@ -1699,7 +1699,7 @@ static void saa711x_write_platform_data(struct saa711x_state *state,
  * the analog demod.
  * If the tuner is not found, it returns -ENODEV.
  * If auto-detection is disabled and the tuner doesn't match what it was
- *     requred, it returns -EINVAL and fills 'name'.
+ *     required, it returns -EINVAL and fills 'name'.
  * If the chip is found, it returns the chip ID and fills 'name'.
  */
 static int saa711x_detect_chip(struct i2c_client *client,
index 0a5c5d4fedd6e375b34a1848f3b646a6577bd97d..d2daa6a8f27245b88f69d832b2f2537ab716b0f9 100644 (file)
@@ -642,7 +642,7 @@ static const struct ov5642_datafmt
 static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
 {
        int ret;
-       /* We have 16-bit i2c addresses - care for endianess */
+       /* We have 16-bit i2c addresses - care for endianness */
        unsigned char data[2] = { reg >> 8, reg & 0xff };
 
        ret = i2c_master_send(client, data, 2);
index 42276d93624cada191b30eb7e3ca7ad40fb923fa..ed9ae8875348b6abdd226e3026e4b1d6f117c12f 100644 (file)
@@ -83,7 +83,8 @@ static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 }
 
 /* following function is used to set ths7303 */
-int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
+static int ths7303_setval(struct v4l2_subdev *sd,
+                         enum ths7303_filter_mode mode)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ths7303_state *state = to_state(sd);
index 3f584a7d0781b9860aad6b6bb9f6ddef4ad2b449..bee7946faa7cc2ba28a690e219cd0c5dcf89ff3b 100644 (file)
@@ -130,12 +130,10 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
                return -EINVAL;
        }
        state->input = input;
-       if (!v4l2_ctrl_g_ctrl(state->mute))
+       if (v4l2_ctrl_g_ctrl(state->mute))
                return 0;
        if (!v4l2_ctrl_g_ctrl(state->vol))
                return 0;
-       if (!v4l2_ctrl_g_ctrl(state->bal))
-               return 0;
        wm8775_set_audio(sd, 1);
        return 0;
 }
index a3b1ee9c00d7152405e9ea0e71549f350194692e..92a06fd858652acddff2dd65ce07dee560445df1 100644 (file)
@@ -4182,7 +4182,8 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
        }
        btv->std = V4L2_STD_PAL;
        init_irqreg(btv);
-       v4l2_ctrl_handler_setup(hdl);
+       if (!bttv_tvcards[btv->c.type].no_video)
+               v4l2_ctrl_handler_setup(hdl);
        if (hdl->error) {
                result = hdl->error;
                goto fail2;
index 2767c64df0c87f9c044aca755a63fbfd0c75adf3..57f4688ea55bdf2488eb14dc523d4a4c542a2609 100644 (file)
@@ -262,7 +262,7 @@ struct cx18_options {
 };
 
 /* per-mdl bit flags */
-#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianess swapped */
+#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianness swapped */
 
 /* per-stream, s_flags */
 #define CX18_F_S_CLAIMED       3       /* this stream is claimed */
index e3fc2c71808abbd0746cc7d9faabdfc14b9c583f..95666eee7b277026f3c1154a78361212653130b9 100644 (file)
@@ -427,7 +427,7 @@ int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
        cx_write(MC417_RWD, regval);
 
        /* Transition RD to effect read transaction across bus.
-        * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+        * Transition 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
         * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
         * input only...)
         */
index 8164d74b46a4590af0db79f56bd8c41bacead624..655d6854a8d7fa165502c711bf6c83a017cc16be 100644 (file)
@@ -401,7 +401,7 @@ static int pluto_hw_init(struct pluto *pluto)
        /* set automatic LED control by FPGA */
        pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
 
-       /* set data endianess */
+       /* set data endianness */
 #ifdef __LITTLE_ENDIAN
        pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
 #else
index 57ef5456f1e87e9cc042ec8dc05cdb07192bc15d..1bf06970ca3e8e180cb6a2f20d732c983af820b2 100644 (file)
@@ -1354,9 +1354,11 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
                if (fw_debug) {
                        dev->kthread = kthread_run(saa7164_thread_function, dev,
                                "saa7164 debug");
-                       if (!dev->kthread)
+                       if (IS_ERR(dev->kthread)) {
+                               dev->kthread = NULL;
                                printk(KERN_ERR "%s() Failed to create "
                                        "debug kernel thread\n", __func__);
+                       }
                }
 
        } /* != BOARD_UNKNOWN */
index bd72fb97fea5ab05924c4eeb4f5452534f3c3f46..61f3dbcc259f40f8a0f6f2b4bfa9b52ed6bf24ee 100644 (file)
@@ -1434,7 +1434,7 @@ static void coda_buf_queue(struct vb2_buffer *vb)
        if (q_data->fourcc == V4L2_PIX_FMT_H264 &&
            vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /*
-                * For backwards compatiblity, queuing an empty buffer marks
+                * For backwards compatibility, queuing an empty buffer marks
                 * the stream end
                 */
                if (vb2_get_plane_payload(vb, 0) == 0)
index 3d66d88ea3a191911ce72a22a8198602d7640e35..f7915695c9073d37ca10da947c29891b8d0e45d5 100644 (file)
@@ -1039,7 +1039,7 @@ static int fimc_runtime_resume(struct device *dev)
 
        dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
 
-       /* Enable clocks and perform basic initalization */
+       /* Enable clocks and perform basic initialization */
        clk_enable(fimc->clock[CLK_GATE]);
        fimc_hw_reset(fimc);
 
index 7a4ee4c0449deea95dc86e82a85af8412a1d5aad..c1bce170df6fbce44d519a498bf6d19694389306 100644 (file)
@@ -759,7 +759,7 @@ static int fimc_md_register_platform_entity(struct fimc_md *fmd,
                goto dev_unlock;
 
        drvdata = dev_get_drvdata(dev);
-       /* Some subdev didn't probe succesfully id drvdata is NULL */
+       /* Some subdev didn't probe successfully id drvdata is NULL */
        if (drvdata) {
                switch (plat_entity) {
                case IDX_FIMC:
index 3458fa0e2fd537916270fd9fbb0908d2b1610821..054507f16734de8c04c67fbda15d9afff60d6f11 100644 (file)
@@ -142,12 +142,6 @@ static int mmpcam_power_up(struct mcam_camera *mcam)
        struct mmp_camera *cam = mcam_to_cam(mcam);
        struct mmp_camera_platform_data *pdata;
 
-       if (mcam->bus_type == V4L2_MBUS_CSI2) {
-               cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
-               if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
-                       return PTR_ERR(cam->mipi_clk);
-       }
-
 /*
  * Turn on power and clocks to the controller.
  */
@@ -186,12 +180,6 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
        gpio_set_value(pdata->sensor_power_gpio, 0);
        gpio_set_value(pdata->sensor_reset_gpio, 0);
 
-       if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) {
-               if (cam->mipi_clk)
-                       devm_clk_put(mcam->dev, cam->mipi_clk);
-               cam->mipi_clk = NULL;
-       }
-
        mcam_clk_disable(mcam);
 }
 
@@ -292,8 +280,9 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
                return;
 
        /* get the escape clk, this is hard coded */
+       clk_prepare_enable(cam->mipi_clk);
        tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12;
-
+       clk_disable_unprepare(cam->mipi_clk);
        /*
         * dphy[2] - CSI2_DPHY6:
         * bit 0 ~ bit 7: CK Term Enable
@@ -325,19 +314,6 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
        return IRQ_RETVAL(handled);
 }
 
-static void mcam_deinit_clk(struct mcam_camera *mcam)
-{
-       unsigned int i;
-
-       for (i = 0; i < NR_MCAM_CLK; i++) {
-               if (!IS_ERR(mcam->clk[i])) {
-                       if (mcam->clk[i])
-                               devm_clk_put(mcam->dev, mcam->clk[i]);
-               }
-               mcam->clk[i] = NULL;
-       }
-}
-
 static void mcam_init_clk(struct mcam_camera *mcam)
 {
        unsigned int i;
@@ -371,7 +347,6 @@ static int mmpcam_probe(struct platform_device *pdev)
        if (cam == NULL)
                return -ENOMEM;
        cam->pdev = pdev;
-       cam->mipi_clk = NULL;
        INIT_LIST_HEAD(&cam->devlist);
 
        mcam = &cam->mcam;
@@ -387,6 +362,11 @@ static int mmpcam_probe(struct platform_device *pdev)
        mcam->mclk_div = pdata->mclk_div;
        mcam->bus_type = pdata->bus_type;
        mcam->dphy = pdata->dphy;
+       if (mcam->bus_type == V4L2_MBUS_CSI2) {
+               cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
+               if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
+                       return PTR_ERR(cam->mipi_clk);
+       }
        mcam->mipi_enabled = false;
        mcam->lane = pdata->lane;
        mcam->chip_id = MCAM_ARMADA610;
@@ -444,7 +424,7 @@ static int mmpcam_probe(struct platform_device *pdev)
         */
        ret = mmpcam_power_up(mcam);
        if (ret)
-               goto out_deinit_clk;
+               return ret;
        ret = mccic_register(mcam);
        if (ret)
                goto out_power_down;
@@ -469,8 +449,6 @@ out_unregister:
        mccic_shutdown(mcam);
 out_power_down:
        mmpcam_power_down(mcam);
-out_deinit_clk:
-       mcam_deinit_clk(mcam);
        return ret;
 }
 
@@ -478,18 +456,10 @@ out_deinit_clk:
 static int mmpcam_remove(struct mmp_camera *cam)
 {
        struct mcam_camera *mcam = &cam->mcam;
-       struct mmp_camera_platform_data *pdata;
 
        mmpcam_remove_device(cam);
        mccic_shutdown(mcam);
        mmpcam_power_down(mcam);
-       pdata = cam->pdev->dev.platform_data;
-       gpio_free(pdata->sensor_reset_gpio);
-       gpio_free(pdata->sensor_power_gpio);
-       mcam_deinit_clk(mcam);
-       iounmap(cam->power_regs);
-       iounmap(mcam->regs);
-       kfree(cam);
        return 0;
 }
 
index 1c3608039663e281d23541f17aedcbce044c87fb..561bce8ffb1b57c87dd1b45bbae6cbf7c2b479c1 100644 (file)
@@ -1673,7 +1673,7 @@ void omap3isp_print_status(struct isp_device *isp)
  * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
  * resume(), and the the pipelines are restarted in complete().
  *
- * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
+ * TODO: PM dependencies between the ISP and sensors are not modelled explicitly
  * yet.
  */
 static int isp_pm_prepare(struct device *dev)
index a908d006f5277c2abe9adebcbb757ea699495fbf..f6304bb074f5edaa598f959515394448d30a3cc9 100644 (file)
@@ -339,14 +339,11 @@ __isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
        if (subdev == NULL)
                return -EINVAL;
 
-       mutex_lock(&video->mutex);
-
        fmt.pad = pad;
        fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
-       if (ret == -ENOIOCTLCMD)
-               ret = -EINVAL;
 
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        mutex_unlock(&video->mutex);
 
        if (ret)
index 9319e93599ae5731241b58535583bc1a04b77e73..6ccc3f8c122add705d7338d0656ac744331823fb 100644 (file)
 #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
 #define S5P_FIMV_R2H_CMD_ERR_RET               32
 
-/* Dummy definition for MFCv6 compatibilty */
+/* Dummy definition for MFCv6 compatibility */
 #define S5P_FIMV_CODEC_H264_MVC_DEC            -1
 #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
 #define S5P_FIMV_MFC_RESET                     -1
index 5f2c4ad6c2cb3427835ed2f40ec9ba5432ae3221..e46067a5785307ac7a1381bd8a8babd8e4ec4fc2 100644 (file)
@@ -239,7 +239,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
        frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
 
        /* Copy timestamp / timecode from decoded src to dst and set
-          appropraite flags */
+          appropriate flags */
        src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
        list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
                if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
@@ -428,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
                case MFCINST_FINISHING:
                case MFCINST_FINISHED:
                case MFCINST_RUNNING:
-                       /* It is higly probable that an error occured
+                       /* It is highly probable that an error occurred
                         * while decoding a frame */
                        clear_work_bit(ctx);
                        ctx->state = MFCINST_ERROR;
@@ -611,7 +611,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
        mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
        switch (reason) {
        case S5P_MFC_R2H_CMD_ERR_RET:
-               /* An error has occured */
+               /* An error has occurred */
                if (ctx->state == MFCINST_RUNNING &&
                        s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
                                dev->warn_start)
@@ -840,7 +840,7 @@ static int s5p_mfc_open(struct file *file)
        mutex_unlock(&dev->mfc_mutex);
        mfc_debug_leave();
        return ret;
-       /* Deinit when failure occured */
+       /* Deinit when failure occurred */
 err_queue_init:
        if (dev->num_inst == 1)
                s5p_mfc_deinit_hw(dev);
@@ -881,14 +881,14 @@ static int s5p_mfc_release(struct file *file)
        /* Mark context as idle */
        clear_work_bit_irqsave(ctx);
        /* If instance was initialised then
-        * return instance and free reosurces */
+        * return instance and free resources */
        if (ctx->inst_no != MFC_NO_INSTANCE_SET) {
                mfc_debug(2, "Has to free instance\n");
                ctx->state = MFCINST_RETURN_INST;
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               /* Wait until instance is returned or timeout occured */
+               /* Wait until instance is returned or timeout occurred */
                if (s5p_mfc_wait_for_done_ctx
                    (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
                        s5p_mfc_clock_off();
index 7cab6849fb5b73d9463c591b4b24eaffcae48bae..2475a3c9a0a62ab27330a347865530466d209e0d 100644 (file)
@@ -69,7 +69,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 
        } else {
                /* In this case bank2 can point to the same address as bank1.
-                * Firmware will always occupy the beggining of this area so it is
+                * Firmware will always occupy the beginning of this area so it is
                 * impossible having a video frame buffer with zero address. */
                dev->bank2 = dev->bank1;
        }
index 04e6490a45befbae453d55ef0a86be0bb32497d2..fb2acc53112a47201be7ec785057cdb491eabffc 100644 (file)
@@ -65,7 +65,7 @@ struct mxr_format {
        int num_subframes;
        /** specifies to which subframe belong given plane */
        int plane2subframe[MXR_MAX_PLANES];
-       /** internal code, driver dependant */
+       /** internal code, driver dependent */
        unsigned long cookie;
 };
 
index 641b1f071e06a2b74796f030ddfdcdc80644179b..81b97db111d8506a1c28df84a86ce4181f6ddccb 100644 (file)
@@ -528,7 +528,7 @@ static int mxr_s_dv_timings(struct file *file, void *fh,
        mutex_lock(&mdev->mutex);
 
        /* timings change cannot be done while there is an entity
-        * dependant on output configuration
+        * dependent on output configuration
         */
        if (mdev->n_output > 0) {
                mutex_unlock(&mdev->mutex);
@@ -585,7 +585,7 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id norm)
        mutex_lock(&mdev->mutex);
 
        /* standard change cannot be done while there is an entity
-        * dependant on output configuration
+        * dependent on output configuration
         */
        if (mdev->n_output > 0) {
                mutex_unlock(&mdev->mutex);
index 6769193c7c7bbeef27f723e98760f73ece8d0219..74ce8b6b79fa91c80644e0646996397befd325cc 100644 (file)
@@ -1495,7 +1495,7 @@ static int omap1_cam_set_bus_param(struct soc_camera_device *icd)
        if (ctrlclock & LCLK_EN)
                CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
 
-       /* select bus endianess */
+       /* select bus endianness */
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        fmt = xlate->host_fmt;
 
index 1d3f1196519669cca0509c1972bdb320d2d35ad1..2d4e73b45c5e3b05d7e4615f6f6fd0d46bd56656 100644 (file)
@@ -1108,7 +1108,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        return 0;
 }
 
-/* timeperframe is arbitrary and continous */
+/* timeperframe is arbitrary and continuous */
 static int vidioc_enum_frameintervals(struct file *file, void *priv,
                                             struct v4l2_frmivalenum *fival)
 {
@@ -1125,7 +1125,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
 
        fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
 
-       /* fill in stepwise (step=1.0 is requred by V4L2 spec) */
+       /* fill in stepwise (step=1.0 is required by V4L2 spec) */
        fival->stepwise.min  = tpf_min;
        fival->stepwise.max  = tpf_max;
        fival->stepwise.step = (struct v4l2_fract) {1, 1};
index 1c9e771aa15c7bb40b5a8a1de25d66b2b108c528..d16bf0f41e247bd69e3af1ebdc31e0309861e0fd 100644 (file)
@@ -323,7 +323,7 @@ static void vsp1_clocks_disable(struct vsp1_device *vsp1)
  * Increment the VSP1 reference count and initialize the device if the first
  * reference is taken.
  *
- * Return a pointer to the VSP1 device or NULL if an error occured.
+ * Return a pointer to the VSP1 device or NULL if an error occurred.
  */
 struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
 {
index 714c53ef6c11b19d48304405f363f750b26547d2..4b0ac07af662c2bca05c6534ecb52bfc15730c74 100644 (file)
@@ -1026,8 +1026,10 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf)
 
        /* ... and the buffers queue... */
        video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev);
-       if (IS_ERR(video->alloc_ctx))
+       if (IS_ERR(video->alloc_ctx)) {
+               ret = PTR_ERR(video->alloc_ctx);
                goto error;
+       }
 
        video->queue.type = video->type;
        video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
index 3db8a8cfe1a87f4eb80e9c22950bbcac93b7daed..050b3bb96fecc13a15f05d3f294147200954e8dd 100644 (file)
@@ -271,8 +271,7 @@ static void shark_unregister_leds(struct shark_device *shark)
        cancel_work_sync(&shark->led_work);
 }
 
-#ifdef CONFIG_PM
-static void shark_resume_leds(struct shark_device *shark)
+static inline void shark_resume_leds(struct shark_device *shark)
 {
        if (test_bit(BLUE_IS_PULSE, &shark->brightness_new))
                set_bit(BLUE_PULSE_LED, &shark->brightness_new);
@@ -281,7 +280,6 @@ static void shark_resume_leds(struct shark_device *shark)
        set_bit(RED_LED, &shark->brightness_new);
        schedule_work(&shark->led_work);
 }
-#endif
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
index d86d90dab8bf880666a05ca0463aa83fc62f77de..8654e0dc5c95376aa7140498e10af342b955d15a 100644 (file)
@@ -237,8 +237,7 @@ static void shark_unregister_leds(struct shark_device *shark)
        cancel_work_sync(&shark->led_work);
 }
 
-#ifdef CONFIG_PM
-static void shark_resume_leds(struct shark_device *shark)
+static inline void shark_resume_leds(struct shark_device *shark)
 {
        int i;
 
@@ -247,7 +246,6 @@ static void shark_resume_leds(struct shark_device *shark)
 
        schedule_work(&shark->led_work);
 }
-#endif
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
index 9c9084cb99f7dd1fde0800f0325c58584edd9e19..2fd9009f86633e74b4752472f5db2829daf6d9ce 100644 (file)
@@ -268,8 +268,8 @@ struct si476x_radio;
  *
  * @tune_freq: Tune chip to a specific frequency
  * @seek_start: Star station seeking
- * @rsq_status: Get Recieved Signal Quality(RSQ) status
- * @rds_blckcnt: Get recived RDS blocks count
+ * @rsq_status: Get Received Signal Quality(RSQ) status
+ * @rds_blckcnt: Get received RDS blocks count
  * @phase_diversity: Change phase diversity mode of the tuner
  * @phase_div_status: Get phase diversity mode status
  * @acf_status: Get the status of Automatically Controlled
index 036e2f54f4db4b1bc5c6f574e19ccde1960da9b5..3ed1f5669f791b9d3015bb91efd80ba2fa82d0c0 100644 (file)
@@ -356,7 +356,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                   So we keep it as-is. */
                return -EINVAL;
        }
-       clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
+       freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
        tea5764_power_up(radio);
        tea5764_tune(radio, (freq * 125) / 2);
        return 0;
index 69e3245a58a0cbfcc1d333d390a30aa45e4c70d8..a9319a24c7efe1290efbc5b309bb719584cf7b5f 100644 (file)
@@ -112,7 +112,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen
        if (f->tuner != 0)
                return -EINVAL;
 
-       clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
+       freq = clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
        pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL;
        i2cmsg[0] = (MSA_MODE_PRESET << MSA_MODE_SHIFT) | WM_SUB_PLLM;
        i2cmsg[1] = (pll >> 8) & 0xff;
index 72e3fa652481671cff04e2c06a1478d21fb0ffb6..f329485c6629b038ff2aee825edff86c82189328 100644 (file)
@@ -1370,7 +1370,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
         * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates
         * 0x688301b7 and the right one 0x688481b7. All other keys generate
         * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with
-        * reversed endianess. Extract direction from buffer, rotate endianess,
+        * reversed endianness. Extract direction from buffer, rotate endianness,
         * adjust sign and feed the values into stabilize(). The resulting codes
         * will be 0x01008000, 0x01007F00, which match the newer devices.
         */
index 094484fac94cdbe52f7832f140f87895e922e631..a5d4f883d053a7b0ebca0543ac82d29d216ec26a 100644 (file)
@@ -118,7 +118,7 @@ static int debug;
 #define RR3_IR_IO_LENGTH_FUZZ  0x04
 /* Timeout for end of signal detection */
 #define RR3_IR_IO_SIG_TIMEOUT  0x05
-/* Minumum value for pause recognition. */
+/* Minimum value for pause recognition. */
 #define RR3_IR_IO_MIN_PAUSE    0x06
 
 /* Clock freq. of EZ-USB chip */
index 2e1a02e360ff0cd7279fed8ca20b80a3ee0b8ad8..20cca405bf452c46195ebbbadb37c8a535e85d0b 100644 (file)
@@ -1195,7 +1195,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
  *   DNC Output is selected, the other is always off)
  *
  * @state:     ptr to mt2063_state structure
- * @Mode:      desired reciever delivery system
+ * @Mode:      desired receiver delivery system
  *
  * Note: Register cache must be valid for it to work
  */
@@ -2119,7 +2119,7 @@ static int mt2063_set_analog_params(struct dvb_frontend *fe,
 
 /*
  * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
- * So, the amount of the needed bandwith is given by:
+ * So, the amount of the needed bandwidth is given by:
  *     Bw = Symbol_rate * (1 + 0.15)
  * As such, the maximum symbol rate supported by 6 MHz is given by:
  *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
index 74dc46a71f64555c07bb67be9ee09facf822ad41..7e4798783db733cc139e557444f12d4bddb820b5 100644 (file)
 #define V4L2_STD_A2            (V4L2_STD_A2_A    | V4L2_STD_A2_B)
 #define V4L2_STD_NICAM         (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
 
-/* To preserve backward compatibilty,
+/* To preserve backward compatibility,
    (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
  */
 
index e9d017bea377069da087751404e75f86b081c7cd..528cce958a82c4a67c91ea0c52841364db36f7d4 100644 (file)
@@ -1412,8 +1412,8 @@ err_v4l2:
        usb_set_intfdata(interface, NULL);
 err_if:
        usb_put_dev(udev);
-       kfree(dev);
        clear_bit(dev->devno, &cx231xx_devused);
+       kfree(dev);
        return retval;
 }
 
index c8fcd78425bd228ca4374daf94fdbf4ed1c0c17a..8f9b2cea88f009ec316fb1b97cbbfa67984fcda0 100644 (file)
@@ -131,7 +131,7 @@ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
 {
        u8 wbuf[MAX_XFER_SIZE];
        u8 mbox = (reg >> 16) & 0xff;
-       struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL };
+       struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL };
 
        if (6 + len > sizeof(wbuf)) {
                dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n",
@@ -238,14 +238,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        /* I2C */
                        u8 buf[MAX_XFER_SIZE];
-                       struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
+                       struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len,
                                        buf, msg[1].len, msg[1].buf };
 
                        if (5 + msg[0].len > sizeof(buf)) {
                                dev_warn(&d->udev->dev,
                                         "%s: i2c xfer: len=%d is too big!\n",
                                         KBUILD_MODNAME, msg[0].len);
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto unlock;
                        }
                        req.mbox |= ((msg[0].addr & 0x80)  >>  3);
                        buf[0] = msg[1].len;
@@ -274,14 +275,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        /* I2C */
                        u8 buf[MAX_XFER_SIZE];
-                       struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf,
-                                       0, NULL };
+                       struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len,
+                                       buf, 0, NULL };
 
                        if (5 + msg[0].len > sizeof(buf)) {
                                dev_warn(&d->udev->dev,
                                         "%s: i2c xfer: len=%d is too big!\n",
                                         KBUILD_MODNAME, msg[0].len);
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto unlock;
                        }
                        req.mbox |= ((msg[0].addr & 0x80)  >>  3);
                        buf[0] = msg[0].len;
@@ -319,6 +321,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                ret = -EOPNOTSUPP;
        }
 
+unlock:
        mutex_unlock(&d->i2c_mutex);
 
        if (ret < 0)
@@ -1534,6 +1537,8 @@ static const struct usb_device_id af9035_id_table[] = {
        /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
                &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) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
index 2627553f7de1f90c262f2d234d1d1faa9288f45f..08240e498451a55810e4bd00a75df73d0c1a607e 100644 (file)
@@ -266,7 +266,7 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
        struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
        int err;
 
-       /* exit if we didnt initialize the driver yet */
+       /* exit if we didn't initialize the driver yet */
        if (!state->chip_id) {
                mxl_debug("driver not yet initialized, exit.");
                goto fail;
@@ -322,7 +322,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
        struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
        int err;
 
-       /* exit if we didnt initialize the driver yet */
+       /* exit if we didn't initialize the driver yet */
        if (!state->chip_id) {
                mxl_debug("driver not yet initialized, exit.");
                goto fail;
index 40832a1aef6c71c0df2eaf51ffdea327bafe18da..98d24aefb640f80e12d6dd720f872273c71e6276 100644 (file)
@@ -102,7 +102,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
        if (rxlen > 62) {
                err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
                                device_addr);
-               txlen = 62;
+               rxlen = 62;
        }
 
        b[0] = I2C_SPEED_100KHZ_BIT;
index fc5d60efd4abe99f19acbafff7b83879da5ff3ac..dd19c9ff76e0f9a159c6630320814c89e9e83d5a 100644 (file)
@@ -1664,8 +1664,8 @@ static int em28xx_v4l2_close(struct file *filp)
 
        em28xx_videodbg("users=%d\n", dev->users);
 
-       mutex_lock(&dev->lock);
        vb2_fop_release(filp);
+       mutex_lock(&dev->lock);
 
        if (dev->users == 1) {
                /* the device is already disconnect,
index cb1e64ca59c9259b59ca1aaaaea036b6bd2c5fa0..cea8d7f51c3cc9430af956066d87b045b453c062 100644 (file)
@@ -438,7 +438,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        s32 nToSkip =
                sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
 
-       /* Test only against 0202h, so endianess does not matter */
+       /* Test only against 0202h, so endianness does not matter */
        switch (*(s16 *) data) {
        case 0x0202:            /* End of frame, start a new one */
                gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
index cd79c180f67b87e84689a8a162b4962bf5691cde..07529e5a0c5605186b3aa619b6b89d06cf98bc45 100644 (file)
@@ -416,7 +416,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        int ret = -EINVAL;
 
index a9150964356329d93ea136e151c0d7f0aebf8590..2fd1c5e31a0f2692a1d59dd88c72cbee74e61054 100644 (file)
@@ -874,7 +874,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        int ret = -EINVAL;
        u8 data0, data1;
index 1fc80af2a18907e57d54eac3f58481ada0f3cda7..48234c9a8b6c3e4b4b927eb654ddb0009aa3d8ba 100644 (file)
@@ -361,6 +361,9 @@ static void stk1135_configure_clock(struct gspca_dev *gspca_dev)
 
        /* set serial interface clock divider (30MHz/0x1f*16+2) = 60240 kHz) */
        reg_w(gspca_dev, STK1135_REG_SICTL + 2, 0x1f);
+
+       /* wait a while for sensor to catch up */
+       udelay(1000);
 }
 
 static void stk1135_camera_disable(struct gspca_dev *gspca_dev)
index 9c0827631b9c105658575ed52e754fd1efa0c740..7f94ec74282e3ea42b0c423130419b038a5e3edd 100644 (file)
@@ -139,7 +139,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam = &gspca_dev->cam;
 
-       /* Give the camera some time to settle, otherwise initalization will
+       /* Give the camera some time to settle, otherwise initialization will
           fail on hotplug, and yes it really needs a full second. */
        msleep(1000);
 
index a517d185febed4590bbb5f58306aa4e4a2c4f0f1..46c9f2229a18675c6a1ca39528dab2196937c0c5 100644 (file)
@@ -1027,6 +1027,7 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
+       {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
index 7b95d8e88a20240305a8817b72c3459d80a5adc6..d3e1b6d8bf494f79d449c38c96be5d022ab61043 100644 (file)
@@ -6905,7 +6905,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        if (len == 8 && data[4] == 1) {
                input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
index 77bbf788965953bbc67f8fa8b3ab18ccbe5806d8..78c9bc8e7f561744364a6de94f4aeaae382dd077 100644 (file)
@@ -1039,7 +1039,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        /* Set the leds off */
        pwc_set_leds(pdev, 0, 0);
 
-       /* Setup intial videomode */
+       /* Setup initial videomode */
        rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
                                V4L2_PIX_FMT_YUV420, 30, &compression, 1);
        if (rc)
index 8a505a90d3189a59876a916507ae50b6e11a0ed9..6222a4ab1e00bfff2d58d7816145bdae58fe4059 100644 (file)
 #define USBTV_ISOC_TRANSFERS   16
 #define USBTV_ISOC_PACKETS     8
 
-#define USBTV_WIDTH            720
-#define USBTV_HEIGHT           480
-
 #define USBTV_CHUNK_SIZE       256
 #define USBTV_CHUNK            240
-#define USBTV_CHUNKS           (USBTV_WIDTH * USBTV_HEIGHT \
-                                       / 4 / USBTV_CHUNK)
 
 /* Chunk header. */
 #define USBTV_MAGIC_OK(chunk)  ((be32_to_cpu(chunk[0]) & 0xff000000) \
 #define USBTV_ODD(chunk)       ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15)
 #define USBTV_CHUNK_NO(chunk)  (be32_to_cpu(chunk[0]) & 0x00000fff)
 
+#define USBTV_TV_STD  (V4L2_STD_525_60 | V4L2_STD_PAL)
+
+/* parameters for supported TV norms */
+struct usbtv_norm_params {
+       v4l2_std_id norm;
+       int cap_width, cap_height;
+};
+
+static struct usbtv_norm_params norm_params[] = {
+       {
+               .norm = V4L2_STD_525_60,
+               .cap_width = 720,
+               .cap_height = 480,
+       },
+       {
+               .norm = V4L2_STD_PAL,
+               .cap_width = 720,
+               .cap_height = 576,
+       }
+};
+
 /* A single videobuf2 frame buffer. */
 struct usbtv_buf {
        struct vb2_buffer vb;
@@ -94,11 +110,38 @@ struct usbtv {
                USBTV_COMPOSITE_INPUT,
                USBTV_SVIDEO_INPUT,
        } input;
+       v4l2_std_id norm;
+       int width, height;
+       int n_chunks;
        int iso_size;
        unsigned int sequence;
        struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS];
 };
 
+static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm)
+{
+       int i, ret = 0;
+       struct usbtv_norm_params *params = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(norm_params); i++) {
+               if (norm_params[i].norm & norm) {
+                       params = &norm_params[i];
+                       break;
+               }
+       }
+
+       if (params) {
+               usbtv->width = params->cap_width;
+               usbtv->height = params->cap_height;
+               usbtv->n_chunks = usbtv->width * usbtv->height
+                                               / 4 / USBTV_CHUNK;
+               usbtv->norm = params->norm;
+       } else
+               ret = -EINVAL;
+
+       return ret;
+}
+
 static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
 {
        int ret;
@@ -158,6 +201,57 @@ static int usbtv_select_input(struct usbtv *usbtv, int input)
        return ret;
 }
 
+static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm)
+{
+       int ret;
+       static const u16 pal[][2] = {
+               { USBTV_BASE + 0x001a, 0x0068 },
+               { USBTV_BASE + 0x010e, 0x0072 },
+               { USBTV_BASE + 0x010f, 0x00a2 },
+               { USBTV_BASE + 0x0112, 0x00b0 },
+               { USBTV_BASE + 0x0117, 0x0001 },
+               { USBTV_BASE + 0x0118, 0x002c },
+               { USBTV_BASE + 0x012d, 0x0010 },
+               { USBTV_BASE + 0x012f, 0x0020 },
+               { USBTV_BASE + 0x024f, 0x0002 },
+               { USBTV_BASE + 0x0254, 0x0059 },
+               { USBTV_BASE + 0x025a, 0x0016 },
+               { USBTV_BASE + 0x025b, 0x0035 },
+               { USBTV_BASE + 0x0263, 0x0017 },
+               { USBTV_BASE + 0x0266, 0x0016 },
+               { USBTV_BASE + 0x0267, 0x0036 }
+       };
+
+       static const u16 ntsc[][2] = {
+               { USBTV_BASE + 0x001a, 0x0079 },
+               { USBTV_BASE + 0x010e, 0x0068 },
+               { USBTV_BASE + 0x010f, 0x009c },
+               { USBTV_BASE + 0x0112, 0x00f0 },
+               { USBTV_BASE + 0x0117, 0x0000 },
+               { USBTV_BASE + 0x0118, 0x00fc },
+               { USBTV_BASE + 0x012d, 0x0004 },
+               { USBTV_BASE + 0x012f, 0x0008 },
+               { USBTV_BASE + 0x024f, 0x0001 },
+               { USBTV_BASE + 0x0254, 0x005f },
+               { USBTV_BASE + 0x025a, 0x0012 },
+               { USBTV_BASE + 0x025b, 0x0001 },
+               { USBTV_BASE + 0x0263, 0x001c },
+               { USBTV_BASE + 0x0266, 0x0011 },
+               { USBTV_BASE + 0x0267, 0x0005 }
+       };
+
+       ret = usbtv_configure_for_norm(usbtv, norm);
+
+       if (!ret) {
+               if (norm & V4L2_STD_525_60)
+                       ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc));
+               else if (norm & V4L2_STD_PAL)
+                       ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal));
+       }
+
+       return ret;
+}
+
 static int usbtv_setup_capture(struct usbtv *usbtv)
 {
        int ret;
@@ -225,26 +319,11 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
 
                { USBTV_BASE + 0x0284, 0x0088 },
                { USBTV_BASE + 0x0003, 0x0004 },
-               { USBTV_BASE + 0x001a, 0x0079 },
                { USBTV_BASE + 0x0100, 0x00d3 },
-               { USBTV_BASE + 0x010e, 0x0068 },
-               { USBTV_BASE + 0x010f, 0x009c },
-               { USBTV_BASE + 0x0112, 0x00f0 },
                { USBTV_BASE + 0x0115, 0x0015 },
-               { USBTV_BASE + 0x0117, 0x0000 },
-               { USBTV_BASE + 0x0118, 0x00fc },
-               { USBTV_BASE + 0x012d, 0x0004 },
-               { USBTV_BASE + 0x012f, 0x0008 },
                { USBTV_BASE + 0x0220, 0x002e },
                { USBTV_BASE + 0x0225, 0x0008 },
                { USBTV_BASE + 0x024e, 0x0002 },
-               { USBTV_BASE + 0x024f, 0x0001 },
-               { USBTV_BASE + 0x0254, 0x005f },
-               { USBTV_BASE + 0x025a, 0x0012 },
-               { USBTV_BASE + 0x025b, 0x0001 },
-               { USBTV_BASE + 0x0263, 0x001c },
-               { USBTV_BASE + 0x0266, 0x0011 },
-               { USBTV_BASE + 0x0267, 0x0005 },
                { USBTV_BASE + 0x024e, 0x0002 },
                { USBTV_BASE + 0x024f, 0x0002 },
        };
@@ -253,6 +332,10 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
        if (ret)
                return ret;
 
+       ret = usbtv_select_norm(usbtv, usbtv->norm);
+       if (ret)
+               return ret;
+
        ret = usbtv_select_input(usbtv, usbtv->input);
        if (ret)
                return ret;
@@ -296,7 +379,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
        frame_id = USBTV_FRAME_ID(chunk);
        odd = USBTV_ODD(chunk);
        chunk_no = USBTV_CHUNK_NO(chunk);
-       if (chunk_no >= USBTV_CHUNKS)
+       if (chunk_no >= usbtv->n_chunks)
                return;
 
        /* Beginning of a frame. */
@@ -324,10 +407,10 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
        usbtv->chunks_done++;
 
        /* Last chunk in a frame, signalling an end */
-       if (odd && chunk_no == USBTV_CHUNKS-1) {
+       if (odd && chunk_no == usbtv->n_chunks-1) {
                int size = vb2_plane_size(&buf->vb, 0);
                enum vb2_buffer_state state = usbtv->chunks_done ==
-                                               USBTV_CHUNKS ?
+                                               usbtv->n_chunks ?
                                                VB2_BUF_STATE_DONE :
                                                VB2_BUF_STATE_ERROR;
 
@@ -500,6 +583,8 @@ static int usbtv_querycap(struct file *file, void *priv,
 static int usbtv_enum_input(struct file *file, void *priv,
                                        struct v4l2_input *i)
 {
+       struct usbtv *dev = video_drvdata(file);
+
        switch (i->index) {
        case USBTV_COMPOSITE_INPUT:
                strlcpy(i->name, "Composite", sizeof(i->name));
@@ -512,7 +597,7 @@ static int usbtv_enum_input(struct file *file, void *priv,
        }
 
        i->type = V4L2_INPUT_TYPE_CAMERA;
-       i->std = V4L2_STD_525_60;
+       i->std = dev->vdev.tvnorms;
        return 0;
 }
 
@@ -531,23 +616,37 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void  *priv,
 static int usbtv_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
-       f->fmt.pix.width = USBTV_WIDTH;
-       f->fmt.pix.height = USBTV_HEIGHT;
+       struct usbtv *usbtv = video_drvdata(file);
+
+       f->fmt.pix.width = usbtv->width;
+       f->fmt.pix.height = usbtv->height;
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.bytesperline = USBTV_WIDTH * 2;
+       f->fmt.pix.bytesperline = usbtv->width * 2;
        f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height);
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
+
        return 0;
 }
 
 static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-       *norm = V4L2_STD_525_60;
+       struct usbtv *usbtv = video_drvdata(file);
+       *norm = usbtv->norm;
        return 0;
 }
 
+static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
+{
+       int ret = -EINVAL;
+       struct usbtv *usbtv = video_drvdata(file);
+
+       if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL))
+               ret = usbtv_select_norm(usbtv, norm);
+
+       return ret;
+}
+
 static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
 {
        struct usbtv *usbtv = video_drvdata(file);
@@ -561,13 +660,6 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
        return usbtv_select_input(usbtv, i);
 }
 
-static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
-{
-       if (norm & V4L2_STD_525_60)
-               return 0;
-       return -EINVAL;
-}
-
 struct v4l2_ioctl_ops usbtv_ioctl_ops = {
        .vidioc_querycap = usbtv_querycap,
        .vidioc_enum_input = usbtv_enum_input,
@@ -604,10 +696,12 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
        const struct v4l2_format *v4l_fmt, unsigned int *nbuffers,
        unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
+       struct usbtv *usbtv = vb2_get_drv_priv(vq);
+
        if (*nbuffers < 2)
                *nbuffers = 2;
        *nplanes = 1;
-       sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
+       sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
 
        return 0;
 }
@@ -690,7 +784,11 @@ static int usbtv_probe(struct usb_interface *intf,
                return -ENOMEM;
        usbtv->dev = dev;
        usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
+
        usbtv->iso_size = size;
+
+       (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60);
+
        spin_lock_init(&usbtv->buflock);
        mutex_init(&usbtv->v4l2_lock);
        mutex_init(&usbtv->vb2q_lock);
@@ -727,7 +825,7 @@ static int usbtv_probe(struct usb_interface *intf,
        usbtv->vdev.release = video_device_release_empty;
        usbtv->vdev.fops = &usbtv_fops;
        usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops;
-       usbtv->vdev.tvnorms = V4L2_STD_525_60;
+       usbtv->vdev.tvnorms = USBTV_TV_STD;
        usbtv->vdev.queue = &usbtv->vb2q;
        usbtv->vdev.lock = &usbtv->v4l2_lock;
        set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
index 899cb6d1c4a4a74a68cae01dbea51de5befc821e..898c208889cd2d55dd5a22522a2d06340eb0891d 100644 (file)
@@ -556,7 +556,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
  *
  * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)   (1)
  *
- * to avoid loosing precision in the division. Similarly, the host timestamp is
+ * to avoid losing precision in the division. Similarly, the host timestamp is
  * computed with
  *
  * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1)       (2)
index 60dcc0f3b32e7b445352b455d377f5b2b794b4fb..fb46790d0eca795d5e411c54bf7129d96e61d3e9 100644 (file)
@@ -420,7 +420,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Advanced Simple",
                "Core",
                "Simple Scalable",
-               "Advanced Coding Efficency",
+               "Advanced Coding Efficiency",
                NULL,
        };
 
index b19b306c8f7f533d3112db441f692e57bd76638d..0edc165f418d9449f46e5696e4e093e7b3288fd1 100644 (file)
@@ -144,6 +144,25 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
                __vb2_plane_dmabuf_put(q, &vb->planes[plane]);
 }
 
+/**
+ * __setup_lengths() - setup initial lengths for every plane in
+ * every buffer on the queue
+ */
+static void __setup_lengths(struct vb2_queue *q, unsigned int n)
+{
+       unsigned int buffer, plane;
+       struct vb2_buffer *vb;
+
+       for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) {
+               vb = q->bufs[buffer];
+               if (!vb)
+                       continue;
+
+               for (plane = 0; plane < vb->num_planes; ++plane)
+                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+       }
+}
+
 /**
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
@@ -169,7 +188,6 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
                        continue;
 
                for (plane = 0; plane < vb->num_planes; ++plane) {
-                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
                        vb->v4l2_planes[plane].m.mem_offset = off;
 
                        dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
@@ -241,6 +259,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
                q->bufs[q->num_buffers + buffer] = vb;
        }
 
+       __setup_lengths(q, buffer);
        if (memory == V4L2_MEMORY_MMAP)
                __setup_offsets(q, buffer);
 
@@ -1824,8 +1843,8 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
                return -EINVAL;
        }
 
-       if (eb->flags & ~O_CLOEXEC) {
-               dprintk(1, "Queue does support only O_CLOEXEC flag\n");
+       if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
+               dprintk(1, "Queue does support only O_CLOEXEC and access mode flags\n");
                return -EINVAL;
        }
 
@@ -1848,14 +1867,14 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
 
        vb_plane = &vb->planes[eb->plane];
 
-       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
        if (IS_ERR_OR_NULL(dbuf)) {
                dprintk(1, "Failed to export buffer %d, plane %d\n",
                        eb->index, eb->plane);
                return -EINVAL;
        }
 
-       ret = dma_buf_fd(dbuf, eb->flags);
+       ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
        if (ret < 0) {
                dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
                        eb->index, eb->plane, ret);
index 646f08f4f504c05ae37dd95cbc1fe8333705e658..33d3871d1e131dce9a2f1d8392020dce5b8ff799 100644 (file)
@@ -393,7 +393,7 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
        return sgt;
 }
 
-static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
        struct vb2_dc_buf *buf = buf_priv;
        struct dma_buf *dbuf;
@@ -404,7 +404,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
        if (WARN_ON(!buf->sgt_base))
                return NULL;
 
-       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags);
        if (IS_ERR(dbuf))
                return NULL;
 
index 2f860543912cd1c3f5dd4f286705b2c8b208dc37..0d3a8ffe47a3c15efc27faef3712f682e6a7f620 100644 (file)
@@ -178,7 +178,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
        buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
                             GFP_KERNEL);
        if (!buf->pages)
-               return NULL;
+               goto userptr_fail_alloc_pages;
 
        num_pages_from_user = get_user_pages(current, current->mm,
                                             vaddr & PAGE_MASK,
@@ -204,6 +204,7 @@ userptr_fail_get_user_pages:
        while (--num_pages_from_user >= 0)
                put_page(buf->pages[num_pages_from_user]);
        kfree(buf->pages);
+userptr_fail_alloc_pages:
        kfree(buf);
        return NULL;
 }
index 62a60caa5d1fe7eb583cb208fef9b96a5b0dd8f0..dd671582c9a1b2dcf8286b2a798a65e6621752ba 100644 (file)
@@ -32,7 +32,7 @@ config MFD_AS3722
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
-       depends on I2C && OF
+       depends on I2C=y && OF
        help
          The ams AS3722 is a compact system PMU suitable for mobile phones,
          tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down
index da1c6566d93d2f755878d358a018835bd7cd1454..37edf9e989b066cbb1a8a667001ce4e655ac7c1c 100644 (file)
@@ -506,7 +506,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
                .iTCO_version = 2,
        },
        [LPC_WPT_LP] = {
-               .name = "Lynx Point_LP",
+               .name = "Wildcat Point_LP",
                .iTCO_version = 2,
        },
 };
index 11e20afbdcacb7d31e49798db6d2dfbf0504afd8..705698fd2c7ed0f8f5e4fcada7b060627352be05 100644 (file)
@@ -1228,8 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)
 
        pcr->remove_pci = true;
 
-       cancel_delayed_work(&pcr->carddet_work);
-       cancel_delayed_work(&pcr->idle_work);
+       /* Disable interrupts at the pcr level */
+       spin_lock_irq(&pcr->lock);
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+       spin_unlock_irq(&pcr->lock);
+
+       cancel_delayed_work_sync(&pcr->carddet_work);
+       cancel_delayed_work_sync(&pcr->idle_work);
 
        mfd_remove_devices(&pcidev->dev);
 
index 34c18fb8c0896b46f49de48b4d5631a5d780a811..54cc25546592c7c7a1ba113104ca96fa5cacab83 100644 (file)
@@ -81,31 +81,31 @@ static struct of_device_id sec_dt_match[] = {
 
 int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest)
 {
-       return regmap_read(sec_pmic->regmap, reg, dest);
+       return regmap_read(sec_pmic->regmap_pmic, reg, dest);
 }
 EXPORT_SYMBOL_GPL(sec_reg_read);
 
 int sec_bulk_read(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf)
 {
-       return regmap_bulk_read(sec_pmic->regmap, reg, buf, count);
+       return regmap_bulk_read(sec_pmic->regmap_pmic, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(sec_bulk_read);
 
 int sec_reg_write(struct sec_pmic_dev *sec_pmic, u8 reg, u8 value)
 {
-       return regmap_write(sec_pmic->regmap, reg, value);
+       return regmap_write(sec_pmic->regmap_pmic, reg, value);
 }
 EXPORT_SYMBOL_GPL(sec_reg_write);
 
 int sec_bulk_write(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf)
 {
-       return regmap_raw_write(sec_pmic->regmap, reg, buf, count);
+       return regmap_raw_write(sec_pmic->regmap_pmic, reg, buf, count);
 }
 EXPORT_SYMBOL_GPL(sec_bulk_write);
 
 int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask)
 {
-       return regmap_update_bits(sec_pmic->regmap, reg, mask, val);
+       return regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(sec_reg_update);
 
@@ -166,6 +166,11 @@ static struct regmap_config s5m8767_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_config sec_rtc_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
 #ifdef CONFIG_OF
 /*
  * Only the common platform data elements for s5m8767 are parsed here from the
@@ -266,9 +271,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                break;
        }
 
-       sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap);
-       if (IS_ERR(sec_pmic->regmap)) {
-               ret = PTR_ERR(sec_pmic->regmap);
+       sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);
+       if (IS_ERR(sec_pmic->regmap_pmic)) {
+               ret = PTR_ERR(sec_pmic->regmap_pmic);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
                        ret);
                return ret;
@@ -277,6 +282,15 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
        i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
 
+       sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc,
+                       &sec_rtc_regmap_config);
+       if (IS_ERR(sec_pmic->regmap_rtc)) {
+               ret = PTR_ERR(sec_pmic->regmap_rtc);
+               dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
+                       ret);
+               return ret;
+       }
+
        if (pdata && pdata->cfg_pmic_irq)
                pdata->cfg_pmic_irq();
 
index 0dd84e99081e9d30539ab96cccc255591a18be82..b441b1be27cbe9165bd66f94e26c9f750125e665 100644 (file)
@@ -280,19 +280,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 
        switch (type) {
        case S5M8763X:
-               ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
+               ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                  sec_pmic->irq_base, &s5m8763_irq_chip,
                                  &sec_pmic->irq_data);
                break;
        case S5M8767X:
-               ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
+               ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                  sec_pmic->irq_base, &s5m8767_irq_chip,
                                  &sec_pmic->irq_data);
                break;
        case S2MPS11X:
-               ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
+               ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                  sec_pmic->irq_base, &s2mps11_irq_chip,
                                  &sec_pmic->irq_data);
index 71e3e0c5bf730c7e8f3423619d9a2e2acc6fa27d..a5424579679cfcd7e0b835964557ea1188c58eaa 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/sched.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/ti_ssp.h>
 
@@ -409,7 +410,6 @@ static int ti_ssp_probe(struct platform_device *pdev)
                cells[id].id            = id;
                cells[id].name          = data->dev_name;
                cells[id].platform_data = data->pdata;
-               cells[id].data_size     = data->pdata_size;
        }
 
        error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
index 0e8df41aaf144c7a00818bb95959a58060c99efe..2cf2bbc0b927e7d46f381d507dd0729d3bdab23c 100644 (file)
@@ -198,6 +198,13 @@ static void enclosure_remove_links(struct enclosure_component *cdev)
 {
        char name[ENCLOSURE_NAME_SIZE];
 
+       /*
+        * In odd circumstances, like multipath devices, something else may
+        * already have removed the links, so check for this condition first.
+        */
+       if (!cdev->dev->kobj.sd)
+               return;
+
        enclosure_link_name(cdev, name);
        sysfs_remove_link(&cdev->dev->kobj, name);
        sysfs_remove_link(&cdev->cdev.kobj, "device");
index 6c0fde55270d3681c6048c1516b6915c291e4c45..66f411a6e8ea502251ede2b92bca60c59e8843fe 100644 (file)
 #define MEI_DEV_ID_PPT_2      0x1CBA  /* Panther Point */
 #define MEI_DEV_ID_PPT_3      0x1DBA  /* Panther Point */
 
-#define MEI_DEV_ID_LPT        0x8C3A  /* Lynx Point */
+#define MEI_DEV_ID_LPT_H      0x8C3A  /* Lynx Point H */
 #define MEI_DEV_ID_LPT_W      0x8D3A  /* Lynx Point - Wellsburg */
 #define MEI_DEV_ID_LPT_LP     0x9C3A  /* Lynx Point LP */
+#define MEI_DEV_ID_LPT_HR     0x8CBA  /* Lynx Point H Refresh */
+
+#define MEI_DEV_ID_WPT_LP     0x9CBA  /* Wildcat Point LP */
 /*
  * MEI HW Section
  */
index b96205aece0c781d267ef9c2ac198cc154145080..2cab3c0a6805364393e69a5410905874c4103e87 100644 (file)
@@ -76,9 +76,11 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_H)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_W)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_HR)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_WPT_LP)},
 
        /* required last entry */
        {0, }
index 8aa42e738acc6dde99a716535f8b27efcd9d0988..653799b96bfae0dd709367fa20a3a74bc296033d 100644 (file)
@@ -154,14 +154,14 @@ static void mic_reset_inform_host(struct virtio_device *vdev)
 {
        struct mic_vdev *mvdev = to_micvdev(vdev);
        struct mic_device_ctrl __iomem *dc = mvdev->dc;
-       int retry = 100, i;
+       int retry;
 
        iowrite8(0, &dc->host_ack);
        iowrite8(1, &dc->vdev_reset);
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
 
        /* Wait till host completes all card accesses and acks the reset */
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                if (ioread8(&dc->host_ack))
                        break;
                msleep(100);
@@ -187,11 +187,12 @@ static void mic_reset(struct virtio_device *vdev)
 /*
  * The virtio_ring code calls this API when it wants to notify the Host.
  */
-static void mic_notify(struct virtqueue *vq)
+static bool mic_notify(struct virtqueue *vq)
 {
        struct mic_vdev *mvdev = vq->priv;
 
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+       return true;
 }
 
 static void mic_del_vq(struct virtqueue *vq, int n)
@@ -247,17 +248,17 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
        /* First assign the vring's allocated in host memory */
        vqconfig = mic_vq_config(mvdev->desc) + index;
        memcpy_fromio(&config, vqconfig, sizeof(config));
-       _vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN);
+       _vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN);
        vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
-       va = mic_card_map(mvdev->mdev, config.address, vr_size);
+       va = mic_card_map(mvdev->mdev, le64_to_cpu(config.address), vr_size);
        if (!va)
                return ERR_PTR(-ENOMEM);
        mvdev->vr[index] = va;
        memset_io(va, 0x0, _vr_size);
-       vq = vring_new_virtqueue(index,
-                               config.num, MIC_VIRTIO_RING_ALIGN, vdev,
-                               false,
-                               va, mic_notify, callback, name);
+       vq = vring_new_virtqueue(index, le16_to_cpu(config.num),
+                                MIC_VIRTIO_RING_ALIGN, vdev, false,
+                                (void __force *)va, mic_notify, callback,
+                                name);
        if (!vq) {
                err = -ENOMEM;
                goto unmap;
@@ -272,7 +273,8 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
 
        /* Allocate and reassign used ring now */
        mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
-                       sizeof(struct vring_used_elem) * config.num);
+                                            sizeof(struct vring_used_elem) *
+                                            le16_to_cpu(config.num));
        used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(mvdev->used_size[index]));
        if (!used) {
@@ -309,7 +311,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct mic_vdev *mvdev = to_micvdev(vdev);
        struct mic_device_ctrl __iomem *dc = mvdev->dc;
-       int i, err, retry = 100;
+       int i, err, retry;
 
        /* We must have this many virtqueues. */
        if (nvqs > ioread8(&mvdev->desc->num_vq))
@@ -331,7 +333,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
         * rings have been re-assigned.
         */
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                if (!ioread8(&dc->used_address_updated))
                        break;
                msleep(100);
@@ -519,8 +521,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
        struct device *dev;
        int ret;
 
-       for (i = mic_aligned_size(struct mic_bootparam);
-               i < MIC_DP_SIZE; i += mic_total_desc_size(d)) {
+       for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE;
+               i += mic_total_desc_size(d)) {
                d = mdrv->dp + i;
                dc = (void __iomem *)d + mic_aligned_desc_size(d);
                /*
@@ -539,7 +541,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
                        continue;
 
                /* device already exists */
-               dev = device_find_child(mdrv->dev, d, mic_match_desc);
+               dev = device_find_child(mdrv->dev, (void __force *)d,
+                                       mic_match_desc);
                if (dev) {
                        if (remove)
                                iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
index 2c5c22c93ba8e787a1666e74d1b2256c4f894a27..d0407ba53bb7e81b45ecc2b6cfeb6af60ef747b8 100644 (file)
@@ -42,8 +42,8 @@
 
 static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc)
 {
-       return mic_aligned_size(*desc)
-               + ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig)
+       return sizeof(*desc)
+               + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig)
                + ioread8(&desc->feature_len) * 2
                + ioread8(&desc->config_len);
 }
@@ -67,8 +67,7 @@ mic_vq_configspace(struct mic_device_desc __iomem *desc)
 }
 static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc)
 {
-       return mic_aligned_desc_size(desc) +
-               mic_aligned_size(struct mic_device_ctrl);
+       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
 }
 
 int mic_devices_init(struct mic_driver *mdrv);
index 7558d91864380ae849d90a24deee4e31985850eb..b75c6b5cc20fc7a908944291add52a5cada071ff 100644 (file)
@@ -62,7 +62,7 @@ void mic_bootparam_init(struct mic_device *mdev)
 {
        struct mic_bootparam *bootparam = mdev->dp;
 
-       bootparam->magic = MIC_MAGIC;
+       bootparam->magic = cpu_to_le32(MIC_MAGIC);
        bootparam->c2h_shutdown_db = mdev->shutdown_db;
        bootparam->h2c_shutdown_db = -1;
        bootparam->h2c_config_db = -1;
index 5b8494bd1e003ff9cb53d49fa7ffd22798893912..e04bb4fe68235a7de2ac7e5c09c7c027776cb39c 100644 (file)
@@ -41,7 +41,7 @@ static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
         * We are copying from IO below an should ideally use something
         * like copy_to_user_fromio(..) if it existed.
         */
-       if (copy_to_user(ubuf, dbuf, len)) {
+       if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
                err = -EFAULT;
                dev_err(mic_dev(mvdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
@@ -66,7 +66,7 @@ static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
         * We are copying to IO below and should ideally use something
         * like copy_from_user_toio(..) if it existed.
         */
-       if (copy_from_user(dbuf, ubuf, len)) {
+       if (copy_from_user((void __force *)dbuf, ubuf, len)) {
                err = -EFAULT;
                dev_err(mic_dev(mvdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
@@ -293,7 +293,7 @@ static void mic_virtio_init_post(struct mic_vdev *mvdev)
                        continue;
                }
                mvdev->mvr[i].vrh.vring.used =
-                       mvdev->mdev->aper.va +
+                       (void __force *)mvdev->mdev->aper.va +
                        le64_to_cpu(vqconfig[i].used_address);
        }
 
@@ -378,7 +378,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev,
                        void __user *argp)
 {
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int ret = 0, retry = 100, i;
+       int ret = 0, retry, i;
        struct mic_bootparam *bootparam = mvdev->mdev->dp;
        s8 db = bootparam->h2c_config_db;
 
@@ -401,7 +401,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev,
        mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
        mvdev->mdev->ops->send_intr(mvdev->mdev, db);
 
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                ret = wait_event_timeout(wake,
                        mvdev->dc->guest_ack, msecs_to_jiffies(100));
                if (ret)
@@ -467,7 +467,7 @@ static int mic_copy_dp_entry(struct mic_vdev *mvdev,
        }
 
        /* Find the first free device page entry */
-       for (i = mic_aligned_size(struct mic_bootparam);
+       for (i = sizeof(struct mic_bootparam);
                i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
                i += mic_total_desc_size(devp)) {
                devp = mdev->dp + i;
@@ -525,6 +525,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
        char irqname[10];
        struct mic_bootparam *bootparam = mdev->dp;
        u16 num;
+       dma_addr_t vr_addr;
 
        mutex_lock(&mdev->mic_mutex);
 
@@ -559,17 +560,16 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
                }
                vr->len = vr_size;
                vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
-               vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i;
-               vqconfig[i].address = mic_map_single(mdev,
-                       vr->va, vr_size);
-               if (mic_map_error(vqconfig[i].address)) {
+               vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i);
+               vr_addr = mic_map_single(mdev, vr->va, vr_size);
+               if (mic_map_error(vr_addr)) {
                        free_pages((unsigned long)vr->va, get_order(vr_size));
                        ret = -ENOMEM;
                        dev_err(mic_dev(mvdev), "%s %d err %d\n",
                                __func__, __LINE__, ret);
                        goto err;
                }
-               vqconfig[i].address = cpu_to_le64(vqconfig[i].address);
+               vqconfig[i].address = cpu_to_le64(vr_addr);
 
                vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
                ret = vringh_init_kern(&mvr->vrh,
@@ -639,7 +639,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
        struct mic_vdev *tmp_mvdev;
        struct mic_device *mdev = mvdev->mdev;
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int i, ret, retry = 100;
+       int i, ret, retry;
        struct mic_vqconfig *vqconfig;
        struct mic_bootparam *bootparam = mdev->dp;
        s8 db;
@@ -652,16 +652,16 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
                "Requesting hot remove id %d\n", mvdev->virtio_id);
        mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
        mdev->ops->send_intr(mdev, db);
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                ret = wait_event_timeout(wake,
                        mvdev->dc->guest_ack, msecs_to_jiffies(100));
                if (ret)
                        break;
        }
        dev_dbg(mdev->sdev->parent,
-               "Device id %d config_change %d guest_ack %d\n",
+               "Device id %d config_change %d guest_ack %d retry %d\n",
                mvdev->virtio_id, mvdev->dc->config_change,
-               mvdev->dc->guest_ack);
+               mvdev->dc->guest_ack, retry);
        mvdev->dc->config_change = 0;
        mvdev->dc->guest_ack = 0;
 skip_hot_remove:
index 81e9541b784c3a4d46bbd352c2aa26faf70c2877..0dfa8a81436e80ebd325d1722caa791d5193936e 100644 (file)
@@ -397,8 +397,8 @@ mic_x100_load_ramdisk(struct mic_device *mdev)
         * so copy over the ramdisk @ 128M.
         */
        memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size);
-       iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image);
-       iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size);
+       iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image);
+       iowrite32(fw->size, &bp->hdr.ramdisk_size);
        release_firmware(fw);
 error:
        return rc;
index 0b10a9030f4e2a85029ea4bab3afcdb8102899be..98b6b6ef7e5c9d737a749e9a3ddf631f5d92c1c0 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
+#include <linux/of.h>
 #include <linux/omap-dma.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #define OMAP_MMC_CMDTYPE_AC    2
 #define OMAP_MMC_CMDTYPE_ADTC  3
 
-#define OMAP_DMA_MMC_TX                21
-#define OMAP_DMA_MMC_RX                22
-#define OMAP_DMA_MMC2_TX       54
-#define OMAP_DMA_MMC2_RX       55
-
-#define OMAP24XX_DMA_MMC2_TX   47
-#define OMAP24XX_DMA_MMC2_RX   48
-#define OMAP24XX_DMA_MMC1_TX   61
-#define OMAP24XX_DMA_MMC1_RX   62
-
-
 #define DRIVER_NAME "mmci-omap"
 
 /* Specifies how often in millisecs to poll for card status changes
@@ -1330,7 +1320,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
        struct mmc_omap_host *host = NULL;
        struct resource *res;
        dma_cap_mask_t mask;
-       unsigned sig;
+       unsigned sig = 0;
        int i, ret = 0;
        int irq;
 
@@ -1340,7 +1330,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
        }
        if (pdata->nr_slots == 0) {
                dev_err(&pdev->dev, "no slots\n");
-               return -ENXIO;
+               return -EPROBE_DEFER;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1407,19 +1397,20 @@ static int mmc_omap_probe(struct platform_device *pdev)
        host->dma_tx_burst = -1;
        host->dma_rx_burst = -1;
 
-       if (mmc_omap2())
-               sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
-       else
-               sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
-       host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+       if (res)
+               sig = res->start;
+       host->dma_tx = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, &pdev->dev, "tx");
        if (!host->dma_tx)
                dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
                        sig);
-       if (mmc_omap2())
-               sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
-       else
-               sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
-       host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+       if (res)
+               sig = res->start;
+       host->dma_rx = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, &pdev->dev, "rx");
        if (!host->dma_rx)
                dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n",
                        sig);
@@ -1512,12 +1503,20 @@ static int mmc_omap_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id mmc_omap_match[] = {
+       { .compatible = "ti,omap2420-mmc", },
+       { },
+};
+#endif
+
 static struct platform_driver mmc_omap_driver = {
        .probe          = mmc_omap_probe,
        .remove         = mmc_omap_remove,
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(mmc_omap_match),
        },
 };
 
index d210d131fef255da97e7d277574ac80f01a66341..0f55589a56b815af4c00bc521c504db468774fa5 100644 (file)
@@ -73,7 +73,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        info->map.cached =
-               ioremap_cached(info->map.phys, info->map.size);
+               ioremap_cache(info->map.phys, info->map.size);
        if (!info->map.cached)
                printk(KERN_WARNING "Failed to ioremap cached %s\n",
                       info->map.name);
index 4cabdc9fda9076ceff440af42e028fb1073f9ed7..4b3aaa898a8b6b3a4975d2218370711981cb59c4 100644 (file)
@@ -962,7 +962,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 {
        struct platform_device *pdev = info->pdev;
-       if (use_dma) {
+       if (info->use_dma) {
                pxa_free_dma(info->data_dma_ch);
                dma_free_coherent(&pdev->dev, info->buf_size,
                                  info->data_buff, info->data_buff_phys);
@@ -1259,10 +1259,6 @@ static struct of_device_id pxa3xx_nand_dt_ids[] = {
                .compatible = "marvell,pxa3xx-nand",
                .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
        },
-       {
-               .compatible = "marvell,armada370-nand",
-               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
-       },
        {}
 };
 MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
index 187b1b7772ef1b873303fc46998a591137bec7b7..4ced59436558e65a723df9975e8302fcec2cbb62 100644 (file)
@@ -2201,20 +2201,25 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                (__get_link_speed(port) << 1);
        pr_debug("Port %d changed speed\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2229,20 +2234,25 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
+       __get_state_machine_lock(port);
+
        port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
        port->actor_oper_port_key = port->actor_admin_port_key |=
                __get_duplex(port);
        pr_debug("Port %d changed duplex\n", port->actor_port_number);
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /**
@@ -2258,15 +2268,21 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
 
        port = &(SLAVE_AD_INFO(slave).port);
 
-       // if slave is null, the whole port is not initialized
+       /* if slave is null, the whole port is not initialized */
        if (!port->slave) {
                pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
                           slave->bond->dev->name, slave->dev->name);
                return;
        }
 
-       // on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
-       // on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+       __get_state_machine_lock(port);
+       /* on link down we are zeroing duplex and speed since
+        * some of the adaptors(ce1000.lan) report full duplex/speed
+        * instead of N/A(duplex) / 0(speed).
+        *
+        * on link up we are forcing recheck on the duplex and speed since
+        * some of he adaptors(ce1000.lan) report.
+        */
        if (link == BOND_LINK_UP) {
                port->is_enabled = true;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
@@ -2282,10 +2298,15 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
                port->actor_oper_port_key = (port->actor_admin_port_key &=
                                             ~AD_SPEED_KEY_BITS);
        }
-       //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
-       // there is no need to reselect a new aggregator, just signal the
-       // state machines to reinitialize
+       pr_debug("Port %d changed link status to %s",
+               port->actor_port_number,
+               (link == BOND_LINK_UP) ? "UP" : "DOWN");
+       /* there is no need to reselect a new aggregator, just signal the
+        * state machines to reinitialize
+        */
        port->sm_vars |= AD_PORT_BEGIN;
+
+       __release_state_machine_lock(port);
 }
 
 /*
index 4dd5ee2a34cc68c4222f4c4115beedaee8b187d2..6191b551a0e83b9083bc17d70a302956af0ed296 100644 (file)
@@ -1763,7 +1763,7 @@ static int __bond_release_one(struct net_device *bond_dev,
        }
 
        if (all) {
-               rcu_assign_pointer(bond->curr_active_slave, NULL);
+               RCU_INIT_POINTER(bond->curr_active_slave, NULL);
        } else if (oldcurrent == slave) {
                /*
                 * Note that we hold RTNL over this sequence, so there
@@ -3732,7 +3732,8 @@ static inline int bond_slave_override(struct bonding *bond,
 }
 
 
-static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
@@ -4110,7 +4111,7 @@ static int bond_check_params(struct bond_params *params)
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
                        pr_warning("Forcing miimon to 100msec\n");
-                       miimon = 100;
+                       miimon = BOND_DEFAULT_MIIMON;
                }
        }
 
@@ -4147,7 +4148,7 @@ static int bond_check_params(struct bond_params *params)
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure and link speed which are essential for TLB/ALB load balancing\n");
                        pr_warning("Forcing miimon to 100msec\n");
-                       miimon = 100;
+                       miimon = BOND_DEFAULT_MIIMON;
                }
        }
 
@@ -4199,9 +4200,9 @@ static int bond_check_params(struct bond_params *params)
             (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[i]; i++) {
                /* not complete check, but should be good enough to
                   catch mistakes */
-               __be32 ip = in_aton(arp_ip_target[i]);
-               if (!isdigit(arp_ip_target[i][0]) || ip == 0 ||
-                   ip == htonl(INADDR_BROADCAST)) {
+               __be32 ip;
+               if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) ||
+                   IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) {
                        pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
                                   arp_ip_target[i]);
                        arp_interval = 0;
index 9a5223c7b4d1a14f9b19354cfba6c4ea3dd933d0..ea6f640782b7456228787fa33ab8882b2bd8aa0b 100644 (file)
@@ -45,10 +45,15 @@ int bond_option_mode_set(struct bonding *bond, int mode)
                return -EPERM;
        }
 
-       if (BOND_MODE_IS_LB(mode) && bond->params.arp_interval) {
-               pr_err("%s: %s mode is incompatible with arp monitoring.\n",
-                      bond->dev->name, bond_mode_tbl[mode].modename);
-               return -EINVAL;
+       if (BOND_NO_USES_ARP(mode) && bond->params.arp_interval) {
+               pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n",
+                       bond->dev->name, bond_mode_tbl[mode].modename);
+               /* disable arp monitoring */
+               bond->params.arp_interval = 0;
+               /* set miimon to default value */
+               bond->params.miimon = BOND_DEFAULT_MIIMON;
+               pr_info("%s: Setting MII monitoring interval to %d.\n",
+                       bond->dev->name, bond->params.miimon);
        }
 
        /* don't cache arp_validate between modes */
index 0ec2a7e8c8a9588170c97715856e7b5f34cf7c60..0ae580bbc5db02ec4dbb3c5855ada7164f32c89a 100644 (file)
@@ -523,9 +523,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                ret = -EINVAL;
                goto out;
        }
-       if (bond->params.mode == BOND_MODE_ALB ||
-           bond->params.mode == BOND_MODE_TLB ||
-           bond->params.mode == BOND_MODE_8023AD) {
+       if (BOND_NO_USES_ARP(bond->params.mode)) {
                pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
                        bond->dev->name, bond->dev->name);
                ret = -EINVAL;
@@ -1637,12 +1635,12 @@ static ssize_t bonding_show_packets_per_slave(struct device *d,
                                              char *buf)
 {
        struct bonding *bond = to_bond(d);
-       int packets_per_slave = bond->params.packets_per_slave;
+       unsigned int packets_per_slave = bond->params.packets_per_slave;
 
        if (packets_per_slave > 1)
                packets_per_slave = reciprocal_value(packets_per_slave);
 
-       return sprintf(buf, "%d\n", packets_per_slave);
+       return sprintf(buf, "%u\n", packets_per_slave);
 }
 
 static ssize_t bonding_store_packets_per_slave(struct device *d,
index ca31286aa028158341a5847382b75afb74a6ea2f..a9f4f9f4d8ceea321061e94f35164829e1de2f7c 100644 (file)
@@ -35,6 +35,8 @@
 
 #define BOND_MAX_ARP_TARGETS   16
 
+#define BOND_DEFAULT_MIIMON    100
+
 #define IS_UP(dev)                                        \
              ((((dev)->flags & IFF_UP) == IFF_UP)      && \
               netif_running(dev)                       && \
                 ((mode) == BOND_MODE_TLB)          ||  \
                 ((mode) == BOND_MODE_ALB))
 
+#define BOND_NO_USES_ARP(mode)                         \
+               (((mode) == BOND_MODE_8023AD)   ||      \
+                ((mode) == BOND_MODE_TLB)      ||      \
+                ((mode) == BOND_MODE_ALB))
+
 #define TX_QUEUE_OVERRIDE(mode)                                \
                        (((mode) == BOND_MODE_ACTIVEBACKUP) ||  \
                         ((mode) == BOND_MODE_ROUNDROBIN))
index e3fc07cf2f6269e5ccf0ca5dbf42897c191cecd4..77061eebb034f4295258d9b0800fed28865d123a 100644 (file)
@@ -712,22 +712,31 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
        return 0;
 }
 
-static int c_can_get_berr_counter(const struct net_device *dev,
-                                       struct can_berr_counter *bec)
+static int __c_can_get_berr_counter(const struct net_device *dev,
+                                   struct can_berr_counter *bec)
 {
        unsigned int reg_err_counter;
        struct c_can_priv *priv = netdev_priv(dev);
 
-       c_can_pm_runtime_get_sync(priv);
-
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
                                ERR_CNT_REC_SHIFT;
        bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
 
+       return 0;
+}
+
+static int c_can_get_berr_counter(const struct net_device *dev,
+                                 struct can_berr_counter *bec)
+{
+       struct c_can_priv *priv = netdev_priv(dev);
+       int err;
+
+       c_can_pm_runtime_get_sync(priv);
+       err = __c_can_get_berr_counter(dev, bec);
        c_can_pm_runtime_put_sync(priv);
 
-       return 0;
+       return err;
 }
 
 /*
@@ -754,6 +763,7 @@ static void c_can_do_tx(struct net_device *dev)
                if (!(val & (1 << (msg_obj_no - 1)))) {
                        can_get_echo_skb(dev,
                                        msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+                       c_can_object_get(dev, 0, msg_obj_no, IF_COMM_ALL);
                        stats->tx_bytes += priv->read_reg(priv,
                                        C_CAN_IFACE(MSGCTRL_REG, 0))
                                        & IF_MCONT_DLC_MASK;
@@ -872,7 +882,7 @@ static int c_can_handle_state_change(struct net_device *dev,
        if (unlikely(!skb))
                return 0;
 
-       c_can_get_berr_counter(dev, &bec);
+       __c_can_get_berr_counter(dev, &bec);
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
                                ERR_CNT_RP_SHIFT;
index ae08cf129ebbb0bda31f4b74893574b9703253f0..aaed97bee4711d1cb2e8b1eb514fc3e343ad21e0 100644 (file)
@@ -1020,13 +1020,13 @@ static int flexcan_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "no ipg clock defined\n");
                        return PTR_ERR(clk_ipg);
                }
-               clock_freq = clk_get_rate(clk_ipg);
 
                clk_per = devm_clk_get(&pdev->dev, "per");
                if (IS_ERR(clk_per)) {
                        dev_err(&pdev->dev, "no per clock defined\n");
                        return PTR_ERR(clk_per);
                }
+               clock_freq = clk_get_rate(clk_per);
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 7164a999f50ff37e176f9995f21cd04451f17043..f17c3018b7c7ffb3f7d75785c3ddd2218b0f3f79 100644 (file)
@@ -494,20 +494,20 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
        uint8_t isrc, status;
        int n = 0;
 
-       /* Shared interrupts and IRQ off? */
-       if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
-               return IRQ_NONE;
-
        if (priv->pre_irq)
                priv->pre_irq(priv);
 
+       /* Shared interrupts and IRQ off? */
+       if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
+               goto out;
+
        while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&
               (n < SJA1000_MAX_IRQ)) {
-               n++;
+
                status = priv->read_reg(priv, SJA1000_SR);
                /* check for absent controller due to hw unplug */
                if (status == 0xFF && sja1000_is_absent(priv))
-                       return IRQ_NONE;
+                       goto out;
 
                if (isrc & IRQ_WUI)
                        netdev_warn(dev, "wakeup interrupt\n");
@@ -535,7 +535,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                                status = priv->read_reg(priv, SJA1000_SR);
                                /* check for absent controller */
                                if (status == 0xFF && sja1000_is_absent(priv))
-                                       return IRQ_NONE;
+                                       goto out;
                        }
                }
                if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
@@ -543,8 +543,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                        if (sja1000_err(dev, isrc, status))
                                break;
                }
+               n++;
        }
-
+out:
        if (priv->post_irq)
                priv->post_irq(priv);
 
index 5f9a7ad9b964da35190f01154492189965ba28ac..8aeec0b4601a2e8fe45290643a910a4fd8e4137b 100644 (file)
@@ -625,6 +625,7 @@ static int ems_usb_start(struct ems_usb *dev)
                        usb_unanchor_urb(urb);
                        usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
                                          urb->transfer_dma);
+                       usb_free_urb(urb);
                        break;
                }
 
@@ -798,8 +799,8 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
         * allowed (MAX_TX_URBS).
         */
        if (!context) {
-               usb_unanchor_urb(urb);
                usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
+               usb_free_urb(urb);
 
                netdev_warn(netdev, "couldn't find free context\n");
 
index 8ee9d1556e6e4eb3b8d32cfb988ba9870fccffaa..263dd921edc42342bba78ce9f2885862f0fc3087 100644 (file)
@@ -927,6 +927,9 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev)
        /* set LED in default state (end of init phase) */
        pcan_usb_pro_set_led(dev, 0, 1);
 
+       kfree(bi);
+       kfree(fi);
+
        return 0;
 
  err_out:
index fb3dd4399cf36e24cd4a1fe809333d140c8419f2..f615fdec0f1b2fb800189d97395554ecd392fa60 100644 (file)
@@ -113,7 +113,7 @@ static const struct net_device_ops hydra_netdev_ops = {
 static int hydra_init(struct zorro_dev *z)
 {
     struct net_device *dev;
-    unsigned long board = ZTWO_VADDR(z->resource.start);
+    unsigned long board = (unsigned long)ZTWO_VADDR(z->resource.start);
     unsigned long ioaddr = board+HYDRA_NIC_BASE;
     const char name[] = "NE2000";
     int start_page, stop_page;
index 85ec4c2d2645582339eb7ecfa796e9b37fee91ad..ae2a12b7db62db6fcc748019af9abca0e2abf051 100644 (file)
@@ -287,7 +287,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
 };
 
 static int zorro8390_init(struct net_device *dev, unsigned long board,
-                         const char *name, unsigned long ioaddr)
+                         const char *name, void __iomem *ioaddr)
 {
        int i;
        int err;
@@ -354,7 +354,7 @@ static int zorro8390_init(struct net_device *dev, unsigned long board,
        start_page = NESM_START_PG;
        stop_page = NESM_STOP_PG;
 
-       dev->base_addr = ioaddr;
+       dev->base_addr = (unsigned long)ioaddr;
        dev->irq = IRQ_AMIGA_PORTS;
 
        /* Install the Interrupt handler */
index 50b853a79d7787c73d0ea8d0ac1f1e0853ac2adf..46dfb1378c17cac79064a5f3f809e94a1d75c584 100644 (file)
@@ -717,8 +717,7 @@ static int emac_open(struct net_device *dev)
        if (netif_msg_ifup(db))
                dev_dbg(db->dev, "enabling %s\n", dev->name);
 
-       if (devm_request_irq(db->dev, dev->irq, &emac_interrupt,
-                            0, dev->name, dev))
+       if (request_irq(dev->irq, &emac_interrupt, 0, dev->name, dev))
                return -EAGAIN;
 
        /* Initialize EMAC board */
@@ -774,6 +773,8 @@ static int emac_stop(struct net_device *ndev)
 
        emac_shutdown(ndev);
 
+       free_irq(ndev->irq, ndev);
+
        return 0;
 }
 
index 0866e7627433c1148037b9ade8064351c2819722..56139184b8019c132428654a5af6a4bd4018de14 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/zorro.h>
 #include <linux/bitops.h>
 
+#include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
@@ -678,6 +679,7 @@ static int a2065_init_one(struct zorro_dev *z,
        unsigned long base_addr = board + A2065_LANCE;
        unsigned long mem_start = board + A2065_RAM;
        struct resource *r1, *r2;
+       u32 serial;
        int err;
 
        r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
@@ -702,6 +704,7 @@ static int a2065_init_one(struct zorro_dev *z,
        r1->name = dev->name;
        r2->name = dev->name;
 
+       serial = be32_to_cpu(z->rom.er_SerialNumber);
        dev->dev_addr[0] = 0x00;
        if (z->id != ZORRO_PROD_AMERISTAR_A2065) {      /* Commodore */
                dev->dev_addr[1] = 0x80;
@@ -710,11 +713,11 @@ static int a2065_init_one(struct zorro_dev *z,
                dev->dev_addr[1] = 0x00;
                dev->dev_addr[2] = 0x9f;
        }
-       dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
-       dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
-       dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-       dev->base_addr = ZTWO_VADDR(base_addr);
-       dev->mem_start = ZTWO_VADDR(mem_start);
+       dev->dev_addr[3] = (serial >> 16) & 0xff;
+       dev->dev_addr[4] = (serial >> 8) & 0xff;
+       dev->dev_addr[5] = serial & 0xff;
+       dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr);
+       dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start);
        dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
 
        priv->ll = (volatile struct lance_regs *)dev->base_addr;
index c178eb4c81668ad3a1b033f11c9070b9e63c934d..b08101b31b8bc547ffbfb486f87abc7a18f92686 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/zorro.h>
 #include <linux/bitops.h>
 
+#include <asm/byteorder.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
 #include <asm/irq.h>
@@ -718,6 +719,7 @@ static int ariadne_init_one(struct zorro_dev *z,
        struct resource *r1, *r2;
        struct net_device *dev;
        struct ariadne_private *priv;
+       u32 serial;
        int err;
 
        r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
@@ -741,14 +743,15 @@ static int ariadne_init_one(struct zorro_dev *z,
        r1->name = dev->name;
        r2->name = dev->name;
 
+       serial = be32_to_cpu(z->rom.er_SerialNumber);
        dev->dev_addr[0] = 0x00;
        dev->dev_addr[1] = 0x60;
        dev->dev_addr[2] = 0x30;
-       dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
-       dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
-       dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-       dev->base_addr = ZTWO_VADDR(base_addr);
-       dev->mem_start = ZTWO_VADDR(mem_start);
+       dev->dev_addr[3] = (serial >> 16) & 0xff;
+       dev->dev_addr[4] = (serial >> 8) & 0xff;
+       dev->dev_addr[5] = serial & 0xff;
+       dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr);
+       dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start);
        dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
 
        dev->netdev_ops = &ariadne_netdev_ops;
index b2ffad1304d221ef54e60cd1a82138a4d8344975..248baf6273fb76a2b179c50fe068aeddff51a42e 100644 (file)
@@ -565,6 +565,8 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        /* Make sure pointer to data buffer is set */
        wmb();
 
+       skb_tx_timestamp(skb);
+
        *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len);
 
        /* Increment index to point to the next BD */
@@ -579,8 +581,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
 
        arc_reg_set(priv, R_STATUS, TXPL_MASK);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
index a36a760ada28af64272a5132a60648c543963bed..29801750f239b247389c7040f6616f9b79d14983 100644 (file)
@@ -145,9 +145,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
         * Mask some pcie error bits
         */
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
-       pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
-       data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
-       pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       if (pos) {
+               pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data);
+               data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP);
+               pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data);
+       }
        /* clear error status */
        pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,
                        PCI_EXP_DEVSTA_NFED |
index a1f66e2c9a8694c9d83471dd63f6659d431840eb..ec6119089b82b8445cd573d961378c70b28632e5 100644 (file)
@@ -520,10 +520,12 @@ struct bnx2x_fastpath {
 #define BNX2X_FP_STATE_IDLE                  0
 #define BNX2X_FP_STATE_NAPI            (1 << 0)    /* NAPI owns this FP */
 #define BNX2X_FP_STATE_POLL            (1 << 1)    /* poll owns this FP */
-#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 2)    /* NAPI yielded this FP */
-#define BNX2X_FP_STATE_POLL_YIELD      (1 << 3)    /* poll yielded this FP */
+#define BNX2X_FP_STATE_DISABLED                (1 << 2)
+#define BNX2X_FP_STATE_NAPI_YIELD      (1 << 3)    /* NAPI yielded this FP */
+#define BNX2X_FP_STATE_POLL_YIELD      (1 << 4)    /* poll yielded this FP */
+#define BNX2X_FP_OWNED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
 #define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD)
-#define BNX2X_FP_LOCKED        (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL)
+#define BNX2X_FP_LOCKED        (BNX2X_FP_OWNED | BNX2X_FP_STATE_DISABLED)
 #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD)
        /* protect state */
        spinlock_t lock;
@@ -613,7 +615,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = true;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        if (fp->state & BNX2X_FP_LOCKED) {
                WARN_ON(fp->state & BNX2X_FP_STATE_NAPI);
                fp->state |= BNX2X_FP_STATE_NAPI_YIELD;
@@ -622,7 +624,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp)
                /* we don't care if someone yielded */
                fp->state = BNX2X_FP_STATE_NAPI;
        }
-       spin_unlock(&fp->lock);
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -631,14 +633,16 @@ static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp)
 {
        bool rc = false;
 
-       spin_lock(&fp->lock);
+       spin_lock_bh(&fp->lock);
        WARN_ON(fp->state &
                (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD));
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
-       spin_unlock(&fp->lock);
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
        return rc;
 }
 
@@ -669,7 +673,9 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 
        if (fp->state & BNX2X_FP_STATE_POLL_YIELD)
                rc = true;
-       fp->state = BNX2X_FP_STATE_IDLE;
+
+       /* state ==> idle, unless currently disabled */
+       fp->state &= BNX2X_FP_STATE_DISABLED;
        spin_unlock_bh(&fp->lock);
        return rc;
 }
@@ -677,9 +683,23 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp)
 /* true if a socket is polling, even if it did not get the lock */
 static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
-       WARN_ON(!(fp->state & BNX2X_FP_LOCKED));
+       WARN_ON(!(fp->state & BNX2X_FP_OWNED));
        return fp->state & BNX2X_FP_USER_PEND;
 }
+
+/* false if fp is currently owned */
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       int rc = true;
+
+       spin_lock_bh(&fp->lock);
+       if (fp->state & BNX2X_FP_OWNED)
+               rc = false;
+       fp->state |= BNX2X_FP_STATE_DISABLED;
+       spin_unlock_bh(&fp->lock);
+
+       return rc;
+}
 #else
 static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp)
 {
@@ -709,6 +729,10 @@ static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp)
 {
        return false;
 }
+static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp)
+{
+       return true;
+}
 #endif /* CONFIG_NET_RX_BUSY_POLL */
 
 /* Use 2500 as a mini-jumbo MTU for FCoE */
@@ -1250,7 +1274,10 @@ struct bnx2x_slowpath {
         * Therefore, if they would have been defined in the same union,
         * data can get corrupted.
         */
-       struct afex_vif_list_ramrod_data func_afex_rdata;
+       union {
+               struct afex_vif_list_ramrod_data        viflist_data;
+               struct function_update_data             func_update;
+       } func_afex_rdata;
 
        /* used by dmae command executer */
        struct dmae_command             dmae[MAX_DMAE_C];
@@ -2499,4 +2526,6 @@ void bnx2x_set_local_cmng(struct bnx2x *bp);
 #define MCPR_SCRATCH_BASE(bp) \
        (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
 
+#define E1H_MAX_MF_SB_COUNT (HC_SB_MAX_SB_E1X/(E1HVN_MAX * PORT_MAX))
+
 #endif /* bnx2x.h */
index ec96130533cc54630c3f26f6253e58b5a0f5a7cf..bf811565ee245a0472cffc0ea5f70b30da053beb 100644 (file)
@@ -160,6 +160,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        struct sk_buff *skb = tx_buf->skb;
        u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
        int nbd;
+       u16 split_bd_len = 0;
 
        /* prefetch skb end pointer to speedup dev_kfree_skb() */
        prefetch(&skb->end);
@@ -167,10 +168,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        DP(NETIF_MSG_TX_DONE, "fp[%d]: pkt_idx %d  buff @(%p)->skb %p\n",
           txdata->txq_index, idx, tx_buf, skb);
 
-       /* unmap first bd */
        tx_start_bd = &txdata->tx_desc_ring[bd_idx].start_bd;
-       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
-                        BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
 
        nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
 #ifdef BNX2X_STOP_ON_ERROR
@@ -188,12 +186,19 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata,
        --nbd;
        bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
 
-       /* ...and the TSO split header bd since they have no mapping */
+       /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */
        if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) {
+               tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd;
+               split_bd_len = BD_UNMAP_LEN(tx_data_bd);
                --nbd;
                bd_idx = TX_BD(NEXT_TX_IDX(bd_idx));
        }
 
+       /* unmap first bd */
+       dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
+                        BD_UNMAP_LEN(tx_start_bd) + split_bd_len,
+                        DMA_TO_DEVICE);
+
        /* now free frags */
        while (nbd > 0) {
 
@@ -1790,26 +1795,22 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_rx_queue_cnic(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 static void bnx2x_napi_disable(struct bnx2x *bp)
 {
        int i;
 
-       local_bh_disable();
        for_each_eth_queue(bp, i) {
                napi_disable(&bnx2x_fp(bp, i, napi));
-               while (!bnx2x_fp_lock_napi(&bp->fp[i]))
-                       mdelay(1);
+               while (!bnx2x_fp_ll_disable(&bp->fp[i]))
+                       usleep_range(1000, 2000);
        }
-       local_bh_enable();
 }
 
 void bnx2x_netif_start(struct bnx2x *bp)
@@ -1832,7 +1833,8 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
                bnx2x_napi_disable_cnic(bp);
 }
 
-u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
index da8fcaa74495475cb2c2c3984f3aa3cf85fc83ba..41f3ca5ad972b396498cbe5b7d7ad72ea9bdb1a7 100644 (file)
@@ -524,7 +524,8 @@ int bnx2x_set_vf_mac(struct net_device *dev, int queue, u8 *mac);
 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);
+u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
+                      void *accel_priv);
 
 static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
                                        struct bnx2x_fastpath *fp,
index 20dcc02431cac441a8bf3076a7fe6db1abfb04e9..11fc79585491f484f7ffd56d7a2e8e876ebb8e79 100644 (file)
@@ -3865,6 +3865,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
        } else {
+               /* Enable Auto-Detect to support 1G over CL37 as well */
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x10);
+
+               /* Force cl48 sync_status LOW to avoid getting stuck in CL73
+                * parallel-detect loop when CL73 and CL37 are enabled.
+                */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI, 0x0800);
+               bnx2x_set_aer_mmd(params, phy);
+
                bnx2x_disable_kr2(params, vars, phy);
        }
 
@@ -8120,17 +8133,20 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                *edc_mode = EDC_MODE_ACTIVE_DAC;
                        else
                                check_limiting_mode = 1;
-               } else if (copper_module_type &
-                       SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
+               } else {
+                       *edc_mode = EDC_MODE_PASSIVE_DAC;
+                       /* Even in case PASSIVE_DAC indication is not set,
+                        * treat it as a passive DAC cable, since some cables
+                        * don't have this indication.
+                        */
+                       if (copper_module_type &
+                           SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
                                   "Passive Copper cable detected\n");
-                               *edc_mode =
-                                     EDC_MODE_PASSIVE_DAC;
-               } else {
-                       DP(NETIF_MSG_LINK,
-                          "Unknown copper-cable-type 0x%x !!!\n",
-                          copper_module_type);
-                       return -EINVAL;
+                       } else {
+                               DP(NETIF_MSG_LINK,
+                                  "Unknown copper-cable-type\n");
+                       }
                }
                break;
        }
@@ -10825,9 +10841,9 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                           (1<<11));
 
        if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
-                       (phy->req_line_speed == SPEED_1000)) {
+            (phy->speed_cap_mask &
+             PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
+           (phy->req_line_speed == SPEED_1000)) {
                an_1000_val |= (1<<8);
                autoneg_val |= (1<<9 | 1<<12);
                if (phy->req_duplex == DUPLEX_FULL)
@@ -10843,30 +10859,32 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
                        0x09,
                        &an_1000_val);
 
-       /* Set 100 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
-               an_10_100_val |= (1<<7);
-               /* Enable autoneg and restart autoneg for legacy speeds */
-               autoneg_val |= (1<<9 | 1<<12);
-
-               if (phy->req_duplex == DUPLEX_FULL)
-                       an_10_100_val |= (1<<8);
-               DP(NETIF_MSG_LINK, "Advertising 100M\n");
-       }
-
-       /* Set 10 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-                       (phy->speed_cap_mask &
-                       (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-                       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
-               an_10_100_val |= (1<<5);
-               autoneg_val |= (1<<9 | 1<<12);
-               if (phy->req_duplex == DUPLEX_FULL)
+       /* Advertise 10/100 link speed */
+       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) {
+                       an_10_100_val |= (1<<5);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) {
                        an_10_100_val |= (1<<6);
-               DP(NETIF_MSG_LINK, "Advertising 10M\n");
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+                       an_10_100_val |= (1<<7);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+               }
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+                       an_10_100_val |= (1<<8);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+               }
        }
 
        /* Only 10/100 are allowed to work in FORCE mode */
@@ -13342,6 +13360,10 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
 
+       /* Do not touch the link in case physical link down */
+       if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
+               return 1;
+
        /* a. Update shmem->link_status accordingly
         * b. Update link_vars->link_up
         */
@@ -13550,7 +13572,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
         */
        not_kr2_device = (((base_page & 0x8000) == 0) ||
                          (((base_page & 0x8000) &&
-                           ((next_page & 0xe0) == 0x2))));
+                           ((next_page & 0xe0) == 0x20))));
 
        /* In case KR2 is already disabled, check if we need to re-enable it */
        if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
index 814d0eca9b334ea86c862bc617a46f137f04d475..0067b975873f1592f0fbc2f7dc4a67de91d8c900 100644 (file)
@@ -11447,9 +11447,9 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp)
                }
        }
 
-       /* adjust igu_sb_cnt to MF for E1x */
-       if (CHIP_IS_E1x(bp) && IS_MF(bp))
-               bp->igu_sb_cnt /= E1HVN_MAX;
+       /* adjust igu_sb_cnt to MF for E1H */
+       if (CHIP_IS_E1H(bp) && IS_MF(bp))
+               bp->igu_sb_cnt = min_t(u8, bp->igu_sb_cnt, E1H_MAX_MF_SB_COUNT);
 
        /* port info */
        bnx2x_get_port_hwinfo(bp);
@@ -12942,25 +12942,26 @@ static void __bnx2x_remove(struct pci_dev *pdev,
                pci_set_power_state(pdev, PCI_D3hot);
        }
 
-       if (bp->regview)
-               iounmap(bp->regview);
+       if (remove_netdev) {
+               if (bp->regview)
+                       iounmap(bp->regview);
 
-       /* for vf doorbells are part of the regview and were unmapped along with
-        * it. FW is only loaded by PF.
-        */
-       if (IS_PF(bp)) {
-               if (bp->doorbells)
-                       iounmap(bp->doorbells);
+               /* For vfs, doorbells are part of the regview and were unmapped
+                * along with it. FW is only loaded by PF.
+                */
+               if (IS_PF(bp)) {
+                       if (bp->doorbells)
+                               iounmap(bp->doorbells);
 
-               bnx2x_release_firmware(bp);
-       }
-       bnx2x_free_mem_bp(bp);
+                       bnx2x_release_firmware(bp);
+               }
+               bnx2x_free_mem_bp(bp);
 
-       if (remove_netdev)
                free_netdev(dev);
 
-       if (atomic_read(&pdev->enable_cnt) == 1)
-               pci_release_regions(pdev);
+               if (atomic_read(&pdev->enable_cnt) == 1)
+                       pci_release_regions(pdev);
+       }
 
        pci_disable_device(pdev);
 }
index 3efbb35267c853d576cc3a4d3104ec4ba1a18d1d..14ffb6e56e593d6a371e1036edf02ff7c193eb08 100644 (file)
@@ -7179,6 +7179,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX1_PCI_CTRL                       0x80ca
 #define MDIO_WC_REG_RX2_PCI_CTRL                       0x80da
 #define MDIO_WC_REG_RX3_PCI_CTRL                       0x80ea
+#define MDIO_WC_REG_RXB_ANA_RX_CONTROL_PCI             0x80fa
 #define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G          0x8104
 #define MDIO_WC_REG_XGXS_STATUS3                       0x8129
 #define MDIO_WC_REG_PAR_DET_10G_STATUS                 0x8130
index 32c92abf50949fa1494812ab9d3734a5a2f3db1f..18438a504d573082239fe53532035d5516ff2881 100644 (file)
@@ -2038,6 +2038,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        struct bnx2x_vlan_mac_ramrod_params p;
        struct bnx2x_exe_queue_obj *exeq = &o->exe_queue;
        struct bnx2x_exeq_elem *exeq_pos, *exeq_pos_n;
+       unsigned long flags;
        int read_lock;
        int rc = 0;
 
@@ -2046,8 +2047,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
        spin_lock_bh(&exeq->lock);
 
        list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
-               if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
-                   *vlan_mac_flags) {
+               flags = exeq_pos->cmd_data.vlan_mac.vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        rc = exeq->remove(bp, exeq->owner, exeq_pos);
                        if (rc) {
                                BNX2X_ERR("Failed to remove command\n");
@@ -2080,7 +2082,9 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
                return read_lock;
 
        list_for_each_entry(pos, &o->head, link) {
-               if (pos->vlan_mac_flags == *vlan_mac_flags) {
+               flags = pos->vlan_mac_flags;
+               if (BNX2X_VLAN_MAC_CMP_FLAGS(flags) ==
+                   BNX2X_VLAN_MAC_CMP_FLAGS(*vlan_mac_flags)) {
                        p.user_req.vlan_mac_flags = pos->vlan_mac_flags;
                        memcpy(&p.user_req.u, &pos->u, sizeof(pos->u));
                        rc = bnx2x_config_vlan_mac(bp, &p);
@@ -4382,8 +4386,11 @@ int bnx2x_config_rss(struct bnx2x *bp,
        struct bnx2x_raw_obj *r = &o->raw;
 
        /* Do nothing if only driver cleanup was requested */
-       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags))
+       if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) {
+               DP(BNX2X_MSG_SP, "Not configuring RSS ramrod_flags=%lx\n",
+                  p->ramrod_flags);
                return 0;
+       }
 
        r->set_pending(r);
 
index 658f4e33abf9281d76e083873cb963c9b47b05f1..6a53c15c85a338c8efbb45ecf3348913272e038a 100644 (file)
@@ -266,6 +266,13 @@ enum {
        BNX2X_DONT_CONSUME_CAM_CREDIT,
        BNX2X_DONT_CONSUME_CAM_CREDIT_DEST,
 };
+/* When looking for matching filters, some flags are not interesting */
+#define BNX2X_VLAN_MAC_CMP_MASK        (1 << BNX2X_UC_LIST_MAC | \
+                                1 << BNX2X_ETH_MAC | \
+                                1 << BNX2X_ISCSI_ETH_MAC | \
+                                1 << BNX2X_NETQ_ETH_MAC)
+#define BNX2X_VLAN_MAC_CMP_FLAGS(flags) \
+       ((flags) & BNX2X_VLAN_MAC_CMP_MASK)
 
 struct bnx2x_vlan_mac_ramrod_params {
        /* Object to run the command from */
index 0216d592d0cee4b080a9d33d7776f632bf639453..e7845e5be1c76fb452d8ecb94943326844ab5eaa 100644 (file)
@@ -1209,6 +1209,11 @@ static void bnx2x_vfop_rxmode(struct bnx2x *bp, struct bnx2x_virtf *vf)
                /* next state */
                vfop->state = BNX2X_VFOP_RXMODE_DONE;
 
+               /* record the accept flags in vfdb so hypervisor can modify them
+                * if necessary
+                */
+               bnx2x_vfq(vf, ramrod->cl_id - vf->igu_base_id, accept_flags) =
+                       ramrod->rx_accept_flags;
                vfop->rc = bnx2x_config_rx_mode(bp, ramrod);
                bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
 op_err:
@@ -1224,39 +1229,43 @@ op_pending:
        return;
 }
 
+static void bnx2x_vf_prep_rx_mode(struct bnx2x *bp, u8 qid,
+                                 struct bnx2x_rx_mode_ramrod_params *ramrod,
+                                 struct bnx2x_virtf *vf,
+                                 unsigned long accept_flags)
+{
+       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
+
+       memset(ramrod, 0, sizeof(*ramrod));
+       ramrod->cid = vfq->cid;
+       ramrod->cl_id = vfq_cl_id(vf, vfq);
+       ramrod->rx_mode_obj = &bp->rx_mode_obj;
+       ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
+       ramrod->rx_accept_flags = accept_flags;
+       ramrod->tx_accept_flags = accept_flags;
+       ramrod->pstate = &vf->filter_state;
+       ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
+
+       set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
+       set_bit(RAMROD_RX, &ramrod->ramrod_flags);
+       set_bit(RAMROD_TX, &ramrod->ramrod_flags);
+
+       ramrod->rdata = bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
+       ramrod->rdata_mapping = bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+}
+
 int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp,
                          struct bnx2x_virtf *vf,
                          struct bnx2x_vfop_cmd *cmd,
                          int qid, unsigned long accept_flags)
 {
-       struct bnx2x_vf_queue *vfq = vfq_get(vf, qid);
        struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
 
        if (vfop) {
                struct bnx2x_rx_mode_ramrod_params *ramrod =
                        &vf->op_params.rx_mode;
 
-               memset(ramrod, 0, sizeof(*ramrod));
-
-               /* Prepare ramrod parameters */
-               ramrod->cid = vfq->cid;
-               ramrod->cl_id = vfq_cl_id(vf, vfq);
-               ramrod->rx_mode_obj = &bp->rx_mode_obj;
-               ramrod->func_id = FW_VF_HANDLE(vf->abs_vfid);
-
-               ramrod->rx_accept_flags = accept_flags;
-               ramrod->tx_accept_flags = accept_flags;
-               ramrod->pstate = &vf->filter_state;
-               ramrod->state = BNX2X_FILTER_RX_MODE_PENDING;
-
-               set_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
-               set_bit(RAMROD_RX, &ramrod->ramrod_flags);
-               set_bit(RAMROD_TX, &ramrod->ramrod_flags);
-
-               ramrod->rdata =
-                       bnx2x_vf_sp(bp, vf, rx_mode_rdata.e2);
-               ramrod->rdata_mapping =
-                       bnx2x_vf_sp_map(bp, vf, rx_mode_rdata.e2);
+               bnx2x_vf_prep_rx_mode(bp, qid, ramrod, vf, accept_flags);
 
                bnx2x_vfop_opset(BNX2X_VFOP_RXMODE_CONFIG,
                                 bnx2x_vfop_rxmode, cmd->done);
@@ -3114,6 +3123,11 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
        struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
 
+       if (!IS_SRIOV(bp)) {
+               BNX2X_ERR("failed to configure SR-IOV since vfdb was not allocated. Check dmesg for errors in probe stage\n");
+               return -EINVAL;
+       }
+
        DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n",
           num_vfs_param, BNX2X_NR_VIRTFN(bp));
 
@@ -3197,13 +3211,16 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                bnx2x_iov_static_resc(bp, vf);
        }
 
-       /* prepare msix vectors in VF configuration space */
+       /* prepare msix vectors in VF configuration space - the value in the
+        * PCI configuration space should be the index of the last entry,
+        * namely one less than the actual size of the table
+        */
        for (vf_idx = first_vf; vf_idx < first_vf + req_vfs; vf_idx++) {
                bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
                REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
-                      num_vf_queues);
+                      num_vf_queues - 1);
                DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
-                  vf_idx, num_vf_queues);
+                  vf_idx, num_vf_queues - 1);
        }
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
@@ -3431,10 +3448,18 @@ out:
 
 int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
 {
+       struct bnx2x_queue_state_params q_params = {NULL};
+       struct bnx2x_vlan_mac_ramrod_params ramrod_param;
+       struct bnx2x_queue_update_params *update_params;
+       struct pf_vf_bulletin_content *bulletin = NULL;
+       struct bnx2x_rx_mode_ramrod_params rx_ramrod;
        struct bnx2x *bp = netdev_priv(dev);
-       int rc, q_logical_state;
+       struct bnx2x_vlan_mac_obj *vlan_obj;
+       unsigned long vlan_mac_flags = 0;
+       unsigned long ramrod_flags = 0;
        struct bnx2x_virtf *vf = NULL;
-       struct pf_vf_bulletin_content *bulletin = NULL;
+       unsigned long accept_flags;
+       int rc;
 
        /* sanity and init */
        rc = bnx2x_vf_ndo_prep(bp, vfidx, &vf, &bulletin);
@@ -3452,104 +3477,118 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
        /* update PF's copy of the VF's bulletin. No point in posting the vlan
         * to the VF since it doesn't have anything to do with it. But it useful
         * to store it here in case the VF is not up yet and we can only
-        * configure the vlan later when it does.
+        * configure the vlan later when it does. Treat vlan id 0 as remove the
+        * Host tag.
         */
-       bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       if (vlan > 0)
+               bulletin->valid_bitmap |= 1 << VLAN_VALID;
+       else
+               bulletin->valid_bitmap &= ~(1 << VLAN_VALID);
        bulletin->vlan = vlan;
 
        /* is vf initialized and queue set up? */
-       q_logical_state =
-               bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj));
-       if (vf->state == VF_ENABLED &&
-           q_logical_state == BNX2X_Q_LOGICAL_STATE_ACTIVE) {
-               /* configure the vlan in device on this vf's queue */
-               unsigned long ramrod_flags = 0;
-               unsigned long vlan_mac_flags = 0;
-               struct bnx2x_vlan_mac_obj *vlan_obj =
-                       &bnx2x_leading_vfq(vf, vlan_obj);
-               struct bnx2x_vlan_mac_ramrod_params ramrod_param;
-               struct bnx2x_queue_state_params q_params = {NULL};
-               struct bnx2x_queue_update_params *update_params;
+       if (vf->state != VF_ENABLED ||
+           bnx2x_get_q_logical_state(bp, &bnx2x_leading_vfq(vf, sp_obj)) !=
+           BNX2X_Q_LOGICAL_STATE_ACTIVE)
+               return rc;
 
-               rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
-               if (rc)
-                       return rc;
-               memset(&ramrod_param, 0, sizeof(ramrod_param));
+       /* configure the vlan in device on this vf's queue */
+       vlan_obj = &bnx2x_leading_vfq(vf, vlan_obj);
+       rc = validate_vlan_mac(bp, &bnx2x_leading_vfq(vf, mac_obj));
+       if (rc)
+               return rc;
 
-               /* must lock vfpf channel to protect against vf flows */
-               bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+       /* must lock vfpf channel to protect against vf flows */
+       bnx2x_lock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 
-               /* remove existing vlans */
-               __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-               rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
-                                         &ramrod_flags);
-               if (rc) {
-                       BNX2X_ERR("failed to delete vlans\n");
-                       rc = -EINVAL;
-                       goto out;
-               }
+       /* remove existing vlans */
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       rc = vlan_obj->delete_all(bp, vlan_obj, &vlan_mac_flags,
+                                 &ramrod_flags);
+       if (rc) {
+               BNX2X_ERR("failed to delete vlans\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* need to remove/add the VF's accept_any_vlan bit */
+       accept_flags = bnx2x_leading_vfq(vf, accept_flags);
+       if (vlan)
+               clear_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+       else
+               set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept_flags);
+
+       bnx2x_vf_prep_rx_mode(bp, LEADING_IDX, &rx_ramrod, vf,
+                             accept_flags);
+       bnx2x_leading_vfq(vf, accept_flags) = accept_flags;
+       bnx2x_config_rx_mode(bp, &rx_ramrod);
+
+       /* configure the new vlan to device */
+       memset(&ramrod_param, 0, sizeof(ramrod_param));
+       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
+       ramrod_param.vlan_mac_obj = vlan_obj;
+       ramrod_param.ramrod_flags = ramrod_flags;
+       set_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+               &ramrod_param.user_req.vlan_mac_flags);
+       ramrod_param.user_req.u.vlan.vlan = vlan;
+       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
+       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
+       if (rc) {
+               BNX2X_ERR("failed to configure vlan\n");
+               rc =  -EINVAL;
+               goto out;
+       }
 
-               /* send queue update ramrod to configure default vlan and silent
-                * vlan removal
+       /* send queue update ramrod to configure default vlan and silent
+        * vlan removal
+        */
+       __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+       q_params.cmd = BNX2X_Q_CMD_UPDATE;
+       q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
+       update_params = &q_params.params.update;
+       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+                 &update_params->update_flags);
+       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+                 &update_params->update_flags);
+       if (vlan == 0) {
+               /* if vlan is 0 then we want to leave the VF traffic
+                * untagged, and leave the incoming traffic untouched
+                * (i.e. do not remove any vlan tags).
+                */
+               __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
+                           &update_params->update_flags);
+               __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+                           &update_params->update_flags);
+       } else {
+               /* configure default vlan to vf queue and set silent
+                * vlan removal (the vf remains unaware of this vlan).
                 */
-               __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
-               q_params.cmd = BNX2X_Q_CMD_UPDATE;
-               q_params.q_obj = &bnx2x_leading_vfq(vf, sp_obj);
-               update_params = &q_params.params.update;
-               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
                          &update_params->update_flags);
-               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
+               __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
                          &update_params->update_flags);
+               update_params->def_vlan = vlan;
+               update_params->silent_removal_value =
+                       vlan & VLAN_VID_MASK;
+               update_params->silent_removal_mask = VLAN_VID_MASK;
+       }
 
-               if (vlan == 0) {
-                       /* if vlan is 0 then we want to leave the VF traffic
-                        * untagged, and leave the incoming traffic untouched
-                        * (i.e. do not remove any vlan tags).
-                        */
-                       __clear_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                   &update_params->update_flags);
-                       __clear_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                   &update_params->update_flags);
-               } else {
-                       /* configure the new vlan to device */
-                       __set_bit(RAMROD_COMP_WAIT, &ramrod_flags);
-                       ramrod_param.vlan_mac_obj = vlan_obj;
-                       ramrod_param.ramrod_flags = ramrod_flags;
-                       ramrod_param.user_req.u.vlan.vlan = vlan;
-                       ramrod_param.user_req.cmd = BNX2X_VLAN_MAC_ADD;
-                       rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-                       if (rc) {
-                               BNX2X_ERR("failed to configure vlan\n");
-                               rc =  -EINVAL;
-                               goto out;
-                       }
-
-                       /* configure default vlan to vf queue and set silent
-                        * vlan removal (the vf remains unaware of this vlan).
-                        */
-                       update_params = &q_params.params.update;
-                       __set_bit(BNX2X_Q_UPDATE_DEF_VLAN_EN,
-                                 &update_params->update_flags);
-                       __set_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM,
-                                 &update_params->update_flags);
-                       update_params->def_vlan = vlan;
-               }
+       /* Update the Queue state */
+       rc = bnx2x_queue_state_change(bp, &q_params);
+       if (rc) {
+               BNX2X_ERR("Failed to configure default VLAN\n");
+               goto out;
+       }
 
-               /* Update the Queue state */
-               rc = bnx2x_queue_state_change(bp, &q_params);
-               if (rc) {
-                       BNX2X_ERR("Failed to configure default VLAN\n");
-                       goto out;
-               }
 
-               /* clear the flag indicating that this VF needs its vlan
-                * (will only be set if the HV configured the Vlan before vf was
-                * up and we were called because the VF came up later
-                */
+       /* clear the flag indicating that this VF needs its vlan
+        * (will only be set if the HV configured the Vlan before vf was
+        * up and we were called because the VF came up later
+        */
 out:
-               vf->cfg_flags &= ~VF_CFG_VLAN;
-               bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
-       }
+       vf->cfg_flags &= ~VF_CFG_VLAN;
+       bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
+
        return rc;
 }
 
index 1ff6a9366629ed88fe79a079391c92e95d1e9baf..8c213fa52174f918d4f445dae554b593b54845db 100644 (file)
@@ -74,6 +74,7 @@ struct bnx2x_vf_queue {
        /* VLANs object */
        struct bnx2x_vlan_mac_obj       vlan_obj;
        atomic_t vlan_count;            /* 0 means vlan-0 is set  ~ untagged */
+       unsigned long accept_flags;     /* last accept flags configured */
 
        /* Queue Slow-path State object */
        struct bnx2x_queue_sp_obj       sp_obj;
index efa8a151d78907d4b17d5f5dd07eaed9b1f2c02c..0756d7dabdd59ae0e58139e07081d9ba02ca5a10 100644 (file)
@@ -208,7 +208,7 @@ static int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id)
                return -EINVAL;
        }
 
-       BNX2X_ERR("valid ME register value: 0x%08x\n", me_reg);
+       DP(BNX2X_MSG_IOV, "valid ME register value: 0x%08x\n", me_reg);
 
        *vf_id = (me_reg & ME_REG_VF_NUM_MASK) >> ME_REG_VF_NUM_SHIFT;
 
@@ -1598,6 +1598,8 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
 
                if (msg->flags & VFPF_SET_Q_FILTERS_RX_MASK_CHANGED) {
                        unsigned long accept = 0;
+                       struct pf_vf_bulletin_content *bulletin =
+                               BP_VF_BULLETIN(bp, vf->index);
 
                        /* covert VF-PF if mask to bnx2x accept flags */
                        if (msg->rx_mask & VFPF_RX_MASK_ACCEPT_MATCHED_UNICAST)
@@ -1617,9 +1619,11 @@ static void bnx2x_vfop_mbx_qfilters(struct bnx2x *bp, struct bnx2x_virtf *vf)
                                __set_bit(BNX2X_ACCEPT_BROADCAST, &accept);
 
                        /* A packet arriving the vf's mac should be accepted
-                        * with any vlan
+                        * with any vlan, unless a vlan has already been
+                        * configured.
                         */
-                       __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
+                       if (!(bulletin->valid_bitmap & (1 << VLAN_VALID)))
+                               __set_bit(BNX2X_ACCEPT_ANY_VLAN, &accept);
 
                        /* set rx-mode */
                        rc = bnx2x_vfop_rxmode_cmd(bp, vf, &cmd,
@@ -1710,6 +1714,21 @@ static void bnx2x_vf_mbx_set_q_filters(struct bnx2x *bp,
                        goto response;
                }
        }
+       /* if vlan was set by hypervisor we don't allow guest to config vlan */
+       if (bulletin->valid_bitmap & 1 << VLAN_VALID) {
+               int i;
+
+               /* search for vlan filters */
+               for (i = 0; i < filters->n_mac_vlan_filters; i++) {
+                       if (filters->filters[i].flags &
+                           VFPF_Q_FILTER_VLAN_TAG_VALID) {
+                               BNX2X_ERR("VF[%d] attempted to configure vlan but one was already set by Hypervisor. Aborting request\n",
+                                         vf->abs_vfid);
+                               vf->op_rc = -EPERM;
+                               goto response;
+                       }
+               }
+       }
 
        /* verify vf_qid */
        if (filters->vf_qid > vf_rxq_count(vf))
@@ -1805,6 +1824,9 @@ static void bnx2x_vf_mbx_update_rss(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf_op_params->rss_result_mask = rss_tlv->rss_result_mask;
 
        /* flags handled individually for backward/forward compatability */
+       vf_op_params->rss_flags = 0;
+       vf_op_params->ramrod_flags = 0;
+
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_DISABLED)
                __set_bit(BNX2X_RSS_MODE_DISABLED, &vf_op_params->rss_flags);
        if (rss_tlv->rss_flags & VFPF_RSS_MODE_REGULAR)
index a9e068423ba0651414cc0c5b23f0eda6937a6c23..15a66e4b1f57a19d2d1e7feb31b557e3809fe6b0 100644 (file)
@@ -7622,7 +7622,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
 {
        u32 base = (u32) mapping & 0xffffffff;
 
-       return (base > 0xffffdcc0) && (base + len + 8 < base);
+       return base + len + 8 < base;
 }
 
 /* Test for TSO DMA buffers that cross into regions which are within MSS bytes
@@ -8932,6 +8932,9 @@ static int tg3_chip_reset(struct tg3 *tp)
        void (*write_op)(struct tg3 *, u32, u32);
        int i, err;
 
+       if (!pci_device_is_present(tp->pdev))
+               return -ENODEV;
+
        tg3_nvram_lock(tp);
 
        tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
@@ -10629,10 +10632,8 @@ static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir)
 static ssize_t tg3_show_temp(struct device *dev,
                             struct device_attribute *devattr, char *buf)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct net_device *netdev = pci_get_drvdata(pdev);
-       struct tg3 *tp = netdev_priv(netdev);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct tg3 *tp = dev_get_drvdata(dev);
        u32 temperature;
 
        spin_lock_bh(&tp->lock);
@@ -10650,29 +10651,25 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, tg3_show_temp, NULL,
 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, tg3_show_temp, NULL,
                          TG3_TEMP_MAX_OFFSET);
 
-static struct attribute *tg3_attributes[] = {
+static struct attribute *tg3_attrs[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_crit.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        NULL
 };
-
-static const struct attribute_group tg3_group = {
-       .attrs = tg3_attributes,
-};
+ATTRIBUTE_GROUPS(tg3);
 
 static void tg3_hwmon_close(struct tg3 *tp)
 {
        if (tp->hwmon_dev) {
                hwmon_device_unregister(tp->hwmon_dev);
                tp->hwmon_dev = NULL;
-               sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group);
        }
 }
 
 static void tg3_hwmon_open(struct tg3 *tp)
 {
-       int i, err;
+       int i;
        u32 size = 0;
        struct pci_dev *pdev = tp->pdev;
        struct tg3_ocir ocirs[TG3_SD_NUM_RECS];
@@ -10690,18 +10687,11 @@ static void tg3_hwmon_open(struct tg3 *tp)
        if (!size)
                return;
 
-       /* Register hwmon sysfs hooks */
-       err = sysfs_create_group(&pdev->dev.kobj, &tg3_group);
-       if (err) {
-               dev_err(&pdev->dev, "Cannot create sysfs group, aborting\n");
-               return;
-       }
-
-       tp->hwmon_dev = hwmon_device_register(&pdev->dev);
+       tp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, "tg3",
+                                                         tp, tg3_groups);
        if (IS_ERR(tp->hwmon_dev)) {
                tp->hwmon_dev = NULL;
                dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n");
-               sysfs_remove_group(&pdev->dev.kobj, &tg3_group);
        }
 }
 
@@ -11594,10 +11584,11 @@ static int tg3_close(struct net_device *dev)
        memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev));
        memset(&tp->estats_prev, 0, sizeof(tp->estats_prev));
 
-       tg3_power_down_prepare(tp);
-
-       tg3_carrier_off(tp);
+       if (pci_device_is_present(tp->pdev)) {
+               tg3_power_down_prepare(tp);
 
+               tg3_carrier_off(tp);
+       }
        return 0;
 }
 
@@ -16512,6 +16503,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
        /* Clear this out for sanity. */
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 
+       /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */
+       tw32(TG3PCI_REG_BASE_ADDR, 0);
+
        pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
                              &pci_state_reg);
        if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
@@ -17739,10 +17733,12 @@ static int tg3_suspend(struct device *device)
        struct pci_dev *pdev = to_pci_dev(device);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int err = 0;
+
+       rtnl_lock();
 
        if (!netif_running(dev))
-               return 0;
+               goto unlock;
 
        tg3_reset_task_cancel(tp);
        tg3_phy_stop(tp);
@@ -17784,6 +17780,8 @@ out:
                        tg3_phy_start(tp);
        }
 
+unlock:
+       rtnl_unlock();
        return err;
 }
 
@@ -17792,10 +17790,12 @@ static int tg3_resume(struct device *device)
        struct pci_dev *pdev = to_pci_dev(device);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int err = 0;
+
+       rtnl_lock();
 
        if (!netif_running(dev))
-               return 0;
+               goto unlock;
 
        netif_device_attach(dev);
 
@@ -17819,6 +17819,8 @@ out:
        if (!err)
                tg3_phy_start(tp);
 
+unlock:
+       rtnl_unlock();
        return err;
 }
 #endif /* CONFIG_PM_SLEEP */
index ecd2fb3ef69596146a7cf155323e624e397b6834..56e0415f8cdff396aca4d6462f2432278e258018 100644 (file)
 #include <asm/io.h>
 #include "cxgb4_uld.h"
 
-#define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 4
-#define FW_VERSION_MICRO 0
+#define T4FW_VERSION_MAJOR 0x01
+#define T4FW_VERSION_MINOR 0x06
+#define T4FW_VERSION_MICRO 0x18
+#define T4FW_VERSION_BUILD 0x00
 
-#define FW_VERSION_MAJOR_T5 0
-#define FW_VERSION_MINOR_T5 0
-#define FW_VERSION_MICRO_T5 0
+#define T5FW_VERSION_MAJOR 0x01
+#define T5FW_VERSION_MINOR 0x08
+#define T5FW_VERSION_MICRO 0x1C
+#define T5FW_VERSION_BUILD 0x00
 
 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
 
@@ -226,6 +228,25 @@ struct tp_params {
 
        uint32_t dack_re;            /* DACK timer resolution */
        unsigned short tx_modq[NCHAN];  /* channel to modulation queue map */
+
+       u32 vlan_pri_map;               /* cached TP_VLAN_PRI_MAP */
+       u32 ingress_config;             /* cached TP_INGRESS_CONFIG */
+
+       /* TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets.  This is a
+        * subset of the set of fields which may be present in the Compressed
+        * Filter Tuple portion of filters and TCP TCB connections.  The
+        * fields which are present are controlled by the TP_VLAN_PRI_MAP.
+        * Since a variable number of fields may or may not be present, their
+        * shifted field positions within the Compressed Filter Tuple may
+        * vary, or not even be present if the field isn't selected in
+        * TP_VLAN_PRI_MAP.  Since some of these fields are needed in various
+        * places we store their offsets here, or a -1 if the field isn't
+        * present.
+        */
+       int vlan_shift;
+       int vnic_shift;
+       int port_shift;
+       int protocol_shift;
 };
 
 struct vpd_params {
@@ -240,6 +261,26 @@ struct pci_params {
        unsigned char width;
 };
 
+#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+#define CHELSIO_CHIP_FPGA          0x100
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
+#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+
+#define CHELSIO_T4             0x4
+#define CHELSIO_T5             0x5
+
+enum chip_type {
+       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+       T4_FIRST_REV    = T4_A1,
+       T4_LAST_REV     = T4_A2,
+
+       T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+       T5_FIRST_REV    = T5_A0,
+       T5_LAST_REV     = T5_A1,
+};
+
 struct adapter_params {
        struct tp_params  tp;
        struct vpd_params vpd;
@@ -259,7 +300,7 @@ struct adapter_params {
 
        unsigned char nports;             /* # of ethernet ports */
        unsigned char portvec;
-       unsigned char rev;                /* chip revision */
+       enum chip_type chip;               /* chip code */
        unsigned char offload;
 
        unsigned char bypass;
@@ -267,6 +308,23 @@ struct adapter_params {
        unsigned int ofldq_wr_cred;
 };
 
+#include "t4fw_api.h"
+
+#define FW_VERSION(chip) ( \
+               FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \
+               FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \
+               FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \
+               FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD))
+#define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf)
+
+struct fw_info {
+       u8 chip;
+       char *fs_name;
+       char *fw_mod_name;
+       struct fw_hdr fw_hdr;
+};
+
+
 struct trace_params {
        u32 data[TRACE_LEN / 4];
        u32 mask[TRACE_LEN / 4];
@@ -512,25 +570,6 @@ struct sge {
 
 struct l2t_data;
 
-#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
-#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
-
-#define CHELSIO_T4             0x4
-#define CHELSIO_T5             0x5
-
-enum chip_type {
-       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
-       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
-       T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
-       T4_FIRST_REV    = T4_A1,
-       T4_LAST_REV     = T4_A3,
-
-       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
-       T5_FIRST_REV    = T5_A1,
-       T5_LAST_REV     = T5_A1,
-};
-
 #ifdef CONFIG_PCI_IOV
 
 /* T4 supports SRIOV on PF0-3 and T5 on PF0-7.  However, the Serial
@@ -715,12 +754,12 @@ enum {
 
 static inline int is_t5(enum chip_type chip)
 {
-       return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5;
 }
 
 static inline int is_t4(enum chip_type chip)
 {
-       return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
 }
 
 static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
@@ -900,8 +939,14 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
-int t4_check_fw_version(struct adapter *adapter);
+int t4_get_fw_version(struct adapter *adapter, u32 *vers);
+int t4_get_tp_version(struct adapter *adapter, u32 *vers);
+int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state, int *reset);
 int t4_prep_adapter(struct adapter *adapter);
+int t4_init_tp_params(struct adapter *adap);
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
 int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
index 8b929eeecd2d37cd3b41e32d57bd1fa50402a230..fff02ed1295e5ef7bab408cbe19c46dbd5eedd52 100644 (file)
@@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
        { 0, }
 };
 
-#define FW_FNAME "cxgb4/t4fw.bin"
+#define FW4_FNAME "cxgb4/t4fw.bin"
 #define FW5_FNAME "cxgb4/t5fw.bin"
-#define FW_CFNAME "cxgb4/t4-config.txt"
+#define FW4_CFNAME "cxgb4/t4-config.txt"
 #define FW5_CFNAME "cxgb4/t5-config.txt"
 
 MODULE_DESCRIPTION(DRV_DESC);
@@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
-MODULE_FIRMWARE(FW_FNAME);
+MODULE_FIRMWARE(FW4_FNAME);
 MODULE_FIRMWARE(FW5_FNAME);
 
 /*
@@ -1070,72 +1070,6 @@ freeout: t4_free_sge_resources(adap);
        return 0;
 }
 
-/*
- * Returns 0 if new FW was successfully loaded, a positive errno if a load was
- * started but failed, and a negative errno if flash load couldn't start.
- */
-static int upgrade_fw(struct adapter *adap)
-{
-       int ret;
-       u32 vers, exp_major;
-       const struct fw_hdr *hdr;
-       const struct firmware *fw;
-       struct device *dev = adap->pdev_dev;
-       char *fw_file_name;
-
-       switch (CHELSIO_CHIP_VERSION(adap->chip)) {
-       case CHELSIO_T4:
-               fw_file_name = FW_FNAME;
-               exp_major = FW_VERSION_MAJOR;
-               break;
-       case CHELSIO_T5:
-               fw_file_name = FW5_FNAME;
-               exp_major = FW_VERSION_MAJOR_T5;
-               break;
-       default:
-               dev_err(dev, "Unsupported chip type, %x\n", adap->chip);
-               return -EINVAL;
-       }
-
-       ret = request_firmware(&fw, fw_file_name, dev);
-       if (ret < 0) {
-               dev_err(dev, "unable to load firmware image %s, error %d\n",
-                       fw_file_name, ret);
-               return ret;
-       }
-
-       hdr = (const struct fw_hdr *)fw->data;
-       vers = ntohl(hdr->fw_ver);
-       if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
-               ret = -EINVAL;              /* wrong major version, won't do */
-               goto out;
-       }
-
-       /*
-        * If the flash FW is unusable or we found something newer, load it.
-        */
-       if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
-           vers > adap->params.fw_vers) {
-               dev_info(dev, "upgrading firmware ...\n");
-               ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
-                                   /*force=*/false);
-               if (!ret)
-                       dev_info(dev,
-                                "firmware upgraded to version %pI4 from %s\n",
-                                &hdr->fw_ver, fw_file_name);
-               else
-                       dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
-       } else {
-               /*
-                * Tell our caller that we didn't upgrade the firmware.
-                */
-               ret = -EINVAL;
-       }
-
-out:   release_firmware(fw);
-       return ret;
-}
-
 /*
  * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
  * The allocated memory is cleared.
@@ -1415,7 +1349,7 @@ static int get_sset_count(struct net_device *dev, int sset)
 static int get_regs_len(struct net_device *dev)
 {
        struct adapter *adap = netdev2adap(dev);
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                return T4_REGMAP_SIZE;
        else
                return T5_REGMAP_SIZE;
@@ -1499,7 +1433,7 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
        data += sizeof(struct port_stats) / sizeof(u64);
        collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
        data += sizeof(struct queue_port_stats) / sizeof(u64);
-       if (!is_t4(adapter->chip)) {
+       if (!is_t4(adapter->params.chip)) {
                t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7));
                val1 = t4_read_reg(adapter, SGE_STAT_TOTAL);
                val2 = t4_read_reg(adapter, SGE_STAT_MATCH);
@@ -1521,8 +1455,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
  */
 static inline unsigned int mk_adap_vers(const struct adapter *ap)
 {
-       return CHELSIO_CHIP_VERSION(ap->chip) |
-               (CHELSIO_CHIP_RELEASE(ap->chip) << 10) | (1 << 16);
+       return CHELSIO_CHIP_VERSION(ap->params.chip) |
+               (CHELSIO_CHIP_RELEASE(ap->params.chip) << 10) | (1 << 16);
 }
 
 static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
@@ -2189,7 +2123,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
        static const unsigned int *reg_ranges;
        int arr_size = 0, buf_size = 0;
 
-       if (is_t4(ap->chip)) {
+       if (is_t4(ap->params.chip)) {
                reg_ranges = &t4_reg_ranges[0];
                arr_size = ARRAY_SIZE(t4_reg_ranges);
                buf_size = T4_REGMAP_SIZE;
@@ -2967,7 +2901,7 @@ static int setup_debugfs(struct adapter *adap)
                size = t4_read_reg(adap, MA_EDRAM1_BAR);
                add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size));
        }
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
                if (i & EXT_MEM_ENABLE)
                        add_debugfs_mem(adap, "mc", MEM_MC,
@@ -3052,7 +2986,14 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
                stid += t->stid_base;
-               t->stids_in_use++;
+               /* IPv6 requires max of 520 bits or 16 cells in TCAM
+                * This is equivalent to 4 TIDs. With CLIP enabled it
+                * needs 2 TIDs.
+                */
+               if (family == PF_INET)
+                       t->stids_in_use++;
+               else
+                       t->stids_in_use += 4;
        }
        spin_unlock_bh(&t->stid_lock);
        return stid;
@@ -3078,7 +3019,8 @@ int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
        }
        if (stid >= 0) {
                t->stid_tab[stid].data = data;
-               stid += t->stid_base;
+               stid -= t->nstids;
+               stid += t->sftid_base;
                t->stids_in_use++;
        }
        spin_unlock_bh(&t->stid_lock);
@@ -3090,14 +3032,24 @@ EXPORT_SYMBOL(cxgb4_alloc_sftid);
  */
 void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        spin_lock_bh(&t->stid_lock);
        if (family == PF_INET)
                __clear_bit(stid, t->stid_bmap);
        else
                bitmap_release_region(t->stid_bmap, stid, 2);
        t->stid_tab[stid].data = NULL;
-       t->stids_in_use--;
+       if (family == PF_INET)
+               t->stids_in_use--;
+       else
+               t->stids_in_use -= 4;
        spin_unlock_bh(&t->stid_lock);
 }
 EXPORT_SYMBOL(cxgb4_free_stid);
@@ -3200,6 +3152,7 @@ static int tid_init(struct tid_info *t)
        size_t size;
        unsigned int stid_bmap_size;
        unsigned int natids = t->natids;
+       struct adapter *adap = container_of(t, struct adapter, tids);
 
        stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
        size = t->ntids * sizeof(*t->tid_tab) +
@@ -3233,6 +3186,11 @@ static int tid_init(struct tid_info *t)
                t->afree = t->atid_tab;
        }
        bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
+       /* Reserve stid 0 for T4/T5 adapters */
+       if (!t->stid_base &&
+           (is_t4(adap->params.chip) || is_t5(adap->params.chip)))
+               __set_bit(0, t->stid_bmap);
+
        return 0;
 }
 
@@ -3419,7 +3377,7 @@ unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
 
        v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
        v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                lp_count = G_LP_COUNT(v1);
                hp_count = G_HP_COUNT(v1);
        } else {
@@ -3588,7 +3546,7 @@ static void drain_db_fifo(struct adapter *adap, int usecs)
        do {
                v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
                v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
-               if (is_t4(adap->chip)) {
+               if (is_t4(adap->params.chip)) {
                        lp_count = G_LP_COUNT(v1);
                        hp_count = G_HP_COUNT(v1);
                } else {
@@ -3708,7 +3666,7 @@ static void process_db_drop(struct work_struct *work)
 
        adap = container_of(work, struct adapter, db_drop_task);
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                disable_dbs(adap);
                notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
                drain_db_fifo(adap, 1);
@@ -3753,7 +3711,7 @@ static void process_db_drop(struct work_struct *work)
 
 void t4_db_full(struct adapter *adap)
 {
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                t4_set_reg_field(adap, SGE_INT_ENABLE3,
                                 DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
                queue_work(workq, &adap->db_full_task);
@@ -3762,7 +3720,7 @@ void t4_db_full(struct adapter *adap)
 
 void t4_db_dropped(struct adapter *adap)
 {
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                queue_work(workq, &adap->db_drop_task);
 }
 
@@ -3789,7 +3747,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.nchan = adap->params.nports;
        lli.nports = adap->params.nports;
        lli.wr_cred = adap->params.ofldq_wr_cred;
-       lli.adapter_type = adap->params.rev;
+       lli.adapter_type = adap->params.chip;
        lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
        lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
@@ -3797,7 +3755,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
                        (adap->fn * 4));
-       lli.filt_mode = adap->filter_mode;
+       lli.filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
                lli.tx_modq[i] = i;
@@ -4245,7 +4203,7 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        /* Check to make sure the filter requested is writable ...
@@ -4271,12 +4229,17 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
                        f->fs.val.lip[i] = val[i];
                        f->fs.mask.lip[i] = ~0;
                }
-               if (adap->filter_mode & F_PORT) {
+               if (adap->params.tp.vlan_pri_map & F_PORT) {
                        f->fs.val.iport = port;
                        f->fs.mask.iport = mask;
                }
        }
 
+       if (adap->params.tp.vlan_pri_map & F_PROTOCOL) {
+               f->fs.val.proto = IPPROTO_TCP;
+               f->fs.mask.proto = ~0;
+       }
+
        f->fs.dirsteer = 1;
        f->fs.iq = queue;
        /* Mark filter as locked */
@@ -4303,7 +4266,7 @@ int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
        adap = netdev2adap(dev);
 
        /* Adjust stid to correct filter index */
-       stid -= adap->tids.nstids;
+       stid -= adap->tids.sftid_base;
        stid += adap->tids.nftids;
 
        f = &adap->tids.ftid_tab[stid];
@@ -4483,7 +4446,7 @@ static void setup_memwin(struct adapter *adap)
        u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
 
        bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mem_win0_base = bar0 + MEMWIN0_BASE;
                mem_win1_base = bar0 + MEMWIN1_BASE;
                mem_win2_base = bar0 + MEMWIN2_BASE;
@@ -4668,8 +4631,10 @@ static int adap_init0_config(struct adapter *adapter, int reset)
        const struct firmware *cf;
        unsigned long mtype = 0, maddr = 0;
        u32 finiver, finicsum, cfcsum;
-       int ret, using_flash;
+       int ret;
+       int config_issued = 0;
        char *fw_config_file, fw_config_file_path[256];
+       char *config_name = NULL;
 
        /*
         * Reset device if necessary.
@@ -4686,9 +4651,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         * then use that.  Otherwise, use the configuration file stored
         * in the adapter flash ...
         */
-       switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
+       switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
        case CHELSIO_T4:
-               fw_config_file = FW_CFNAME;
+               fw_config_file = FW4_CFNAME;
                break;
        case CHELSIO_T5:
                fw_config_file = FW5_CFNAME;
@@ -4702,13 +4667,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 
        ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
        if (ret < 0) {
-               using_flash = 1;
+               config_name = "On FLASH";
                mtype = FW_MEMTYPE_CF_FLASH;
                maddr = t4_flash_cfg_addr(adapter);
        } else {
                u32 params[7], val[7];
 
-               using_flash = 0;
+               sprintf(fw_config_file_path,
+                       "/lib/firmware/%s", fw_config_file);
+               config_name = fw_config_file_path;
+
                if (cf->size >= FLASH_CFG_MAX_SIZE)
                        ret = -ENOMEM;
                else {
@@ -4776,6 +4744,26 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                      FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
+
+       /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware
+        * Configuration File in FLASH), our last gasp effort is to use the
+        * Firmware Configuration File which is embedded in the firmware.  A
+        * very few early versions of the firmware didn't have one embedded
+        * but we can ignore those.
+        */
+       if (ret == -ENOENT) {
+               memset(&caps_cmd, 0, sizeof(caps_cmd));
+               caps_cmd.op_to_write =
+                       htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+                                       FW_CMD_REQUEST |
+                                       FW_CMD_READ);
+               caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
+               ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
+                               sizeof(caps_cmd), &caps_cmd);
+               config_name = "Firmware Default";
+       }
+
+       config_issued = 1;
        if (ret < 0)
                goto bye;
 
@@ -4816,7 +4804,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-       sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
        /*
         * Return successfully and note that we're operating with parameters
         * not supplied by the driver, rather than from hard-wired
@@ -4824,11 +4811,8 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         */
        adapter->flags |= USING_SOFT_PARAMS;
        dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
-                "Configuration File %s, version %#x, computed checksum %#x\n",
-                (using_flash
-                 ? "in device FLASH"
-                 : fw_config_file_path),
-                finiver, cfcsum);
+                "Configuration File \"%s\", version %#x, computed checksum %#x\n",
+                config_name, finiver, cfcsum);
        return 0;
 
        /*
@@ -4837,9 +4821,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         * want to issue a warning since this is fairly common.)
         */
 bye:
-       if (ret != -ENOENT)
-               dev_warn(adapter->pdev_dev, "Configuration file error %d\n",
-                        -ret);
+       if (config_issued && ret != -ENOENT)
+               dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n",
+                        config_name, -ret);
        return ret;
 }
 
@@ -5086,6 +5070,47 @@ bye:
        return ret;
 }
 
+static struct fw_info fw_info_array[] = {
+       {
+               .chip = CHELSIO_T4,
+               .fs_name = FW4_CFNAME,
+               .fw_mod_name = FW4_FNAME,
+               .fw_hdr = {
+                       .chip = FW_HDR_CHIP_T4,
+                       .fw_ver = __cpu_to_be32(FW_VERSION(T4)),
+                       .intfver_nic = FW_INTFVER(T4, NIC),
+                       .intfver_vnic = FW_INTFVER(T4, VNIC),
+                       .intfver_ri = FW_INTFVER(T4, RI),
+                       .intfver_iscsi = FW_INTFVER(T4, ISCSI),
+                       .intfver_fcoe = FW_INTFVER(T4, FCOE),
+               },
+       }, {
+               .chip = CHELSIO_T5,
+               .fs_name = FW5_CFNAME,
+               .fw_mod_name = FW5_FNAME,
+               .fw_hdr = {
+                       .chip = FW_HDR_CHIP_T5,
+                       .fw_ver = __cpu_to_be32(FW_VERSION(T5)),
+                       .intfver_nic = FW_INTFVER(T5, NIC),
+                       .intfver_vnic = FW_INTFVER(T5, VNIC),
+                       .intfver_ri = FW_INTFVER(T5, RI),
+                       .intfver_iscsi = FW_INTFVER(T5, ISCSI),
+                       .intfver_fcoe = FW_INTFVER(T5, FCOE),
+               },
+       }
+};
+
+static struct fw_info *find_fw_info(int chip)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
+               if (fw_info_array[i].chip == chip)
+                       return &fw_info_array[i];
+       }
+       return NULL;
+}
+
 /*
  * Phase 0 of initialization: contact FW, obtain config, perform basic init.
  */
@@ -5096,7 +5121,7 @@ static int adap_init0(struct adapter *adap)
        enum dev_state state;
        u32 params[7], val[7];
        struct fw_caps_config_cmd caps_cmd;
-       int reset = 1, j;
+       int reset = 1;
 
        /*
         * Contact FW, advertising Master capability (and potentially forcing
@@ -5123,44 +5148,54 @@ static int adap_init0(struct adapter *adap)
         * later reporting and B. to warn if the currently loaded firmware
         * is excessively mismatched relative to the driver.)
         */
-       ret = t4_check_fw_version(adap);
-
-       /* The error code -EFAULT is returned by t4_check_fw_version() if
-        * firmware on adapter < supported firmware. If firmware on adapter
-        * is too old (not supported by driver) and we're the MASTER_PF set
-        * adapter state to DEV_STATE_UNINIT to force firmware upgrade
-        * and reinitialization.
-        */
-       if ((adap->flags & MASTER_PF) && ret == -EFAULT)
-               state = DEV_STATE_UNINIT;
+       t4_get_fw_version(adap, &adap->params.fw_vers);
+       t4_get_tp_version(adap, &adap->params.tp_vers);
        if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
-               if (ret == -EINVAL || ret == -EFAULT || ret > 0) {
-                       if (upgrade_fw(adap) >= 0) {
-                               /*
-                                * Note that the chip was reset as part of the
-                                * firmware upgrade so we don't reset it again
-                                * below and grab the new firmware version.
-                                */
-                               reset = 0;
-                               ret = t4_check_fw_version(adap);
-                       } else
-                               if (ret == -EFAULT) {
-                                       /*
-                                        * Firmware is old but still might
-                                        * work if we force reinitialization
-                                        * of the adapter. Ignoring FW upgrade
-                                        * failure.
-                                        */
-                                       dev_warn(adap->pdev_dev,
-                                                "Ignoring firmware upgrade "
-                                                "failure, and forcing driver "
-                                                "to reinitialize the "
-                                                "adapter.\n");
-                                       ret = 0;
-                               }
+               struct fw_info *fw_info;
+               struct fw_hdr *card_fw;
+               const struct firmware *fw;
+               const u8 *fw_data = NULL;
+               unsigned int fw_size = 0;
+
+               /* This is the firmware whose headers the driver was compiled
+                * against
+                */
+               fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip));
+               if (fw_info == NULL) {
+                       dev_err(adap->pdev_dev,
+                               "unable to get firmware info for chip %d.\n",
+                               CHELSIO_CHIP_VERSION(adap->params.chip));
+                       return -EINVAL;
                }
+
+               /* allocate memory to read the header of the firmware on the
+                * card
+                */
+               card_fw = t4_alloc_mem(sizeof(*card_fw));
+
+               /* Get FW from from /lib/firmware/ */
+               ret = request_firmware(&fw, fw_info->fw_mod_name,
+                                      adap->pdev_dev);
+               if (ret < 0) {
+                       dev_err(adap->pdev_dev,
+                               "unable to load firmware image %s, error %d\n",
+                               fw_info->fw_mod_name, ret);
+               } else {
+                       fw_data = fw->data;
+                       fw_size = fw->size;
+               }
+
+               /* upgrade FW logic */
+               ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw,
+                                state, &reset);
+
+               /* Cleaning up */
+               if (fw != NULL)
+                       release_firmware(fw);
+               t4_free_mem(card_fw);
+
                if (ret < 0)
-                       return ret;
+                       goto bye;
        }
 
        /*
@@ -5245,7 +5280,7 @@ static int adap_init0(struct adapter *adap)
                                if (ret == -ENOENT) {
                                        dev_info(adap->pdev_dev,
                                            "No Configuration File present "
-                                           "on adapter.  Using hard-wired "
+                                           "on adapter. Using hard-wired "
                                            "configuration parameters.\n");
                                        ret = adap_init0_no_config(adap, reset);
                                }
@@ -5428,21 +5463,11 @@ static int adap_init0(struct adapter *adap)
        /*
         * These are finalized by FW initialization, load their values now.
         */
-       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
-       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
-       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
        t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
        t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
                     adap->params.b_wnd);
 
-       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
-       for (j = 0; j < NCHAN; j++)
-               adap->params.tp.tx_modq[j] = j;
-
-       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
-                        &adap->filter_mode, 1,
-                        TP_VLAN_PRI_MAP);
-
+       t4_init_tp_params(adap);
        adap->flags |= FW_OK;
        return 0;
 
@@ -5787,7 +5812,7 @@ static void print_port_info(const struct net_device *dev)
 
        netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
                    adap->params.vpd.id,
-                   CHELSIO_CHIP_RELEASE(adap->params.rev), buf,
+                   CHELSIO_CHIP_RELEASE(adap->params.chip), buf,
                    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
                    (adap->flags & USING_MSIX) ? " MSI-X" :
                    (adap->flags & USING_MSI) ? " MSI" : "");
@@ -5910,7 +5935,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto out_unmap_bar0;
 
-       if (!is_t4(adapter->chip)) {
+       if (!is_t4(adapter->params.chip)) {
                s_qpp = QUEUESPERPAGEPF1 * adapter->fn;
                qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter,
                      SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
@@ -6064,7 +6089,7 @@ sriov:
  out_free_dev:
        free_some_resources(adapter);
  out_unmap_bar:
-       if (!is_t4(adapter->chip))
+       if (!is_t4(adapter->params.chip))
                iounmap(adapter->bar2);
  out_unmap_bar0:
        iounmap(adapter->regs);
@@ -6116,7 +6141,7 @@ static void remove_one(struct pci_dev *pdev)
 
                free_some_resources(adapter);
                iounmap(adapter->regs);
-               if (!is_t4(adapter->chip))
+               if (!is_t4(adapter->params.chip))
                        iounmap(adapter->bar2);
                kfree(adapter);
                pci_disable_pcie_error_reporting(pdev);
index 6f21f2451c3052a24ecd2e8d8d16ee9bdf9996fe..4dd0a82533e442f8b330c5ede554359ea450a087 100644 (file)
@@ -131,7 +131,14 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
 
 static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
 {
-       stid -= t->stid_base;
+       /* Is it a server filter TID? */
+       if (t->nsftids && (stid >= t->sftid_base)) {
+               stid -= t->sftid_base;
+               stid += t->nstids;
+       } else {
+               stid -= t->stid_base;
+       }
+
        return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
 }
 
index 29878098101eb07771626399a1c5050a9544d055..81e8402a74b41c910114b4d10b3b796161ed0ea2 100644 (file)
@@ -45,6 +45,7 @@
 #include "l2t.h"
 #include "t4_msg.h"
 #include "t4fw_api.h"
+#include "t4_regs.h"
 
 #define VLAN_NONE 0xfff
 
@@ -411,6 +412,40 @@ done:
 }
 EXPORT_SYMBOL(cxgb4_l2t_get);
 
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t)
+{
+       struct adapter *adap = netdev2adap(dev);
+       struct tp_params *tp = &adap->params.tp;
+       u64 ntuple = 0;
+
+       /* Initialize each of the fields which we care about which are present
+        * in the Compressed Filter Tuple.
+        */
+       if (tp->vlan_shift >= 0 && l2t->vlan != VLAN_NONE)
+               ntuple |= (u64)(F_FT_VLAN_VLD | l2t->vlan) << tp->vlan_shift;
+
+       if (tp->port_shift >= 0)
+               ntuple |= (u64)l2t->lport << tp->port_shift;
+
+       if (tp->protocol_shift >= 0)
+               ntuple |= (u64)IPPROTO_TCP << tp->protocol_shift;
+
+       if (tp->vnic_shift >= 0) {
+               u32 viid = cxgb4_port_viid(dev);
+               u32 vf = FW_VIID_VIN_GET(viid);
+               u32 pf = FW_VIID_PFN_GET(viid);
+               u32 vld = FW_VIID_VIVLD_GET(viid);
+
+               ntuple |= (u64)(V_FT_VNID_ID_VF(vf) |
+                               V_FT_VNID_ID_PF(pf) |
+                               V_FT_VNID_ID_VLD(vld)) << tp->vnic_shift;
+       }
+
+       return ntuple;
+}
+EXPORT_SYMBOL(cxgb4_select_ntuple);
+
 /*
  * Called when address resolution fails for an L2T entry to handle packets
  * on the arpq head.  If a packet specifies a failure handler it is invoked,
index 108c0f1fce1c4e5776b687538d741cd6f771a909..85eb5c71358d80ad91e21df648289047165dbf39 100644 (file)
@@ -98,7 +98,8 @@ int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
 struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
                                const struct net_device *physdev,
                                unsigned int priority);
-
+u64 cxgb4_select_ntuple(struct net_device *dev,
+                       const struct l2t_entry *l2t);
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh);
 struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d);
 int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan,
index ac311f5f3eb9590d1d9b5fb3bb0a9c3f0fac5ce7..cc3511a5cd0c0f9ea54e0d186878821f3dad8096 100644 (file)
@@ -509,7 +509,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
        u32 val;
        if (q->pend_cred >= 8) {
                val = PIDX(q->pend_cred / 8);
-               if (!is_t4(adap->chip))
+               if (!is_t4(adap->params.chip))
                        val |= DBTYPE(1);
                wmb();
                t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
@@ -847,7 +847,7 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
        wmb();            /* write descriptors before telling HW */
        spin_lock(&q->db_lock);
        if (!q->db_disabled) {
-               if (is_t4(adap->chip)) {
+               if (is_t4(adap->params.chip)) {
                        t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
                                     QID(q->cntxt_id) | PIDX(n));
                } else {
@@ -1596,7 +1596,7 @@ static noinline int handle_trace_pkt(struct adapter *adap,
                return 0;
        }
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                __skb_pull(skb, sizeof(struct cpl_trace_pkt));
        else
                __skb_pull(skb, sizeof(struct cpl_t5_trace_pkt));
@@ -1661,7 +1661,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
        const struct cpl_rx_pkt *pkt;
        struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
        struct sge *s = &q->adap->sge;
-       int cpl_trace_pkt = is_t4(q->adap->chip) ?
+       int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
                            CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
 
        if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
@@ -2182,7 +2182,7 @@ err:
 static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
 {
        q->cntxt_id = id;
-       if (!is_t4(adap->chip)) {
+       if (!is_t4(adap->params.chip)) {
                unsigned int s_qpp;
                unsigned short udb_density;
                unsigned long qpshift;
@@ -2581,7 +2581,7 @@ static int t4_sge_init_soft(struct adapter *adap)
        #undef READ_FL_BUF
 
        if (fl_small_pg != PAGE_SIZE ||
-           (fl_large_pg != 0 && (fl_large_pg <= fl_small_pg ||
+           (fl_large_pg != 0 && (fl_large_pg < fl_small_pg ||
                                  (fl_large_pg & (fl_large_pg-1)) != 0))) {
                dev_err(adap->pdev_dev, "bad SGE FL page buffer sizes [%d, %d]\n",
                        fl_small_pg, fl_large_pg);
@@ -2641,7 +2641,7 @@ static int t4_sge_init_hard(struct adapter *adap)
         * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
         * and generate an interrupt when this occurs so we can recover.
         */
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
                                 V_HP_INT_THRESH(M_HP_INT_THRESH) |
                                 V_LP_INT_THRESH(M_LP_INT_THRESH),
index 4cbb2f9850be554c9ec48afd7479b4fcd9e5ebc2..e1413eacdbd20ab2233fd3217222bb76e6b779d1 100644 (file)
@@ -296,7 +296,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        u32 mc_bist_cmd, mc_bist_cmd_addr, mc_bist_cmd_len;
        u32 mc_bist_status_rdata, mc_bist_data_pattern;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mc_bist_cmd = MC_BIST_CMD;
                mc_bist_cmd_addr = MC_BIST_CMD_ADDR;
                mc_bist_cmd_len = MC_BIST_CMD_LEN;
@@ -349,7 +349,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        u32 edc_bist_cmd, edc_bist_cmd_addr, edc_bist_cmd_len;
        u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                edc_bist_cmd = EDC_REG(EDC_BIST_CMD, idx);
                edc_bist_cmd_addr = EDC_REG(EDC_BIST_CMD_ADDR, idx);
                edc_bist_cmd_len = EDC_REG(EDC_BIST_CMD_LEN, idx);
@@ -402,7 +402,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
 static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
 {
        int i;
-       u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
+       u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
        /*
         * Setup offset into PCIE memory window.  Address must be a
@@ -863,104 +863,169 @@ unlock:
 }
 
 /**
- *     get_fw_version - read the firmware version
+ *     t4_get_fw_version - read the firmware version
  *     @adapter: the adapter
  *     @vers: where to place the version
  *
  *     Reads the FW version from flash.
  */
-static int get_fw_version(struct adapter *adapter, u32 *vers)
+int t4_get_fw_version(struct adapter *adapter, u32 *vers)
 {
-       return t4_read_flash(adapter, adapter->params.sf_fw_start +
-                            offsetof(struct fw_hdr, fw_ver), 1, vers, 0);
+       return t4_read_flash(adapter, FLASH_FW_START +
+                            offsetof(struct fw_hdr, fw_ver), 1,
+                            vers, 0);
 }
 
 /**
- *     get_tp_version - read the TP microcode version
+ *     t4_get_tp_version - read the TP microcode version
  *     @adapter: the adapter
  *     @vers: where to place the version
  *
  *     Reads the TP microcode version from flash.
  */
-static int get_tp_version(struct adapter *adapter, u32 *vers)
+int t4_get_tp_version(struct adapter *adapter, u32 *vers)
 {
-       return t4_read_flash(adapter, adapter->params.sf_fw_start +
+       return t4_read_flash(adapter, FLASH_FW_START +
                             offsetof(struct fw_hdr, tp_microcode_ver),
                             1, vers, 0);
 }
 
-/**
- *     t4_check_fw_version - check if the FW is compatible with this driver
- *     @adapter: the adapter
- *
- *     Checks if an adapter's FW is compatible with the driver.  Returns 0
- *     if there's exact match, a negative error if the version could not be
- *     read or there's a major version mismatch, and a positive value if the
- *     expected major version is found but there's a minor version mismatch.
+/* Is the given firmware API compatible with the one the driver was compiled
+ * with?
  */
-int t4_check_fw_version(struct adapter *adapter)
+static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
 {
-       u32 api_vers[2];
-       int ret, major, minor, micro;
-       int exp_major, exp_minor, exp_micro;
 
-       ret = get_fw_version(adapter, &adapter->params.fw_vers);
-       if (!ret)
-               ret = get_tp_version(adapter, &adapter->params.tp_vers);
-       if (!ret)
-               ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
-                                   offsetof(struct fw_hdr, intfver_nic),
-                                   2, api_vers, 1);
-       if (ret)
-               return ret;
+       /* short circuit if it's the exact same firmware version */
+       if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
+               return 1;
 
-       major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers);
-       minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
-       micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
+#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
+       if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
+           SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe))
+               return 1;
+#undef SAME_INTF
 
-       switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
-       case CHELSIO_T4:
-               exp_major = FW_VERSION_MAJOR;
-               exp_minor = FW_VERSION_MINOR;
-               exp_micro = FW_VERSION_MICRO;
-               break;
-       case CHELSIO_T5:
-               exp_major = FW_VERSION_MAJOR_T5;
-               exp_minor = FW_VERSION_MINOR_T5;
-               exp_micro = FW_VERSION_MICRO_T5;
-               break;
-       default:
-               dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
-                       adapter->chip);
-               return -EINVAL;
-       }
+       return 0;
+}
 
-       memcpy(adapter->params.api_vers, api_vers,
-              sizeof(adapter->params.api_vers));
+/* The firmware in the filesystem is usable, but should it be installed?
+ * This routine explains itself in detail if it indicates the filesystem
+ * firmware should be installed.
+ */
+static int should_install_fs_fw(struct adapter *adap, int card_fw_usable,
+                               int k, int c)
+{
+       const char *reason;
 
-       if (major < exp_major || (major == exp_major && minor < exp_minor) ||
-           (major == exp_major && minor == exp_minor && micro < exp_micro)) {
-               dev_err(adapter->pdev_dev,
-                       "Card has firmware version %u.%u.%u, minimum "
-                       "supported firmware is %u.%u.%u.\n", major, minor,
-                       micro, exp_major, exp_minor, exp_micro);
-               return -EFAULT;
+       if (!card_fw_usable) {
+               reason = "incompatible or unusable";
+               goto install;
        }
 
-       if (major != exp_major) {            /* major mismatch - fail */
-               dev_err(adapter->pdev_dev,
-                       "card FW has major version %u, driver wants %u\n",
-                       major, exp_major);
-               return -EINVAL;
+       if (k > c) {
+               reason = "older than the version supported with this driver";
+               goto install;
        }
 
-       if (minor == exp_minor && micro == exp_micro)
-               return 0;                                   /* perfect match */
+       return 0;
+
+install:
+       dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, "
+               "installing firmware %u.%u.%u.%u on card.\n",
+               FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
+               FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason,
+               FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
+               FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
 
-       /* Minor/micro version mismatch.  Report it but often it's OK. */
        return 1;
 }
 
+int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state,
+              int *reset)
+{
+       int ret, card_fw_usable, fs_fw_usable;
+       const struct fw_hdr *fs_fw;
+       const struct fw_hdr *drv_fw;
+
+       drv_fw = &fw_info->fw_hdr;
+
+       /* Read the header of the firmware on the card */
+       ret = -t4_read_flash(adap, FLASH_FW_START,
+                           sizeof(*card_fw) / sizeof(uint32_t),
+                           (uint32_t *)card_fw, 1);
+       if (ret == 0) {
+               card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
+       } else {
+               dev_err(adap->pdev_dev,
+                       "Unable to read card's firmware header: %d\n", ret);
+               card_fw_usable = 0;
+       }
+
+       if (fw_data != NULL) {
+               fs_fw = (const void *)fw_data;
+               fs_fw_usable = fw_compatible(drv_fw, fs_fw);
+       } else {
+               fs_fw = NULL;
+               fs_fw_usable = 0;
+       }
+
+       if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
+           (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
+               /* Common case: the firmware on the card is an exact match and
+                * the filesystem one is an exact match too, or the filesystem
+                * one is absent/incompatible.
+                */
+       } else if (fs_fw_usable && state == DEV_STATE_UNINIT &&
+                  should_install_fs_fw(adap, card_fw_usable,
+                                       be32_to_cpu(fs_fw->fw_ver),
+                                       be32_to_cpu(card_fw->fw_ver))) {
+               ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
+                                    fw_size, 0);
+               if (ret != 0) {
+                       dev_err(adap->pdev_dev,
+                               "failed to install firmware: %d\n", ret);
+                       goto bye;
+               }
+
+               /* Installed successfully, update the cached header too. */
+               memcpy(card_fw, fs_fw, sizeof(*card_fw));
+               card_fw_usable = 1;
+               *reset = 0;     /* already reset as part of load_fw */
+       }
+
+       if (!card_fw_usable) {
+               uint32_t d, c, k;
+
+               d = be32_to_cpu(drv_fw->fw_ver);
+               c = be32_to_cpu(card_fw->fw_ver);
+               k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
+
+               dev_err(adap->pdev_dev, "Cannot find a usable firmware: "
+                       "chip state %d, "
+                       "driver compiled with %d.%d.%d.%d, "
+                       "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
+                       state,
+                       FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d),
+                       FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d),
+                       FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
+                       FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c),
+                       FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
+                       FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
+               ret = EINVAL;
+               goto bye;
+       }
+
+       /* We're using whatever's on the card and it's known to be good. */
+       adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver);
+       adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
+
+bye:
+       return ret;
+}
+
 /**
  *     t4_flash_erase_sectors - erase a range of flash sectors
  *     @adapter: the adapter
@@ -1368,7 +1433,7 @@ static void pcie_intr_handler(struct adapter *adapter)
                                    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
                                    pcie_port_intr_info) +
              t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
-                                   is_t4(adapter->chip) ?
+                                   is_t4(adapter->params.chip) ?
                                    pcie_intr_info : t5_pcie_intr_info);
 
        if (fat)
@@ -1782,7 +1847,7 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
 {
        u32 v, int_cause_reg;
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                int_cause_reg = PORT_REG(port, XGMAC_PORT_INT_CAUSE);
        else
                int_cause_reg = T5_PORT_REG(port, MAC_PORT_INT_CAUSE);
@@ -2250,7 +2315,7 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
 
 #define GET_STAT(name) \
        t4_read_reg64(adap, \
-       (is_t4(adap->chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
+       (is_t4(adap->params.chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
        T5_PORT_REG(idx, MPS_PORT_STAT_##name##_L)))
 #define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
 
@@ -2332,7 +2397,7 @@ void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
 {
        u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO);
                mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI);
                port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
@@ -2374,7 +2439,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
        int i;
        u32 port_cfg_reg;
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
        else
                port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2);
@@ -2387,7 +2452,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
                return -EINVAL;
 
 #define EPIO_REG(name) \
-       (is_t4(adap->chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
+       (is_t4(adap->params.chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
        T5_PORT_REG(port, MAC_PORT_EPIO_##name))
 
        t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
@@ -2474,7 +2539,7 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
 int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
 {
        int i, off;
-       u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
+       u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
        /* Align on a 2KB boundary.
         */
@@ -3306,7 +3371,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
        int i, ret;
        struct fw_vi_mac_cmd c;
        struct fw_vi_mac_exact *p;
-       unsigned int max_naddr = is_t4(adap->chip) ?
+       unsigned int max_naddr = is_t4(adap->params.chip) ?
                                       NUM_MPS_CLS_SRAM_L_INSTANCES :
                                       NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -3368,7 +3433,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
        int ret, mode;
        struct fw_vi_mac_cmd c;
        struct fw_vi_mac_exact *p = c.u.exact;
-       unsigned int max_mac_addr = is_t4(adap->chip) ?
+       unsigned int max_mac_addr = is_t4(adap->params.chip) ?
                                    NUM_MPS_CLS_SRAM_L_INSTANCES :
                                    NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -3699,13 +3764,14 @@ int t4_prep_adapter(struct adapter *adapter)
 {
        int ret, ver;
        uint16_t device_id;
+       u32 pl_rev;
 
        ret = t4_wait_dev_ready(adapter);
        if (ret < 0)
                return ret;
 
        get_pci_mode(adapter, &adapter->params.pci);
-       adapter->params.rev = t4_read_reg(adapter, PL_REV);
+       pl_rev = G_REV(t4_read_reg(adapter, PL_REV));
 
        ret = get_flash_params(adapter);
        if (ret < 0) {
@@ -3717,14 +3783,13 @@ int t4_prep_adapter(struct adapter *adapter)
         */
        pci_read_config_word(adapter->pdev, PCI_DEVICE_ID, &device_id);
        ver = device_id >> 12;
+       adapter->params.chip = 0;
        switch (ver) {
        case CHELSIO_T4:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4,
-                                                 adapter->params.rev);
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
                break;
        case CHELSIO_T5:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5,
-                                                 adapter->params.rev);
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
                break;
        default:
                dev_err(adapter->pdev_dev, "Device %d is not supported\n",
@@ -3732,9 +3797,6 @@ int t4_prep_adapter(struct adapter *adapter)
                return -EINVAL;
        }
 
-       /* Reassign the updated revision field */
-       adapter->params.rev = adapter->chip;
-
        init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
 
        /*
@@ -3746,6 +3808,109 @@ int t4_prep_adapter(struct adapter *adapter)
        return 0;
 }
 
+/**
+ *      t4_init_tp_params - initialize adap->params.tp
+ *      @adap: the adapter
+ *
+ *      Initialize various fields of the adapter's TP Parameters structure.
+ */
+int t4_init_tp_params(struct adapter *adap)
+{
+       int chan;
+       u32 v;
+
+       v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
+       adap->params.tp.tre = TIMERRESOLUTION_GET(v);
+       adap->params.tp.dack_re = DELAYEDACKRESOLUTION_GET(v);
+
+       /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */
+       for (chan = 0; chan < NCHAN; chan++)
+               adap->params.tp.tx_modq[chan] = chan;
+
+       /* Cache the adapter's Compressed Filter Mode and global Incress
+        * Configuration.
+        */
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.vlan_pri_map, 1,
+                        TP_VLAN_PRI_MAP);
+       t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
+                        &adap->params.tp.ingress_config, 1,
+                        TP_INGRESS_CONFIG);
+
+       /* Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field
+        * shift positions of several elements of the Compressed Filter Tuple
+        * for this adapter which we need frequently ...
+        */
+       adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN);
+       adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID);
+       adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT);
+       adap->params.tp.protocol_shift = t4_filter_field_shift(adap,
+                                                              F_PROTOCOL);
+
+       /* If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID
+        * represents the presense of an Outer VLAN instead of a VNIC ID.
+        */
+       if ((adap->params.tp.ingress_config & F_VNIC) == 0)
+               adap->params.tp.vnic_shift = -1;
+
+       return 0;
+}
+
+/**
+ *      t4_filter_field_shift - calculate filter field shift
+ *      @adap: the adapter
+ *      @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits)
+ *
+ *      Return the shift position of a filter field within the Compressed
+ *      Filter Tuple.  The filter field is specified via its selection bit
+ *      within TP_VLAN_PRI_MAL (filter mode).  E.g. F_VLAN.
+ */
+int t4_filter_field_shift(const struct adapter *adap, int filter_sel)
+{
+       unsigned int filter_mode = adap->params.tp.vlan_pri_map;
+       unsigned int sel;
+       int field_shift;
+
+       if ((filter_mode & filter_sel) == 0)
+               return -1;
+
+       for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) {
+               switch (filter_mode & sel) {
+               case F_FCOE:
+                       field_shift += W_FT_FCOE;
+                       break;
+               case F_PORT:
+                       field_shift += W_FT_PORT;
+                       break;
+               case F_VNIC_ID:
+                       field_shift += W_FT_VNIC_ID;
+                       break;
+               case F_VLAN:
+                       field_shift += W_FT_VLAN;
+                       break;
+               case F_TOS:
+                       field_shift += W_FT_TOS;
+                       break;
+               case F_PROTOCOL:
+                       field_shift += W_FT_PROTOCOL;
+                       break;
+               case F_ETHERTYPE:
+                       field_shift += W_FT_ETHERTYPE;
+                       break;
+               case F_MACMATCH:
+                       field_shift += W_FT_MACMATCH;
+                       break;
+               case F_MPSHITTYPE:
+                       field_shift += W_FT_MPSHITTYPE;
+                       break;
+               case F_FRAGMENTATION:
+                       field_shift += W_FT_FRAGMENTATION;
+                       break;
+               }
+       }
+       return field_shift;
+}
+
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
        u8 addr[6];
index ef146c0ba4814ef5abff64794075b9d5e806c62b..4082522d81408bf0a23cff8eaf9700bef14533a9 100644 (file)
 
 #define PL_REV 0x1943c
 
+#define S_REV    0
+#define M_REV    0xfU
+#define V_REV(x) ((x) << S_REV)
+#define G_REV(x) (((x) >> S_REV) & M_REV)
+
 #define LE_DB_CONFIG 0x19c04
 #define  HASHEN 0x00100000U
 
 
 #define A_TP_TX_SCHED_PCMD 0x25
 
+#define S_VNIC    11
+#define V_VNIC(x) ((x) << S_VNIC)
+#define F_VNIC    V_VNIC(1U)
+
+#define S_FRAGMENTATION    9
+#define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION)
+#define F_FRAGMENTATION    V_FRAGMENTATION(1U)
+
+#define S_MPSHITTYPE    8
+#define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE)
+#define F_MPSHITTYPE    V_MPSHITTYPE(1U)
+
+#define S_MACMATCH    7
+#define V_MACMATCH(x) ((x) << S_MACMATCH)
+#define F_MACMATCH    V_MACMATCH(1U)
+
+#define S_ETHERTYPE    6
+#define V_ETHERTYPE(x) ((x) << S_ETHERTYPE)
+#define F_ETHERTYPE    V_ETHERTYPE(1U)
+
+#define S_PROTOCOL    5
+#define V_PROTOCOL(x) ((x) << S_PROTOCOL)
+#define F_PROTOCOL    V_PROTOCOL(1U)
+
+#define S_TOS    4
+#define V_TOS(x) ((x) << S_TOS)
+#define F_TOS    V_TOS(1U)
+
+#define S_VLAN    3
+#define V_VLAN(x) ((x) << S_VLAN)
+#define F_VLAN    V_VLAN(1U)
+
+#define S_VNIC_ID    2
+#define V_VNIC_ID(x) ((x) << S_VNIC_ID)
+#define F_VNIC_ID    V_VNIC_ID(1U)
+
 #define S_PORT    1
 #define V_PORT(x) ((x) << S_PORT)
 #define F_PORT    V_PORT(1U)
 
+#define S_FCOE    0
+#define V_FCOE(x) ((x) << S_FCOE)
+#define F_FCOE    V_FCOE(1U)
+
 #define NUM_MPS_CLS_SRAM_L_INSTANCES 336
 #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512
 
 #define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
 #define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
 
+#define A_PL_VF_REV 0x4
+#define A_PL_VF_WHOAMI 0x0
+#define A_PL_VF_REVISION 0x8
+
+#define S_CHIPID    4
+#define M_CHIPID    0xfU
+#define V_CHIPID(x) ((x) << S_CHIPID)
+#define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
+
+/* TP_VLAN_PRI_MAP controls which subset of fields will be present in the
+ * Compressed Filter Tuple for LE filters.  Each bit set in TP_VLAN_PRI_MAP
+ * selects for a particular field being present.  These fields, when present
+ * in the Compressed Filter Tuple, have the following widths in bits.
+ */
+#define W_FT_FCOE                       1
+#define W_FT_PORT                       3
+#define W_FT_VNIC_ID                    17
+#define W_FT_VLAN                       17
+#define W_FT_TOS                        8
+#define W_FT_PROTOCOL                   8
+#define W_FT_ETHERTYPE                  16
+#define W_FT_MACMATCH                   9
+#define W_FT_MPSHITTYPE                 3
+#define W_FT_FRAGMENTATION              1
+
+/* Some of the Compressed Filter Tuple fields have internal structure.  These
+ * bit shifts/masks describe those structures.  All shifts are relative to the
+ * base position of the fields within the Compressed Filter Tuple
+ */
+#define S_FT_VLAN_VLD                   16
+#define V_FT_VLAN_VLD(x)                ((x) << S_FT_VLAN_VLD)
+#define F_FT_VLAN_VLD                   V_FT_VLAN_VLD(1U)
+
+#define S_FT_VNID_ID_VF                 0
+#define V_FT_VNID_ID_VF(x)              ((x) << S_FT_VNID_ID_VF)
+
+#define S_FT_VNID_ID_PF                 7
+#define V_FT_VNID_ID_PF(x)              ((x) << S_FT_VNID_ID_PF)
+
+#define S_FT_VNID_ID_VLD                16
+#define V_FT_VNID_ID_VLD(x)             ((x) << S_FT_VNID_ID_VLD)
+
 #endif /* __T4_REGS_H */
index 6f77ac487743edfbe899f470805f58cc38d9c61b..74fea74ce0aa25a676045868fa0b48c4a3800860 100644 (file)
@@ -2157,7 +2157,7 @@ struct fw_debug_cmd {
 
 struct fw_hdr {
        u8 ver;
-       u8 reserved1;
+       u8 chip;                        /* terminator chip type */
        __be16  len512;                 /* bin length in units of 512-bytes */
        __be32  fw_ver;                 /* firmware version */
        __be32  tp_microcode_ver;
@@ -2176,6 +2176,11 @@ struct fw_hdr {
        __be32  reserved6[23];
 };
 
+enum fw_hdr_chip {
+       FW_HDR_CHIP_T4,
+       FW_HDR_CHIP_T5
+};
+
 #define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
 #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
 #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
index be5c7ef6ca939654365b6aec6dc108e03e0f74d9..68eaa9c88c7d8a77646bd217e00877a281254a59 100644 (file)
@@ -344,7 +344,6 @@ struct adapter {
        unsigned long registered_device_map;
        unsigned long open_device_map;
        unsigned long flags;
-       enum chip_type chip;
        struct adapter_params params;
 
        /* queue and interrupt resources */
index 5f90ec5f7519a4ac6e7916396cff31446f5c614b..0899c098359446346f7abe1939ac214705fd0acb 100644 (file)
@@ -1064,7 +1064,7 @@ static inline unsigned int mk_adap_vers(const struct adapter *adapter)
        /*
         * Chip version 4, revision 0x3f (cxgb4vf).
         */
-       return CHELSIO_CHIP_VERSION(adapter->chip) | (0x3f << 10);
+       return CHELSIO_CHIP_VERSION(adapter->params.chip) | (0x3f << 10);
 }
 
 /*
@@ -1551,9 +1551,13 @@ static void cxgb4vf_get_regs(struct net_device *dev,
        reg_block_dump(adapter, regbuf,
                       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_FIRST,
                       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_LAST);
+
+       /* T5 adds new registers in the PL Register map.
+        */
        reg_block_dump(adapter, regbuf,
                       T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_FIRST,
-                      T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_LAST);
+                      T4VF_PL_BASE_ADDR + (is_t4(adapter->params.chip)
+                      ? A_PL_VF_WHOAMI : A_PL_VF_REVISION));
        reg_block_dump(adapter, regbuf,
                       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_FIRST,
                       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_LAST);
@@ -2087,6 +2091,7 @@ static int adap_init0(struct adapter *adapter)
        unsigned int ethqsets;
        int err;
        u32 param, val = 0;
+       unsigned int chipid;
 
        /*
         * Wait for the device to become ready before proceeding ...
@@ -2114,12 +2119,14 @@ static int adap_init0(struct adapter *adapter)
                return err;
        }
 
+       adapter->params.chip = 0;
        switch (adapter->pdev->device >> 12) {
        case CHELSIO_T4:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
+               adapter->params.chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
                break;
        case CHELSIO_T5:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, 0);
+               chipid = G_REV(t4_read_reg(adapter, A_PL_VF_REV));
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, chipid);
                break;
        }
 
index 8475c4cda9e4ca72ef8a2b309788620e82fb67d3..0a89963c48ce78148d1abe6cd86151e850c24062 100644 (file)
@@ -537,7 +537,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
         */
        if (fl->pend_cred >= FL_PER_EQ_UNIT) {
                val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT);
-               if (!is_t4(adapter->chip))
+               if (!is_t4(adapter->params.chip))
                        val |= DBTYPE(1);
                wmb();
                t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
index 53cbfed21d0b9871fe257ee75836dc2dadbdc185..61362450d05b4f83daeacf9a0c54ebed35e2da4c 100644 (file)
 #include "../cxgb4/t4fw_api.h"
 
 #define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
 #define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
 
+/* All T4 and later chips have their PCI-E Device IDs encoded as 0xVFPP where:
+ *
+ *   V  = "4" for T4; "5" for T5, etc. or
+ *      = "a" for T4 FPGA; "b" for T4 FPGA, etc.
+ *   F  = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs
+ *   PP = adapter product designation
+ */
 #define CHELSIO_T4             0x4
 #define CHELSIO_T5             0x5
 
 enum chip_type {
-       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
-       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
-       T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
        T4_FIRST_REV    = T4_A1,
-       T4_LAST_REV     = T4_A3,
+       T4_LAST_REV     = T4_A2,
 
-       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
-       T5_FIRST_REV    = T5_A1,
+       T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+       T5_FIRST_REV    = T5_A0,
        T5_LAST_REV     = T5_A1,
 };
 
@@ -203,6 +210,7 @@ struct adapter_params {
        struct vpd_params vpd;          /* Vital Product Data */
        struct rss_params rss;          /* Receive Side Scaling */
        struct vf_resources vfres;      /* Virtual Function Resource limits */
+       enum chip_type chip;            /* chip code */
        u8 nports;                      /* # of Ethernet "ports" */
 };
 
@@ -253,7 +261,7 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
 
 static inline int is_t4(enum chip_type chip)
 {
-       return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
 }
 
 int t4vf_wait_dev_ready(struct adapter *);
index 9f96dc3bb11203e0781faa785d12ec31df4f76f3..d958c44341b5cb299d704600494de5be9d15bb72 100644 (file)
@@ -1027,7 +1027,7 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
        unsigned nfilters = 0;
        unsigned int rem = naddr;
        struct fw_vi_mac_cmd cmd, rpl;
-       unsigned int max_naddr = is_t4(adapter->chip) ?
+       unsigned int max_naddr = is_t4(adapter->params.chip) ?
                                 NUM_MPS_CLS_SRAM_L_INSTANCES :
                                 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -1121,7 +1121,7 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid,
        struct fw_vi_mac_exact *p = &cmd.u.exact[0];
        size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
                                             u.exact[1]), 16);
-       unsigned int max_naddr = is_t4(adapter->chip) ?
+       unsigned int max_naddr = is_t4(adapter->params.chip) ?
                                 NUM_MPS_CLS_SRAM_L_INSTANCES :
                                 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
index f4825db5d1792419924bab4f9d08e17abbfd6128..4ccaf9af6fc90cde0d9d13490fa5753e480c543e 100644 (file)
@@ -104,6 +104,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE3_MAX_RSS_QS         16
 #define BE3_MAX_TX_QS          16
 #define BE3_MAX_EVT_QS         16
+#define BE3_SRIOV_MAX_EVT_QS   8
 
 #define MAX_RX_QS              32
 #define MAX_EVT_QS             32
@@ -480,7 +481,7 @@ struct be_adapter {
        struct list_head entry;
 
        u32 flash_status;
-       struct completion flash_compl;
+       struct completion et_cmd_compl;
 
        struct be_resources res;        /* resources available for the func */
        u16 num_vfs;                    /* Number of VFs provisioned by PF */
@@ -503,6 +504,7 @@ struct be_adapter {
 };
 
 #define be_physfn(adapter)             (!adapter->virtfn)
+#define be_virtfn(adapter)             (adapter->virtfn)
 #define        sriov_enabled(adapter)          (adapter->num_vfs > 0)
 #define sriov_want(adapter)             (be_physfn(adapter) && \
                                         (num_vfs || pci_num_vf(adapter->pdev)))
index dbcd5262c0167c1ae0dacf7dd578b5c3a2a43ce5..94c35c8d799d9f1e4f4b9fd78121600ad600505e 100644 (file)
@@ -141,11 +141,17 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                subsystem = resp_hdr->subsystem;
        }
 
+       if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
+           subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
+               complete(&adapter->et_cmd_compl);
+               return 0;
+       }
+
        if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
             (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
            (subsystem == CMD_SUBSYSTEM_COMMON)) {
                adapter->flash_status = compl_status;
-               complete(&adapter->flash_compl);
+               complete(&adapter->et_cmd_compl);
        }
 
        if (compl_status == MCC_STATUS_SUCCESS) {
@@ -1032,6 +1038,13 @@ int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
        } else {
                req->hdr.version = 2;
                req->page_size = 1; /* 1 for 4K */
+
+               /* coalesce-wm field in this cmd is not relevant to Lancer.
+                * Lancer uses COMMON_MODIFY_CQ to set this field
+                */
+               if (!lancer_chip(adapter))
+                       AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+                                     ctxt, coalesce_wm);
                AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
                                                                no_delay);
                AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
@@ -2010,6 +2023,9 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
                        0x3ea83c02, 0x4a110304};
        int status;
 
+       if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
+               return 0;
+
        if (mutex_lock_interruptible(&adapter->mbox_lock))
                return -1;
 
@@ -2153,7 +2169,7 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
                                         msecs_to_jiffies(60000)))
                status = -1;
        else
@@ -2248,8 +2264,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        be_mcc_notify(adapter);
        spin_unlock_bh(&adapter->mcc_lock);
 
-       if (!wait_for_completion_timeout(&adapter->flash_compl,
-                       msecs_to_jiffies(40000)))
+       if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
+                                        msecs_to_jiffies(40000)))
                status = -1;
        else
                status = adapter->flash_status;
@@ -2360,6 +2376,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_req_loopback_test *req;
+       struct be_cmd_resp_loopback_test *resp;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2374,8 +2391,8 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req), wrb, NULL);
-       req->hdr.timeout = cpu_to_le32(4);
 
+       req->hdr.timeout = cpu_to_le32(15);
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
        req->dest_port = cpu_to_le32(port_num);
@@ -2383,12 +2400,15 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
        req->num_pkts = cpu_to_le32(num_pkts);
        req->loopback_type = cpu_to_le32(loopback_type);
 
-       status = be_mcc_notify_wait(adapter);
-       if (!status) {
-               struct be_cmd_resp_loopback_test *resp = embedded_payload(wrb);
-               status = le32_to_cpu(resp->status);
-       }
+       be_mcc_notify(adapter);
+
+       spin_unlock_bh(&adapter->mcc_lock);
+
+       wait_for_completion(&adapter->et_cmd_compl);
+       resp = embedded_payload(wrb);
+       status = le32_to_cpu(resp->status);
 
+       return status;
 err:
        spin_unlock_bh(&adapter->mcc_lock);
        return status;
index 3e2162121601e79481428c4d7ca02c3523dc0e33..dc88782185f26f000e4e58cd793f90f6064bbfb6 100644 (file)
@@ -64,6 +64,9 @@
 #define SLIPORT_ERROR_NO_RESOURCE1     0x2
 #define SLIPORT_ERROR_NO_RESOURCE2     0x9
 
+#define SLIPORT_ERROR_FW_RESET1                0x2
+#define SLIPORT_ERROR_FW_RESET2                0x0
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET     0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
index abde97471636918a6b7e2381634cdc743678d24c..a37039d353c57e999a9235a0af2ca3d48f3c3b14 100644 (file)
@@ -1776,6 +1776,7 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
        struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
        struct be_queue_info *rxq = &rxo->q;
        struct page *pagep = NULL;
+       struct device *dev = &adapter->pdev->dev;
        struct be_eth_rx_d *rxd;
        u64 page_dmaaddr = 0, frag_dmaaddr;
        u32 posted, page_offset = 0;
@@ -1788,9 +1789,15 @@ static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
                                rx_stats(rxo)->rx_post_fail++;
                                break;
                        }
-                       page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
-                                                   0, adapter->big_page_size,
+                       page_dmaaddr = dma_map_page(dev, pagep, 0,
+                                                   adapter->big_page_size,
                                                    DMA_FROM_DEVICE);
+                       if (dma_mapping_error(dev, page_dmaaddr)) {
+                               put_page(pagep);
+                               pagep = NULL;
+                               rx_stats(rxo)->rx_post_fail++;
+                               break;
+                       }
                        page_info->page_offset = 0;
                } else {
                        get_page(pagep);
@@ -2464,8 +2471,16 @@ void be_detect_error(struct be_adapter *adapter)
         */
        if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
                adapter->hw_error = true;
-               dev_err(&adapter->pdev->dev,
-                       "Error detected in the card\n");
+               /* Do not log error messages if its a FW reset */
+               if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
+                   sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
+                       dev_info(&adapter->pdev->dev,
+                                "Firmware update in progress\n");
+                       return;
+               } else {
+                       dev_err(&adapter->pdev->dev,
+                               "Error detected in the card\n");
+               }
        }
 
        if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
@@ -2658,8 +2673,8 @@ static int be_close(struct net_device *netdev)
 
        be_roce_dev_close(adapter);
 
-       for_all_evt_queues(adapter, eqo, i) {
-               if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
+       if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
+               for_all_evt_queues(adapter, eqo, i) {
                        napi_disable(&eqo->napi);
                        be_disable_busy_poll(eqo);
                }
@@ -2736,13 +2751,16 @@ static int be_rx_qs_create(struct be_adapter *adapter)
                if (!BEx_chip(adapter))
                        adapter->rss_flags |= RSS_ENABLE_UDP_IPV4 |
                                                RSS_ENABLE_UDP_IPV6;
+       } else {
+               /* Disable RSS, if only default RX Q is created */
+               adapter->rss_flags = RSS_ENABLE_NONE;
+       }
 
-               rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
-                                      128);
-               if (rc) {
-                       adapter->rss_flags = 0;
-                       return rc;
-               }
+       rc = be_cmd_rss_config(adapter, rsstable, adapter->rss_flags,
+                              128);
+       if (rc) {
+               adapter->rss_flags = RSS_ENABLE_NONE;
+               return rc;
        }
 
        /* First time posting */
@@ -2932,28 +2950,35 @@ static void be_cancel_worker(struct be_adapter *adapter)
        }
 }
 
-static int be_clear(struct be_adapter *adapter)
+static void be_mac_clear(struct be_adapter *adapter)
 {
        int i;
 
+       if (adapter->pmac_id) {
+               for (i = 0; i < (adapter->uc_macs + 1); i++)
+                       be_cmd_pmac_del(adapter, adapter->if_handle,
+                                       adapter->pmac_id[i], 0);
+               adapter->uc_macs = 0;
+
+               kfree(adapter->pmac_id);
+               adapter->pmac_id = NULL;
+       }
+}
+
+static int be_clear(struct be_adapter *adapter)
+{
        be_cancel_worker(adapter);
 
        if (sriov_enabled(adapter))
                be_vf_clear(adapter);
 
        /* delete the primary mac along with the uc-mac list */
-       for (i = 0; i < (adapter->uc_macs + 1); i++)
-               be_cmd_pmac_del(adapter, adapter->if_handle,
-                               adapter->pmac_id[i], 0);
-       adapter->uc_macs = 0;
+       be_mac_clear(adapter);
 
        be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
        be_clear_queues(adapter);
 
-       kfree(adapter->pmac_id);
-       adapter->pmac_id = NULL;
-
        be_msix_disable(adapter);
        return 0;
 }
@@ -3109,11 +3134,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
        bool use_sriov = false;
+       int max_vfs;
 
-       if (BE3_chip(adapter) && sriov_want(adapter)) {
-               int max_vfs;
+       max_vfs = pci_sriov_get_totalvfs(pdev);
 
-               max_vfs = pci_sriov_get_totalvfs(pdev);
+       if (BE3_chip(adapter) && sriov_want(adapter)) {
                res->max_vfs = max_vfs > 0 ? min(MAX_VFS, max_vfs) : 0;
                use_sriov = res->max_vfs;
        }
@@ -3144,7 +3169,11 @@ static void BEx_get_resources(struct be_adapter *adapter,
                                           BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
        res->max_rx_qs = res->max_rss_qs + 1;
 
-       res->max_evt_qs = be_physfn(adapter) ? BE3_MAX_EVT_QS : 1;
+       if (be_physfn(adapter))
+               res->max_evt_qs = (max_vfs > 0) ?
+                                       BE3_SRIOV_MAX_EVT_QS : BE3_MAX_EVT_QS;
+       else
+               res->max_evt_qs = 1;
 
        res->if_cap_flags = BE_IF_CAP_FLAGS_WANT;
        if (!(adapter->function_caps & BE_FUNCTION_CAPS_RSS))
@@ -3253,12 +3282,10 @@ static int be_mac_setup(struct be_adapter *adapter)
                memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
        }
 
-       /* On BE3 VFs this cmd may fail due to lack of privilege.
-        * Ignore the failure as in this case pmac_id is fetched
-        * in the IFACE_CREATE cmd.
-        */
-       be_cmd_pmac_add(adapter, mac, adapter->if_handle,
-                       &adapter->pmac_id[0], 0);
+       /* For BE3-R VFs, the PF programs the initial MAC address */
+       if (!(BEx_chip(adapter) && be_virtfn(adapter)))
+               be_cmd_pmac_add(adapter, mac, adapter->if_handle,
+                               &adapter->pmac_id[0], 0);
        return 0;
 }
 
@@ -3814,6 +3841,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
        }
 
        if (change_status == LANCER_FW_RESET_NEEDED) {
+               dev_info(&adapter->pdev->dev,
+                        "Resetting adapter to activate new FW\n");
                status = lancer_physdev_ctrl(adapter,
                                             PHYSDEV_CONTROL_FW_RESET_MASK);
                if (status) {
@@ -4190,7 +4219,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
 
-       init_completion(&adapter->flash_compl);
+       init_completion(&adapter->et_cmd_compl);
        pci_save_state(adapter->pdev);
        return 0;
 
@@ -4365,13 +4394,13 @@ static int lancer_recover_func(struct be_adapter *adapter)
                        goto err;
        }
 
-       dev_err(dev, "Error recovery successful\n");
+       dev_err(dev, "Adapter recovery successful\n");
        return 0;
 err:
        if (status == -EAGAIN)
                dev_err(dev, "Waiting for resource provisioning\n");
        else
-               dev_err(dev, "Error recovery failed\n");
+               dev_err(dev, "Adapter recovery failed\n");
 
        return status;
 }
@@ -4599,6 +4628,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
        if (adapter->wol)
                be_setup_wol(adapter, true);
 
+       be_intr_set(adapter, false);
        cancel_delayed_work_sync(&adapter->func_recovery_work);
 
        netif_device_detach(netdev);
@@ -4634,6 +4664,7 @@ static int be_resume(struct pci_dev *pdev)
        if (status)
                return status;
 
+       be_intr_set(adapter, true);
        /* tell fw we're ready to fire cmds */
        status = be_cmd_fw_init(adapter);
        if (status)
index 4cbebf3d80eb1492d847f1ad8a9888e2a6c17b97..50bb71c663e20a010c9a4390c3d1c38726037c85 100644 (file)
@@ -98,10 +98,6 @@ static void set_multicast_list(struct net_device *ndev);
  * detected as not set during a prior frame transmission, then the
  * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
  * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
- * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
- * detected as not set during a prior frame transmission, then the
- * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
- * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
  * frames not being transmitted until there is a 0-to-1 transition on
  * ENET_TDAR[TDAR].
  */
@@ -385,7 +381,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
         * data.
         */
        bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
-                       FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+                       skb->len, DMA_TO_DEVICE);
        if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
                bdp->cbd_bufaddr = 0;
                fep->tx_skbuff[index] = NULL;
@@ -432,6 +428,8 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* If this was the last BD in the ring, start at the beginning again. */
        bdp = fec_enet_get_nextdesc(bdp, fep);
 
+       skb_tx_timestamp(skb);
+
        fep->cur_tx = bdp;
 
        if (fep->cur_tx == fep->dirty_tx)
@@ -440,8 +438,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* Trigger transmission start */
        writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
-       skb_tx_timestamp(skb);
-
        return NETDEV_TX_OK;
 }
 
@@ -779,11 +775,10 @@ fec_enet_tx(struct net_device *ndev)
                else
                        index = bdp - fep->tx_bd_base;
 
-               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-                               FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-               bdp->cbd_bufaddr = 0;
-
                skb = fep->tx_skbuff[index];
+               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
+                               DMA_TO_DEVICE);
+               bdp->cbd_bufaddr = 0;
 
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
index 2d1c6bdd36189f9f595ada15599301ce992330a9..7628e0fd84554fd56eca5f4181f2ff31c85eca0d 100644 (file)
@@ -3033,7 +3033,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 
        dev->hw_features = NETIF_F_SG | NETIF_F_TSO |
                      NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX;
-       dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO |
+       dev->features = NETIF_F_SG | NETIF_F_TSO |
                      NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
                      NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
                      NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM;
index 58c147271a362e68914d55d97b71b327b194e86b..f9313b36c88716068611b44d3c7a6b182d4277e9 100644 (file)
@@ -83,6 +83,11 @@ struct e1000_adapter;
 
 #define E1000_MAX_INTR                 10
 
+/*
+ * Count for polling __E1000_RESET condition every 10-20msec.
+ */
+#define E1000_CHECK_RESET_COUNT        50
+
 /* TX/RX descriptor defines */
 #define E1000_DEFAULT_TXD              256
 #define E1000_MAX_TXD                  256
@@ -312,8 +317,6 @@ struct e1000_adapter {
        struct delayed_work watchdog_task;
        struct delayed_work fifo_stall_task;
        struct delayed_work phy_info_task;
-
-       struct mutex mutex;
 };
 
 enum e1000_state_t {
index e38622825fa7336ae74f64229f3e5619cb668335..46e6544ed1b7f5c1ba9367dd1dfe444d725cd0e3 100644 (file)
@@ -494,13 +494,20 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
 {
        set_bit(__E1000_DOWN, &adapter->flags);
 
-       /* Only kill reset task if adapter is not resetting */
-       if (!test_bit(__E1000_RESETTING, &adapter->flags))
-               cancel_work_sync(&adapter->reset_task);
-
        cancel_delayed_work_sync(&adapter->watchdog_task);
+
+       /*
+        * Since the watchdog task can reschedule other tasks, we should cancel
+        * it first, otherwise we can run into the situation when a work is
+        * still running after the adapter has been turned down.
+        */
+
        cancel_delayed_work_sync(&adapter->phy_info_task);
        cancel_delayed_work_sync(&adapter->fifo_stall_task);
+
+       /* Only kill reset task if adapter is not resetting */
+       if (!test_bit(__E1000_RESETTING, &adapter->flags))
+               cancel_work_sync(&adapter->reset_task);
 }
 
 void e1000_down(struct e1000_adapter *adapter)
@@ -544,21 +551,8 @@ void e1000_down(struct e1000_adapter *adapter)
        e1000_clean_all_rx_rings(adapter);
 }
 
-static void e1000_reinit_safe(struct e1000_adapter *adapter)
-{
-       while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-               msleep(1);
-       mutex_lock(&adapter->mutex);
-       e1000_down(adapter);
-       e1000_up(adapter);
-       mutex_unlock(&adapter->mutex);
-       clear_bit(__E1000_RESETTING, &adapter->flags);
-}
-
 void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
-       /* if rtnl_lock is not held the call path is bogus */
-       ASSERT_RTNL();
        WARN_ON(in_interrupt());
        while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
                msleep(1);
@@ -1316,7 +1310,6 @@ static int e1000_sw_init(struct e1000_adapter *adapter)
        e1000_irq_disable(adapter);
 
        spin_lock_init(&adapter->stats_lock);
-       mutex_init(&adapter->mutex);
 
        set_bit(__E1000_DOWN, &adapter->flags);
 
@@ -1440,6 +1433,10 @@ static int e1000_close(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
+       int count = E1000_CHECK_RESET_COUNT;
+
+       while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+               usleep_range(10000, 20000);
 
        WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
        e1000_down(adapter);
@@ -2325,11 +2322,8 @@ static void e1000_update_phy_info_task(struct work_struct *work)
        struct e1000_adapter *adapter = container_of(work,
                                                     struct e1000_adapter,
                                                     phy_info_task.work);
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-       mutex_lock(&adapter->mutex);
+
        e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
-       mutex_unlock(&adapter->mutex);
 }
 
 /**
@@ -2345,9 +2339,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
        struct net_device *netdev = adapter->netdev;
        u32 tctl;
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-       mutex_lock(&adapter->mutex);
        if (atomic_read(&adapter->tx_fifo_stall)) {
                if ((er32(TDT) == er32(TDH)) &&
                   (er32(TDFT) == er32(TDFH)) &&
@@ -2368,7 +2359,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
                        schedule_delayed_work(&adapter->fifo_stall_task, 1);
                }
        }
-       mutex_unlock(&adapter->mutex);
 }
 
 bool e1000_has_link(struct e1000_adapter *adapter)
@@ -2422,10 +2412,6 @@ static void e1000_watchdog(struct work_struct *work)
        struct e1000_tx_ring *txdr = adapter->tx_ring;
        u32 link, tctl;
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-
-       mutex_lock(&adapter->mutex);
        link = e1000_has_link(adapter);
        if ((netif_carrier_ok(netdev)) && link)
                goto link_up;
@@ -2516,7 +2502,7 @@ link_up:
                        adapter->tx_timeout_count++;
                        schedule_work(&adapter->reset_task);
                        /* exit immediately since reset is imminent */
-                       goto unlock;
+                       return;
                }
        }
 
@@ -2544,9 +2530,6 @@ link_up:
        /* Reschedule the task */
        if (!test_bit(__E1000_DOWN, &adapter->flags))
                schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
-
-unlock:
-       mutex_unlock(&adapter->mutex);
 }
 
 enum latency_range {
@@ -3495,10 +3478,8 @@ static void e1000_reset_task(struct work_struct *work)
        struct e1000_adapter *adapter =
                container_of(work, struct e1000_adapter, reset_task);
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
        e_err(drv, "Reset adapter\n");
-       e1000_reinit_safe(adapter);
+       e1000_reinit_locked(adapter);
 }
 
 /**
@@ -4963,6 +4944,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        netif_device_detach(netdev);
 
        if (netif_running(netdev)) {
+               int count = E1000_CHECK_RESET_COUNT;
+
+               while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+                       usleep_range(10000, 20000);
+
                WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
                e1000_down(adapter);
        }
index 895450e9bb3cfe81d22f19148b4a52d9fc14352a..ff2d806eaef71bc2a7a861a8971c228cd6856e2a 100644 (file)
@@ -718,8 +718,11 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
        e1000_release_phy_80003es2lan(hw);
 
        /* Disable IBIST slave mode (far-end loopback) */
-       e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
-                                       &kum_reg_data);
+       ret_val =
+           e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                           &kum_reg_data);
+       if (ret_val)
+               return ret_val;
        kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
        e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
                                         kum_reg_data);
index 8d3945ab7334840684db42ea6eefa9bafc52c061..6d14eea1791846c59077f98478ab95f480538624 100644 (file)
@@ -7015,13 +7015,11 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 };
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-#ifdef CONFIG_PM
 static const struct dev_pm_ops e1000_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
        SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume,
                           e1000_idle)
 };
-#endif
 
 /* PCI Device API Driver */
 static struct pci_driver e1000_driver = {
@@ -7029,11 +7027,9 @@ static struct pci_driver e1000_driver = {
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
        .remove   = e1000_remove,
-#ifdef CONFIG_PM
        .driver   = {
                .pm = &e1000_pm_ops,
        },
-#endif
        .shutdown = e1000_shutdown,
        .err_handler = &e1000_err_handler
 };
index da2be59505c06226b4cd79f9e8cc120945ca1d17..20e71f4ca4261f99694b04eccd3647906326239d 100644 (file)
@@ -1757,19 +1757,23 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                 * it across the board.
                 */
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
-               if (ret_val)
+               if (ret_val) {
                        /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               msleep(usec_interval / 1000);
+                       else
+                               udelay(usec_interval);
+               }
                ret_val = e1e_rphy(hw, MII_BMSR, &phy_status);
                if (ret_val)
                        break;
                if (phy_status & BMSR_LSTATUS)
                        break;
                if (usec_interval >= 1000)
-                       mdelay(usec_interval / 1000);
+                       msleep(usec_interval / 1000);
                else
                        udelay(usec_interval);
        }
index be15938ba2130372192276670e1621c3e470505c..12b0932204ba8ce425109714053d4bebbddc65b6 100644 (file)
@@ -354,6 +354,9 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
        struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
        int i;
 
+       if (!vsi->tx_rings)
+               return stats;
+
        rcu_read_lock();
        for (i = 0; i < vsi->num_queue_pairs; i++) {
                struct i40e_ring *tx_ring, *rx_ring;
index c4c4fe332c7ee06af09696cc8e5ba027d6d9ba15..ad2b74d95138c1542bb78a55b7d620e5695f2abb 100644 (file)
@@ -1728,7 +1728,10 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
-                       udelay(usec_interval);
+                       if (usec_interval >= 1000)
+                               mdelay(usec_interval/1000);
+                       else
+                               udelay(usec_interval);
                }
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
                if (ret_val)
index b0f3666b1d7f1c669181a9f62534aa8096baeccc..c3143da497c82be85c4f580776290872e647e317 100644 (file)
@@ -2062,14 +2062,15 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       wol->supported = WAKE_UCAST | WAKE_MCAST |
-                        WAKE_BCAST | WAKE_MAGIC |
-                        WAKE_PHY;
        wol->wolopts = 0;
 
        if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
                return;
 
+       wol->supported = WAKE_UCAST | WAKE_MCAST |
+                        WAKE_BCAST | WAKE_MAGIC |
+                        WAKE_PHY;
+
        /* apply any specific unsupported masks here */
        switch (adapter->hw.device_id) {
        default:
index 0c55079ebee37c03d0a5a9a5cbdc6681d78c19a9..5bcc870f8367f803c309f5c28115cded7284748c 100644 (file)
@@ -4251,8 +4251,8 @@ static void ixgbe_disable_fwd_ring(struct ixgbe_fwd_adapter *vadapter,
        rx_ring->l2_accel_priv = NULL;
 }
 
-int ixgbe_fwd_ring_down(struct net_device *vdev,
-                       struct ixgbe_fwd_adapter *accel)
+static int ixgbe_fwd_ring_down(struct net_device *vdev,
+                              struct ixgbe_fwd_adapter *accel)
 {
        struct ixgbe_adapter *adapter = accel->real_adapter;
        unsigned int rxbase = accel->rx_base_queue;
@@ -6827,12 +6827,20 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
        return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
 
-#ifdef IXGBE_FCOE
-static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb,
+                             void *accel_priv)
 {
+       struct ixgbe_fwd_adapter *fwd_adapter = accel_priv;
+#ifdef IXGBE_FCOE
        struct ixgbe_adapter *adapter;
        struct ixgbe_ring_feature *f;
        int txq;
+#endif
+
+       if (fwd_adapter)
+               return skb->queue_mapping + fwd_adapter->tx_base_queue;
+
+#ifdef IXGBE_FCOE
 
        /*
         * only execute the code below if protocol is FCoE
@@ -6858,9 +6866,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
                txq -= f->indices;
 
        return txq + f->offset;
+#else
+       return __netdev_pick_tx(dev, skb);
+#endif
 }
 
-#endif
 netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
                          struct ixgbe_adapter *adapter,
                          struct ixgbe_ring *tx_ring)
@@ -7629,27 +7639,11 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
        kfree(fwd_adapter);
 }
 
-static netdev_tx_t ixgbe_fwd_xmit(struct sk_buff *skb,
-                                 struct net_device *dev,
-                                 void *priv)
-{
-       struct ixgbe_fwd_adapter *fwd_adapter = priv;
-       unsigned int queue;
-       struct ixgbe_ring *tx_ring;
-
-       queue = skb->queue_mapping + fwd_adapter->tx_base_queue;
-       tx_ring = fwd_adapter->real_adapter->tx_ring[queue];
-
-       return __ixgbe_xmit_frame(skb, dev, tx_ring);
-}
-
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
        .ndo_start_xmit         = ixgbe_xmit_frame,
-#ifdef IXGBE_FCOE
        .ndo_select_queue       = ixgbe_select_queue,
-#endif
        .ndo_set_rx_mode        = ixgbe_set_rx_mode,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = ixgbe_set_mac,
@@ -7689,7 +7683,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
        .ndo_dfwd_add_station   = ixgbe_fwd_add,
        .ndo_dfwd_del_station   = ixgbe_fwd_del,
-       .ndo_dfwd_start_xmit    = ixgbe_fwd_xmit,
 };
 
 /**
@@ -7986,10 +7979,9 @@ skip_sriov:
                           NETIF_F_TSO |
                           NETIF_F_TSO6 |
                           NETIF_F_RXHASH |
-                          NETIF_F_RXCSUM |
-                          NETIF_F_HW_L2FW_DOFFLOAD;
+                          NETIF_F_RXCSUM;
 
-       netdev->hw_features = netdev->features;
+       netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
 
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82599EB:
index e4c676006be97db79d3208607f36bb503bdaecaa..39217e5ff7dcd74ddcfc49c7e33e43ec2633c515 100644 (file)
@@ -46,6 +46,7 @@ static bool ixgbe_get_i2c_data(u32 *i2cctl);
 static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
 static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
 static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
+static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 
 /**
  *  ixgbe_identify_phy_generic - Get physical layer module
@@ -1164,7 +1165,7 @@ err_read_i2c_eeprom:
  *
  * Searches for and identifies the QSFP module and assigns appropriate PHY type
  **/
-s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
+static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
 {
        struct ixgbe_adapter *adapter = hw->back;
        s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
index aae900a256da98601a501a121eed1f14347d3997..fffcbdd2bf0e49ab129abf04cd16a650a4d5cb91 100644 (file)
@@ -145,7 +145,6 @@ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
 s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
 s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
-s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                                         u16 *list_offset,
                                         u16 *data_offset);
index d6f0c0d8cf11ddb395617e2749bbf25329cae42c..72084f70adbba84c5b3e4df8f890155c2643a13b 100644 (file)
@@ -291,7 +291,9 @@ static int ixgbe_pci_sriov_disable(struct pci_dev *dev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
        int err;
+#ifdef CONFIG_PCI_IOV
        u32 current_flags = adapter->flags;
+#endif
 
        err = ixgbe_disable_sriov(adapter);
 
index 6a6c1f76d8e04406b1c6de12820a48a7d27337fd..ec94a20d709952d1f678f69ac7778205f75e8ffe 100644 (file)
@@ -619,7 +619,8 @@ ltq_etop_set_multicast_list(struct net_device *dev)
 }
 
 static u16
-ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     void *accel_priv)
 {
        /* we are currently only using the first queue */
        return 0;
index 7354960b583bc83b45a8aadd001c03c456912f81..c4eeb69a5beee6f4e4214746b9c958c614e64beb 100644 (file)
@@ -92,6 +92,12 @@ static int orion_mdio_wait_ready(struct mii_bus *bus)
                        if (time_is_before_jiffies(end))
                                ++timedout;
                } else {
+                       /* wait_event_timeout does not guarantee a delay of at
+                        * least one whole jiffie, so timeout must be no less
+                        * than two.
+                        */
+                       if (timeout < 2)
+                               timeout = 2;
                        wait_event_timeout(dev->smi_busy_wait,
                                           orion_mdio_smi_is_done(dev),
                                           timeout);
index b8e232b4ea2da88aca164039f81f1852ba9f779e..d5f0d72e5e331792bb8a0078078627df66a83fb5 100644 (file)
@@ -1378,7 +1378,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
 
                dev_kfree_skb_any(skb);
                dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
-                                rx_desc->data_size, DMA_FROM_DEVICE);
+                                MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
        }
 
        if (rx_done)
@@ -1424,7 +1424,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
                }
 
                dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
-                                rx_desc->data_size, DMA_FROM_DEVICE);
+                                MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
 
                rx_bytes = rx_desc->data_size -
                        (ETH_FCS_LEN + MVNETA_MH_SIZE);
index 40626690e8a8679d9812d4edee4ede897ec55a2a..c11d063473e5f9aaa162aacd32b4cac386d53464 100644 (file)
@@ -140,7 +140,6 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
-       struct mlx4_en_tx_ring *tx_ring;
        int i, carrier_ok;
 
        memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
@@ -150,16 +149,10 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
                carrier_ok = netif_carrier_ok(dev);
 
                netif_carrier_off(dev);
-retry_tx:
                /* Wait until all tx queues are empty.
                 * there should not be any additional incoming traffic
                 * since we turned the carrier off */
                msleep(200);
-               for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
-                       tx_ring = priv->tx_ring[i];
-                       if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
-                               goto retry_tx;
-               }
 
                if (priv->mdev->dev->caps.flags &
                                        MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
index f54ebd5a1702457524bf5fc6918fbdf191a5d73f..a7fcd593b2dbb397bdf3d2a810ff42f71d0806b6 100644 (file)
@@ -592,7 +592,8 @@ 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)
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        u16 rings_p_up = priv->num_tx_rings_p_up;
index 5789ea2c934d4aaa15218bdaea2d565f42a82b41..01fc6515384db04fe03d548db8c16f8952f211e4 100644 (file)
@@ -2635,6 +2635,8 @@ static int __init mlx4_init(void)
                return -ENOMEM;
 
        ret = pci_register_driver(&mlx4_driver);
+       if (ret < 0)
+               destroy_workqueue(mlx4_wq);
        return ret < 0 ? ret : 0;
 }
 
index f3758de59c05f5adeb195661814ff4041b405c4a..d5758adceaa2f264b74d83e99f8091b7e1ead948 100644 (file)
@@ -714,7 +714,8 @@ int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 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);
+u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
+                        void *accel_priv);
 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 346a4e025c34100315b1ca2785d631d3bc5d3408..04b3ec1352f1eb9f532f7a6ab770615441f023fd 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/bitrev.h>
 #include <linux/slab.h>
 
-#include <asm/bootinfo.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
index 2d045be4b5cf64a5921a6687b127609093df376e..1e8b9514718b8620859bc38025dbb878878dd0c0 100644 (file)
@@ -5150,8 +5150,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       int result;
-       memset(buffer, 0, nv_get_sset_count(dev, ETH_SS_TEST)*sizeof(u64));
+       int result, count;
+
+       count = nv_get_sset_count(dev, ETH_SS_TEST);
+       memset(buffer, 0, count * sizeof(u64));
 
        if (!nv_link_test(dev)) {
                test->flags |= ETH_TEST_FL_FAILED;
@@ -5195,7 +5197,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        return;
                }
 
-               if (!nv_loopback_test(dev)) {
+               if (count > NV_TEST_COUNT_BASE && !nv_loopback_test(dev)) {
                        test->flags |= ETH_TEST_FL_FAILED;
                        buffer[3] = 1;
                }
index 7692dfd4f262db9045f285aadc194c1713fb724a..cc68657f05368d5642b62091bc6dbec1bc00bd1c 100644 (file)
@@ -1604,13 +1604,13 @@ netxen_process_lro(struct netxen_adapter *adapter,
        u32 seq_number;
        u8 vhdr_len = 0;
 
-       if (unlikely(ring > adapter->max_rds_rings))
+       if (unlikely(ring >= adapter->max_rds_rings))
                return NULL;
 
        rds_ring = &recv_ctx->rds_rings[ring];
 
        index = netxen_get_lro_sts_refhandle(sts_data0);
-       if (unlikely(index > rds_ring->num_desc))
+       if (unlikely(index >= rds_ring->num_desc))
                return NULL;
 
        buffer = &rds_ring->rx_buf_arr[index];
index 631ea0ac1cd89c47bddb863c56f04c28469bd745..f2a7c7166e2408a747dd03ef0fc456ba6121486c 100644 (file)
@@ -487,6 +487,7 @@ struct qlcnic_hardware_context {
        struct qlcnic_mailbox *mailbox;
        u8 extend_lb_time;
        u8 phys_port_id[ETH_ALEN];
+       u8 lb_mode;
 };
 
 struct qlcnic_adapter_stats {
@@ -578,6 +579,8 @@ struct qlcnic_host_tx_ring {
        dma_addr_t phys_addr;
        dma_addr_t hw_cons_phys_addr;
        struct netdev_queue *txq;
+       /* Lock to protect Tx descriptors cleanup */
+       spinlock_t tx_clean_lock;
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -808,6 +811,7 @@ struct qlcnic_mac_list_s {
 
 #define QLCNIC_ILB_MODE                0x1
 #define QLCNIC_ELB_MODE                0x2
+#define QLCNIC_LB_MODE_MASK    0x3
 
 #define QLCNIC_LINKEVENT       0x1
 #define QLCNIC_LB_RESPONSE     0x2
@@ -1093,7 +1097,6 @@ struct qlcnic_adapter {
        struct qlcnic_filter_hash rx_fhash;
        struct list_head vf_mc_list;
 
-       spinlock_t tx_clean_lock;
        spinlock_t mac_learn_lock;
        /* spinlock for catching rcv filters for eswitch traffic */
        spinlock_t rx_mac_learn_lock;
@@ -1708,6 +1711,7 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
 void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
 void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);
+void qlcnic_update_stats(struct qlcnic_adapter *);
 
 /* Adapter hardware abstraction */
 struct qlcnic_hardware_ops {
index b1cb0ffb15c70d1970f3cbebab28ff7f8e8530ce..f776f99f79155ea42d3371b7e9aadcc901421898 100644 (file)
@@ -447,8 +447,9 @@ irqreturn_t qlcnic_83xx_intr(int irq, void *data)
 
        qlcnic_83xx_poll_process_aen(adapter);
 
-       if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
-               ahw->diag_cnt++;
+       if (ahw->diag_test) {
+               if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
+                       ahw->diag_cnt++;
                qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
                return IRQ_HANDLED;
        }
@@ -1345,11 +1346,6 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
        }
 
        if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               /* disable and free mailbox interrupt */
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       qlcnic_83xx_enable_mbx_poll(adapter);
-                       qlcnic_83xx_free_mbx_intr(adapter);
-               }
                adapter->ahw->loopback_state = 0;
                adapter->ahw->hw_ops->setup_link_event(adapter, 1);
        }
@@ -1363,33 +1359,20 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
-       int ring, err;
+       int ring;
 
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_83xx_disable_intr(adapter, sds_ring);
-                       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-                               qlcnic_83xx_enable_mbx_poll(adapter);
+                       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+                               qlcnic_83xx_disable_intr(adapter, sds_ring);
                }
        }
 
        qlcnic_fw_destroy_ctx(adapter);
        qlcnic_detach(adapter);
 
-       if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       err = qlcnic_83xx_setup_mbx_intr(adapter);
-                       qlcnic_83xx_disable_mbx_poll(adapter);
-                       if (err) {
-                               dev_err(&adapter->pdev->dev,
-                                       "%s: failed to setup mbx interrupt\n",
-                                       __func__);
-                               goto out;
-                       }
-               }
-       }
        adapter->ahw->diag_test = 0;
        adapter->drv_sds_rings = drv_sds_rings;
 
@@ -1399,9 +1382,6 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
        if (netif_running(netdev))
                __qlcnic_up(adapter, netdev);
 
-       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
-           !(adapter->flags & QLCNIC_MSIX_ENABLED))
-               qlcnic_83xx_disable_mbx_poll(adapter);
 out:
        netif_device_attach(netdev);
 }
@@ -1704,12 +1684,6 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
                }
        } while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
 
-       /* Make sure carrier is off and queue is stopped during loopback */
-       if (netif_running(netdev)) {
-               netif_carrier_off(netdev);
-               netif_tx_stop_all_queues(netdev);
-       }
-
        ret = qlcnic_do_lb_test(adapter, mode);
 
        qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2141,6 +2115,7 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
        ahw->link_autoneg = MSB(MSW(data[3]));
        ahw->module_type = MSB(LSW(data[3]));
        ahw->has_link_events = 1;
+       ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
        qlcnic_advert_link_change(adapter, link_status);
 }
 
@@ -3754,6 +3729,19 @@ static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
        return;
 }
 
+static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 offset;
+
+       offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
+       dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
+                readl(ahw->pci_base0 + offset),
+                QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
+                QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
+                QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
+}
+
 static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
 {
        struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
@@ -3798,6 +3786,8 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
                                __func__, cmd->cmd_op, cmd->type, ahw->pci_func,
                                ahw->op_mode);
                        clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+                       qlcnic_dump_mailbox_registers(adapter);
+                       qlcnic_83xx_get_mbx_data(adapter, cmd);
                        qlcnic_dump_mbx(adapter, cmd);
                        qlcnic_83xx_idc_request_reset(adapter,
                                                      QLCNIC_FORCE_FW_DUMP_KEY);
index 4cae6caa6bfa42476ff79b881784dd2f42a36db6..a6a33508e40137b124541f07e3433361b086afec 100644 (file)
@@ -662,4 +662,5 @@ pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
                                               pci_channel_state_t);
 pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
 void qlcnic_83xx_io_resume(struct pci_dev *);
+void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
 #endif
index 89208e5b25d6a1bc5c829a52ea2d79edcb5d110e..918e18ddf0381acd2f8a3097603ec6bd914fc5a8 100644 (file)
@@ -740,6 +740,7 @@ static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter)
        adapter->ahw->idc.err_code = -EIO;
        dev_err(&adapter->pdev->dev,
                "%s: Device in unknown state\n", __func__);
+       clear_bit(__QLCNIC_RESETTING, &adapter->state);
        return 0;
 }
 
@@ -818,7 +819,6 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_mailbox *mbx = ahw->mailbox;
        int ret = 0;
-       u32 owner;
        u32 val;
 
        /* Perform NIC configuration based ready state entry actions */
@@ -848,9 +848,9 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
                        set_bit(__QLCNIC_RESETTING, &adapter->state);
                        qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
                }  else {
-                       owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
-                       if (ahw->pci_func == owner)
-                               qlcnic_dump_fw(adapter);
+                       netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                                   __func__);
+                       qlcnic_83xx_idc_enter_failed_state(adapter, 1);
                }
                return -EIO;
        }
@@ -948,13 +948,26 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter)
        return 0;
 }
 
-static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
+static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
 {
-       dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 val, owner;
+
+       val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
+               if (ahw->pci_func == owner) {
+                       qlcnic_83xx_stop_hw(adapter);
+                       qlcnic_dump_fw(adapter);
+               }
+       }
+
+       netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
+                   __func__);
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       adapter->ahw->idc.err_code = -EIO;
+       ahw->idc.err_code = -EIO;
 
-       return 0;
+       return;
 }
 
 static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
@@ -1063,12 +1076,6 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work)
        adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
        qlcnic_83xx_periodic_tasks(adapter);
 
-       /* Do not reschedule if firmaware is in hanged state and auto
-        * recovery is disabled
-        */
-       if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
-               return;
-
        /* Re-schedule the function */
        if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
                qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
@@ -1219,10 +1226,10 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
        }
 
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
-       if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) ||
-           !qlcnic_auto_fw_reset) {
-               dev_err(&adapter->pdev->dev,
-                       "%s:failed, device in non reset mode\n", __func__);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 0);
                qlcnic_83xx_unlock_driver(adapter);
                return;
        }
@@ -1254,24 +1261,24 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
        if (size & 0xF)
                size = (size + 16) & ~0xF;
 
-       p_cache = kzalloc(size, GFP_KERNEL);
+       p_cache = vzalloc(size);
        if (p_cache == NULL)
                return -ENOMEM;
 
        ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
                                                size / sizeof(u32));
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
        /* 16 byte write to MS memory */
        ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache,
                                          size / 16);
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
-       kfree(p_cache);
+       vfree(p_cache);
 
        return ret;
 }
@@ -1939,7 +1946,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev,
        p_dev->ahw->reset.seq_index = index;
 }
 
-static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
+void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
 {
        p_dev->ahw->reset.seq_index = 0;
 
@@ -1994,6 +2001,14 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
        if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
                qlcnic_dump_fw(adapter);
+
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+               return err;
+       }
+
        qlcnic_83xx_init_hw(adapter);
 
        if (qlcnic_83xx_copy_bootloader(adapter))
@@ -2073,8 +2088,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
                ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
-               adapter->max_sds_rings = ahw->max_rx_ques;
-               adapter->max_tx_rings = ahw->max_tx_ques;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
+               adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
        } else {
                return -EIO;
        }
index b36c02fafcfd1ebe6f6ce8da49e73f73364f64b5..6b08194aa0d4900f8e29a4c5eca433f1d1709d9c 100644 (file)
@@ -167,27 +167,35 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 #define QLCNIC_TEST_LEN        ARRAY_SIZE(qlcnic_gstrings_test)
 
-static inline int qlcnic_82xx_statistics(void)
+static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_device_gstrings_stats) +
-              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
-static inline int qlcnic_83xx_statistics(void)
+static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
 {
-       return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
+       return ARRAY_SIZE(qlcnic_gstrings_stats) +
+              ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
               ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
-              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
+              ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
+              QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
 }
 
 static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
 {
-       if (qlcnic_82xx_check(adapter))
-               return qlcnic_82xx_statistics();
-       else if (qlcnic_83xx_check(adapter))
-               return qlcnic_83xx_statistics();
-       else
-               return -1;
+       int len = -1;
+
+       if (qlcnic_82xx_check(adapter)) {
+               len = qlcnic_82xx_statistics(adapter);
+               if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+                       len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
+       } else if (qlcnic_83xx_check(adapter)) {
+               len = qlcnic_83xx_statistics(adapter);
+       }
+
+       return len;
 }
 
 #define        QLCNIC_TX_INTR_NOT_CONFIGURED   0X78563412
@@ -667,30 +675,25 @@ qlcnic_set_ringparam(struct net_device *dev,
 static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
                                      u8 rx_ring, u8 tx_ring)
 {
+       if (rx_ring == 0 || tx_ring == 0)
+               return -EINVAL;
+
        if (rx_ring != 0) {
                if (rx_ring > adapter->max_sds_rings) {
-                       netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
+                       netdev_err(adapter->netdev,
+                                  "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
                                   rx_ring, adapter->max_sds_rings);
                        return -EINVAL;
                }
        }
 
         if (tx_ring != 0) {
-               if (qlcnic_82xx_check(adapter) &&
-                   (tx_ring > adapter->max_tx_rings)) {
+               if (tx_ring > adapter->max_tx_rings) {
                        netdev_err(adapter->netdev,
                                   "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
                                   tx_ring, adapter->max_tx_rings);
                        return -EINVAL;
                }
-
-               if (qlcnic_83xx_check(adapter) &&
-                   (tx_ring > QLCNIC_SINGLE_RING)) {
-                       netdev_err(adapter->netdev,
-                                  "Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
-                                  tx_ring, QLCNIC_SINGLE_RING);
-                        return -EINVAL;
-               }
        }
 
        return 0;
@@ -925,18 +928,13 @@ static int qlcnic_eeprom_test(struct net_device *dev)
 
 static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 {
-       int len;
 
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        switch (sset) {
        case ETH_SS_TEST:
                return QLCNIC_TEST_LEN;
        case ETH_SS_STATS:
-               len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN;
-               if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-                   qlcnic_83xx_check(adapter))
-                       return len;
-               return qlcnic_82xx_statistics();
+               return qlcnic_dev_statistics_len(adapter);
        default:
                return -EOPNOTSUPP;
        }
@@ -948,6 +946,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_cmd_args cmd;
        int ret, drv_sds_rings = adapter->drv_sds_rings;
+       int drv_tx_rings = adapter->drv_tx_rings;
 
        if (qlcnic_83xx_check(adapter))
                return qlcnic_83xx_interrupt_test(netdev);
@@ -980,6 +979,7 @@ free_diag_res:
 
 clear_diag_irq:
        adapter->drv_sds_rings = drv_sds_rings;
+       adapter->drv_tx_rings = drv_tx_rings;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
        return ret;
@@ -1270,7 +1270,7 @@ static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
        return data;
 }
 
-static void qlcnic_update_stats(struct qlcnic_adapter *adapter)
+void qlcnic_update_stats(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;
index e9c21e5d0ca95c7cc08df0c5f29cca2f7b473ba4..c4262c23ed7c77b009f6c5cebf233a54ebfd685b 100644 (file)
@@ -134,6 +134,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
        struct qlcnic_skb_frag *buffrag;
        int i, j;
 
+       spin_lock(&tx_ring->tx_clean_lock);
+
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -157,6 +159,8 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
                }
                cmd_buf++;
        }
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 }
 
 void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
index 0149c94953474e6ad0ffd56b93cc440c67e77687..ad1531ae3aa8f8e3cda7f56c36bb12ec46694464 100644 (file)
@@ -687,17 +687,15 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
        if (adapter->ahw->linkup && !linkup) {
                netdev_info(netdev, "NIC Link is down\n");
                adapter->ahw->linkup = 0;
-               if (netif_running(netdev)) {
-                       netif_carrier_off(netdev);
-                       netif_tx_stop_all_queues(netdev);
-               }
+               netif_carrier_off(netdev);
        } else if (!adapter->ahw->linkup && linkup) {
+               /* Do not advertise Link up if the port is in loopback mode */
+               if (qlcnic_83xx_check(adapter) && adapter->ahw->lb_mode)
+                       return;
+
                netdev_info(netdev, "NIC Link is up\n");
                adapter->ahw->linkup = 1;
-               if (netif_running(netdev)) {
-                       netif_carrier_on(netdev);
-                       netif_wake_queue(netdev);
-               }
+               netif_carrier_on(netdev);
        }
 }
 
@@ -784,7 +782,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
        struct net_device *netdev = adapter->netdev;
        struct qlcnic_skb_frag *frag;
 
-       if (!spin_trylock(&adapter->tx_clean_lock))
+       if (!spin_trylock(&tx_ring->tx_clean_lock))
                return 1;
 
        sw_consumer = tx_ring->sw_consumer;
@@ -813,8 +811,9 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
                        break;
        }
 
+       tx_ring->sw_consumer = sw_consumer;
+
        if (count && netif_running(netdev)) {
-               tx_ring->sw_consumer = sw_consumer;
                smp_mb();
                if (netif_tx_queue_stopped(tx_ring->txq) &&
                    netif_carrier_ok(netdev)) {
@@ -840,7 +839,8 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter,
         */
        hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
        done = (sw_consumer == hw_consumer);
-       spin_unlock(&adapter->tx_clean_lock);
+
+       spin_unlock(&tx_ring->tx_clean_lock);
 
        return done;
 }
index 05c1eef8df1325359ef1bf73df8344492a95876d..550791b8fbae98404f4be790520d0c4985871802 100644 (file)
@@ -1178,6 +1178,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        } else {
                adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
        }
 
@@ -1755,7 +1756,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (qlcnic_sriov_vf_check(adapter))
                qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
        smp_mb();
-       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
        adapter->ahw->linkup = 0;
        netif_tx_disable(netdev);
@@ -1776,7 +1776,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
        for (ring = 0; ring < adapter->drv_tx_rings; ring++)
                qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]);
-       spin_unlock(&adapter->tx_clean_lock);
 }
 
 /* Usage: During suspend and firmware recovery module */
@@ -1940,7 +1939,6 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
        qlcnic_detach(adapter);
 
        adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
-       adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
        adapter->ahw->diag_test = test;
        adapter->ahw->linkup = 0;
 
@@ -2172,6 +2170,7 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
                }
                memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
                tx_ring->cmd_buf_arr = cmd_buf_arr;
+               spin_lock_init(&tx_ring->tx_clean_lock);
        }
 
        if (qlcnic_83xx_check(adapter) ||
@@ -2299,7 +2298,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        rwlock_init(&adapter->ahw->crb_lock);
        mutex_init(&adapter->ahw->mem_lock);
 
-       spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
 
        qlcnic_register_dcb(adapter);
@@ -2782,6 +2780,9 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct net_device_stats *stats = &netdev->stats;
 
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               qlcnic_update_stats(adapter);
+
        stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
        stats->tx_packets = adapter->stats.xmitfinished;
        stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
index 686f460b15022b4b2b7759ad29493a64a1f84592..024f8161d2fe1cccd0e97cc2a1eccd67371b8ab4 100644 (file)
@@ -75,7 +75,6 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
        num_vfs = sriov->num_vfs;
        max = num_vfs + 1;
        info->bit_offsets = 0xffff;
-       info->max_tx_ques = res->num_tx_queues / max;
        info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
        num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC;
 
@@ -86,6 +85,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_mac_filters = temp;
                info->min_tx_bw = 0;
                info->max_tx_bw = MAX_BW;
+               info->max_tx_ques = res->num_tx_queues - sriov->num_vfs;
        } else {
                id = qlcnic_sriov_func_to_index(adapter, func);
                if (id < 0)
@@ -95,6 +95,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
                info->max_tx_bw = vp->max_tx_bw;
                info->max_rx_ucast_mac_filters = num_vf_macs;
                info->max_tx_mac_filters = num_vf_macs;
+               info->max_tx_ques = QLCNIC_SINGLE_RING;
        }
 
        info->max_rx_ip_addr = res->num_destip / max;
index 0c9c4e89559524d78aa789dfb65e5e32211b8bc1..03517478e589495dd763a13eaab31101a9ea0a08 100644 (file)
@@ -18,7 +18,7 @@
  */
 #define DRV_NAME       "qlge"
 #define DRV_STRING     "QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION    "1.00.00.33"
+#define DRV_VERSION    "1.00.00.34"
 
 #define WQ_ADDR_ALIGN  0x3     /* 4 byte alignment */
 
index 0780e039b2718d902805414daeb6844b7d2086e7..8dee1beb9854813c94c1de36264a241703f9d0be 100644 (file)
@@ -181,6 +181,7 @@ static const char ql_gstrings_test[][ETH_GSTRING_LEN] = {
 };
 #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN)
 #define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats)
+#define QLGE_RCV_MAC_ERR_STATS 7
 
 static int ql_update_ring_coalescing(struct ql_adapter *qdev)
 {
@@ -280,6 +281,9 @@ static void ql_update_stats(struct ql_adapter *qdev)
                iter++;
        }
 
+       /* Update receive mac error statistics */
+       iter += QLGE_RCV_MAC_ERR_STATS;
+
        /*
         * Get Per-priority TX pause frame counter statistics.
         */
index a245dc18d769241bcf23d607458e33538c7ee99c..f705aeeba767eec647670c8d9b1a0e210f9f5e40 100644 (file)
@@ -2376,14 +2376,6 @@ static netdev_features_t qlge_fix_features(struct net_device *ndev,
        netdev_features_t features)
 {
        int err;
-       /*
-        * Since there is no support for separate rx/tx vlan accel
-        * enable/disable make sure tx flag is always in same state as rx.
-        */
-       if (features & NETIF_F_HW_VLAN_CTAG_RX)
-               features |= NETIF_F_HW_VLAN_CTAG_TX;
-       else
-               features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
        /* Update the behavior of vlan accel in the adapter */
        err = qlge_update_hw_vlan_features(ndev, features);
@@ -4773,6 +4765,8 @@ static int qlge_probe(struct pci_dev *pdev,
                            NETIF_F_RXCSUM;
        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;
 
        if (test_bit(QL_DMA64, &qdev->flags))
                ndev->features |= NETIF_F_HIGHDMA;
index f2a2128165dd98b4c41598fb481c4e4f40417614..737c1a881f781917061d8b39ad43762f62ee7a6e 100644 (file)
@@ -678,9 +678,6 @@ static void cp_tx (struct cp_private *cp)
                                 le32_to_cpu(txd->opts1) & 0xffff,
                                 PCI_DMA_TODEVICE);
 
-               bytes_compl += skb->len;
-               pkts_compl++;
-
                if (status & LastFrag) {
                        if (status & (TxError | TxFIFOUnder)) {
                                netif_dbg(cp, tx_err, cp->dev,
@@ -702,6 +699,8 @@ static void cp_tx (struct cp_private *cp)
                                netif_dbg(cp, tx_done, cp->dev,
                                          "tx done, slot %d\n", tx_tail);
                        }
+                       bytes_compl += skb->len;
+                       pkts_compl++;
                        dev_kfree_skb_irq(skb);
                }
 
index 799387570766b6642ad4fdbc13f917acd358887a..c737f0ea5de751b7de9b1cb710fb101dc170ee41 100644 (file)
@@ -3465,6 +3465,11 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x14, 0x9065);
        rtl_writephy(tp, 0x14, 0x1065);
 
+       /* Check ALDPS bit, disable it if enabled */
+       rtl_writephy(tp, 0x1f, 0x0a43);
+       if (rtl_readphy(tp, 0x10) & 0x0004)
+               rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
+
        rtl_writephy(tp, 0x1f, 0x0000);
 }
 
index 2e27837ce6a289dc033c806e613f8dbca42496b9..fd844b53e38565cffa3e267fe0229f01f522a0d6 100644 (file)
@@ -585,7 +585,7 @@ static void efx_start_datapath(struct efx_nic *efx)
                           EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
                           efx->type->rx_buffer_padding);
        rx_buf_len = (sizeof(struct efx_rx_page_state) +
-                     NET_IP_ALIGN + efx->rx_dma_len);
+                     efx->rx_ip_align + efx->rx_dma_len);
        if (rx_buf_len <= PAGE_SIZE) {
                efx->rx_scatter = efx->type->always_rx_scatter;
                efx->rx_buffer_order = 0;
@@ -645,6 +645,8 @@ static void efx_start_datapath(struct efx_nic *efx)
                WARN_ON(channel->rx_pkt_n_frags);
        }
 
+       efx_ptp_start_datapath(efx);
+
        if (netif_device_present(efx->net_dev))
                netif_tx_wake_all_queues(efx->net_dev);
 }
@@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx_nic *efx)
        EFX_ASSERT_RESET_SERIALISED(efx);
        BUG_ON(efx->port_enabled);
 
+       efx_ptp_stop_datapath(efx);
+
        /* Stop RX refill */
        efx_for_each_channel(channel, efx) {
                efx_for_each_channel_rx_queue(rx_queue, channel)
@@ -2540,6 +2544,8 @@ static int efx_init_struct(struct efx_nic *efx,
 
        efx->net_dev = net_dev;
        efx->rx_prefix_size = efx->type->rx_prefix_size;
+       efx->rx_ip_align =
+               NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0;
        efx->rx_packet_hash_offset =
                efx->type->rx_hash_offset - efx->type->rx_prefix_size;
        spin_lock_init(&efx->stats_lock);
index 366c8e3e37844c8e2d8840a4662467067e937b3b..4b0bd8a1514dbb7035c7c0562cefc072901e585c 100644 (file)
@@ -50,6 +50,7 @@ struct efx_mcdi_async_param {
 static void efx_mcdi_timeout_async(unsigned long context);
 static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
                               bool *was_attached_out);
+static bool efx_mcdi_poll_once(struct efx_nic *efx);
 
 static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
 {
@@ -237,6 +238,21 @@ static void efx_mcdi_read_response_header(struct efx_nic *efx)
        }
 }
 
+static bool efx_mcdi_poll_once(struct efx_nic *efx)
+{
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+       rmb();
+       if (!efx->type->mcdi_poll_response(efx))
+               return false;
+
+       spin_lock_bh(&mcdi->iface_lock);
+       efx_mcdi_read_response_header(efx);
+       spin_unlock_bh(&mcdi->iface_lock);
+
+       return true;
+}
+
 static int efx_mcdi_poll(struct efx_nic *efx)
 {
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
@@ -272,18 +288,13 @@ static int efx_mcdi_poll(struct efx_nic *efx)
 
                time = jiffies;
 
-               rmb();
-               if (efx->type->mcdi_poll_response(efx))
+               if (efx_mcdi_poll_once(efx))
                        break;
 
                if (time_after(time, finish))
                        return -ETIMEDOUT;
        }
 
-       spin_lock_bh(&mcdi->iface_lock);
-       efx_mcdi_read_response_header(efx);
-       spin_unlock_bh(&mcdi->iface_lock);
-
        /* Return rc=0 like wait_event_timeout() */
        return 0;
 }
@@ -619,6 +630,16 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
                rc = efx_mcdi_await_completion(efx);
 
        if (rc != 0) {
+               netif_err(efx, hw, efx->net_dev,
+                         "MC command 0x%x inlen %d mode %d timed out\n",
+                         cmd, (int)inlen, mcdi->mode);
+
+               if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) {
+                       netif_err(efx, hw, efx->net_dev,
+                                 "MCDI request was completed without an event\n");
+                       rc = 0;
+               }
+
                /* Close the race with efx_mcdi_ev_cpl() executing just too late
                 * and completing a request we've just cancelled, by ensuring
                 * that the seqno check therein fails.
@@ -627,11 +648,9 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
                ++mcdi->seqno;
                ++mcdi->credits;
                spin_unlock_bh(&mcdi->iface_lock);
+       }
 
-               netif_err(efx, hw, efx->net_dev,
-                         "MC command 0x%x inlen %d mode %d timed out\n",
-                         cmd, (int)inlen, mcdi->mode);
-       } else {
+       if (rc == 0) {
                size_t hdr_len, data_len;
 
                /* At the very least we need a memory barrier here to ensure
index 656a3277c2b210e69ffd028d059ce10b809e8db8..15816cacb548161bd4a7299909bb83ccd9c222be 100644 (file)
@@ -75,6 +75,8 @@ struct efx_mcdi_mon {
        unsigned long last_update;
        struct device *device;
        struct efx_mcdi_mon_attribute *attrs;
+       struct attribute_group group;
+       const struct attribute_group *groups[2];
        unsigned int n_attrs;
 };
 
index 4cc5d95b2a5a5ea36869625843bf4daba064e84f..d72ad4fc36172241d5aeccbe883f4a82c8ee2daf 100644 (file)
@@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx)
        return rc;
 }
 
-static ssize_t efx_mcdi_mon_show_name(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "%s\n", KBUILD_MODNAME);
-}
-
 static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index,
                                  efx_dword_t *entry)
 {
-       struct efx_nic *efx = dev_get_drvdata(dev);
+       struct efx_nic *efx = dev_get_drvdata(dev->parent);
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        int rc;
 
@@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev,
                       efx_mcdi_sensor_type[mon_attr->type].label);
 }
 
-static int
+static void
 efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
                      ssize_t (*reader)(struct device *,
                                        struct device_attribute *, char *),
@@ -272,7 +265,6 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
 {
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
-       int rc;
 
        strlcpy(attr->name, name, sizeof(attr->name));
        attr->index = index;
@@ -286,10 +278,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
        attr->dev_attr.attr.name = attr->name;
        attr->dev_attr.attr.mode = S_IRUGO;
        attr->dev_attr.show = reader;
-       rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr);
-       if (rc == 0)
-               ++hwmon->n_attrs;
-       return rc;
+       hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr;
 }
 
 int efx_mcdi_mon_probe(struct efx_nic *efx)
@@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
        efx_mcdi_mon_update(efx);
 
        /* Allocate space for the maximum possible number of
-        * attributes for this set of sensors: name of the driver plus
+        * attributes for this set of sensors:
         * value, min, max, crit, alarm and label for each sensor.
         */
-       n_attrs = 1 + 6 * n_sensors;
+       n_attrs = 6 * n_sensors;
        hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
        if (!hwmon->attrs) {
                rc = -ENOMEM;
                goto fail;
        }
-
-       hwmon->device = hwmon_device_register(&efx->pci_dev->dev);
-       if (IS_ERR(hwmon->device)) {
-               rc = PTR_ERR(hwmon->device);
+       hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
+                                    GFP_KERNEL);
+       if (!hwmon->group.attrs) {
+               rc = -ENOMEM;
                goto fail;
        }
 
-       rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0);
-       if (rc)
-               goto fail;
-
        for (i = 0, j = -1, type = -1; ; i++) {
                enum efx_hwmon_type hwmon_type;
                const char *hwmon_prefix;
@@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                                page = type / 32;
                                j = -1;
                                if (page == n_pages)
-                                       return 0;
+                                       goto hwmon_register;
 
                                MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE,
                                               page);
@@ -453,28 +438,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                if (min1 != max1) {
                        snprintf(name, sizeof(name), "%s%u_input",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_value, i, type, 0);
-                       if (rc)
-                               goto fail;
 
                        if (hwmon_type != EFX_HWMON_POWER) {
                                snprintf(name, sizeof(name), "%s%u_min",
                                         hwmon_prefix, hwmon_index);
-                               rc = efx_mcdi_mon_add_attr(
+                               efx_mcdi_mon_add_attr(
                                        efx, name, efx_mcdi_mon_show_limit,
                                        i, type, min1);
-                               if (rc)
-                                       goto fail;
                        }
 
                        snprintf(name, sizeof(name), "%s%u_max",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_limit,
                                i, type, max1);
-                       if (rc)
-                               goto fail;
 
                        if (min2 != max2) {
                                /* Assume max2 is critical value.
@@ -482,32 +461,38 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                                 */
                                snprintf(name, sizeof(name), "%s%u_crit",
                                         hwmon_prefix, hwmon_index);
-                               rc = efx_mcdi_mon_add_attr(
+                               efx_mcdi_mon_add_attr(
                                        efx, name, efx_mcdi_mon_show_limit,
                                        i, type, max2);
-                               if (rc)
-                                       goto fail;
                        }
                }
 
                snprintf(name, sizeof(name), "%s%u_alarm",
                         hwmon_prefix, hwmon_index);
-               rc = efx_mcdi_mon_add_attr(
+               efx_mcdi_mon_add_attr(
                        efx, name, efx_mcdi_mon_show_alarm, i, type, 0);
-               if (rc)
-                       goto fail;
 
                if (type < ARRAY_SIZE(efx_mcdi_sensor_type) &&
                    efx_mcdi_sensor_type[type].label) {
                        snprintf(name, sizeof(name), "%s%u_label",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_label, i, type, 0);
-                       if (rc)
-                               goto fail;
                }
        }
 
+hwmon_register:
+       hwmon->groups[0] = &hwmon->group;
+       hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev,
+                                                         KBUILD_MODNAME, NULL,
+                                                         hwmon->groups);
+       if (IS_ERR(hwmon->device)) {
+               rc = PTR_ERR(hwmon->device);
+               goto fail;
+       }
+
+       return 0;
+
 fail:
        efx_mcdi_mon_remove(efx);
        return rc;
@@ -516,14 +501,11 @@ fail:
 void efx_mcdi_mon_remove(struct efx_nic *efx)
 {
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
-       unsigned int i;
 
-       for (i = 0; i < hwmon->n_attrs; i++)
-               device_remove_file(&efx->pci_dev->dev,
-                                  &hwmon->attrs[i].dev_attr);
-       kfree(hwmon->attrs);
        if (hwmon->device)
                hwmon_device_unregister(hwmon->device);
+       kfree(hwmon->attrs);
+       kfree(hwmon->group.attrs);
        efx_nic_free_buffer(efx, &hwmon->dma_buf);
 }
 
index b14a717ac3e8d95099b5d2648be590e138bc9e61..542a0d252ae0c25f6c60167c1ec9dba3943ba3d8 100644 (file)
@@ -683,6 +683,8 @@ struct vfdi_status;
  * @n_channels: Number of channels in use
  * @n_rx_channels: Number of channels used for RX (= number of RX queues)
  * @n_tx_channels: Number of channels used for TX
+ * @rx_ip_align: RX DMA address offset to have IP header aligned in
+ *     in accordance with NET_IP_ALIGN
  * @rx_dma_len: Current maximum RX DMA length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
  * @rx_buffer_truesize: Amortised allocation size of an RX buffer,
@@ -816,6 +818,7 @@ struct efx_nic {
        unsigned rss_spread;
        unsigned tx_channel_offset;
        unsigned n_tx_channels;
+       unsigned int rx_ip_align;
        unsigned int rx_dma_len;
        unsigned int rx_buffer_order;
        unsigned int rx_buffer_truesize;
index 11b6112d9249a734701eebe66414bd039702bcdd..91c63ec79c5fcb21d96545c0a6bad98e58cce5b9 100644 (file)
@@ -560,6 +560,8 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info);
 bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
+void efx_ptp_start_datapath(struct efx_nic *efx);
+void efx_ptp_stop_datapath(struct efx_nic *efx);
 
 extern const struct efx_nic_type falcon_a1_nic_type;
 extern const struct efx_nic_type falcon_b0_nic_type;
index 03acf57df04579bed5d0986f735f807491248cfb..3dd39dcfe36b92f3221119171b1e0c26729d85e8 100644 (file)
@@ -220,6 +220,7 @@ struct efx_ptp_timeset {
  * @evt_list: List of MC receive events awaiting packets
  * @evt_free_list: List of free events
  * @evt_lock: Lock for manipulating evt_list and evt_free_list
+ * @evt_overflow: Boolean indicating that event list has overflowed
  * @rx_evts: Instantiated events (on evt_list and evt_free_list)
  * @workwq: Work queue for processing pending PTP operations
  * @work: Work task
@@ -270,6 +271,7 @@ struct efx_ptp_data {
        struct list_head evt_list;
        struct list_head evt_free_list;
        spinlock_t evt_lock;
+       bool evt_overflow;
        struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS];
        struct workqueue_struct *workwq;
        struct work_struct work;
@@ -635,6 +637,11 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx)
                        }
                }
        }
+       /* If the event overflow flag is set and the event list is now empty
+        * clear the flag to re-enable the overflow warning message.
+        */
+       if (ptp->evt_overflow && list_empty(&ptp->evt_list))
+               ptp->evt_overflow = false;
        spin_unlock_bh(&ptp->evt_lock);
 }
 
@@ -676,6 +683,11 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx,
                        break;
                }
        }
+       /* If the event overflow flag is set and the event list is now empty
+        * clear the flag to re-enable the overflow warning message.
+        */
+       if (ptp->evt_overflow && list_empty(&ptp->evt_list))
+               ptp->evt_overflow = false;
        spin_unlock_bh(&ptp->evt_lock);
 
        return rc;
@@ -705,8 +717,9 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q)
                        __skb_queue_tail(q, skb);
                } else if (time_after(jiffies, match->expiry)) {
                        match->state = PTP_PACKET_STATE_TIMED_OUT;
-                       netif_warn(efx, rx_err, efx->net_dev,
-                                  "PTP packet - no timestamp seen\n");
+                       if (net_ratelimit())
+                               netif_warn(efx, rx_err, efx->net_dev,
+                                          "PTP packet - no timestamp seen\n");
                        __skb_queue_tail(q, skb);
                } else {
                        /* Replace unprocessed entry and stop */
@@ -788,9 +801,14 @@ fail:
 static int efx_ptp_stop(struct efx_nic *efx)
 {
        struct efx_ptp_data *ptp = efx->ptp_data;
-       int rc = efx_ptp_disable(efx);
        struct list_head *cursor;
        struct list_head *next;
+       int rc;
+
+       if (ptp == NULL)
+               return 0;
+
+       rc = efx_ptp_disable(efx);
 
        if (ptp->rxfilter_installed) {
                efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
@@ -809,11 +827,19 @@ static int efx_ptp_stop(struct efx_nic *efx)
        list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) {
                list_move(cursor, &efx->ptp_data->evt_free_list);
        }
+       ptp->evt_overflow = false;
        spin_unlock_bh(&efx->ptp_data->evt_lock);
 
        return rc;
 }
 
+static int efx_ptp_restart(struct efx_nic *efx)
+{
+       if (efx->ptp_data && efx->ptp_data->enabled)
+               return efx_ptp_start(efx);
+       return 0;
+}
+
 static void efx_ptp_pps_worker(struct work_struct *work)
 {
        struct efx_ptp_data *ptp =
@@ -901,6 +927,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel)
        spin_lock_init(&ptp->evt_lock);
        for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++)
                list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list);
+       ptp->evt_overflow = false;
 
        ptp->phc_clock_info.owner = THIS_MODULE;
        snprintf(ptp->phc_clock_info.name,
@@ -989,7 +1016,11 @@ bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
                skb->len >= PTP_MIN_LENGTH &&
                skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM &&
                likely(skb->protocol == htons(ETH_P_IP)) &&
+               skb_transport_header_was_set(skb) &&
+               skb_network_header_len(skb) >= sizeof(struct iphdr) &&
                ip_hdr(skb)->protocol == IPPROTO_UDP &&
+               skb_headlen(skb) >=
+               skb_transport_offset(skb) + sizeof(struct udphdr) &&
                udp_hdr(skb)->dest == htons(PTP_EVENT_PORT);
 }
 
@@ -1106,7 +1137,7 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
 {
        if ((enable_wanted != efx->ptp_data->enabled) ||
            (enable_wanted && (efx->ptp_data->mode != new_mode))) {
-               int rc;
+               int rc = 0;
 
                if (enable_wanted) {
                        /* Change of mode requires disable */
@@ -1123,7 +1154,8 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
                         * succeed.
                         */
                        efx->ptp_data->mode = new_mode;
-                       rc = efx_ptp_start(efx);
+                       if (netif_running(efx->net_dev))
+                               rc = efx_ptp_start(efx);
                        if (rc == 0) {
                                rc = efx_ptp_synchronize(efx,
                                                         PTP_SYNC_ATTEMPTS * 2);
@@ -1295,8 +1327,13 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp)
                list_add_tail(&evt->link, &ptp->evt_list);
 
                queue_work(ptp->workwq, &ptp->work);
-       } else {
-               netif_err(efx, rx_err, efx->net_dev, "No free PTP event");
+       } else if (!ptp->evt_overflow) {
+               /* Log a warning message and set the event overflow flag.
+                * The message won't be logged again until the event queue
+                * becomes empty.
+                */
+               netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n");
+               ptp->evt_overflow = true;
        }
        spin_unlock_bh(&ptp->evt_lock);
 }
@@ -1389,7 +1426,7 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
        if (rc != 0)
                return rc;
 
-       ptp_data->current_adjfreq = delta;
+       ptp_data->current_adjfreq = adjustment_ns;
        return 0;
 }
 
@@ -1404,7 +1441,7 @@ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
 
        MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST);
        MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
-       MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, 0);
+       MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq);
        MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec);
        MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec);
        return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
@@ -1491,3 +1528,14 @@ void efx_ptp_probe(struct efx_nic *efx)
                efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] =
                        &efx_ptp_channel_type;
 }
+
+void efx_ptp_start_datapath(struct efx_nic *efx)
+{
+       if (efx_ptp_restart(efx))
+               netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n");
+}
+
+void efx_ptp_stop_datapath(struct efx_nic *efx)
+{
+       efx_ptp_stop(efx);
+}
index 8f09e686fc2392a80f56610c78a61c6374b4a410..42488df1f4ec2af02feb9a46c408168b6a7dabec 100644 (file)
@@ -94,7 +94,7 @@ static inline void efx_sync_rx_buffer(struct efx_nic *efx,
 
 void efx_rx_config_page_split(struct efx_nic *efx)
 {
-       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + NET_IP_ALIGN,
+       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align,
                                      EFX_RX_BUF_ALIGNMENT);
        efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
                ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) /
@@ -189,9 +189,9 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue)
                do {
                        index = rx_queue->added_count & rx_queue->ptr_mask;
                        rx_buf = efx_rx_buffer(rx_queue, index);
-                       rx_buf->dma_addr = dma_addr + NET_IP_ALIGN;
+                       rx_buf->dma_addr = dma_addr + efx->rx_ip_align;
                        rx_buf->page = page;
-                       rx_buf->page_offset = page_offset + NET_IP_ALIGN;
+                       rx_buf->page_offset = page_offset + efx->rx_ip_align;
                        rx_buf->len = efx->rx_dma_len;
                        rx_buf->flags = 0;
                        ++rx_queue->added_count;
index 0c9b5d94154f8d215ddaf40d3fb252764983d73b..8bf29eb4a5a003eacabb6ea1f93590f566bb1ede 100644 (file)
@@ -82,6 +82,7 @@ static const char version[] =
 #include <linux/mii.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2184,6 +2185,15 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
        }
 }
 
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id smc91x_match[] = {
+       { .compatible = "smsc,lan91c94", },
+       { .compatible = "smsc,lan91c111", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, smc91x_match);
+#endif
+
 /*
  * smc_init(void)
  *   Input parameters:
@@ -2198,6 +2208,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
 static int smc_drv_probe(struct platform_device *pdev)
 {
        struct smc91x_platdata *pd = dev_get_platdata(&pdev->dev);
+       const struct of_device_id *match = NULL;
        struct smc_local *lp;
        struct net_device *ndev;
        struct resource *res, *ires;
@@ -2217,11 +2228,34 @@ static int smc_drv_probe(struct platform_device *pdev)
         */
 
        lp = netdev_priv(ndev);
+       lp->cfg.flags = 0;
 
        if (pd) {
                memcpy(&lp->cfg, pd, sizeof(lp->cfg));
                lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
-       } else {
+       }
+
+#if IS_BUILTIN(CONFIG_OF)
+       match = of_match_device(of_match_ptr(smc91x_match), &pdev->dev);
+       if (match) {
+               struct device_node *np = pdev->dev.of_node;
+               u32 val;
+
+               /* Combination of IO widths supported, default to 16-bit */
+               if (!of_property_read_u32(np, "reg-io-width", &val)) {
+                       if (val & 1)
+                               lp->cfg.flags |= SMC91X_USE_8BIT;
+                       if ((val == 0) || (val & 2))
+                               lp->cfg.flags |= SMC91X_USE_16BIT;
+                       if (val & 4)
+                               lp->cfg.flags |= SMC91X_USE_32BIT;
+               } else {
+                       lp->cfg.flags |= SMC91X_USE_16BIT;
+               }
+       }
+#endif
+
+       if (!pd && !match) {
                lp->cfg.flags |= (SMC_CAN_USE_8BIT)  ? SMC91X_USE_8BIT  : 0;
                lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
                lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
@@ -2370,15 +2404,6 @@ static int smc_drv_resume(struct device *dev)
        return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id smc91x_match[] = {
-       { .compatible = "smsc,lan91c94", },
-       { .compatible = "smsc,lan91c111", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, smc91x_match);
-#endif
-
 static struct dev_pm_ops smc_drv_pm_ops = {
        .suspend        = smc_drv_suspend,
        .resume         = smc_drv_resume,
index c9d4c872e81da1888cf8678ceb2fd7df5381ac03..749654b976bcf85fd07558f175274b9f01551705 100644 (file)
@@ -46,7 +46,8 @@
     defined(CONFIG_MACH_LITTLETON) ||\
     defined(CONFIG_MACH_ZYLONITE2) ||\
     defined(CONFIG_ARCH_VIPER) ||\
-    defined(CONFIG_MACH_STARGATE2)
+    defined(CONFIG_MACH_STARGATE2) ||\
+    defined(CONFIG_ARCH_VERSATILE)
 
 #include <asm/mach-types.h>
 
@@ -154,6 +155,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_outl(v, a, r)      writel(v, (a) + (r))
 #define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
 #define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+#define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
 #define SMC_IRQ_FLAGS          (-1)    /* from resource */
 
 /* We actually can't write halfwords properly if not word aligned */
@@ -206,23 +209,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
 
-#elif  defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT       1
-#define SMC_CAN_USE_16BIT      1
-#define SMC_CAN_USE_32BIT      1
-#define SMC_NOWAIT             1
-
-#define SMC_inb(a, r)          readb((a) + (r))
-#define SMC_inw(a, r)          readw((a) + (r))
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)      writew(v, (a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
-#define SMC_IRQ_FLAGS          (-1)    /* from resource */
-
 #elif defined(CONFIG_MN10300)
 
 /*
index 8a7a23a84ac5c3b6a7b7d4979e8c5866097895a5..797b56a0efc4a4e7ab1ff5c9af1f0e50f29e9d17 100644 (file)
@@ -622,17 +622,15 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
                return -EOPNOTSUPP;
 
-       if (netif_msg_hw(priv)) {
-               if (priv->dma_cap.time_stamp) {
-                       pr_debug("IEEE 1588-2002 Time Stamp supported\n");
-                       priv->adv_ts = 0;
-               }
-               if (priv->dma_cap.atime_stamp && priv->extend_desc) {
-                       pr_debug
-                           ("IEEE 1588-2008 Advanced Time Stamp supported\n");
-                       priv->adv_ts = 1;
-               }
-       }
+       priv->adv_ts = 0;
+       if (priv->dma_cap.atime_stamp && priv->extend_desc)
+               priv->adv_ts = 1;
+
+       if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
+               pr_debug("IEEE 1588-2002 Time Stamp supported\n");
+
+       if (netif_msg_hw(priv) && priv->adv_ts)
+               pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
 
        priv->hw->ptp = &stmmac_ptp;
        priv->hwts_tx_en = 0;
index b8b0eeed0f92bb68f34e1dac22e1f072faec77ce..7680581ebe12fe58a60de42b419467e3f2f065f7 100644 (file)
@@ -56,7 +56,7 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
 
        priv->hw->ptp->config_addend(priv->ioaddr, addend);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
@@ -91,7 +91,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
 
        priv->hw->ptp->adjust_systime(priv->ioaddr, sec, nsec, neg_adj);
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->ptp_lock, flags);
 
        return 0;
 }
index dd0dd6279b4eec8168c006457643568032ee358f..4f1d2549130e3396909f5287776663fa5bfb4e9e 100644 (file)
@@ -2019,7 +2019,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO
                    | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
                    NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM
-                   /*| NETIF_F_FRAGLIST */
                    ;
                ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
                        NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX;
index 7536a4c01293a9b3e97bf1171941b6724213ad6c..5330fd298705e06181b7d1a2a1557e0cea27e85c 100644 (file)
@@ -740,6 +740,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
                /* set speed_in input in case RMII mode is used in 100Mbps */
                if (phy->speed == 100)
                        mac_control |= BIT(15);
+               else if (phy->speed == 10)
+                       mac_control |= BIT(18); /* In Band mode */
 
                *link = true;
        } else {
@@ -1151,6 +1153,12 @@ static int cpsw_ndo_open(struct net_device *ndev)
                 * receive descs
                 */
                cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
+
+               if (cpts_register(&priv->pdev->dev, priv->cpts,
+                                 priv->data.cpts_clock_mult,
+                                 priv->data.cpts_clock_shift))
+                       dev_err(priv->dev, "error registering cpts device\n");
+
        }
 
        /* Enable Interrupt pacing if configured */
@@ -1197,6 +1205,7 @@ static int cpsw_ndo_stop(struct net_device *ndev)
        netif_carrier_off(priv->ndev);
 
        if (cpsw_common_res_usage_state(priv) <= 1) {
+               cpts_unregister(priv->cpts);
                cpsw_intr_disable(priv);
                cpdma_ctlr_int_ctrl(priv->dma, false);
                cpdma_ctlr_stop(priv->dma);
@@ -1816,6 +1825,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                }
 
                i++;
+               if (i == data->slaves)
+                       break;
        }
 
        return 0;
@@ -1983,9 +1994,15 @@ static int cpsw_probe(struct platform_device *pdev)
                goto clean_runtime_disable_ret;
        }
        priv->regs = ss_regs;
-       priv->version = __raw_readl(&priv->regs->id_ver);
        priv->host_port = HOST_PORT_NUM;
 
+       /* Need to enable clocks with runtime PM api to access module
+        * registers
+        */
+       pm_runtime_get_sync(&pdev->dev);
+       priv->version = readl(&priv->regs->id_ver);
+       pm_runtime_put_sync(&pdev->dev);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        priv->wr_regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->wr_regs)) {
@@ -2091,7 +2108,7 @@ static int cpsw_probe(struct platform_device *pdev)
        while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
                for (i = res->start; i <= res->end; i++) {
                        if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
-                                            dev_name(priv->dev), priv)) {
+                                            dev_name(&pdev->dev), priv)) {
                                dev_err(priv->dev, "error attaching irq\n");
                                goto clean_ale_ret;
                        }
@@ -2155,8 +2172,6 @@ static int cpsw_remove(struct platform_device *pdev)
                unregister_netdev(cpsw_get_slave_ndev(priv, 1));
        unregister_netdev(ndev);
 
-       cpts_unregister(priv->cpts);
-
        cpsw_ale_destroy(priv->ale);
        cpdma_chan_destroy(priv->txch);
        cpdma_chan_destroy(priv->rxch);
index 41ba974bf37cb9175c74ab40bba1817e890749e7..cd9b164a0434acb3a51066b5d0e17262a4bdc0dd 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/davinci_emac.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_net.h>
 
@@ -1752,10 +1753,14 @@ static const struct net_device_ops emac_netdev_ops = {
 #endif
 };
 
+static const struct of_device_id davinci_emac_of_match[];
+
 static struct emac_platform_data *
 davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
 {
        struct device_node *np;
+       const struct of_device_id *match;
+       const struct emac_platform_data *auxdata;
        struct emac_platform_data *pdata = NULL;
        const u8 *mac_addr;
 
@@ -1793,7 +1798,20 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
 
        priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
        if (!priv->phy_node)
-               pdata->phy_id = "";
+               pdata->phy_id = NULL;
+
+       auxdata = pdev->dev.platform_data;
+       if (auxdata) {
+               pdata->interrupt_enable = auxdata->interrupt_enable;
+               pdata->interrupt_disable = auxdata->interrupt_disable;
+       }
+
+       match = of_match_device(davinci_emac_of_match, &pdev->dev);
+       if (match && match->data) {
+               auxdata = match->data;
+               pdata->version = auxdata->version;
+               pdata->hw_ram_addr = auxdata->hw_ram_addr;
+       }
 
        pdev->dev.platform_data = pdata;
 
@@ -2020,8 +2038,14 @@ static const struct dev_pm_ops davinci_emac_pm_ops = {
 };
 
 #if IS_ENABLED(CONFIG_OF)
+static const struct emac_platform_data am3517_emac_data = {
+       .version                = EMAC_VERSION_2,
+       .hw_ram_addr            = 0x01e20000,
+};
+
 static const struct of_device_id davinci_emac_of_match[] = {
        {.compatible = "ti,davinci-dm6467-emac", },
+       {.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
        {},
 };
 MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
index 628b736e5ae776fcf00333bed8c355e4b518314e..0e9fb3301b1136e333cdd3d9bc62bcacc89dd4bb 100644 (file)
@@ -2080,7 +2080,8 @@ 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)
+static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb,
+                                void *accel_priv)
 {
        return smp_processor_id();
 }
index cce6c4bc556a97e03fbe5f1648396aed6bf7070a..ef312bc6b8658deabae28d179c39237564b8ede4 100644 (file)
@@ -1618,6 +1618,7 @@ static void rhine_reset_task(struct work_struct *work)
                goto out_unlock;
 
        napi_disable(&rp->napi);
+       netif_tx_disable(dev);
        spin_lock_bh(&rp->lock);
 
        /* clear all descriptors */
index d022bf936572ea857cbcb9f0fded1899077d5a95..ad61d26a44f31d26fc3b6d96f8430a5264e28e6f 100644 (file)
@@ -2172,16 +2172,13 @@ static int velocity_poll(struct napi_struct *napi, int budget)
        unsigned int rx_done;
        unsigned long flags;
 
-       spin_lock_irqsave(&vptr->lock, flags);
        /*
         * Do rx and tx twice for performance (taken from the VIA
         * out-of-tree driver).
         */
-       rx_done = velocity_rx_srv(vptr, budget / 2);
-       velocity_tx_srv(vptr);
-       rx_done += velocity_rx_srv(vptr, budget - rx_done);
+       rx_done = velocity_rx_srv(vptr, budget);
+       spin_lock_irqsave(&vptr->lock, flags);
        velocity_tx_srv(vptr);
-
        /* If budget not fully consumed, exit the polling mode */
        if (rx_done < budget) {
                napi_complete(napi);
@@ -2342,6 +2339,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
                if (ret < 0)
                        goto out_free_tmp_vptr_1;
 
+               napi_disable(&vptr->napi);
+
                spin_lock_irqsave(&vptr->lock, flags);
 
                netif_stop_queue(dev);
@@ -2362,6 +2361,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
 
                velocity_give_many_rx_descs(vptr);
 
+               napi_enable(&vptr->napi);
+
                mac_enable_int(vptr->mac_regs);
                netif_start_queue(dev);
 
index 1f23641263232fce0255d237976cbf5470e22a6c..2166e879a0961544af056802b1dbcff5a011d2aa 100644 (file)
@@ -1017,7 +1017,7 @@ static int temac_of_probe(struct platform_device *op)
        platform_set_drvdata(op, ndev);
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-       ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+       ndev->features = NETIF_F_SG;
        ndev->netdev_ops = &temac_netdev_ops;
        ndev->ethtool_ops = &temac_ethtool_ops;
 #if 0
index b2ff038d6d200abc5dbcd9315806e6791cec3335..f9293da19e260caa8e06829242150ccc72c0ded0 100644 (file)
@@ -1486,7 +1486,7 @@ static int axienet_of_probe(struct platform_device *op)
 
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-       ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+       ndev->features = NETIF_F_SG;
        ndev->netdev_ops = &axienet_netdev_ops;
        ndev->ethtool_ops = &axienet_ethtool_ops;
 
index 74234a51c851186c0c9bcfbc140b261724144e20..fefb8cd5eb65e1cb462f2a277c0bda422a89cd60 100644 (file)
@@ -163,26 +163,9 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
        __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
                     drvdata->base_addr + XEL_TSR_OFFSET);
 
-       /* Enable the Tx interrupts for the second Buffer if
-        * configured in HW */
-       if (drvdata->tx_ping_pong != 0) {
-               reg_data = __raw_readl(drvdata->base_addr +
-                                  XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
-               __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
-       }
-
        /* Enable the Rx interrupts for the first buffer */
        __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
 
-       /* Enable the Rx interrupts for the second Buffer if
-        * configured in HW */
-       if (drvdata->rx_ping_pong != 0) {
-               __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr +
-                            XEL_BUFFER_OFFSET + XEL_RSR_OFFSET);
-       }
-
        /* Enable the Global Interrupt Enable */
        __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 }
@@ -206,31 +189,10 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
        __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
                     drvdata->base_addr + XEL_TSR_OFFSET);
 
-       /* Disable the Tx interrupts for the second Buffer
-        * if configured in HW */
-       if (drvdata->tx_ping_pong != 0) {
-               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_TSR_OFFSET);
-               __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
-       }
-
        /* Disable the Rx interrupts for the first buffer */
        reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
        __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
                     drvdata->base_addr + XEL_RSR_OFFSET);
-
-       /* Disable the Rx interrupts for the second buffer
-        * if configured in HW */
-       if (drvdata->rx_ping_pong != 0) {
-
-               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_RSR_OFFSET);
-               __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_RSR_OFFSET);
-       }
 }
 
 /**
@@ -258,6 +220,13 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
                *to_u16_ptr++ = *from_u16_ptr++;
                *to_u16_ptr++ = *from_u16_ptr++;
 
+               /* This barrier resolves occasional issues seen around
+                * cases where the data is not properly flushed out
+                * from the processor store buffers to the destination
+                * memory locations.
+                */
+               wmb();
+
                /* Output a word */
                *to_u32_ptr++ = align_buffer;
        }
@@ -273,6 +242,12 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
                for (; length > 0; length--)
                        *to_u8_ptr++ = *from_u8_ptr++;
 
+               /* This barrier resolves occasional issues seen around
+                * cases where the data is not properly flushed out
+                * from the processor store buffers to the destination
+                * memory locations.
+                */
+               wmb();
                *to_u32_ptr = align_buffer;
        }
 }
index 3169252613faae400904201fa5ad9f1a7decf1cf..5d78c1d08abd60fcc6bcee5dea5ab178a2a166da 100644 (file)
@@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HDLCDRVCTL_CALIBRATE:
                if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
+               if (bi.data.calibrate > INT_MAX / s->par.bitrate)
+                       return -EINVAL;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
                return 0;
 
index 1971411574db1c7ae2dd6549490ab6975e816cd1..61dd2447e1bb4eedb5d8e6b72abcf21e9f273afb 100644 (file)
@@ -1057,6 +1057,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
 
        case SIOCYAMGCFG:
+               memset(&yi, 0, sizeof(yi));
                yi.cfg.mask = 0xffffffff;
                yi.cfg.iobase = yp->iobase;
                yi.cfg.irq = yp->irq;
index 524f713f60170b2d5632bbac6958ae0529a80b1c..71baeb3ed905cfa9ed930ab9f7ac63c3edd206b7 100644 (file)
@@ -261,9 +261,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        struct sk_buff *skb;
 
        net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
-       if (!net) {
-               netdev_err(net, "got receive callback but net device"
-                       " not initialized yet\n");
+       if (!net || net->reg_state != NETREG_REGISTERED) {
                packet->status = NVSP_STAT_FAIL;
                return 0;
        }
@@ -327,7 +325,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
                return -EINVAL;
 
        nvdev->start_remove = true;
-       cancel_delayed_work_sync(&ndevctx->dwork);
        cancel_work_sync(&ndevctx->work);
        netif_tx_disable(ndev);
        rndis_filter_device_remove(hdev);
@@ -436,19 +433,11 @@ static int netvsc_probe(struct hv_device *dev,
        SET_ETHTOOL_OPS(net, &ethtool_ops);
        SET_NETDEV_DEV(net, &dev->device);
 
-       ret = register_netdev(net);
-       if (ret != 0) {
-               pr_err("Unable to register netdev.\n");
-               free_netdev(net);
-               goto out;
-       }
-
        /* Notify the netvsc driver of the new device */
        device_info.ring_size = ring_size;
        ret = rndis_filter_device_add(dev, &device_info);
        if (ret != 0) {
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
-               unregister_netdev(net);
                free_netdev(net);
                hv_set_drvdata(dev, NULL);
                return ret;
@@ -457,7 +446,13 @@ static int netvsc_probe(struct hv_device *dev,
 
        netif_carrier_on(net);
 
-out:
+       ret = register_netdev(net);
+       if (ret != 0) {
+               pr_err("Unable to register netdev.\n");
+               rndis_filter_device_remove(dev);
+               free_netdev(net);
+       }
+
        return ret;
 }
 
index acf93798dc675929394e82ffed96cd1616c3a31d..bc8faaec33f5afb0bbf7efdd88cd082122c3cc7f 100644 (file)
@@ -299,7 +299,7 @@ netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
 
        if (vlan->fwd_priv) {
                skb->dev = vlan->lowerdev;
-               ret = dev_hard_start_xmit(skb, skb->dev, NULL, vlan->fwd_priv);
+               ret = dev_queue_xmit_accel(skb, vlan->fwd_priv);
        } else {
                ret = macvlan_queue_xmit(skb, dev);
        }
@@ -338,6 +338,8 @@ static const struct header_ops macvlan_hard_header_ops = {
        .cache_update   = eth_header_cache_update,
 };
 
+static struct rtnl_link_ops macvlan_link_ops;
+
 static int macvlan_open(struct net_device *dev)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
@@ -353,7 +355,8 @@ static int macvlan_open(struct net_device *dev)
                goto hash_add;
        }
 
-       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD) {
+       if (lowerdev->features & NETIF_F_HW_L2FW_DOFFLOAD &&
+           dev->rtnl_link_ops == &macvlan_link_ops) {
                vlan->fwd_priv =
                      lowerdev->netdev_ops->ndo_dfwd_add_station(lowerdev, dev);
 
@@ -362,10 +365,8 @@ static int macvlan_open(struct net_device *dev)
                 */
                if (IS_ERR_OR_NULL(vlan->fwd_priv)) {
                        vlan->fwd_priv = NULL;
-               } else {
-                       dev->features &= ~NETIF_F_LLTX;
+               } else
                        return 0;
-               }
        }
 
        err = -EBUSY;
@@ -690,8 +691,18 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
                                              netdev_features_t features)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
+       netdev_features_t mask;
+
+       features |= NETIF_F_ALL_FOR_ALL;
+       features &= (vlan->set_features | ~MACVLAN_FEATURES);
+       mask = features;
+
+       features = netdev_increment_features(vlan->lowerdev->features,
+                                            features,
+                                            mask);
+       features |= NETIF_F_LLTX;
 
-       return features & (vlan->set_features | ~MACVLAN_FEATURES);
+       return features;
 }
 
 static const struct ethtool_ops macvlan_ethtool_ops = {
@@ -1019,9 +1030,8 @@ static int macvlan_device_event(struct notifier_block *unused,
                break;
        case NETDEV_FEAT_CHANGE:
                list_for_each_entry(vlan, &port->vlans, list) {
-                       vlan->dev->features = dev->features & MACVLAN_FEATURES;
                        vlan->dev->gso_max_size = dev->gso_max_size;
-                       netdev_features_change(vlan->dev);
+                       netdev_update_features(vlan->dev);
                }
                break;
        case NETDEV_UNREGISTER:
index dc76670c2f2a16c244d0ec58a779a8742d0e6c3e..2a89da0803177355ebae2f31ce92ceb2fae00599 100644 (file)
@@ -744,7 +744,7 @@ err:
        rcu_read_lock();
        vlan = rcu_dereference(q->vlan);
        if (vlan)
-               vlan->dev->stats.tx_dropped++;
+               this_cpu_inc(vlan->pcpu_stats->tx_dropped);
        rcu_read_unlock();
 
        return err;
@@ -767,11 +767,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                                const struct sk_buff *skb,
                                const struct iovec *iv, int len)
 {
-       struct macvlan_dev *vlan;
        int ret;
        int vnet_hdr_len = 0;
        int vlan_offset = 0;
-       int copied;
+       int copied, total;
 
        if (q->flags & IFF_VNET_HDR) {
                struct virtio_net_hdr vnet_hdr;
@@ -786,7 +785,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
                        return -EFAULT;
        }
-       copied = vnet_hdr_len;
+       total = copied = vnet_hdr_len;
+       total += skb->len;
 
        if (!vlan_tx_tag_present(skb))
                len = min_t(int, skb->len, len);
@@ -801,6 +801,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
                ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
@@ -818,19 +819,9 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
        }
 
        ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
-       copied += len;
 
 done:
-       rcu_read_lock();
-       vlan = rcu_dereference(q->vlan);
-       if (vlan) {
-               preempt_disable();
-               macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0);
-               preempt_enable();
-       }
-       rcu_read_unlock();
-
-       return ret ? ret : copied;
+       return ret ? ret : total;
 }
 
 static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
@@ -885,7 +876,9 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
        }
 
        ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK);
-       ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */
+       ret = min_t(ssize_t, ret, len);
+       if (ret > 0)
+               iocb->ki_pos = ret;
 out:
        return ret;
 }
index 3ae28f420868fc35af3b3ed4e652f96e43a8f35b..26fa05a472b467679071ee6d76642e87f8bc10cf 100644 (file)
@@ -335,6 +335,21 @@ static struct phy_driver ksphy_driver[] = {
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_KSZ8041RNLI,
+       .phy_id_mask    = 0x00fffff0,
+       .name           = "Micrel KSZ8041RNLI",
+       .features       = PHY_BASIC_FEATURES |
+                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = kszphy_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = kszphy_ack_interrupt,
+       .config_intr    = kszphy_config_intr,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
+       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_KSZ8051,
        .phy_id_mask    = 0x00fffff0,
index 36c6994436b7ce7edb9ff9a0d9725c1aa09a4407..98434b84f0415ef2bfd635ba9dc4bc2f7a9ea762 100644 (file)
@@ -565,10 +565,8 @@ int phy_start_interrupts(struct phy_device *phydev)
        int err = 0;
 
        atomic_set(&phydev->irq_disable, 0);
-       if (request_irq(phydev->irq, phy_interrupt,
-                               IRQF_SHARED,
-                               "phy_interrupt",
-                               phydev) < 0) {
+       if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt",
+                       phydev) < 0) {
                pr_warn("%s: Can't get IRQ %d (PHY)\n",
                        phydev->bus->name, phydev->irq);
                phydev->irq = PHY_POLL;
index 508e4359338bc385dc2a0901e24a6351f735f780..14372c65a7e8209b5f97da6416ef80d1f41a522c 100644 (file)
@@ -64,6 +64,7 @@
 
 #define PHY_ID_VSC8234                 0x000fc620
 #define PHY_ID_VSC8244                 0x000fc6c0
+#define PHY_ID_VSC8514                 0x00070670
 #define PHY_ID_VSC8574                 0x000704a0
 #define PHY_ID_VSC8662                 0x00070660
 #define PHY_ID_VSC8221                 0x000fc550
@@ -131,6 +132,7 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
                err = phy_write(phydev, MII_VSC8244_IMASK,
                        (phydev->drv->phy_id == PHY_ID_VSC8234 ||
                         phydev->drv->phy_id == PHY_ID_VSC8244 ||
+                        phydev->drv->phy_id == PHY_ID_VSC8514 ||
                         phydev->drv->phy_id == PHY_ID_VSC8574) ?
                                MII_VSC8244_IMASK_MASK :
                                MII_VSC8221_IMASK_MASK);
@@ -245,6 +247,18 @@ static struct phy_driver vsc82xx_driver[] = {
        .ack_interrupt  = &vsc824x_ack_interrupt,
        .config_intr    = &vsc82xx_config_intr,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_VSC8514,
+       .name           = "Vitesse VSC8514",
+       .phy_id_mask    = 0x000ffff0,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &vsc824x_config_init,
+       .config_aneg    = &vsc82x4_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc824x_ack_interrupt,
+       .config_intr    = &vsc82xx_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_VSC8574,
        .name           = "Vitesse VSC8574",
@@ -315,6 +329,7 @@ module_exit(vsc82xx_exit);
 static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
        { PHY_ID_VSC8234, 0x000ffff0 },
        { PHY_ID_VSC8244, 0x000fffc0 },
+       { PHY_ID_VSC8514, 0x000ffff0 },
        { PHY_ID_VSC8574, 0x000ffff0 },
        { PHY_ID_VSC8662, 0x000ffff0 },
        { PHY_ID_VSC8221, 0x000ffff0 },
index 34b0de09d88190a04e30d867e31ad001f35f0e34..b75ae5bde6734c1c70b196c00a841d84f0f984dd 100644 (file)
@@ -1366,6 +1366,8 @@ static int team_user_linkup_option_get(struct team *team,
        return 0;
 }
 
+static void __team_carrier_check(struct team *team);
+
 static int team_user_linkup_option_set(struct team *team,
                                       struct team_gsetter_ctx *ctx)
 {
@@ -1373,6 +1375,7 @@ static int team_user_linkup_option_set(struct team *team,
 
        port->user.linkup = ctx->data.bool_val;
        team_refresh_port_linkup(port);
+       __team_carrier_check(port->team);
        return 0;
 }
 
@@ -1392,6 +1395,7 @@ static int team_user_linkup_en_option_set(struct team *team,
 
        port->user.linkup_enabled = ctx->data.bool_val;
        team_refresh_port_linkup(port);
+       __team_carrier_check(port->team);
        return 0;
 }
 
@@ -1643,7 +1647,8 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
+                            void *accel_priv)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
index 782e38bfc1eeea38215492aee5aaa587cc534525..ecec8029c5e84c557374817429c29a505f699c0d 100644 (file)
@@ -348,7 +348,8 @@ unlock:
  * different rxq no. here. If we could not get rxhash, then we would
  * hope the rxq no. may help here.
  */
-static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct tun_struct *tun = netdev_priv(dev);
        struct tun_flow_entry *e;
@@ -1184,7 +1185,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 {
        struct tun_pi pi = { 0, skb->protocol };
        ssize_t total = 0;
-       int vlan_offset = 0;
+       int vlan_offset = 0, copied;
 
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) < 0)
@@ -1248,6 +1249,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                total += tun->vnet_hdr_sz;
        }
 
+       copied = total;
+       total += skb->len;
        if (!vlan_tx_tag_present(skb)) {
                len = min_t(int, skb->len, len);
        } else {
@@ -1262,24 +1265,24 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
-               ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
+               ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
 
                copy = min_t(int, sizeof(veth), len);
-               ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
+               ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
        }
 
-       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
-       total += len;
+       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
 
 done:
        tun->dev->stats.tx_packets++;
@@ -1356,6 +1359,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
        ret = tun_do_read(tun, tfile, iocb, iv, len,
                          file->f_flags & O_NONBLOCK);
        ret = min_t(ssize_t, ret, len);
+       if (ret > 0)
+               iocb->ki_pos = ret;
 out:
        tun_put(tun);
        return ret;
index 85e4a01670f06e207609299ecacd035df3e098f3..47b0f732b0b10d21a07d4567e778efcbe4a7fddb 100644 (file)
@@ -276,12 +276,12 @@ config USB_NET_CDC_MBIM
          module will be called cdc_mbim.
 
 config USB_NET_DM9601
-       tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
+       tristate "Davicom DM96xx based USB 10/100 ethernet devices"
        depends on USB_USBNET
        select CRC32
        help
-         This option adds support for Davicom DM9601 based USB 1.1
-         10/100 Ethernet adapters.
+         This option adds support for Davicom DM9601/DM9620/DM9621A
+         based USB 10/100 Ethernet adapters.
 
 config USB_NET_SR9700
        tristate "CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices"
index c6867f926cffc18a981c7682e5493ae36924d988..e80219877730973a74e04791a42eae6a3eee038b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Davicom DM9601 USB 1.1 10/100Mbps ethernet devices
+ * Davicom DM96xx USB 10/100Mbps ethernet devices
  *
  * Peter Korsgaard <jacmet@sunsite.dk>
  *
@@ -364,7 +364,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
-       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD;
+
+       /* dm9620/21a require room for 4 byte padding, even in dm9601
+        * mode, so we need +1 to be able to receive full size
+        * ethernet frames.
+        */
+       dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1;
 
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = dm9601_mdio_read;
@@ -468,7 +473,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
                                       gfp_t flags)
 {
-       int len;
+       int len, pad;
 
        /* format:
           b1: packet length low
@@ -476,12 +481,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
           b3..n: packet data
        */
 
-       len = skb->len;
+       len = skb->len + DM_TX_OVERHEAD;
 
-       if (skb_headroom(skb) < DM_TX_OVERHEAD) {
+       /* workaround for dm962x errata with tx fifo getting out of
+        * sync if a USB bulk transfer retry happens right after a
+        * packet with odd / maxpacket length by adding up to 3 bytes
+        * padding.
+        */
+       while ((len & 1) || !(len % dev->maxpacket))
+               len++;
+
+       len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */
+       pad = len - skb->len;
+
+       if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) {
                struct sk_buff *skb2;
 
-               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags);
+               skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags);
                dev_kfree_skb_any(skb);
                skb = skb2;
                if (!skb)
@@ -490,10 +506,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
 
        __skb_push(skb, DM_TX_OVERHEAD);
 
-       /* usbnet adds padding if length is a multiple of packet size
-          if so, adjust length value in header */
-       if ((skb->len % dev->maxpacket) == 0)
-               len++;
+       if (pad) {
+               memset(skb->data + skb->len, 0, pad);
+               __skb_put(skb, pad);
+       }
 
        skb->data[0] = len;
        skb->data[1] = len >> 8;
@@ -543,7 +559,7 @@ static int dm9601_link_reset(struct usbnet *dev)
 }
 
 static const struct driver_info dm9601_info = {
-       .description    = "Davicom DM9601 USB Ethernet",
+       .description    = "Davicom DM96xx USB 10/100 Ethernet",
        .flags          = FLAG_ETHER | FLAG_LINK_INTR,
        .bind           = dm9601_bind,
        .rx_fixup       = dm9601_rx_fixup,
@@ -594,6 +610,22 @@ static const struct usb_device_id products[] = {
         USB_DEVICE(0x0a46, 0x9620),    /* DM9620 USB to Fast Ethernet Adapter */
         .driver_info = (unsigned long)&dm9601_info,
         },
+       {
+        USB_DEVICE(0x0a46, 0x9621),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
+       {
+        USB_DEVICE(0x0a46, 0x9622),    /* DM9622 USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
+       {
+        USB_DEVICE(0x0a46, 0x0269),    /* DM962OA USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
+       {
+        USB_DEVICE(0x0a46, 0x1269),    /* DM9621A USB to Fast Ethernet Adapter */
+        .driver_info = (unsigned long)&dm9601_info,
+       },
        {},                     // END
 };
 
@@ -612,5 +644,5 @@ static struct usb_driver dm9601_driver = {
 module_usb_driver(dm9601_driver);
 
 MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
-MODULE_DESCRIPTION("Davicom DM9601 USB 1.1 ethernet devices");
+MODULE_DESCRIPTION("Davicom DM96xx USB 10/100 ethernet devices");
 MODULE_LICENSE("GPL");
index 86292e6aaf4955c4412ead6579f74e6848bcd089..1a482344b3f507e97486059d56280dfd3f23d37c 100644 (file)
@@ -185,7 +185,6 @@ enum rx_ctrl_state{
 #define BM_REQUEST_TYPE (0xa1)
 #define B_NOTIFICATION  (0x20)
 #define W_VALUE         (0x0)
-#define W_INDEX         (0x2)
 #define W_LENGTH        (0x2)
 
 #define B_OVERRUN       (0x1<<6)
@@ -1487,6 +1486,7 @@ static void tiocmget_intr_callback(struct urb *urb)
        struct uart_icount *icount;
        struct hso_serial_state_notification *serial_state_notification;
        struct usb_device *usb;
+       int if_num;
 
        /* Sanity checks */
        if (!serial)
@@ -1495,15 +1495,24 @@ static void tiocmget_intr_callback(struct urb *urb)
                handle_usb_error(status, __func__, serial->parent);
                return;
        }
+
+       /* tiocmget is only supported on HSO_PORT_MODEM */
        tiocmget = serial->tiocmget;
        if (!tiocmget)
                return;
+       BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
+
        usb = serial->parent->usb;
+       if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+
+       /* wIndex should be the USB interface number of the port to which the
+        * notification applies, which should always be the Modem port.
+        */
        serial_state_notification = &tiocmget->serial_state_notification;
        if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
            serial_state_notification->bNotification != B_NOTIFICATION ||
            le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
-           le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+           le16_to_cpu(serial_state_notification->wIndex) != if_num ||
            le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
                dev_warn(&usb->dev,
                         "hso received invalid serial state notification\n");
index 03832d3780aa6134059dc4768bb7614d71075b82..f54637828574f6b4af868d978288d4920aa3061a 100644 (file)
@@ -117,7 +117,6 @@ enum {
 struct mcs7830_data {
        u8 multi_filter[8];
        u8 config;
-       u8 link_counter;
 };
 
 static const char driver_name[] = "MOSCHIP usb-ethernet driver";
@@ -561,26 +560,16 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 {
        u8 *buf = urb->transfer_buffer;
        bool link, link_changed;
-       struct mcs7830_data *data = mcs7830_get_data(dev);
 
        if (urb->actual_length < 16)
                return;
 
-       link = !(buf[1] & 0x20);
+       link = !(buf[1] == 0x20);
        link_changed = netif_carrier_ok(dev->net) != link;
        if (link_changed) {
-               data->link_counter++;
-               /*
-                  track link state 20 times to guard against erroneous
-                  link state changes reported sometimes by the chip
-                */
-               if (data->link_counter > 20) {
-                       data->link_counter = 0;
-                       usbnet_link_change(dev, link, 0);
-                       netdev_dbg(dev->net, "Link Status is: %d\n", link);
-               }
-       } else
-               data->link_counter = 0;
+               usbnet_link_change(dev, link, 0);
+               netdev_dbg(dev->net, "Link Status is: %d\n", link);
+       }
 }
 
 static const struct driver_info moschip_info = {
index 8494bb53ebdc9f33abee1d8e5a27f7d0dea3cc17..aba04f56176008aa12d0eaf72590d239f0affce8 100644 (file)
@@ -1245,7 +1245,7 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
                return -ENOMEM;
 
        urb->num_sgs = num_sgs;
-       sg_init_table(urb->sg, urb->num_sgs);
+       sg_init_table(urb->sg, urb->num_sgs + 1);
 
        sg_set_buf(&urb->sg[s++], skb->data, skb_headlen(skb));
        total_len += skb_headlen(skb);
index 7bab4de658a91d9fb1231f5e45461a268efc8487..5d776447d9c33e2da56b622a2537536cf950ca0c 100644 (file)
@@ -299,35 +299,76 @@ static struct sk_buff *page_to_skb(struct receive_queue *rq,
        return skb;
 }
 
-static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
+static struct sk_buff *receive_small(void *buf, unsigned int len)
 {
-       struct skb_vnet_hdr *hdr = skb_vnet_hdr(head_skb);
+       struct sk_buff * skb = buf;
+
+       len -= sizeof(struct virtio_net_hdr);
+       skb_trim(skb, len);
+
+       return skb;
+}
+
+static struct sk_buff *receive_big(struct net_device *dev,
+                                  struct receive_queue *rq,
+                                  void *buf,
+                                  unsigned int len)
+{
+       struct page *page = buf;
+       struct sk_buff *skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
+
+       if (unlikely(!skb))
+               goto err;
+
+       return skb;
+
+err:
+       dev->stats.rx_dropped++;
+       give_pages(rq, page);
+       return NULL;
+}
+
+static struct sk_buff *receive_mergeable(struct net_device *dev,
+                                        struct receive_queue *rq,
+                                        void *buf,
+                                        unsigned int len)
+{
+       struct skb_vnet_hdr *hdr = buf;
+       int num_buf = hdr->mhdr.num_buffers;
+       struct page *page = virt_to_head_page(buf);
+       int offset = buf - page_address(page);
+       struct sk_buff *head_skb = page_to_skb(rq, page, offset, len,
+                                              MERGE_BUFFER_LEN);
        struct sk_buff *curr_skb = head_skb;
-       char *buf;
-       struct page *page;
-       int num_buf, len, offset;
 
-       num_buf = hdr->mhdr.num_buffers;
+       if (unlikely(!curr_skb))
+               goto err_skb;
+
        while (--num_buf) {
-               int num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
+               int num_skb_frags;
+
                buf = virtqueue_get_buf(rq->vq, &len);
                if (unlikely(!buf)) {
-                       pr_debug("%s: rx error: %d buffers missing\n",
-                                head_skb->dev->name, hdr->mhdr.num_buffers);
-                       head_skb->dev->stats.rx_length_errors++;
-                       return -EINVAL;
+                       pr_debug("%s: rx error: %d buffers out of %d missing\n",
+                                dev->name, num_buf, hdr->mhdr.num_buffers);
+                       dev->stats.rx_length_errors++;
+                       goto err_buf;
                }
                if (unlikely(len > MERGE_BUFFER_LEN)) {
                        pr_debug("%s: rx error: merge buffer too long\n",
-                                head_skb->dev->name);
+                                dev->name);
                        len = MERGE_BUFFER_LEN;
                }
+
+               page = virt_to_head_page(buf);
+               --rq->num;
+
+               num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
                if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) {
                        struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC);
-                       if (unlikely(!nskb)) {
-                               head_skb->dev->stats.rx_dropped++;
-                               return -ENOMEM;
-                       }
+
+                       if (unlikely(!nskb))
+                               goto err_skb;
                        if (curr_skb == head_skb)
                                skb_shinfo(curr_skb)->frag_list = nskb;
                        else
@@ -341,8 +382,7 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
                        head_skb->len += len;
                        head_skb->truesize += MERGE_BUFFER_LEN;
                }
-               page = virt_to_head_page(buf);
-               offset = buf - (char *)page_address(page);
+               offset = buf - page_address(page);
                if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) {
                        put_page(page);
                        skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1,
@@ -351,9 +391,28 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
                        skb_add_rx_frag(curr_skb, num_skb_frags, page,
                                        offset, len, MERGE_BUFFER_LEN);
                }
+       }
+
+       return head_skb;
+
+err_skb:
+       put_page(page);
+       while (--num_buf) {
+               buf = virtqueue_get_buf(rq->vq, &len);
+               if (unlikely(!buf)) {
+                       pr_debug("%s: rx error: %d buffers missing\n",
+                                dev->name, num_buf);
+                       dev->stats.rx_length_errors++;
+                       break;
+               }
+               page = virt_to_head_page(buf);
+               put_page(page);
                --rq->num;
        }
-       return 0;
+err_buf:
+       dev->stats.rx_dropped++;
+       dev_kfree_skb(head_skb);
+       return NULL;
 }
 
 static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
@@ -362,48 +421,29 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
        struct net_device *dev = vi->dev;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
        struct sk_buff *skb;
-       struct page *page;
        struct skb_vnet_hdr *hdr;
 
        if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
                pr_debug("%s: short packet %i\n", dev->name, len);
                dev->stats.rx_length_errors++;
-               if (vi->big_packets)
-                       give_pages(rq, buf);
-               else if (vi->mergeable_rx_bufs)
+               if (vi->mergeable_rx_bufs)
                        put_page(virt_to_head_page(buf));
+               else if (vi->big_packets)
+                       give_pages(rq, buf);
                else
                        dev_kfree_skb(buf);
                return;
        }
 
-       if (!vi->mergeable_rx_bufs && !vi->big_packets) {
-               skb = buf;
-               len -= sizeof(struct virtio_net_hdr);
-               skb_trim(skb, len);
-       } else if (vi->mergeable_rx_bufs) {
-               struct page *page = virt_to_head_page(buf);
-               skb = page_to_skb(rq, page,
-                                 (char *)buf - (char *)page_address(page),
-                                 len, MERGE_BUFFER_LEN);
-               if (unlikely(!skb)) {
-                       dev->stats.rx_dropped++;
-                       put_page(page);
-                       return;
-               }
-               if (receive_mergeable(rq, skb)) {
-                       dev_kfree_skb(skb);
-                       return;
-               }
-       } else {
-               page = buf;
-               skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
-               if (unlikely(!skb)) {
-                       dev->stats.rx_dropped++;
-                       give_pages(rq, page);
-                       return;
-               }
-       }
+       if (vi->mergeable_rx_bufs)
+               skb = receive_mergeable(dev, rq, buf, len);
+       else if (vi->big_packets)
+               skb = receive_big(dev, rq, buf, len);
+       else
+               skb = receive_small(buf, len);
+
+       if (unlikely(!skb))
+               return;
 
        hdr = skb_vnet_hdr(skb);
 
@@ -1084,7 +1124,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
                                  VIRTIO_NET_CTRL_MAC_TABLE_SET,
                                  sg, NULL))
-               dev_warn(&dev->dev, "Failed to set MAC fitler table.\n");
+               dev_warn(&dev->dev, "Failed to set MAC filter table.\n");
 
        kfree(buf);
 }
@@ -1327,6 +1367,11 @@ static void virtnet_config_changed(struct virtio_device *vdev)
 
 static void virtnet_free_queues(struct virtnet_info *vi)
 {
+       int i;
+
+       for (i = 0; i < vi->max_queue_pairs; i++)
+               netif_napi_del(&vi->rq[i].napi);
+
        kfree(vi->rq);
        kfree(vi->sq);
 }
@@ -1356,10 +1401,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
                struct virtqueue *vq = vi->rq[i].vq;
 
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-                       if (vi->big_packets)
-                               give_pages(&vi->rq[i], buf);
-                       else if (vi->mergeable_rx_bufs)
+                       if (vi->mergeable_rx_bufs)
                                put_page(virt_to_head_page(buf));
+                       else if (vi->big_packets)
+                               give_pages(&vi->rq[i], buf);
                        else
                                dev_kfree_skb(buf);
                        --vi->rq[i].num;
@@ -1752,16 +1797,17 @@ static int virtnet_restore(struct virtio_device *vdev)
        if (err)
                return err;
 
-       if (netif_running(vi->dev))
+       if (netif_running(vi->dev)) {
+               for (i = 0; i < vi->curr_queue_pairs; i++)
+                       if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                               schedule_delayed_work(&vi->refill, 0);
+
                for (i = 0; i < vi->max_queue_pairs; i++)
                        virtnet_napi_enable(&vi->rq[i]);
+       }
 
        netif_device_attach(vi->dev);
 
-       for (i = 0; i < vi->curr_queue_pairs; i++)
-               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
-                       schedule_delayed_work(&vi->refill, 0);
-
        mutex_lock(&vi->config_lock);
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
index 0358c07f7669142034e089660425a8fdb88236e2..ed384fee76ac9ffa12eff0563864424f95ab2d01 100644 (file)
@@ -1668,7 +1668,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        netdev_dbg(dev, "circular route to %pI4\n",
                                   &dst->sin.sin_addr.s_addr);
                        dev->stats.collisions++;
-                       goto tx_error;
+                       goto rt_tx_error;
                }
 
                /* Bypass encapsulation if the destination is local */
@@ -2440,7 +2440,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                /* update header length based on lower device */
                dev->hard_header_len = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       }
+       } else if (use_ipv6)
+               vxlan->flags |= VXLAN_F_IPV6;
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
index 8d78253c26cee6f459121e7e8ef5c3e0e44b8b2a..a366d6b4626f5fdd0bcf04b1d6b9c6063a70afbd 100644 (file)
@@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                                mask2 |= ATH9K_INT_CST;
                        if (isr2 & AR_ISR_S2_TSFOOR)
                                mask2 |= ATH9K_INT_TSFOOR;
+
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                               REG_WRITE(ah, AR_ISR_S2, isr2);
+                               isr &= ~AR_ISR_BCNMISC;
+                       }
                }
 
-               isr = REG_READ(ah, AR_ISR_RAC);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
+                       isr = REG_READ(ah, AR_ISR_RAC);
+
                if (isr == 0xffffffff) {
                        *masked = 0;
                        return false;
@@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
                        *masked |= ATH9K_INT_TX;
 
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
+                       if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                               s0_s = REG_READ(ah, AR_ISR_S0_S);
+                               s1_s = REG_READ(ah, AR_ISR_S1_S);
+                       } else {
+                               s0_s = REG_READ(ah, AR_ISR_S0);
+                               REG_WRITE(ah, AR_ISR_S0, s0_s);
+                               s1_s = REG_READ(ah, AR_ISR_S1);
+                               REG_WRITE(ah, AR_ISR_S1, s1_s);
+
+                               isr &= ~(AR_ISR_TXOK |
+                                        AR_ISR_TXDESC |
+                                        AR_ISR_TXERR |
+                                        AR_ISR_TXEOL);
+                       }
+
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
                        ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
                        ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
                }
@@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                *masked |= mask2;
        }
 
-       if (AR_SREV_9100(ah))
-               return true;
-
-       if (isr & AR_ISR_GENTMR) {
+       if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
                u32 s5_s;
 
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
+               if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
+                       s5_s = REG_READ(ah, AR_ISR_S5_S);
+               } else {
+                       s5_s = REG_READ(ah, AR_ISR_S5);
+               }
+
                ah->intr_gen_timer_trigger =
                                MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
@@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
                    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
                        *masked |= ATH9K_INT_TIM_TIMER;
+
+               if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+                       REG_WRITE(ah, AR_ISR_S5, s5_s);
+                       isr &= ~AR_ISR_GENTMR;
+               }
        }
 
+       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
+               REG_WRITE(ah, AR_ISR, isr);
+               REG_READ(ah, AR_ISR);
+       }
+
+       if (AR_SREV_9100(ah))
+               return true;
+
        if (sync_cause) {
                ath9k_debug_sync_cause(common, sync_cause);
                fatal_int =
index 1ec52356b5a16956dda70a2f7365103497b43c68..130657db5c4314321159b8d3fb7ec69c1ee01d21 100644 (file)
@@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
        int quick_drop;
        s32 t[3], f[3] = {5180, 5500, 5785};
 
-       if (!(pBase->miscConfiguration & BIT(1)))
+       if (!(pBase->miscConfiguration & BIT(4)))
                return;
 
-       if (freq < 4000)
-               quick_drop = eep->modalHeader2G.quick_drop;
-       else {
-               t[0] = eep->base_ext1.quick_drop_low;
-               t[1] = eep->modalHeader5G.quick_drop;
-               t[2] = eep->base_ext1.quick_drop_high;
-               quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+       if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) {
+               if (freq < 4000) {
+                       quick_drop = eep->modalHeader2G.quick_drop;
+               } else {
+                       t[0] = eep->base_ext1.quick_drop_low;
+                       t[1] = eep->modalHeader5G.quick_drop;
+                       t[2] = eep->base_ext1.quick_drop_high;
+                       quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+               }
+               REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
        }
-       REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
 }
 
 static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
@@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz)
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 bias;
 
-       if (!(eep->baseEepHeader.featureEnable & 0x40))
+       if (!(eep->baseEepHeader.miscConfiguration & 0x40))
                return;
 
        if (!AR_SREV_9300(ah))
index 9a2657fdd9ccd4ec62f96f8a639182e2ded29fec..608d739d13782233db4271f9248c3472601b1a5f 100644 (file)
@@ -127,21 +127,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        struct ath9k_vif_iter_data *iter_data = data;
        int i;
 
-       for (i = 0; i < ETH_ALEN; i++)
-               iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       if (iter_data->hw_macaddr != NULL) {
+               for (i = 0; i < ETH_ALEN; i++)
+                       iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+       } else {
+               iter_data->hw_macaddr = mac;
+       }
 }
 
-static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv,
                                     struct ieee80211_vif *vif)
 {
        struct ath_common *common = ath9k_hw_common(priv->ah);
        struct ath9k_vif_iter_data iter_data;
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
-       iter_data.hw_macaddr = common->macaddr;
+       iter_data.hw_macaddr = NULL;
        memset(&iter_data.mask, 0xff, ETH_ALEN);
 
        if (vif)
@@ -153,6 +158,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
                ath9k_htc_bssid_iter, &iter_data);
 
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+
+       if (iter_data.hw_macaddr)
+               memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+
        ath_hw_setbssidmask(common);
 }
 
@@ -1063,7 +1072,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
                goto out;
        }
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        priv->vif_slot |= (1 << avp->index);
        priv->nvifs++;
@@ -1128,7 +1137,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 
        ath9k_htc_set_opmode(priv);
 
-       ath9k_htc_set_bssid_mask(priv, vif);
+       ath9k_htc_set_mac_bssid_mask(priv, vif);
 
        /*
         * Stop ANI only if there are no associated station interfaces.
index 54b04155e43b1058575aa44df3e6ece1ab18e55e..8918035da3a3510c04ad45e106cebd3d267ad6e8 100644 (file)
@@ -146,10 +146,9 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
        else
                clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
 
-       if (IS_CHAN_HT40(chan))
-               clockrate *= 2;
-
-       if (ah->curchan) {
+       if (chan) {
+               if (IS_CHAN_HT40(chan))
+                       clockrate *= 2;
                if (IS_CHAN_HALF_RATE(chan))
                        clockrate /= 2;
                if (IS_CHAN_QUARTER_RATE(chan))
index 74f452c7b1667c47a65506a077042f2b0668c3a8..21aa09e0e825df1161a4fcca3753ca08e9632558 100644 (file)
@@ -965,8 +965,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(ah);
 
        /*
-        * Use the hardware MAC address as reference, the hardware uses it
-        * together with the BSSID mask when matching addresses.
+        * Pick the MAC address of the first interface as the new hardware
+        * MAC address. The hardware will use it together with the BSSID mask
+        * when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
index 09cdbcd097394a3a2c324230c2743f5d181b0900..b5a19e098f2d72f49dde181184bce20dc47bcebf 100644 (file)
@@ -1276,6 +1276,10 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
                                if (!rts_thresh || (len > rts_thresh))
                                        rts = true;
                        }
+
+                       if (!aggr)
+                               len = fi->framelen;
+
                        ath_buf_set_rate(sc, bf, &info, len, rts);
                }
 
index de9eb2cfbf4b5784c36a97da2748acd357250c37..366339421d4f1c924e4e1e69c34ce88bce9ab028 100644 (file)
@@ -2041,13 +2041,20 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
        case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
                mutex_lock(&wcn->hal_ind_mutex);
                msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-               msg_ind->msg_len = len;
-               msg_ind->msg = kmalloc(len, GFP_KERNEL);
-               memcpy(msg_ind->msg, buf, len);
-               list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
-               queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-               wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               if (msg_ind) {
+                       msg_ind->msg_len = len;
+                       msg_ind->msg = kmalloc(len, GFP_KERNEL);
+                       memcpy(msg_ind->msg, buf, len);
+                       list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
+                       queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
+                       wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               }
                mutex_unlock(&wcn->hal_ind_mutex);
+               if (msg_ind)
+                       break;
+               /* FIXME: Do something smarter then just printing an error. */
+               wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
+                           msg_header->msg_type);
                break;
        default:
                wcn36xx_err("SMD_EVENT (%d) not supported\n",
index b00a7e92225f7b928f5a3cf7395f860af27299bd..54e36fcb39542e8361dfdc019134f3ba1538de8f 100644 (file)
@@ -5,6 +5,8 @@ config BRCMSMAC
        tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
        depends on MAC80211
        depends on BCMA
+       select NEW_LEDS if BCMA_DRIVER_GPIO
+       select LEDS_CLASS if BCMA_DRIVER_GPIO
        select BRCMUTIL
        select FW_LOADER
        select CRC_CCITT
index 905704e335d7164b90a4ecb6fd51c2324911c154..abc9ceca70f3630251ad077fe307f05a8a979adc 100644 (file)
@@ -109,6 +109,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
                                        brcmf_err("Disable F2 failed:%d\n",
                                                  err_ret);
                        }
+               } else {
+                       err_ret = -ENOENT;
                }
        } else if ((regaddr == SDIO_CCCR_ABORT) ||
                   (regaddr == SDIO_CCCR_IENx)) {
index 85879dbaa402cdaa88d93247b678aaac9a3ff000..3c34a72a5d64769b8bbf156f9a74d4748fcb0228 100644 (file)
@@ -67,8 +67,8 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  7
-#define IWL3160_UCODE_API_MAX  7
+#define IWL7260_UCODE_API_MAX  8
+#define IWL3160_UCODE_API_MAX  8
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK   7
@@ -130,6 +130,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
@@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
        .high_temp = true,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_2n_cfg = {
@@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_2n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_n_cfg = {
@@ -158,6 +161,7 @@ const struct iwl_cfg iwl7260_n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_2ac_cfg = {
@@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_2n_cfg = {
@@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_n_cfg = {
@@ -185,6 +191,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7265_2ac_cfg = {
@@ -196,5 +203,23 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
 };
 
+const struct iwl_cfg iwl7265_2n_cfg = {
+       .name = "Intel(R) Dual Band Wireless N 7265",
+       .fw_name_pre = IWL7265_FW_PRE,
+       IWL_DEVICE_7000,
+       .ht_params = &iwl7000_ht_params,
+       .nvm_ver = IWL7265_NVM_VERSION,
+       .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+};
+
+const struct iwl_cfg iwl7265_n_cfg = {
+       .name = "Intel(R) Wireless N 7265",
+       .fw_name_pre = IWL7265_FW_PRE,
+       IWL_DEVICE_7000,
+       .ht_params = &iwl7000_ht_params,
+       .nvm_ver = IWL7265_NVM_VERSION,
+       .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+};
+
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
index 18f232e8e81253b31d730755f242b7a51552157c..03fd9aa8bfda93b67122b1fea0688c60aad1f95c 100644 (file)
@@ -207,6 +207,8 @@ struct iwl_eeprom_params {
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
  * @high_temp: Is this NIC is designated to be in high temperature.
+ * @host_interrupt_operation_mode: device needs host interrupt operation
+ *     mode set
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -235,6 +237,7 @@ struct iwl_cfg {
        enum iwl_led_mode led_mode;
        const bool rx_with_siso_diversity;
        const bool internal_wimax_coex;
+       const bool host_interrupt_operation_mode;
        bool high_temp;
 };
 
@@ -294,6 +297,8 @@ extern const struct iwl_cfg iwl3160_2ac_cfg;
 extern const struct iwl_cfg iwl3160_2n_cfg;
 extern const struct iwl_cfg iwl3160_n_cfg;
 extern const struct iwl_cfg iwl7265_2ac_cfg;
+extern const struct iwl_cfg iwl7265_2n_cfg;
+extern const struct iwl_cfg iwl7265_n_cfg;
 #endif /* CONFIG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
index 54a4fdc631b73c987f12e459e8245d38b18f0c0b..da4eca8b3007feabb267a1710c95a70306224455 100644 (file)
@@ -495,14 +495,11 @@ enum secure_load_status_reg {
  * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
  *
  * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
  */
 #define IWL_HOST_INT_TIMEOUT_MAX       (0xFF)
 #define IWL_HOST_INT_TIMEOUT_DEF       (0x40)
 #define IWL_HOST_INT_TIMEOUT_MIN       (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
+#define IWL_HOST_INT_OPER_MODE         BIT(31)
 
 /*****************************************************************************
  *                        7000/3000 series SHR DTS addresses                 *
index 5d066cbc5ac7eda17914e85c2510c53fe4a5be2a..75b72a956552759685613c249f51a31926059a8f 100644 (file)
@@ -391,7 +391,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
                                            BT_VALID_LUT |
                                            BT_VALID_WIFI_RX_SW_PRIO_BOOST |
                                            BT_VALID_WIFI_TX_SW_PRIO_BOOST |
-                                           BT_VALID_MULTI_PRIO_LUT |
                                            BT_VALID_CORUN_LUT_20 |
                                            BT_VALID_CORUN_LUT_40 |
                                            BT_VALID_ANT_ISOLATION |
@@ -842,6 +841,11 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
 
        sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
                                        lockdep_is_held(&mvm->mutex));
+
+       /* This can happen if the station has been removed right now */
+       if (IS_ERR_OR_NULL(sta))
+               return;
+
        mvmsta = (void *)sta->drv_priv;
 
        data->num_bss_ifaces++;
index 6f45966817bb4c1d34cd3a10c4db74536f4a13bf..b9b81e881dd011e5ca06747f2bcceea4ece64ac9 100644 (file)
@@ -895,7 +895,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm,
                /* new API returns next, not last-used seqno */
                if (mvm->fw->ucode_capa.flags &
                                IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)
-                       err -= 0x10;
+                       err = (u16) (err - 0x10);
        }
 
        iwl_free_resp(&cmd);
@@ -1549,7 +1549,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
        if (gtkdata.unhandled_cipher)
                return false;
        if (!gtkdata.num_keys)
-               return true;
+               goto out;
        if (!gtkdata.last_gtk)
                return false;
 
@@ -1600,6 +1600,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                                           (void *)&replay_ctr, GFP_KERNEL);
        }
 
+out:
        mvmvif->seqno_valid = true;
        /* +0x10 because the set API expects next-to-use, not last-used */
        mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10;
index 9864d713eb2cb54920053fb971a65866f5ec0bf4..a8fe6b41f9a34b417a12e5295c7b86c75361bb1b 100644 (file)
@@ -119,6 +119,10 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct file *file,
 
        if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
                return -EINVAL;
+       if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
+               return -EINVAL;
+       if (drain < 0 || drain > 1)
+               return -EINVAL;
 
        mutex_lock(&mvm->mutex);
 
index 33cf56fdfc41f86b8bb517a8824740bdbb71a896..95ce4b601fef3050085518e59a4e32036c57fbfc 100644 (file)
@@ -176,8 +176,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * P2P Device discoveribility, while there are other higher priority
         * events in the system).
         */
-       if (WARN_ONCE(!le32_to_cpu(notif->status),
-                     "Failed to schedule time event\n")) {
+       if (!le32_to_cpu(notif->status)) {
+               bool start = le32_to_cpu(notif->action) &
+                               TE_V2_NOTIF_HOST_EVENT_START;
+               IWL_WARN(mvm, "Time Event %s notification failure\n",
+                        start ? "start" : "end");
                if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
                        iwl_mvm_te_clear_data(mvm, te_data);
                        return;
index 941c0c88f982639b28436a60e52a0fdc6fba8c4b..e6272546395a982d6d3e6e23239eaddc1bc3bf60 100644 (file)
@@ -353,6 +353,33 @@ 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(0x095B, 0x5310, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_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, 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(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, 0x9110, 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)},
+       {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5190, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
 
        {0}
index fa22639b63c947d68247698cf109070a823b792b..051268c037b1d4f7d03715cdbf13b68311f883ff 100644 (file)
@@ -477,4 +477,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
                CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 }
 
+static inline void iwl_nic_error(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       set_bit(STATUS_FW_ERROR, &trans_pcie->status);
+       iwl_op_mode_nic_error(trans->op_mode);
+}
+
 #endif /* __iwl_trans_int_pcie_h__ */
index 3f237b42eb36d3c94cc84f94d0ba86b6a7861e41..be3995afa9d0acee4ce7f6e0d60907f896594c53 100644 (file)
@@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
 
        /* Set interrupt coalescing timer to default (2048 usecs) */
        iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+
+       /* W/A for interrupt coalescing bug in 7260 and 3160 */
+       if (trans->cfg->host_interrupt_operation_mode)
+               iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE);
 }
 
 static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
@@ -796,12 +800,13 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
        iwl_pcie_dump_csr(trans);
        iwl_dump_fh(trans, NULL);
 
+       /* set the ERROR bit before we wake up the caller */
        set_bit(STATUS_FW_ERROR, &trans_pcie->status);
        clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
        wake_up(&trans_pcie->wait_command_queue);
 
        local_bh_disable();
-       iwl_op_mode_nic_error(trans->op_mode);
+       iwl_nic_error(trans);
        local_bh_enable();
 }
 
index 5d9337bec67a87c59f3ccef73e5f5b26644930d5..cde9c16f6e4febb26c66c2206068bdba973c708a 100644 (file)
@@ -279,9 +279,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
        spin_lock_irqsave(&trans_pcie->irq_lock, flags);
        iwl_pcie_apm_init(trans);
 
-       /* Set interrupt coalescing calibration timer to default (512 usecs) */
-       iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
        spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
        iwl_pcie_set_pwr(trans, false);
index 059c5acad3a0d2e7b9eb73bf6466ef088e54e5c2..0adde919a258a65f9585651e8efb89add27f2add 100644 (file)
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
                        le32_to_cpu(txq->scratchbufs[i].scratch));
 
-       iwl_op_mode_nic_error(trans->op_mode);
+       iwl_nic_error(trans);
 }
 
 /*
@@ -1023,7 +1023,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
                if (nfreed++ > 0) {
                        IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
                                idx, q->write_ptr, q->read_ptr);
-                       iwl_op_mode_nic_error(trans->op_mode);
+                       iwl_nic_error(trans);
                }
        }
 
@@ -1562,7 +1562,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
                                       get_cmd_string(trans_pcie, cmd->id));
                        ret = -ETIMEDOUT;
 
-                       iwl_op_mode_nic_error(trans->op_mode);
+                       iwl_nic_error(trans);
 
                        goto cancel;
                }
index 9df7bc91a26f54c9812718e481c538895aa5b4f8..a1b32ee9594a6b9b899caa03cea53f3d9a0ddf90 100644 (file)
@@ -383,6 +383,14 @@ struct hwsim_radiotap_hdr {
        __le16 rt_chbitmask;
 } __packed;
 
+struct hwsim_radiotap_ack_hdr {
+       struct ieee80211_radiotap_header hdr;
+       u8 rt_flags;
+       u8 pad;
+       __le16 rt_channel;
+       __le16 rt_chbitmask;
+} __packed;
+
 /* MAC80211_HWSIM netlinf family */
 static struct genl_family hwsim_genl_family = {
        .id = GENL_ID_GENERATE,
@@ -500,7 +508,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
                                       const u8 *addr)
 {
        struct sk_buff *skb;
-       struct hwsim_radiotap_hdr *hdr;
+       struct hwsim_radiotap_ack_hdr *hdr;
        u16 flags;
        struct ieee80211_hdr *hdr11;
 
@@ -511,14 +519,14 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
        if (skb == NULL)
                return;
 
-       hdr = (struct hwsim_radiotap_hdr *) skb_put(skb, sizeof(*hdr));
+       hdr = (struct hwsim_radiotap_ack_hdr *) skb_put(skb, sizeof(*hdr));
        hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
        hdr->hdr.it_pad = 0;
        hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
        hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
                                          (1 << IEEE80211_RADIOTAP_CHANNEL));
        hdr->rt_flags = 0;
-       hdr->rt_rate = 0;
+       hdr->pad = 0;
        hdr->rt_channel = cpu_to_le16(chan->center_freq);
        flags = IEEE80211_CHAN_2GHZ;
        hdr->rt_chbitmask = cpu_to_le16(flags);
@@ -1230,7 +1238,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
                                              HRTIMER_MODE_REL);
                } else if (!info->enable_beacon) {
                        unsigned int count = 0;
-                       ieee80211_iterate_active_interfaces(
+                       ieee80211_iterate_active_interfaces_atomic(
                                data->hw, IEEE80211_IFACE_ITER_NORMAL,
                                mac80211_hwsim_bcn_en_iter, &count);
                        wiphy_debug(hw->wiphy, "  beaconing vifs remaining: %u",
@@ -2003,7 +2011,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
           (hwsim_flags & HWSIM_TX_STAT_ACK)) {
                if (skb->len >= 16) {
                        hdr = (struct ieee80211_hdr *) skb->data;
-                       mac80211_hwsim_monitor_ack(txi->rate_driver_data[0],
+                       mac80211_hwsim_monitor_ack(data2->channel,
                                                   hdr->addr2);
                }
                txi->flags |= IEEE80211_TX_STAT_ACK;
index 78e8a6666cc6edad81bd87c98dcf0353af371866..8bb8988c435cf04b0280aef69d4e9d01acc24fee 100644 (file)
@@ -746,7 +746,8 @@ 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)
+mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        skb->priority = cfg80211_classify8021d(skb);
        return mwifiex_1d_to_wmm_queue[skb->priority];
index c8e029df770e38cac9a52dccb660666bd8cc9f74..a09398fe9e2a67218f50530af8a0b4616443cbbb 100644 (file)
@@ -319,8 +319,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                if (bss_desc && bss_desc->ssid.ssid_len &&
                    (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
                                       ssid, &bss_desc->ssid))) {
-                       kfree(bss_desc);
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
 
                /* Exit Adhoc mode first */
index 0f494444bcd1d90b457b927d704bf77abe0592ca..5a53195d016b61da57f3198ad1f616343e1ebd3d 100644 (file)
@@ -740,6 +740,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
        };
        int index = rtlpci->rx_ring[rx_queue_idx].idx;
 
+       if (rtlpci->driver_is_goingto_unload)
+               return;
        /*RX NORMAL PKT */
        while (count--) {
                /*rx descriptor */
@@ -1636,6 +1638,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
         */
        set_hal_stop(rtlhal);
 
+       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->disable_interrupt(hw);
        cancel_work_sync(&rtlpriv->works.lps_change_work);
 
@@ -1653,7 +1656,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        ppsc->rfchange_inprogress = true;
        spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags);
 
-       rtlpci->driver_is_goingto_unload = true;
        rtlpriv->cfg->ops->hw_disable(hw);
        /* some things are not needed if firmware not available */
        if (!rtlpriv->max_fw_size)
index 08ae01b41c832d7144bdeceb70b976adaf281d4c..c47794b9d42f9bfd71d2761a48f8429a8b4633c5 100644 (file)
@@ -101,6 +101,13 @@ struct xenvif_rx_meta {
 
 #define MAX_PENDING_REQS 256
 
+/* It's possible for an skb to have a maximal number of frags
+ * but still be less than MAX_BUFFER_OFFSET in size. Thus the
+ * worst-case number of copy operations is MAX_SKB_FRAGS per
+ * ring slot.
+ */
+#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE)
+
 struct xenvif {
        /* Unique identifier for this interface. */
        domid_t          domid;
@@ -143,13 +150,13 @@ struct xenvif {
         */
        RING_IDX rx_req_cons_peek;
 
-       /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
-        * head/fragment page uses 2 copy operations because it
-        * straddles two buffers in the frontend.
-        */
-       struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
-       struct xenvif_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+       /* This array is allocated seperately as it is large */
+       struct gnttab_copy *grant_copy_op;
 
+       /* We create one meta structure per ring request we consume, so
+        * the maximum number is the same as the ring size.
+        */
+       struct xenvif_rx_meta meta[XEN_NETIF_RX_RING_SIZE];
 
        u8               fe_dev_addr[6];
 
index 2329cccf1fa6dd15f65c4dc30c54c62cce0551a7..fff8cddfed816d3479fac57a6f91b4d827272033 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
 
 #include <xen/events.h>
 #include <asm/xen/hypercall.h>
@@ -307,6 +308,15 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        SET_NETDEV_DEV(dev, parent);
 
        vif = netdev_priv(dev);
+
+       vif->grant_copy_op = vmalloc(sizeof(struct gnttab_copy) *
+                                    MAX_GRANT_COPY_OPS);
+       if (vif->grant_copy_op == NULL) {
+               pr_warn("Could not allocate grant copy space for %s\n", name);
+               free_netdev(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+
        vif->domid  = domid;
        vif->handle = handle;
        vif->can_sg = 1;
@@ -368,11 +378,11 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
                   unsigned long rx_ring_ref, unsigned int tx_evtchn,
                   unsigned int rx_evtchn)
 {
+       struct task_struct *task;
        int err = -ENOMEM;
 
-       /* Already connected through? */
-       if (vif->tx_irq)
-               return 0;
+       BUG_ON(vif->tx_irq);
+       BUG_ON(vif->task);
 
        err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
        if (err < 0)
@@ -411,14 +421,16 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
        }
 
        init_waitqueue_head(&vif->wq);
-       vif->task = kthread_create(xenvif_kthread,
-                                  (void *)vif, "%s", vif->dev->name);
-       if (IS_ERR(vif->task)) {
+       task = kthread_create(xenvif_kthread,
+                             (void *)vif, "%s", vif->dev->name);
+       if (IS_ERR(task)) {
                pr_warn("Could not allocate kthread for %s\n", vif->dev->name);
-               err = PTR_ERR(vif->task);
+               err = PTR_ERR(task);
                goto err_rx_unbind;
        }
 
+       vif->task = task;
+
        rtnl_lock();
        if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
                dev_set_mtu(vif->dev, ETH_DATA_LEN);
@@ -461,8 +473,10 @@ void xenvif_disconnect(struct xenvif *vif)
        if (netif_carrier_ok(vif->dev))
                xenvif_carrier_off(vif);
 
-       if (vif->task)
+       if (vif->task) {
                kthread_stop(vif->task);
+               vif->task = NULL;
+       }
 
        if (vif->tx_irq) {
                if (vif->tx_irq == vif->rx_irq)
@@ -483,6 +497,7 @@ void xenvif_free(struct xenvif *vif)
 
        unregister_netdev(vif->dev);
 
+       vfree(vif->grant_copy_op);
        free_netdev(vif->dev);
 
        module_put(THIS_MODULE);
index 919b6509455cfbaf45ba63c7d8b378fa13a8e758..78425554a537579b01378b99295913c1706f0b0a 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/udp.h>
 
 #include <net/tcp.h>
+#include <net/ip6_checksum.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
@@ -451,7 +452,7 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        }
 
        /* Set up a GSO prefix descriptor, if necessary */
-       if ((1 << skb_shinfo(skb)->gso_type) & vif->gso_prefix_mask) {
+       if ((1 << gso_type) & vif->gso_prefix_mask) {
                req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
                meta = npo->meta + npo->meta_prod++;
                meta->gso_type = gso_type;
@@ -607,7 +608,7 @@ void xenvif_rx_action(struct xenvif *vif)
        if (!npo.copy_prod)
                return;
 
-       BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
+       BUG_ON(npo.copy_prod > MAX_GRANT_COPY_OPS);
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
@@ -1148,75 +1149,99 @@ static int xenvif_set_skb_gso(struct xenvif *vif,
        return 0;
 }
 
-static inline void maybe_pull_tail(struct sk_buff *skb, unsigned int len)
+static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len,
+                                 unsigned int max)
 {
-       if (skb_is_nonlinear(skb) && skb_headlen(skb) < len) {
-               /* If we need to pullup then pullup to the max, so we
-                * won't need to do it again.
-                */
-               int target = min_t(int, skb->len, MAX_TCP_HEADER);
-               __pskb_pull_tail(skb, target - skb_headlen(skb));
-       }
+       if (skb_headlen(skb) >= len)
+               return 0;
+
+       /* If we need to pullup then pullup to the max, so we
+        * won't need to do it again.
+        */
+       if (max > skb->len)
+               max = skb->len;
+
+       if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
+               return -ENOMEM;
+
+       if (skb_headlen(skb) < len)
+               return -EPROTO;
+
+       return 0;
 }
 
+/* This value should be large enough to cover a tagged ethernet header plus
+ * maximally sized IP and TCP or UDP headers.
+ */
+#define MAX_IP_HDR_LEN 128
+
 static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                             int recalculate_partial_csum)
 {
-       struct iphdr *iph = (void *)skb->data;
-       unsigned int header_size;
        unsigned int off;
-       int err = -EPROTO;
+       bool fragment;
+       int err;
 
-       off = sizeof(struct iphdr);
+       fragment = false;
 
-       header_size = skb->network_header + off + MAX_IPOPTLEN;
-       maybe_pull_tail(skb, header_size);
+       err = maybe_pull_tail(skb,
+                             sizeof(struct iphdr),
+                             MAX_IP_HDR_LEN);
+       if (err < 0)
+               goto out;
 
-       off = iph->ihl * 4;
+       if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
+               fragment = true;
 
-       switch (iph->protocol) {
-       case IPPROTO_TCP:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
-                       goto out;
+       off = ip_hdrlen(skb);
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
+       err = -EPROTO;
+
+       if (fragment)
+               goto out;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
+       switch (ip_hdr(skb)->protocol) {
+       case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
 
-                       tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_TCP, 0);
+               if (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               if (recalculate_partial_csum)
+                       tcp_hdr(skb)->check =
+                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                                  ip_hdr(skb)->daddr,
+                                                  skb->len - off,
+                                                  IPPROTO_TCP, 0);
                break;
        case IPPROTO_UDP:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct udphdr *udph = udp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct udphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_UDP, 0);
+               if (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               if (recalculate_partial_csum)
+                       udp_hdr(skb)->check =
+                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                                  ip_hdr(skb)->daddr,
+                                                  skb->len - off,
+                                                  IPPROTO_UDP, 0);
                break;
        default:
-               if (net_ratelimit())
-                       netdev_err(vif->dev,
-                                  "Attempting to checksum a non-TCP/UDP packet, "
-                                  "dropping a protocol %d packet\n",
-                                  iph->protocol);
                goto out;
        }
 
@@ -1226,121 +1251,142 @@ out:
        return err;
 }
 
+/* This value should be large enough to cover a tagged ethernet header plus
+ * an IPv6 header, all options, and a maximal TCP or UDP header.
+ */
+#define MAX_IPV6_HDR_LEN 256
+
+#define OPT_HDR(type, skb, off) \
+       (type *)(skb_network_header(skb) + (off))
+
 static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                               int recalculate_partial_csum)
 {
-       int err = -EPROTO;
-       struct ipv6hdr *ipv6h = (void *)skb->data;
+       int err;
        u8 nexthdr;
-       unsigned int header_size;
        unsigned int off;
+       unsigned int len;
        bool fragment;
        bool done;
 
+       fragment = false;
        done = false;
 
        off = sizeof(struct ipv6hdr);
 
-       header_size = skb->network_header + off;
-       maybe_pull_tail(skb, header_size);
+       err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
+       if (err < 0)
+               goto out;
 
-       nexthdr = ipv6h->nexthdr;
+       nexthdr = ipv6_hdr(skb)->nexthdr;
 
-       while ((off <= sizeof(struct ipv6hdr) + ntohs(ipv6h->payload_len)) &&
-              !done) {
+       len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
+       while (off <= len && !done) {
                switch (nexthdr) {
                case IPPROTO_DSTOPTS:
                case IPPROTO_HOPOPTS:
                case IPPROTO_ROUTING: {
-                       struct ipv6_opt_hdr *hp = (void *)(skb->data + off);
+                       struct ipv6_opt_hdr *hp;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ipv6_opt_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ipv6_opt_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
+                       hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
                        nexthdr = hp->nexthdr;
                        off += ipv6_optlen(hp);
                        break;
                }
                case IPPROTO_AH: {
-                       struct ip_auth_hdr *hp = (void *)(skb->data + off);
+                       struct ip_auth_hdr *hp;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ip_auth_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ip_auth_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
+                       hp = OPT_HDR(struct ip_auth_hdr, skb, off);
                        nexthdr = hp->nexthdr;
-                       off += (hp->hdrlen+2)<<2;
+                       off += ipv6_authlen(hp);
+                       break;
+               }
+               case IPPROTO_FRAGMENT: {
+                       struct frag_hdr *hp;
+
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct frag_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
+
+                       hp = OPT_HDR(struct frag_hdr, skb, off);
+
+                       if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
+                               fragment = true;
+
+                       nexthdr = hp->nexthdr;
+                       off += sizeof(struct frag_hdr);
                        break;
                }
-               case IPPROTO_FRAGMENT:
-                       fragment = true;
-                       /* fall through */
                default:
                        done = true;
                        break;
                }
        }
 
-       if (!done) {
-               if (net_ratelimit())
-                       netdev_err(vif->dev, "Failed to parse packet header\n");
-               goto out;
-       }
+       err = -EPROTO;
 
-       if (fragment) {
-               if (net_ratelimit())
-                       netdev_err(vif->dev, "Packet is a fragment!\n");
+       if (!done || fragment)
                goto out;
-       }
 
        switch (nexthdr) {
        case IPPROTO_TCP:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check)))
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       tcph->check = ~csum_ipv6_magic(&ipv6h->saddr,
-                                                      &ipv6h->daddr,
-                                                      skb->len - off,
-                                                      IPPROTO_TCP, 0);
+               if (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct tcphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               if (recalculate_partial_csum)
+                       tcp_hdr(skb)->check =
+                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+                                                &ipv6_hdr(skb)->daddr,
+                                                skb->len - off,
+                                                IPPROTO_TCP, 0);
                break;
        case IPPROTO_UDP:
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check)))
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct udphdr *udph = udp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct udphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       udph->check = ~csum_ipv6_magic(&ipv6h->saddr,
-                                                      &ipv6h->daddr,
-                                                      skb->len - off,
-                                                      IPPROTO_UDP, 0);
+               if (!skb_partial_csum_set(skb, off,
+                                         offsetof(struct udphdr, check))) {
+                       err = -EPROTO;
+                       goto out;
                }
+
+               if (recalculate_partial_csum)
+                       udp_hdr(skb)->check =
+                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+                                                &ipv6_hdr(skb)->daddr,
+                                                skb->len - off,
+                                                IPPROTO_UDP, 0);
                break;
        default:
-               if (net_ratelimit())
-                       netdev_err(vif->dev,
-                                  "Attempting to checksum a non-TCP/UDP packet, "
-                                  "dropping a protocol %d packet\n",
-                                  nexthdr);
                goto out;
        }
 
@@ -1410,14 +1456,15 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
        return false;
 }
 
-static unsigned xenvif_tx_build_gops(struct xenvif *vif)
+static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
 {
        struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop;
        struct sk_buff *skb;
        int ret;
 
        while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX
-               < MAX_PENDING_REQS)) {
+               < MAX_PENDING_REQS) &&
+              (skb_queue_len(&vif->tx_queue) < budget)) {
                struct xen_netif_tx_request txreq;
                struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX];
                struct page *page;
@@ -1439,7 +1486,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif)
                        continue;
                }
 
-               RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
+               work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
                if (!work_to_do)
                        break;
 
@@ -1579,14 +1626,13 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif)
 }
 
 
-static int xenvif_tx_submit(struct xenvif *vif, int budget)
+static int xenvif_tx_submit(struct xenvif *vif)
 {
        struct gnttab_copy *gop = vif->tx_copy_ops;
        struct sk_buff *skb;
        int work_done = 0;
 
-       while (work_done < budget &&
-              (skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
+       while ((skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
                struct xen_netif_tx_request *txp;
                u16 pending_idx;
                unsigned data_len;
@@ -1661,14 +1707,14 @@ int xenvif_tx_action(struct xenvif *vif, int budget)
        if (unlikely(!tx_work_todo(vif)))
                return 0;
 
-       nr_gops = xenvif_tx_build_gops(vif);
+       nr_gops = xenvif_tx_build_gops(vif, budget);
 
        if (nr_gops == 0)
                return 0;
 
        gnttab_batch_copy(vif->tx_copy_ops, nr_gops);
 
-       work_done = xenvif_tx_submit(vif, nr_gops);
+       work_done = xenvif_tx_submit(vif);
 
        return work_done;
 }
index de6f8990246fefc8aaef7c0e88e0371143ae9859..c6973f101a3e4ae9e00c604cd9e1708d1bd88485 100644 (file)
@@ -20,7 +20,7 @@ config OF_SELFTEST
        depends on OF_IRQ
        help
          This option builds in test cases for the device tree infrastructure
-         that are executed one at boot time, and the results dumped to the
+         that are executed once at boot time, and the results dumped to the
          console.
 
          If unsure, say N here, but this option is safe to enable.
index 4b9317bdb81ce85209573e6c28f86492e643962b..d3dd41c840f1cd8d6784e4a61382cb3e4987ad1a 100644 (file)
@@ -69,14 +69,6 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                 (unsigned long long)cp, (unsigned long long)s,
                 (unsigned long long)da);
 
-       /*
-        * If the number of address cells is larger than 2 we assume the
-        * mapping doesn't specify a physical address. Rather, the address
-        * specifies an identifier that must match exactly.
-        */
-       if (na > 2 && memcmp(range, addr, na * 4) != 0)
-               return OF_BAD_ADDR;
-
        if (da < cp || da >= (cp + s))
                return OF_BAD_ADDR;
        return da - cp;
index 2fa024b97c4350c680e384c645dc17d0fc5dc177..758b4f8b30b7d237c92b6a541f01db535d37101b 100644 (file)
@@ -922,8 +922,16 @@ void __init unflatten_device_tree(void)
  */
 void __init unflatten_and_copy_device_tree(void)
 {
-       int size = __be32_to_cpu(initial_boot_params->totalsize);
-       void *dt = early_init_dt_alloc_memory_arch(size,
+       int size;
+       void *dt;
+
+       if (!initial_boot_params) {
+               pr_warn("No valid device tree found, continuing without\n");
+               return;
+       }
+
+       size = __be32_to_cpu(initial_boot_params->totalsize);
+       dt = early_init_dt_alloc_memory_arch(size,
                __alignof__(struct boot_param_header));
 
        if (dt) {
index 786b0b47fae46802503ecbecee5719887830c44c..27212402c53247819cf4edf09e576d2cc69f3136 100644 (file)
@@ -165,7 +165,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                if (of_get_property(ipar, "interrupt-controller", NULL) !=
                                NULL) {
                        pr_debug(" -> got it !\n");
-                       of_node_put(old);
                        return 0;
                }
 
@@ -250,8 +249,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                 * Successfully parsed an interrrupt-map translation; copy new
                 * interrupt specifier into the out_irq structure
                 */
-               of_node_put(out_irq->np);
-               out_irq->np = of_node_get(newpar);
+               out_irq->np = newpar;
 
                match_array = imap - newaddrsize - newintsize;
                for (i = 0; i < newintsize; i++)
@@ -268,7 +266,6 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
        }
  fail:
        of_node_put(ipar);
-       of_node_put(out_irq->np);
        of_node_put(newpar);
 
        return -EINVAL;
index 7578d79b368831085dc5ee70850fd6578ee13357..2f650f68af14e4ec9e37e2c837db3fd55408b9ff 100644 (file)
@@ -300,7 +300,7 @@ static int __init parport_mfc3_init(void)
                if (!request_mem_region(piabase, sizeof(struct pia), "PIA"))
                        continue;
 
-               pp = (struct pia *)ZTWO_VADDR(piabase);
+               pp = ZTWO_VADDR(piabase);
                pp->crb = 0;
                pp->pddrb = 255; /* all data pins output */
                pp->crb = PIA_DDR|32|8;
index c269e430c760a9bc80ad982db9cb4aa211f16f45..2aa7b77c7c88bab6c2b70b79666205c061afec7d 100644 (file)
@@ -447,6 +447,11 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
                *value = 0;
                break;
 
+       case PCI_INTERRUPT_LINE:
+               /* LINE PIN MIN_GNT MAX_LAT */
+               *value = 0;
+               break;
+
        default:
                *value = 0xffffffff;
                return PCIBIOS_BAD_REGISTER_NUMBER;
index 1cf605f6767357947e9a097981caa7d7869ca2f0..e86439283a5d1911933eed185e22a50146093968 100644 (file)
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
-               acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
+               if (status != AE_NOT_FOUND)
+                       acpi_handle_warn(handle,
+                               "can't evaluate _ADR (%#x)\n", status);
                return AE_OK;
        }
 
@@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot)
        slot->flags &= (~SLOT_ENABLED);
 }
 
+static bool acpiphp_no_hotplug(acpi_handle handle)
+{
+       struct acpi_device *adev = NULL;
+
+       acpi_bus_get_device(handle, &adev);
+       return adev && adev->flags.no_hotplug;
+}
+
+static bool slot_no_hotplug(struct acpiphp_slot *slot)
+{
+       struct acpiphp_func *func;
+
+       list_for_each_entry(func, &slot->funcs, sibling)
+               if (acpiphp_no_hotplug(func_to_handle(func)))
+                       return true;
+
+       return false;
+}
 
 /**
  * get_slot_status - get ACPI slot status
@@ -701,7 +721,8 @@ 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) && sta == ACPI_STA_ALL)
+                       || acpiphp_no_hotplug(handle);
        }
        if (!alive) {
                u32 v;
@@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                struct pci_dev *dev, *tmp;
 
                mutex_lock(&slot->crit_sect);
-               /* wake up all functions */
-               if (get_slot_status(slot) == ACPI_STA_ALL) {
+               if (slot_no_hotplug(slot)) {
+                       ; /* do nothing */
+               } else if (get_slot_status(slot) == ACPI_STA_ALL) {
                        /* remove stale devices if any */
                        list_for_each_entry_safe(dev, tmp, &bus->devices,
                                                 bus_list)
index 577074efbe62f93f39ac00c6f5c4963d53bd2b0d..f7ebdba14bde9bc1c7e3dd702bc6e47506067ff5 100644 (file)
@@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
 
-       if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+       if (!adev)
+               return;
+
+       pci_acpi_add_pm_notifier(adev, pci_dev);
+       if (!adev->wakeup.flags.valid)
                return;
 
        device_set_wakeup_capable(dev, true);
        acpi_pci_sleep_wake(pci_dev, false);
-
-       pci_acpi_add_pm_notifier(adev, pci_dev);
        if (adev->wakeup.flags.run_wake)
                device_set_run_wake(dev, true);
 }
 
 static void pci_acpi_cleanup(struct device *dev)
 {
-       acpi_handle handle = ACPI_HANDLE(dev);
-       struct acpi_device *adev;
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+
+       if (!adev)
+               return;
 
-       if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) {
+       pci_acpi_remove_pm_notifier(adev);
+       if (adev->wakeup.flags.valid) {
                device_set_wakeup_capable(dev, false);
                device_set_run_wake(dev, false);
-               pci_acpi_remove_pm_notifier(adev);
        }
 }
 
index 9042fdbd724405bc96808ed699a1d543fcf17c17..25f0bc6591645707bb3b452bbaa4c28bee0efc59 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
+#include <linux/kexec.h>
 #include "pci.h"
 
 struct pci_dynid {
@@ -288,12 +289,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
        int error, node;
        struct drv_dev_and_id ddi = { drv, dev, id };
 
-       /* Execute driver initialization on node where the device's
-          bus is attached to.  This way the driver likely allocates
-          its local memory on the right node without any need to
-          change it. */
+       /*
+        * Execute driver initialization on node where the device is
+        * attached.  This way the driver likely allocates its local memory
+        * on the right node.
+        */
        node = dev_to_node(&dev->dev);
-       if (node >= 0) {
+
+       /*
+        * On NUMA systems, we are likely to call a PF probe function using
+        * work_on_cpu().  If that probe calls pci_enable_sriov() (which
+        * adds the VF devices via pci_bus_add_device()), we may re-enter
+        * this function to call the VF probe function.  Calling
+        * work_on_cpu() again will cause a lockdep warning.  Since VFs are
+        * always on the same node as the PF, we can work around this by
+        * avoiding work_on_cpu() when we're already on the correct node.
+        *
+        * Preemption is enabled, so it's theoretically unsafe to use
+        * numa_node_id(), but even if we run the probe function on the
+        * wrong node, it should be functionally correct.
+        */
+       if (node >= 0 && node != numa_node_id()) {
                int cpu;
 
                get_online_cpus();
@@ -305,6 +321,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
                put_online_cpus();
        } else
                error = local_pci_probe(&ddi);
+
        return error;
 }
 
@@ -399,12 +416,17 @@ static void pci_device_shutdown(struct device *dev)
        pci_msi_shutdown(pci_dev);
        pci_msix_shutdown(pci_dev);
 
+#ifdef CONFIG_KEXEC
        /*
-        * Turn off Bus Master bit on the device to tell it to not
-        * continue to do DMA. Don't touch devices in D3cold or unknown states.
+        * If this is a kexec reboot, turn off Bus Master bit on the
+        * device to tell it to not continue to do DMA. Don't touch
+        * devices in D3cold or unknown states.
+        * If it is not a kexec reboot, firmware will hit the PCI
+        * devices with big hammer and stop their DMA any way.
         */
-       if (pci_dev->current_state <= PCI_D3hot)
+       if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot))
                pci_clear_master(pci_dev);
+#endif
 }
 
 #ifdef CONFIG_PM
index 33120d15666895a2b48aec1c83f7b41f7b93c3be..07369f32e8bbdd79b1294ad844baeb7dc80ef7ea 100644 (file)
@@ -4165,6 +4165,14 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
        return 0;
 }
 
+bool pci_device_is_present(struct pci_dev *pdev)
+{
+       u32 v;
+
+       return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
+}
+EXPORT_SYMBOL_GPL(pci_device_is_present);
+
 #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
 static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
 static DEFINE_SPINLOCK(resource_alignment_lock);
index 1576851028db700be2413b01e815cc8387b3cd47..cc9337a71529180eaebc7beb991dfb7c9e186ea8 100644 (file)
@@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev)
        if (dev->is_added) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
-               device_del(&dev->dev);
+               device_release_driver(&dev->dev);
                dev->is_added = 0;
        }
 
@@ -34,6 +34,8 @@ static void pci_stop_dev(struct pci_dev *dev)
 
 static void pci_destroy_dev(struct pci_dev *dev)
 {
+       device_del(&dev->dev);
+
        down_write(&pci_bus_sem);
        list_del(&dev->bus_list);
        up_write(&pci_bus_sem);
index a344f3d52361f0eed4d2a0d1fdc81a957e3a7967..330ef2d065670eb91b84a6d553bdf1df2dabf79f 100644 (file)
@@ -24,8 +24,8 @@ config PHY_EXYNOS_MIPI_VIDEO
 config OMAP_USB2
        tristate "OMAP USB2 PHY Driver"
        depends on ARCH_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        select OMAP_CONTROL_USB
        help
          Enable this to support the transceiver that is part of SOC. This
@@ -36,8 +36,8 @@ config OMAP_USB2
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
        depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        help
          Enable this to support the USB OTG transceiver on TWL4030
          family chips (including the TWL5030 and TPS659x0 devices).
index 03cf8fb815543537fb14995fde36a5216706dab9..58e0e97390287364287eae1eecdf8b43ba7b72f1 100644 (file)
@@ -437,23 +437,18 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
        int id;
        struct phy *phy;
 
-       if (!dev) {
-               dev_WARN(dev, "no device provided for PHY\n");
-               ret = -EINVAL;
-               goto err0;
-       }
+       if (WARN_ON(!dev))
+               return ERR_PTR(-EINVAL);
 
        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               ret = -ENOMEM;
-               goto err0;
-       }
+       if (!phy)
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
        if (id < 0) {
                dev_err(dev, "unable to get id\n");
                ret = id;
-               goto err0;
+               goto free_phy;
        }
 
        device_initialize(&phy->dev);
@@ -468,11 +463,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        ret = device_add(&phy->dev);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        if (pm_runtime_enabled(dev)) {
                pm_runtime_enable(&phy->dev);
@@ -481,12 +476,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        return phy;
 
-err1:
-       ida_remove(&phy_ida, phy->id);
+put_dev:
        put_device(&phy->dev);
+       ida_remove(&phy_ida, phy->id);
+free_phy:
        kfree(phy);
-
-err0:
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(phy_create);
index 4780959e11d4c858e55703bee4a3835876d05550..5183e7bb8de33632618b360c2c607009539c73b8 100644 (file)
@@ -418,7 +418,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        ret = abx500_gpio_set_bits(chip,
                                        AB8500_GPIO_ALTFUN_REG,
                                        af.alt_bit1,
-                                       !!(af.alta_val && BIT(0)));
+                                       !!(af.alta_val & BIT(0)));
                        if (ret < 0)
                                goto out;
 
@@ -439,7 +439,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        goto out;
 
                ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-                               af.alt_bit1, !!(af.altb_val && BIT(0)));
+                               af.alt_bit1, !!(af.altb_val & BIT(0)));
                if (ret < 0)
                        goto out;
 
@@ -462,7 +462,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        goto out;
 
                ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-                               af.alt_bit2, !!(af.altc_val && BIT(1)));
+                               af.alt_bit2, !!(af.altc_val & BIT(1)));
                break;
 
        default:
index eeca8f97399923c462f43328b1850ad3da7ee77d..82293806e842c1b86b55c1b8f229da1aec1c58d5 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef PINCTRL_PINCTRL_ABx5O0_H
+#ifndef PINCTRL_PINCTRL_ABx500_H
 #define PINCTRL_PINCTRL_ABx500_H
 
 /* Package definitions */
index e939c28cbf1fe13573f7538a2e9d01071b094aa1..46dddc159286387dbbbe979d729d4d00cf159d43 100644 (file)
@@ -504,6 +504,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                        data |= (3 << bit);
                        break;
                default:
+                       spin_unlock_irqrestore(&bank->slock, flags);
                        dev_err(info->dev, "unsupported pull setting %d\n",
                                pull);
                        return -EINVAL;
@@ -1453,8 +1454,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
        if (ctrl->type == RK3188) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                info->reg_pull = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(info->reg_base))
-                       return PTR_ERR(info->reg_base);
+               if (IS_ERR(info->reg_pull))
+                       return PTR_ERR(info->reg_pull);
        }
 
        ret = rockchip_gpiolib_register(pdev, info);
index 009174d07767ff71451ac70cb4ce4de8b50efdf1..bc5eb453a45ccfb7826e60825b75afed8de868a7 100644 (file)
@@ -3720,7 +3720,7 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
                const struct r8a7740_portcr_group *group =
                        &r8a7740_portcr_offsets[i];
 
-               if (i <= group->end_pin)
+               if (pin <= group->end_pin)
                        return pfc->window->virt + group->offset + pin;
        }
 
index 70b522d348218e43dad2952f9c54b3c90c18c215..cc097b6938208ea029902f8dc2f68af548f9429a 100644 (file)
@@ -2584,7 +2584,7 @@ static void __iomem *sh7372_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
                const struct sh7372_portcr_group *group =
                        &sh7372_portcr_offsets[i];
 
-               if (i <= group->end_pin)
+               if (pin <= group->end_pin)
                        return pfc->window->virt + group->offset + pin;
        }
 
index 11bd0d970a5246a378185e77955e957d7b4e7376..e2142956a8e5fff5bd1363f3e6837e00b1064bff 100644 (file)
@@ -254,7 +254,7 @@ struct sh_pfc_soc_info {
 #define PINMUX_GPIO(_pin)                                              \
        [GPIO_##_pin] = {                                               \
                .pin = (u16)-1,                                         \
-               .name = __stringify(name),                              \
+               .name = __stringify(GPIO_##_pin),                       \
                .enum_id = _pin##_DATA,                                 \
        }
 
index 6936e0acedcd6bfce4b8166bb4b8da6a922e0f47..f748cc8cbb031cf3ad3fd943688fc6172a452bd2 100644 (file)
@@ -197,6 +197,11 @@ static int pnp_bus_freeze(struct device *dev)
        return __pnp_bus_suspend(dev, PMSG_FREEZE);
 }
 
+static int pnp_bus_poweroff(struct device *dev)
+{
+       return __pnp_bus_suspend(dev, PMSG_HIBERNATE);
+}
+
 static int pnp_bus_resume(struct device *dev)
 {
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
@@ -234,9 +239,14 @@ static int pnp_bus_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
+       /* Suspend callbacks */
        .suspend = pnp_bus_suspend,
-       .freeze = pnp_bus_freeze,
        .resume = pnp_bus_resume,
+       /* Hibernate callbacks */
+       .freeze = pnp_bus_freeze,
+       .thaw = pnp_bus_resume,
+       .poweroff = pnp_bus_poweroff,
+       .restore = pnp_bus_resume,
 };
 
 struct bus_type pnp_bus_type = {
index 5e2054afe840e9d6412a28c5250f34d1017aa7b2..85ad58c6da17233a9503650500b69579887c84bb 100644 (file)
@@ -196,6 +196,7 @@ config BATTERY_MAX17040
 config BATTERY_MAX17042
        tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge"
        depends on I2C
+       select REGMAP_I2C
        help
          MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
          in handheld and portable equipment. The MAX17042 is configured
index 00e6672963601754262ced9e842f31c27e07c69e..557af943b2f53d0a3ee2a280122e42e69db94c67 100644 (file)
@@ -511,6 +511,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        dev_set_drvdata(dev, psy);
        psy->dev = dev;
 
+       rc = dev_set_name(dev, "%s", psy->name);
+       if (rc)
+               goto dev_set_name_failed;
+
        INIT_WORK(&psy->changed_work, power_supply_changed_work);
 
        rc = power_supply_check_supplies(psy);
@@ -524,10 +528,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto wakeup_init_failed;
 
-       rc = kobject_set_name(&dev->kobj, "%s", psy->name);
-       if (rc)
-               goto kobject_set_name_failed;
-
        rc = device_add(dev);
        if (rc)
                goto device_add_failed;
@@ -553,11 +553,11 @@ create_triggers_failed:
 register_cooler_failed:
        psy_unregister_thermal(psy);
 register_thermal_failed:
-wakeup_init_failed:
        device_del(dev);
-kobject_set_name_failed:
 device_add_failed:
+wakeup_init_failed:
 check_supplies_failed:
+dev_set_name_failed:
        put_device(dev);
 success:
        return rc;
index 2a786c504460f5be0246c363fab622223ebd990e..3c6768378a94600bc487c61bc9d3fffcbf581750 100644 (file)
@@ -833,6 +833,11 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
        return 0;
 }
 
+static const struct x86_cpu_id energy_unit_quirk_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
+       {}
+};
+
 static int rapl_check_unit(struct rapl_package *rp, int cpu)
 {
        u64 msr_val;
@@ -853,8 +858,11 @@ static int rapl_check_unit(struct rapl_package *rp, int cpu)
         * time unit: 1/time_unit_divisor Seconds
         */
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit_divisor = 1 << value;
-
+       /* some CPUs have different way to calculate energy unit */
+       if (x86_match_cpu(energy_unit_quirk_ids))
+               rp->energy_unit_divisor = 1000000 / (1 << value);
+       else
+               rp->energy_unit_divisor = 1 << value;
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit_divisor = 1 << value;
@@ -941,6 +949,7 @@ static void package_power_limit_irq_restore(int package_id)
 static const struct x86_cpu_id rapl_ids[] = {
        { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
        { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
+       { X86_VENDOR_INTEL, 6, 0x37},/* VLV */
        { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
        { X86_VENDOR_INTEL, 6, 0x45},/* HSW */
        /* TODO: Add more CPU IDs after testing */
index 8d0fe431dbdd54ef0c175c06dbbc4b5d76f6d9cd..84419af16f777095687eddb59d74c7ca6762e3bb 100644 (file)
@@ -377,9 +377,14 @@ static void create_power_zone_common_attributes(
        if (power_zone->ops->get_max_energy_range_uj)
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_max_energy_range_uj.attr;
-       if (power_zone->ops->get_energy_uj)
+       if (power_zone->ops->get_energy_uj) {
+               if (power_zone->ops->reset_energy_uj)
+                       dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
+               else
+                       dev_attr_energy_uj.attr.mode = S_IRUGO;
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_energy_uj.attr;
+       }
        if (power_zone->ops->get_power_uw)
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_power_uw.attr;
index 5917fe3dc983dc5335d62e393fe079459817d439..b9f1d24c6812eb91d0cf55031c617888b914c560 100644 (file)
@@ -590,8 +590,8 @@ static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
        default:
                return -EINVAL;
        }
+       ret <<= ffs(mask) - 1;
        val = ret & mask;
-       val <<= ffs(mask) - 1;
        return as3722_update_bits(as3722, reg, mask, val);
 }
 
index 3fe13130baec12218a58230863b313bf4c20d034..d85f31385b24fe9b68ae45dfe0ece4be0ecc2ceb 100644 (file)
@@ -119,6 +119,11 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
                return "";
 }
 
+static bool have_full_constraints(void)
+{
+       return has_full_constraints || of_have_populated_dt();
+}
+
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
@@ -1340,7 +1345,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
         * Assume that a regulator is physically present and enabled
         * even if it isn't hooked up and just provide a dummy.
         */
-       if (has_full_constraints && allow_dummy) {
+       if (have_full_constraints() && allow_dummy) {
                pr_warn("%s supply %s not found, using dummy regulator\n",
                        devname, id);
 
@@ -3627,7 +3632,7 @@ int regulator_suspend_finish(void)
                        if (error)
                                ret = error;
                } else {
-                       if (!has_full_constraints)
+                       if (!have_full_constraints())
                                goto unlock;
                        if (!ops->disable)
                                goto unlock;
@@ -3825,7 +3830,7 @@ static int __init regulator_init_complete(void)
                if (!enabled)
                        goto unlock;
 
-               if (has_full_constraints) {
+               if (have_full_constraints()) {
                        /* We log since this may kill the system if it
                         * goes wrong. */
                        rdev_info(rdev, "disabling\n");
index 032df3799efb7a144f6c1eef5cd0a3dfe17b6e50..8b5e4c712a0190b0643c6ee40a8918582829d4fd 100644 (file)
@@ -38,7 +38,7 @@
 
 #define PFUZE100_DEVICEID      0x0
 #define PFUZE100_REVID         0x3
-#define PFUZE100_FABID         0x3
+#define PFUZE100_FABID         0x4
 
 #define PFUZE100_SW1ABVOL      0x20
 #define PFUZE100_SW1CVOL       0x2e
index 333677d68d0ee31f784e76906bc930b592fc7257..9e61922d82302372c08ab5499b676a4b51363248 100644 (file)
@@ -438,7 +438,7 @@ common_reg:
        platform_set_drvdata(pdev, s2mps11);
 
        config.dev = &pdev->dev;
-       config.regmap = iodev->regmap;
+       config.regmap = iodev->regmap_pmic;
        config.driver_data = s2mps11;
        for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
                if (!reg_np) {
index cbf91e25cf7ff2a632270caed53d05533fcf81db..aeb40aad0ae7775442f775403fdaea047bdd16d8 100644 (file)
@@ -925,7 +925,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
                config.dev = s5m8767->dev;
                config.init_data = pdata->regulators[i].initdata;
                config.driver_data = s5m8767;
-               config.regmap = iodev->regmap;
+               config.regmap = iodev->regmap_pmic;
                config.of_node = pdata->regulators[i].reg_node;
 
                rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
index c0da95e95702123d403bf58ed4b894a104eeb2ec..3281c90691c3e143fe14142c9234e3f0a60650e6 100644 (file)
@@ -220,6 +220,8 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        at91_alarm_year = tm.tm_year;
 
+       tm.tm_mon = alrm->time.tm_mon;
+       tm.tm_mday = alrm->time.tm_mday;
        tm.tm_hour = alrm->time.tm_hour;
        tm.tm_min = alrm->time.tm_min;
        tm.tm_sec = alrm->time.tm_sec;
index f14876256a4a5d242695746355149703ed743003..a2325bc5e497e7dbee4c72ac805da1c324ae4d27 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
-#include <linux/mod_devicetable.h>
 #include <linux/log2.h>
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/dmi.h>
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <asm-generic/rtc.h>
@@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        return 0;
 }
 
+/*
+ * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes.
+ */
+static bool alarm_disable_quirk;
+
+static int __init set_alarm_disable_quirk(const struct dmi_system_id *id)
+{
+       alarm_disable_quirk = true;
+       pr_info("rtc-cmos: BIOS has alarm-disable quirk. ");
+       pr_info("RTC alarms disabled\n");
+       return 0;
+}
+
+static const struct dmi_system_id rtc_quirks[] __initconst = {
+       /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */
+       {
+               .callback = set_alarm_disable_quirk,
+               .ident    = "IBM Truman",
+               .matches  = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "4852570"),
+               },
+       },
+       /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */
+       {
+               .callback = set_alarm_disable_quirk,
+               .ident    = "Gigabyte GA-990XA-UD3",
+               .matches  = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "Gigabyte Technology Co., Ltd."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"),
+               },
+       },
+       /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */
+       {
+               .callback = set_alarm_disable_quirk,
+               .ident    = "Toshiba Satellite L300",
+               .matches  = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"),
+               },
+       },
+       {}
+};
+
 static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
        if (!is_valid_irq(cmos->irq))
                return -EINVAL;
 
+       if (alarm_disable_quirk)
+               return 0;
+
        spin_lock_irqsave(&rtc_lock, flags);
 
        if (enabled)
@@ -1157,6 +1205,8 @@ static int __init cmos_init(void)
                        platform_driver_registered = true;
        }
 
+       dmi_check_system(rtc_quirks);
+
        if (retval == 0)
                return 0;
 
index b7fd02bc0a1473a41f00bc233f845551085f5009..ae8119dc2846aac28c8f47019720bf93fd39803f 100644 (file)
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/rtc.h>
 
+/*
+ * Maximum number of retries for checking changes in UDR field
+ * of SEC_RTC_UDR_CON register (to limit possible endless loop).
+ *
+ * After writing to RTC registers (setting time or alarm) read the UDR field
+ * in SEC_RTC_UDR_CON register. UDR is auto-cleared when data have
+ * been transferred.
+ */
+#define UDR_READ_RETRY_CNT     5
+
 struct s5m_rtc_info {
        struct device *dev;
        struct sec_pmic_dev *s5m87xx;
-       struct regmap *rtc;
+       struct regmap *regmap;
        struct rtc_device *rtc_dev;
        int irq;
        int device_type;
@@ -84,12 +94,31 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
        }
 }
 
+/*
+ * Read RTC_UDR_CON register and wait till UDR field is cleared.
+ * This indicates that time/alarm update ended.
+ */
+static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
+{
+       int ret, retry = UDR_READ_RETRY_CNT;
+       unsigned int data;
+
+       do {
+               ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
+       } while (--retry && (data & RTC_UDR_MASK) && !ret);
+
+       if (!retry)
+               dev_err(info->dev, "waiting for UDR update, reached max number of retries\n");
+
+       return ret;
+}
+
 static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 {
        int ret;
        unsigned int data;
 
-       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
        if (ret < 0) {
                dev_err(info->dev, "failed to read update reg(%d)\n", ret);
                return ret;
@@ -98,15 +127,13 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
        data |= RTC_TIME_EN_MASK;
        data |= RTC_UDR_MASK;
 
-       ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data);
+       ret = regmap_write(info->regmap, SEC_RTC_UDR_CON, data);
        if (ret < 0) {
                dev_err(info->dev, "failed to write update reg(%d)\n", ret);
                return ret;
        }
 
-       do {
-               ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
-       } while ((data & RTC_UDR_MASK) && !ret);
+       ret = s5m8767_wait_for_udr_update(info);
 
        return ret;
 }
@@ -116,7 +143,7 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
        int ret;
        unsigned int data;
 
-       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
+       ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &data);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to read update reg(%d)\n",
                        __func__, ret);
@@ -126,16 +153,14 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
        data &= ~RTC_TIME_EN_MASK;
        data |= RTC_UDR_MASK;
 
-       ret = regmap_write(info->rtc, SEC_RTC_UDR_CON, data);
+       ret = regmap_write(info->regmap, SEC_RTC_UDR_CON, data);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to write update reg(%d)\n",
                        __func__, ret);
                return ret;
        }
 
-       do {
-               ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &data);
-       } while ((data & RTC_UDR_MASK) && !ret);
+       ret = s5m8767_wait_for_udr_update(info);
 
        return ret;
 }
@@ -178,7 +203,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
        u8 data[8];
        int ret;
 
-       ret = regmap_bulk_read(info->rtc, SEC_RTC_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_RTC_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -226,7 +251,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
                1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
                tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
 
-       ret = regmap_raw_write(info->rtc, SEC_RTC_SEC, data, 8);
+       ret = regmap_raw_write(info->regmap, SEC_RTC_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -242,20 +267,20 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        unsigned int val;
        int ret, i;
 
-       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
        switch (info->device_type) {
        case S5M8763X:
                s5m8763_data_to_tm(data, &alrm->time);
-               ret = regmap_read(info->rtc, SEC_ALARM0_CONF, &val);
+               ret = regmap_read(info->regmap, SEC_ALARM0_CONF, &val);
                if (ret < 0)
                        return ret;
 
                alrm->enabled = !!val;
 
-               ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val);
+               ret = regmap_read(info->regmap, SEC_RTC_STATUS, &val);
                if (ret < 0)
                        return ret;
 
@@ -278,7 +303,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                }
 
                alrm->pending = 0;
-               ret = regmap_read(info->rtc, SEC_RTC_STATUS, &val);
+               ret = regmap_read(info->regmap, SEC_RTC_STATUS, &val);
                if (ret < 0)
                        return ret;
                break;
@@ -301,7 +326,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
        int ret, i;
        struct rtc_time tm;
 
-       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -312,14 +337,14 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
 
        switch (info->device_type) {
        case S5M8763X:
-               ret = regmap_write(info->rtc, SEC_ALARM0_CONF, 0);
+               ret = regmap_write(info->regmap, SEC_ALARM0_CONF, 0);
                break;
 
        case S5M8767X:
                for (i = 0; i < 7; i++)
                        data[i] &= ~ALARM_ENABLE_MASK;
 
-               ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+               ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8);
                if (ret < 0)
                        return ret;
 
@@ -341,7 +366,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
        u8 alarm0_conf;
        struct rtc_time tm;
 
-       ret = regmap_bulk_read(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_bulk_read(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -353,7 +378,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
        switch (info->device_type) {
        case S5M8763X:
                alarm0_conf = 0x77;
-               ret = regmap_write(info->rtc, SEC_ALARM0_CONF, alarm0_conf);
+               ret = regmap_write(info->regmap, SEC_ALARM0_CONF, alarm0_conf);
                break;
 
        case S5M8767X:
@@ -368,7 +393,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
                if (data[RTC_YEAR1] & 0x7f)
                        data[RTC_YEAR1] |= ALARM_ENABLE_MASK;
 
-               ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+               ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8);
                if (ret < 0)
                        return ret;
                ret = s5m8767_rtc_set_alarm_reg(info);
@@ -410,7 +435,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        if (ret < 0)
                return ret;
 
-       ret = regmap_raw_write(info->rtc, SEC_ALARM0_SEC, data, 8);
+       ret = regmap_raw_write(info->regmap, SEC_ALARM0_SEC, data, 8);
        if (ret < 0)
                return ret;
 
@@ -455,7 +480,7 @@ static const struct rtc_class_ops s5m_rtc_ops = {
 static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
 {
        int ret;
-       ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL,
+       ret = regmap_update_bits(info->regmap, SEC_WTSR_SMPL_CNTL,
                                 WTSR_ENABLE_MASK,
                                 enable ? WTSR_ENABLE_MASK : 0);
        if (ret < 0)
@@ -466,7 +491,7 @@ static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
 static void s5m_rtc_enable_smpl(struct s5m_rtc_info *info, bool enable)
 {
        int ret;
-       ret = regmap_update_bits(info->rtc, SEC_WTSR_SMPL_CNTL,
+       ret = regmap_update_bits(info->regmap, SEC_WTSR_SMPL_CNTL,
                                 SMPL_ENABLE_MASK,
                                 enable ? SMPL_ENABLE_MASK : 0);
        if (ret < 0)
@@ -481,7 +506,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
        int ret;
        struct rtc_time tm;
 
-       ret = regmap_read(info->rtc, SEC_RTC_UDR_CON, &tp_read);
+       ret = regmap_read(info->regmap, SEC_RTC_UDR_CON, &tp_read);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to read control reg(%d)\n",
                        __func__, ret);
@@ -493,7 +518,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
        data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
 
        info->rtc_24hr_mode = 1;
-       ret = regmap_raw_write(info->rtc, SEC_ALARM0_CONF, data, 2);
+       ret = regmap_raw_write(info->regmap, SEC_ALARM0_CONF, data, 2);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
                        __func__, ret);
@@ -515,7 +540,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
                ret = s5m_rtc_set_time(info->dev, &tm);
        }
 
-       ret = regmap_update_bits(info->rtc, SEC_RTC_UDR_CON,
+       ret = regmap_update_bits(info->regmap, SEC_RTC_UDR_CON,
                                 RTC_TCON_MASK, tp_read | RTC_TCON_MASK);
        if (ret < 0)
                dev_err(info->dev, "%s: fail to update TCON reg(%d)\n",
@@ -542,17 +567,19 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 
        info->dev = &pdev->dev;
        info->s5m87xx = s5m87xx;
-       info->rtc = s5m87xx->rtc;
+       info->regmap = s5m87xx->regmap_rtc;
        info->device_type = s5m87xx->device_type;
        info->wtsr_smpl = s5m87xx->wtsr_smpl;
 
        switch (pdata->device_type) {
        case S5M8763X:
-               info->irq = s5m87xx->irq_base + S5M8763_IRQ_ALARM0;
+               info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
+                               S5M8763_IRQ_ALARM0);
                break;
 
        case S5M8767X:
-               info->irq = s5m87xx->irq_base + S5M8767_IRQ_RTCA1;
+               info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
+                               S5M8767_IRQ_RTCA1);
                break;
 
        default:
@@ -596,7 +623,7 @@ static void s5m_rtc_shutdown(struct platform_device *pdev)
        if (info->wtsr_smpl) {
                for (i = 0; i < 3; i++) {
                        s5m_rtc_enable_wtsr(info, false);
-                       regmap_read(info->rtc, SEC_WTSR_SMPL_CNTL, &val);
+                       regmap_read(info->regmap, SEC_WTSR_SMPL_CNTL, &val);
                        pr_debug("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val);
                        if (val & WTSR_ENABLE_MASK)
                                pr_emerg("%s: fail to disable WTSR\n",
@@ -612,6 +639,30 @@ static void s5m_rtc_shutdown(struct platform_device *pdev)
        s5m_rtc_enable_smpl(info, false);
 }
 
+static int s5m_rtc_resume(struct device *dev)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (device_may_wakeup(dev))
+               ret = disable_irq_wake(info->irq);
+
+       return ret;
+}
+
+static int s5m_rtc_suspend(struct device *dev)
+{
+       struct s5m_rtc_info *info = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (device_may_wakeup(dev))
+               ret = enable_irq_wake(info->irq);
+
+       return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
+
 static const struct platform_device_id s5m_rtc_id[] = {
        { "s5m-rtc", 0 },
 };
@@ -620,6 +671,7 @@ static struct platform_driver s5m_rtc_driver = {
        .driver         = {
                .name   = "s5m-rtc",
                .owner  = THIS_MODULE,
+               .pm     = &s5m_rtc_pm_ops,
        },
        .probe          = s5m_rtc_probe,
        .shutdown       = s5m_rtc_shutdown,
index f302efa937ef042412bf8b3c0df1585542ee12de..1eef0f586950b6014ab46a60170a2ccf74f0a299 100644 (file)
@@ -3386,7 +3386,7 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
 
        if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) {
                /*
-                * safe offline allready running
+                * safe offline already running
                 * could only be called by normal offline so safe_offline flag
                 * needs to be removed to run normal offline and kill all I/O
                 */
index f64921756ad610375134b3b59f13bbdb5d9906af..f224d59c4b6be35b8a5d827dde6cdc173953f3f5 100644 (file)
@@ -87,7 +87,6 @@ void dasd_gendisk_free(struct dasd_block *block)
 {
        if (block->gdp) {
                del_gendisk(block->gdp);
-               block->gdp->queue = NULL;
                block->gdp->private_data = NULL;
                put_disk(block->gdp);
                block->gdp = NULL;
index 6fbe09686d18fc1024fb3f1151914fc69abaa394..fea76aed9eea41c0c9dec84b59ab585cb703fea9 100644 (file)
@@ -183,7 +183,6 @@ extern unsigned long sclp_console_full;
 extern u8 sclp_fac84;
 extern unsigned long long sclp_rzm;
 extern unsigned long long sclp_rnmax;
-extern __initdata int sclp_early_read_info_sccb_valid;
 
 /* useful inlines */
 
index eaa21d542c5cb102c19753eeec8abd2fff719cf0..cb3c4e05a38503c043f35f1f9a70bc8f186e929f 100644 (file)
@@ -455,8 +455,6 @@ static int __init sclp_detect_standby_memory(void)
 
        if (OLDMEM_BASE) /* No standby memory in kdump mode */
                return 0;
-       if (!sclp_early_read_info_sccb_valid)
-               return 0;
        if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL)
                return 0;
        rc = -ENOMEM;
index f7aa080e9b28db1d5b962de7b5380f60ae97cc10..82f2c389b4d1f51e882de45cd5e0fadfa3405f3e 100644 (file)
@@ -35,12 +35,12 @@ struct read_info_sccb {
        u8      _reserved5[4096 - 112]; /* 112-4095 */
 } __packed __aligned(PAGE_SIZE);
 
-static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE);
-static __initdata struct read_info_sccb early_read_info_sccb;
-static __initdata char sccb_early[PAGE_SIZE] __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 struct sclp_ipl_info sclp_ipl_info;
 
-__initdata int sclp_early_read_info_sccb_valid;
 u64 sclp_facilities;
 u8 sclp_fac84;
 unsigned long long sclp_rzm;
@@ -64,15 +64,12 @@ out:
        return rc;
 }
 
-static void __init sclp_read_info_early(void)
+static int __init sclp_read_info_early(struct read_info_sccb *sccb)
 {
-       int rc;
-       int i;
-       struct read_info_sccb *sccb;
+       int rc, i;
        sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
                                  SCLP_CMDW_READ_SCP_INFO};
 
-       sccb = &early_read_info_sccb;
        for (i = 0; i < ARRAY_SIZE(commands); i++) {
                do {
                        memset(sccb, 0, sizeof(*sccb));
@@ -84,24 +81,19 @@ static void __init sclp_read_info_early(void)
 
                if (rc)
                        break;
-               if (sccb->header.response_code == 0x10) {
-                       sclp_early_read_info_sccb_valid = 1;
-                       break;
-               }
+               if (sccb->header.response_code == 0x10)
+                       return 0;
                if (sccb->header.response_code != 0x1f0)
                        break;
        }
+       return -EIO;
 }
 
-static void __init sclp_facilities_detect(void)
+static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
 {
-       struct read_info_sccb *sccb;
-
-       sclp_read_info_early();
-       if (!sclp_early_read_info_sccb_valid)
+       if (sclp_read_info_early(sccb))
                return;
 
-       sccb = &early_read_info_sccb;
        sclp_facilities = sccb->facilities;
        sclp_fac84 = sccb->fac84;
        if (sccb->fac85 & 0x02)
@@ -109,30 +101,22 @@ static void __init sclp_facilities_detect(void)
        sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
        sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
        sclp_rzm <<= 20;
+
+       /* Save IPL information */
+       sclp_ipl_info.is_valid = 1;
+       if (sccb->flags & 0x2)
+               sclp_ipl_info.has_dump = 1;
+       memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN);
 }
 
 bool __init sclp_has_linemode(void)
 {
-       struct init_sccb *sccb = &early_event_mask_sccb;
-
-       if (sccb->header.response_code != 0x20)
-               return 0;
-       if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK)))
-               return 0;
-       if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
-               return 0;
-       return 1;
+       return !!sclp_con_has_linemode;
 }
 
 bool __init sclp_has_vt220(void)
 {
-       struct init_sccb *sccb = &early_event_mask_sccb;
-
-       if (sccb->header.response_code != 0x20)
-               return 0;
-       if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
-               return 1;
-       return 0;
+       return !!sclp_con_has_vt220;
 }
 
 unsigned long long sclp_get_rnmax(void)
@@ -147,19 +131,12 @@ unsigned long long sclp_get_rzm(void)
 
 /*
  * This function will be called after sclp_facilities_detect(), which gets
- * called from early.c code. Therefore the sccb should have valid contents.
+ * called from early.c code. The sclp_facilities_detect() function retrieves
+ * and saves the IPL information.
  */
 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
 {
-       struct read_info_sccb *sccb;
-
-       if (!sclp_early_read_info_sccb_valid)
-               return;
-       sccb = &early_read_info_sccb;
-       info->is_valid = 1;
-       if (sccb->flags & 0x2)
-               info->has_dump = 1;
-       memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
+       *info = sclp_ipl_info;
 }
 
 static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb)
@@ -190,11 +167,10 @@ static void __init sccb_init_eq_size(struct sdias_sccb *sccb)
        sccb->evbuf.dbs = 1;
 }
 
-static int __init sclp_set_event_mask(unsigned long receive_mask,
+static int __init sclp_set_event_mask(struct init_sccb *sccb,
+                                     unsigned long receive_mask,
                                      unsigned long send_mask)
 {
-       struct init_sccb *sccb = (void *) &sccb_early;
-
        memset(sccb, 0, sizeof(*sccb));
        sccb->header.length = sizeof(*sccb);
        sccb->mask_length = sizeof(sccb_mask_t);
@@ -203,10 +179,8 @@ static int __init sclp_set_event_mask(unsigned long receive_mask,
        return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
 }
 
-static long __init sclp_hsa_size_init(void)
+static long __init sclp_hsa_size_init(struct sdias_sccb *sccb)
 {
-       struct sdias_sccb *sccb = (void *) &sccb_early;
-
        sccb_init_eq_size(sccb);
        if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
                return -EIO;
@@ -215,10 +189,8 @@ static long __init sclp_hsa_size_init(void)
        return 0;
 }
 
-static long __init sclp_hsa_copy_wait(void)
+static long __init sclp_hsa_copy_wait(struct sccb_header *sccb)
 {
-       struct sccb_header *sccb = (void *) &sccb_early;
-
        memset(sccb, 0, PAGE_SIZE);
        sccb->length = PAGE_SIZE;
        if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
@@ -231,34 +203,62 @@ unsigned long sclp_get_hsa_size(void)
        return sclp_hsa_size;
 }
 
-static void __init sclp_hsa_size_detect(void)
+static void __init sclp_hsa_size_detect(void *sccb)
 {
        long size;
 
        /* First try synchronous interface (LPAR) */
-       if (sclp_set_event_mask(0, 0x40000010))
+       if (sclp_set_event_mask(sccb, 0, 0x40000010))
                return;
-       size = sclp_hsa_size_init();
+       size = sclp_hsa_size_init(sccb);
        if (size < 0)
                return;
        if (size != 0)
                goto out;
        /* Then try asynchronous interface (z/VM) */
-       if (sclp_set_event_mask(0x00000010, 0x40000010))
+       if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010))
                return;
-       size = sclp_hsa_size_init();
+       size = sclp_hsa_size_init(sccb);
        if (size < 0)
                return;
-       size = sclp_hsa_copy_wait();
+       size = sclp_hsa_copy_wait(sccb);
        if (size < 0)
                return;
 out:
        sclp_hsa_size = size;
 }
 
+static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb)
+{
+       if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK)))
+               return 0;
+       if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
+               return 0;
+       return 1;
+}
+
+static void __init sclp_console_detect(struct init_sccb *sccb)
+{
+       if (sccb->header.response_code != 0x20)
+               return;
+
+       if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
+               sclp_con_has_vt220 = 1;
+
+       if (sclp_con_check_linemode(sccb))
+               sclp_con_has_linemode = 1;
+}
+
 void __init sclp_early_detect(void)
 {
-       sclp_facilities_detect();
-       sclp_hsa_size_detect();
-       sclp_set_event_mask(0, 0);
+       void *sccb = &sccb_early;
+
+       sclp_facilities_detect(sccb);
+       sclp_hsa_size_detect(sccb);
+
+       /* Turn off SCLP event notifications.  Also save remote masks in the
+        * sccb.  These are sufficient to detect sclp console capabilities.
+        */
+       sclp_set_event_mask(sccb, 0, 0);
+       sclp_console_detect(sccb);
 }
index 3f4ca4e09a4ccc4d49fba39d64094fafe1f1fdc7..e91b89dc6d1f61878e9191c8f66b7a90e32acd44 100644 (file)
@@ -125,10 +125,7 @@ static void tty3270_resize_work(struct work_struct *work);
  */
 static void tty3270_set_timer(struct tty3270 *tp, int expires)
 {
-       if (expires == 0)
-               del_timer(&tp->timer);
-       else
-               mod_timer(&tp->timer, jiffies + expires);
+       mod_timer(&tp->timer, jiffies + expires);
 }
 
 /*
@@ -744,7 +741,6 @@ tty3270_free_view(struct tty3270 *tp)
 {
        int pages;
 
-       del_timer_sync(&tp->timer);
        kbd_free(tp->kbd);
        raw3270_request_free(tp->kreset);
        raw3270_request_free(tp->read);
@@ -877,6 +873,7 @@ tty3270_free(struct raw3270_view *view)
 {
        struct tty3270 *tp = container_of(view, struct tty3270, view);
 
+       del_timer_sync(&tp->timer);
        tty3270_free_screen(tp->screen, tp->view.rows);
        tty3270_free_view(tp);
 }
@@ -942,7 +939,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
                return rc;
        }
 
-       tp->screen = tty3270_alloc_screen(tp->view.cols, tp->view.rows);
+       tp->screen = tty3270_alloc_screen(tp->view.rows, tp->view.cols);
        if (IS_ERR(tp->screen)) {
                rc = PTR_ERR(tp->screen);
                raw3270_put_view(&tp->view);
index a9fe3de2dec17fcce1717d99389468dfc46f4f98..b3f791b2c1f8994de2287052275fc8853b3b946a 100644 (file)
@@ -260,16 +260,16 @@ static int blacklist_parse_proc_parameters(char *buf)
 
        parm = strsep(&buf, " ");
 
-       if (strcmp("free", parm) == 0)
+       if (strcmp("free", parm) == 0) {
                rc = blacklist_parse_parameters(buf, free, 0);
-       else if (strcmp("add", parm) == 0)
+               css_schedule_eval_all_unreg(0);
+       } else if (strcmp("add", parm) == 0)
                rc = blacklist_parse_parameters(buf, add, 0);
        else if (strcmp("purge", parm) == 0)
                return ccw_purge_blacklisted();
        else
                return -EINVAL;
 
-       css_schedule_reprobe();
 
        return rc;
 }
index 959135a01847940a5ecee33ae902b83cf8ecfe44..fd3367a1dc7a0bc59cca626e5b7ada39a56bb39c 100644 (file)
@@ -128,14 +128,14 @@ static ssize_t ccwgroup_online_store(struct device *dev,
                                     const char *buf, size_t count)
 {
        struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
-       struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
        unsigned long value;
        int ret;
 
-       if (!dev->driver)
-               return -EINVAL;
-       if (!try_module_get(gdrv->driver.owner))
-               return -EINVAL;
+       device_lock(dev);
+       if (!dev->driver) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        ret = kstrtoul(buf, 0, &value);
        if (ret)
@@ -148,7 +148,7 @@ static ssize_t ccwgroup_online_store(struct device *dev,
        else
                ret = -EINVAL;
 out:
-       module_put(gdrv->driver.owner);
+       device_unlock(dev);
        return (ret == 0) ? count : ret;
 }
 
index 13299f902676e647d43dce13d95f864c81300f53..f6b9188c5af581b8c0d587932c5de1af5d996951 100644 (file)
@@ -55,6 +55,7 @@ int chsc_error_from_response(int response)
        case 0x0004:
                return -EOPNOTSUPP;
        case 0x000b:
+       case 0x0107:            /* "Channel busy" for the op 0x003d */
                return -EBUSY;
        case 0x0100:
        case 0x0102:
@@ -237,26 +238,6 @@ void chsc_chp_offline(struct chp_id chpid)
        for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
 }
 
-static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
-{
-       struct schib schib;
-       /*
-        * We don't know the device yet, but since a path
-        * may be available now to the device we'll have
-        * to do recognition again.
-        * Since we don't have any idea about which chpid
-        * that beast may be on we'll have to do a stsch
-        * on all devices, grr...
-        */
-       if (stsch_err(schid, &schib))
-               /* We're through */
-               return -ENXIO;
-
-       /* Put it on the slow path. */
-       css_schedule_eval(schid);
-       return 0;
-}
-
 static int __s390_process_res_acc(struct subchannel *sch, void *data)
 {
        spin_lock_irq(sch->lock);
@@ -287,8 +268,8 @@ static void s390_process_res_acc(struct chp_link *link)
         * The more information we have (info), the less scanning
         * will we have to do.
         */
-       for_each_subchannel_staged(__s390_process_res_acc,
-                                  s390_process_res_acc_new_sch, link);
+       for_each_subchannel_staged(__s390_process_res_acc, NULL, link);
+       css_schedule_reprobe();
 }
 
 static int
@@ -663,19 +644,6 @@ static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data)
        return 0;
 }
 
-static int
-__s390_vary_chpid_on(struct subchannel_id schid, void *data)
-{
-       struct schib schib;
-
-       if (stsch_err(schid, &schib))
-               /* We're through */
-               return -ENXIO;
-       /* Put it on the slow path. */
-       css_schedule_eval(schid);
-       return 0;
-}
-
 /**
  * chsc_chp_vary - propagate channel-path vary operation to subchannels
  * @chpid: channl-path ID
@@ -694,7 +662,8 @@ int chsc_chp_vary(struct chp_id chpid, int on)
                /* Try to update the channel path description. */
                chp_update_desc(chp);
                for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
-                                          __s390_vary_chpid_on, &chpid);
+                                          NULL, &chpid);
+               css_schedule_reprobe();
        } else
                for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
                                           NULL, &chpid);
@@ -1234,3 +1203,35 @@ out:
        return ret;
 }
 EXPORT_SYMBOL_GPL(chsc_scm_info);
+
+/**
+ * chsc_pnso_brinfo() - Perform Network-Subchannel Operation, Bridge Info.
+ * @schid:             id of the subchannel on which PNSO is performed
+ * @brinfo_area:       request and response block for the operation
+ * @resume_token:      resume token for multiblock response
+ * @cnc:               Boolean change-notification control
+ *
+ * brinfo_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
+ *
+ * Returns 0 on success.
+ */
+int chsc_pnso_brinfo(struct subchannel_id schid,
+               struct chsc_pnso_area *brinfo_area,
+               struct chsc_brinfo_resume_token resume_token,
+               int cnc)
+{
+       memset(brinfo_area, 0, sizeof(*brinfo_area));
+       brinfo_area->request.length = 0x0030;
+       brinfo_area->request.code = 0x003d; /* network-subchannel operation */
+       brinfo_area->m     = schid.m;
+       brinfo_area->ssid  = schid.ssid;
+       brinfo_area->sch   = schid.sch_no;
+       brinfo_area->cssid = schid.cssid;
+       brinfo_area->oc    = 0; /* Store-network-bridging-information list */
+       brinfo_area->resume_token = resume_token;
+       brinfo_area->n     = (cnc != 0);
+       if (chsc(brinfo_area))
+               return -EIO;
+       return chsc_error_from_response(brinfo_area->response.code);
+}
+EXPORT_SYMBOL_GPL(chsc_pnso_brinfo);
index 23d072e70eb2f4e87e1a9dbefcd244c35a98b977..7e53a9c8b0b991fce45e9cc488ddcc73a0e14be4 100644 (file)
@@ -61,7 +61,9 @@ struct css_chsc_char {
        u32 : 20;
        u32 scssc : 1;  /* bit 107 */
        u32 scsscf : 1; /* bit 108 */
-       u32 : 19;
+       u32:7;
+       u32 pnso:1; /* bit 116 */
+       u32:11;
 }__attribute__((packed));
 
 extern struct css_chsc_char css_chsc_characteristics;
@@ -188,6 +190,53 @@ struct chsc_scm_info {
 
 int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
 
+struct chsc_brinfo_resume_token {
+       u64 t1;
+       u64 t2;
+} __packed;
+
+struct chsc_brinfo_naihdr {
+       struct chsc_brinfo_resume_token resume_token;
+       u32:32;
+       u32 instance;
+       u32:24;
+       u8 naids;
+       u32 reserved[3];
+} __packed;
+
+struct chsc_pnso_area {
+       struct chsc_header request;
+       u8:2;
+       u8 m:1;
+       u8:5;
+       u8:2;
+       u8 ssid:2;
+       u8 fmt:4;
+       u16 sch;
+       u8:8;
+       u8 cssid;
+       u16:16;
+       u8 oc;
+       u32:24;
+       struct chsc_brinfo_resume_token resume_token;
+       u32 n:1;
+       u32:31;
+       u32 reserved[3];
+       struct chsc_header response;
+       u32:32;
+       struct chsc_brinfo_naihdr naihdr;
+       union {
+               struct qdio_brinfo_entry_l3_ipv6 l3_ipv6[0];
+               struct qdio_brinfo_entry_l3_ipv4 l3_ipv4[0];
+               struct qdio_brinfo_entry_l2      l2[0];
+       } entries;
+} __packed;
+
+int chsc_pnso_brinfo(struct subchannel_id schid,
+               struct chsc_pnso_area *brinfo_area,
+               struct chsc_brinfo_resume_token resume_token,
+               int cnc);
+
 #ifdef CONFIG_SCM_BUS
 int scm_update_information(void);
 int scm_process_availability_information(void);
index 8c2cb87bccc5d8b1a195ff1dc43181309aa75d82..0268e5fd59b5522fe1d61dbf90ddf17ed4e2df1f 100644 (file)
@@ -69,7 +69,8 @@ static int call_fn_known_sch(struct device *dev, void *data)
        struct cb_data *cb = data;
        int rc = 0;
 
-       idset_sch_del(cb->set, sch->schid);
+       if (cb->set)
+               idset_sch_del(cb->set, sch->schid);
        if (cb->fn_known_sch)
                rc = cb->fn_known_sch(sch, cb->data);
        return rc;
@@ -115,6 +116,13 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
        cb.fn_known_sch = fn_known;
        cb.fn_unknown_sch = fn_unknown;
 
+       if (fn_known && !fn_unknown) {
+               /* Skip idset allocation in case of known-only loop. */
+               cb.set = NULL;
+               return bus_for_each_dev(&css_bus_type, NULL, &cb,
+                                       call_fn_known_sch);
+       }
+
        cb.set = idset_sch_new();
        if (!cb.set)
                /* fall back to brute force scanning in case of oom */
@@ -553,6 +561,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
                default:
                        rc = 0;
                }
+               /* Allow scheduling here since the containing loop might
+                * take a while.  */
+               cond_resched();
        }
        return rc;
 }
@@ -572,7 +583,7 @@ static void css_slow_path_func(struct work_struct *unused)
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
-static DECLARE_WORK(slow_path_work, css_slow_path_func);
+static DECLARE_DELAYED_WORK(slow_path_work, css_slow_path_func);
 struct workqueue_struct *cio_work_q;
 
 void css_schedule_eval(struct subchannel_id schid)
@@ -582,7 +593,7 @@ void css_schedule_eval(struct subchannel_id schid)
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        idset_sch_add(slow_subchannel_set, schid);
        atomic_set(&css_eval_scheduled, 1);
-       queue_work(cio_work_q, &slow_path_work);
+       queue_delayed_work(cio_work_q, &slow_path_work, 0);
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
@@ -593,7 +604,7 @@ void css_schedule_eval_all(void)
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        idset_fill(slow_subchannel_set);
        atomic_set(&css_eval_scheduled, 1);
-       queue_work(cio_work_q, &slow_path_work);
+       queue_delayed_work(cio_work_q, &slow_path_work, 0);
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
@@ -606,7 +617,7 @@ static int __unset_registered(struct device *dev, void *data)
        return 0;
 }
 
-static void css_schedule_eval_all_unreg(void)
+void css_schedule_eval_all_unreg(unsigned long delay)
 {
        unsigned long flags;
        struct idset *unreg_set;
@@ -624,7 +635,7 @@ static void css_schedule_eval_all_unreg(void)
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        idset_add_set(slow_subchannel_set, unreg_set);
        atomic_set(&css_eval_scheduled, 1);
-       queue_work(cio_work_q, &slow_path_work);
+       queue_delayed_work(cio_work_q, &slow_path_work, delay);
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
        idset_free(unreg_set);
 }
@@ -637,7 +648,8 @@ void css_wait_for_slow_path(void)
 /* Schedule reprobing of all unregistered subchannels. */
 void css_schedule_reprobe(void)
 {
-       css_schedule_eval_all_unreg();
+       /* Schedule with a delay to allow merging of subsequent calls. */
+       css_schedule_eval_all_unreg(1 * HZ);
 }
 EXPORT_SYMBOL_GPL(css_schedule_reprobe);
 
index 29351321bad6c73b97cdfc490c1d5d71ae12e6ce..2c9107e2025143b34fc5da2be3118b0fe013e7c9 100644 (file)
@@ -133,6 +133,7 @@ extern struct channel_subsystem *channel_subsystems[];
 /* Helper functions to build lists for the slow path. */
 void css_schedule_eval(struct subchannel_id schid);
 void css_schedule_eval_all(void);
+void css_schedule_eval_all_unreg(unsigned long delay);
 int css_complete_work(void);
 
 int sch_is_pseudo_sch(struct subchannel *);
index e4a7ab2bb629f76358896e1389072c391fe3504c..e9d783563cbb8894182efcfde40376eb731d286b 100644 (file)
@@ -333,9 +333,9 @@ int ccw_device_set_offline(struct ccw_device *cdev)
                if (ret != 0)
                        return ret;
        }
-       cdev->online = 0;
        spin_lock_irq(cdev->ccwlock);
        sch = to_subchannel(cdev->dev.parent);
+       cdev->online = 0;
        /* Wait until a final state or DISCONNECTED is reached */
        while (!dev_fsm_final_state(cdev) &&
               cdev->private->state != DEV_STATE_DISCONNECTED) {
@@ -446,7 +446,10 @@ int ccw_device_set_online(struct ccw_device *cdev)
                ret = cdev->drv->set_online(cdev);
        if (ret)
                goto rollback;
+
+       spin_lock_irq(cdev->ccwlock);
        cdev->online = 1;
+       spin_unlock_irq(cdev->ccwlock);
        return 0;
 
 rollback:
@@ -546,17 +549,12 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
        if (!dev_fsm_final_state(cdev) &&
            cdev->private->state != DEV_STATE_DISCONNECTED) {
                ret = -EAGAIN;
-               goto out_onoff;
+               goto out;
        }
        /* Prevent conflict between pending work and on-/offline processing.*/
        if (work_pending(&cdev->private->todo_work)) {
                ret = -EAGAIN;
-               goto out_onoff;
-       }
-
-       if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) {
-               ret = -EINVAL;
-               goto out_onoff;
+               goto out;
        }
        if (!strncmp(buf, "force\n", count)) {
                force = 1;
@@ -568,6 +566,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
        }
        if (ret)
                goto out;
+
+       device_lock(dev);
        switch (i) {
        case 0:
                ret = online_store_handle_offline(cdev);
@@ -578,10 +578,9 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
        default:
                ret = -EINVAL;
        }
+       device_unlock(dev);
+
 out:
-       if (cdev->drv)
-               module_put(cdev->drv->driver.owner);
-out_onoff:
        atomic_set(&cdev->private->onoff, 0);
        return (ret < 0) ? ret : count;
 }
@@ -1745,8 +1744,7 @@ ccw_device_probe (struct device *dev)
        return 0;
 }
 
-static int
-ccw_device_remove (struct device *dev)
+static int ccw_device_remove(struct device *dev)
 {
        struct ccw_device *cdev = to_ccwdev(dev);
        struct ccw_driver *cdrv = cdev->drv;
@@ -1754,9 +1752,10 @@ ccw_device_remove (struct device *dev)
 
        if (cdrv->remove)
                cdrv->remove(cdev);
+
+       spin_lock_irq(cdev->ccwlock);
        if (cdev->online) {
                cdev->online = 0;
-               spin_lock_irq(cdev->ccwlock);
                ret = ccw_device_offline(cdev);
                spin_unlock_irq(cdev->ccwlock);
                if (ret == 0)
@@ -1769,10 +1768,12 @@ ccw_device_remove (struct device *dev)
                                      cdev->private->dev_id.devno);
                /* Give up reference obtained in ccw_device_set_online(). */
                put_device(&cdev->dev);
+               spin_lock_irq(cdev->ccwlock);
        }
        ccw_device_set_timeout(cdev, 0);
        cdev->drv = NULL;
        cdev->private->int_class = IRQIO_CIO;
+       spin_unlock_irq(cdev->ccwlock);
        return 0;
 }
 
index 3e602e8affa78cba97282e41c5f9e3a18315e45b..c883a085c0591cd8a0673d495f36e74f9f6e0427 100644 (file)
@@ -1752,6 +1752,97 @@ int qdio_stop_irq(struct ccw_device *cdev, int nr)
 }
 EXPORT_SYMBOL(qdio_stop_irq);
 
+/**
+ * qdio_pnso_brinfo() - perform network subchannel op #0 - bridge info.
+ * @schid:             Subchannel ID.
+ * @cnc:               Boolean Change-Notification Control
+ * @response:          Response code will be stored at this address
+ * @cb:                Callback function will be executed for each element
+ *                     of the address list
+ * @priv:              Pointer passed from the caller to qdio_pnso_brinfo()
+ * @type:              Type of the address entry passed to the callback
+ * @entry:             Entry containg the address of the specified type
+ * @priv:              Pointer to pass to the callback function.
+ *
+ * Performs "Store-network-bridging-information list" operation and calls
+ * the callback function for every entry in the list. If "change-
+ * notification-control" is set, further changes in the address list
+ * will be reported via the IPA command.
+ */
+int qdio_pnso_brinfo(struct subchannel_id schid,
+               int cnc, u16 *response,
+               void (*cb)(void *priv, enum qdio_brinfo_entry_type type,
+                               void *entry),
+               void *priv)
+{
+       struct chsc_pnso_area *rr;
+       int rc;
+       u32 prev_instance = 0;
+       int isfirstblock = 1;
+       int i, size, elems;
+
+       rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL);
+       if (rr == NULL)
+               return -ENOMEM;
+       do {
+               /* on the first iteration, naihdr.resume_token will be zero */
+               rc = chsc_pnso_brinfo(schid, rr, rr->naihdr.resume_token, cnc);
+               if (rc != 0 && rc != -EBUSY)
+                       goto out;
+               if (rr->response.code != 1) {
+                       rc = -EIO;
+                       continue;
+               } else
+                       rc = 0;
+
+               if (cb == NULL)
+                       continue;
+
+               size = rr->naihdr.naids;
+               elems = (rr->response.length -
+                               sizeof(struct chsc_header) -
+                               sizeof(struct chsc_brinfo_naihdr)) /
+                               size;
+
+               if (!isfirstblock && (rr->naihdr.instance != prev_instance)) {
+                       /* Inform the caller that they need to scrap */
+                       /* the data that was already reported via cb */
+                               rc = -EAGAIN;
+                               break;
+               }
+               isfirstblock = 0;
+               prev_instance = rr->naihdr.instance;
+               for (i = 0; i < elems; i++)
+                       switch (size) {
+                       case sizeof(struct qdio_brinfo_entry_l3_ipv6):
+                               (*cb)(priv, l3_ipv6_addr,
+                                               &rr->entries.l3_ipv6[i]);
+                               break;
+                       case sizeof(struct qdio_brinfo_entry_l3_ipv4):
+                               (*cb)(priv, l3_ipv4_addr,
+                                               &rr->entries.l3_ipv4[i]);
+                               break;
+                       case sizeof(struct qdio_brinfo_entry_l2):
+                               (*cb)(priv, l2_addr_lnid,
+                                               &rr->entries.l2[i]);
+                               break;
+                       default:
+                               WARN_ON_ONCE(1);
+                               rc = -EIO;
+                               goto out;
+                       }
+       } while (rr->response.code == 0x0107 ||  /* channel busy */
+                 (rr->response.code == 1 && /* list stored */
+                  /* resume token is non-zero => list incomplete */
+                  (rr->naihdr.resume_token.t1 || rr->naihdr.resume_token.t2)));
+       (*response) = rr->response.code;
+
+out:
+       free_page((unsigned long)rr);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(qdio_pnso_brinfo);
+
 static int __init init_QDIO(void)
 {
        int rc;
index 02300dcfac91f87397c030f11eab825d1361f393..ab3baa7f95082e0cabf03906354c69ae9ed8880b 100644 (file)
@@ -591,7 +591,13 @@ static int ap_init_queue(ap_qid_t qid)
                if (rc != -ENODEV && rc != -EBUSY)
                        break;
                if (i < AP_MAX_RESET - 1) {
-                       udelay(5);
+                       /* Time we are waiting until we give up (0.7sec * 90).
+                        * Since the actual request (in progress) will not
+                        * interrupted immediately for the reset command,
+                        * we have to be patient. In worst case we have to
+                        * wait 60sec + reset time (some msec).
+                        */
+                       schedule_timeout(AP_RESET_TIMEOUT);
                        status = ap_test_queue(qid, &dummy, &dummy);
                }
        }
@@ -992,6 +998,28 @@ static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
 
 static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
 
+static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf)
+{
+       if (ap_configuration != NULL) { /* QCI not supported */
+               if (test_facility(76)) { /* format 1 - 256 bit domain field */
+                       return snprintf(buf, PAGE_SIZE,
+                               "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+                       ap_configuration->adm[0], ap_configuration->adm[1],
+                       ap_configuration->adm[2], ap_configuration->adm[3],
+                       ap_configuration->adm[4], ap_configuration->adm[5],
+                       ap_configuration->adm[6], ap_configuration->adm[7]);
+               } else { /* format 0 - 16 bit domain field */
+                       return snprintf(buf, PAGE_SIZE, "%08x%08x\n",
+                       ap_configuration->adm[0], ap_configuration->adm[1]);
+                 }
+       } else {
+               return snprintf(buf, PAGE_SIZE, "not supported\n");
+         }
+}
+
+static BUS_ATTR(ap_control_domain_mask, 0444,
+               ap_control_domain_mask_show, NULL);
+
 static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
@@ -1077,6 +1105,7 @@ static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
 
 static struct bus_attribute *const ap_bus_attrs[] = {
        &bus_attr_ap_domain,
+       &bus_attr_ap_control_domain_mask,
        &bus_attr_config_time,
        &bus_attr_poll_thread,
        &bus_attr_ap_interrupts,
index 685f6cc022f92e929e60d865d817caca13269afb..6405ae24a7a69674ddc602d5bbef2a9ccd29d7bf 100644 (file)
@@ -33,7 +33,7 @@
 #define AP_DEVICES 64          /* Number of AP devices. */
 #define AP_DOMAINS 16          /* Number of AP domains. */
 #define AP_MAX_RESET 90                /* Maximum number of resets. */
-#define AP_RESET_TIMEOUT (HZ/2)        /* Time in ticks for reset timeouts. */
+#define AP_RESET_TIMEOUT (HZ*0.7)      /* Time in ticks for reset timeouts. */
 #define AP_CONFIG_TIME 30      /* Time in seconds between AP bus rescans. */
 #define AP_POLL_TIME 1         /* Time in ticks between receive polls. */
 
@@ -125,6 +125,8 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
 #define AP_FUNC_CRT4K 2
 #define AP_FUNC_COPRO 3
 #define AP_FUNC_ACCEL 4
+#define AP_FUNC_EP11  5
+#define AP_FUNC_APXA  6
 
 /*
  * AP reset flag states
index 31cfaa556072c0154373d0d3a7fbccb0b54a30e9..4b824b15194f6eb034c4dd2ef4a7f0ab3ee9c3b7 100644 (file)
@@ -44,6 +44,8 @@
 #include "zcrypt_debug.h"
 #include "zcrypt_api.h"
 
+#include "zcrypt_msgtype6.h"
+
 /*
  * Module description.
  */
@@ -554,9 +556,9 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
        spin_lock_bh(&zcrypt_device_lock);
        list_for_each_entry(zdev, &zcrypt_device_list, list) {
                if (!zdev->online || !zdev->ops->send_cprb ||
-                   (xcRB->user_defined != AUTOSELECT &&
-                       AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)
-                   )
+                  (zdev->ops->variant == MSGTYPE06_VARIANT_EP11) ||
+                  (xcRB->user_defined != AUTOSELECT &&
+                   AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined))
                        continue;
                zcrypt_device_get(zdev);
                get_device(&zdev->ap_dev->device);
@@ -581,6 +583,90 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
        return -ENODEV;
 }
 
+struct ep11_target_dev_list {
+       unsigned short          targets_num;
+       struct ep11_target_dev  *targets;
+};
+
+static bool is_desired_ep11dev(unsigned int dev_qid,
+                              struct ep11_target_dev_list dev_list)
+{
+       int n;
+
+       for (n = 0; n < dev_list.targets_num; n++, dev_list.targets++) {
+               if ((AP_QID_DEVICE(dev_qid) == dev_list.targets->ap_id) &&
+                   (AP_QID_QUEUE(dev_qid) == dev_list.targets->dom_id)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
+{
+       struct zcrypt_device *zdev;
+       bool autoselect = false;
+       int rc;
+       struct ep11_target_dev_list ep11_dev_list = {
+               .targets_num    =  0x00,
+               .targets        =  NULL,
+       };
+
+       ep11_dev_list.targets_num = (unsigned short) xcrb->targets_num;
+
+       /* empty list indicates autoselect (all available targets) */
+       if (ep11_dev_list.targets_num == 0)
+               autoselect = true;
+       else {
+               ep11_dev_list.targets = kcalloc((unsigned short)
+                                               xcrb->targets_num,
+                                               sizeof(struct ep11_target_dev),
+                                               GFP_KERNEL);
+               if (!ep11_dev_list.targets)
+                       return -ENOMEM;
+
+               if (copy_from_user(ep11_dev_list.targets,
+                                  (struct ep11_target_dev *)xcrb->targets,
+                                  xcrb->targets_num *
+                                  sizeof(struct ep11_target_dev)))
+                       return -EFAULT;
+       }
+
+       spin_lock_bh(&zcrypt_device_lock);
+       list_for_each_entry(zdev, &zcrypt_device_list, list) {
+               /* check if device is eligible */
+               if (!zdev->online ||
+                   zdev->ops->variant != MSGTYPE06_VARIANT_EP11)
+                       continue;
+
+               /* check if device is selected as valid target */
+               if (!is_desired_ep11dev(zdev->ap_dev->qid, ep11_dev_list) &&
+                   !autoselect)
+                       continue;
+
+               zcrypt_device_get(zdev);
+               get_device(&zdev->ap_dev->device);
+               zdev->request_count++;
+               __zcrypt_decrease_preference(zdev);
+               if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+                       spin_unlock_bh(&zcrypt_device_lock);
+                       rc = zdev->ops->send_ep11_cprb(zdev, xcrb);
+                       spin_lock_bh(&zcrypt_device_lock);
+                       module_put(zdev->ap_dev->drv->driver.owner);
+               } else {
+                       rc = -EAGAIN;
+                 }
+               zdev->request_count--;
+               __zcrypt_increase_preference(zdev);
+               put_device(&zdev->ap_dev->device);
+               zcrypt_device_put(zdev);
+               spin_unlock_bh(&zcrypt_device_lock);
+               return rc;
+       }
+       spin_unlock_bh(&zcrypt_device_lock);
+       return -ENODEV;
+}
+
 static long zcrypt_rng(char *buffer)
 {
        struct zcrypt_device *zdev;
@@ -784,6 +870,23 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                return rc;
        }
+       case ZSENDEP11CPRB: {
+               struct ep11_urb __user *uxcrb = (void __user *)arg;
+               struct ep11_urb xcrb;
+               if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
+                       return -EFAULT;
+               do {
+                       rc = zcrypt_send_ep11_cprb(&xcrb);
+               } while (rc == -EAGAIN);
+               /* on failure: retry once again after a requested rescan */
+               if ((rc == -ENODEV) && (zcrypt_process_rescan()))
+                       do {
+                               rc = zcrypt_send_ep11_cprb(&xcrb);
+                       } while (rc == -EAGAIN);
+               if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
+                       return -EFAULT;
+               return rc;
+       }
        case Z90STAT_STATUS_MASK: {
                char status[AP_DEVICES];
                zcrypt_status_mask(status);
index 89632919c993ab4ea436c8bf38ade793820de824..b3d496bfaa7eadd08aa27e15a26c0e177a507685 100644 (file)
@@ -74,6 +74,7 @@ struct ica_z90_status {
 #define ZCRYPT_CEX2A           6
 #define ZCRYPT_CEX3C           7
 #define ZCRYPT_CEX3A           8
+#define ZCRYPT_CEX4           10
 
 /**
  * Large random numbers are pulled in 4096 byte chunks from the crypto cards
@@ -89,6 +90,7 @@ struct zcrypt_ops {
        long (*rsa_modexpo_crt)(struct zcrypt_device *,
                                struct ica_rsa_modexpo_crt *);
        long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
+       long (*send_ep11_cprb)(struct zcrypt_device *, struct ep11_urb *);
        long (*rng)(struct zcrypt_device *, char *);
        struct list_head list;          /* zcrypt ops list. */
        struct module *owner;
index ce1226398ac996a13b0546ba11df3ccfee6fa272..569f8b1d86c05305501530b33d2fdfba84e114a9 100644 (file)
 #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE
 #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE
 
-#define CEX4_CLEANUP_TIME      (15*HZ)
+/* Waiting time for requests to be processed.
+ * Currently there are some types of request which are not deterministic.
+ * But the maximum time limit managed by the stomper code is set to 60sec.
+ * Hence we have to wait at least that time period.
+ */
+#define CEX4_CLEANUP_TIME      (61*HZ)
 
 static struct ap_device_id zcrypt_cex4_ids[] = {
        { AP_DEVICE(AP_DEVICE_TYPE_CEX4)  },
@@ -101,6 +106,19 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev)
                        zdev->speed_rating = CEX4C_SPEED_RATING;
                        zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
                                                           MSGTYPE06_VARIANT_DEFAULT);
+               } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_EP11)) {
+                       zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE);
+                       if (!zdev)
+                               return -ENOMEM;
+                       zdev->type_string = "CEX4P";
+                       zdev->user_space_type = ZCRYPT_CEX4;
+                       zdev->min_mod_size = CEX4C_MIN_MOD_SIZE;
+                       zdev->max_mod_size = CEX4C_MAX_MOD_SIZE;
+                       zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
+                       zdev->short_crt = 0;
+                       zdev->speed_rating = CEX4C_SPEED_RATING;
+                       zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
+                                                       MSGTYPE06_VARIANT_EP11);
                }
                break;
        }
index 0079b661721139e4f8ec7f58ef39bb99d08b045f..7b23f43c7b080cc81b4de94ed9016cc0d8a91546 100644 (file)
@@ -106,15 +106,15 @@ static inline int convert_error(struct zcrypt_device *zdev,
        //   REP88_ERROR_MESSAGE_TYPE           // '20' CEX2A
                /*
                 * To sent a message of the wrong type is a bug in the
-                * device driver. Warn about it, disable the device
+                * device driver. Send error msg, disable the device
                 * and then repeat the request.
                 */
-               WARN_ON(1);
                atomic_set(&zcrypt_rescan_req, 1);
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
                ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
-                              zdev->ap_dev->qid,
-                              zdev->online, ehdr->reply_code);
+                       zdev->ap_dev->qid, zdev->online, ehdr->reply_code);
                return -EAGAIN;
        case REP82_ERROR_TRANSPORT_FAIL:
        case REP82_ERROR_MACHINE_FAILURE:
@@ -122,15 +122,17 @@ static inline int convert_error(struct zcrypt_device *zdev,
                /* If a card fails disable it and repeat the request. */
                atomic_set(&zcrypt_rescan_req, 1);
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
                ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
-                              zdev->ap_dev->qid,
-                              zdev->online, ehdr->reply_code);
+                       zdev->ap_dev->qid, zdev->online, ehdr->reply_code);
                return -EAGAIN;
        default:
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
                ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
-                              zdev->ap_dev->qid,
-                              zdev->online, ehdr->reply_code);
+                       zdev->ap_dev->qid, zdev->online, ehdr->reply_code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 7c522f338bda16a50f11cf04aa845a8f6f937637..334e282f255b7d9b0a6288bad94d6702a729a556 100644 (file)
@@ -25,6 +25,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -332,6 +335,11 @@ static int convert_type80(struct zcrypt_device *zdev,
        if (t80h->len < sizeof(*t80h) + outputdatalength) {
                /* The result is too short, the CEX2A card may not do that.. */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online, t80h->code);
+
                return -EAGAIN; /* repeat the request on a different device. */
        }
        if (zdev->user_space_type == ZCRYPT_CEX2A)
@@ -359,6 +367,10 @@ static int convert_response(struct zcrypt_device *zdev,
                                      outputdata, outputdatalength);
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 7d97fa5a26d0cca4e6f318e5d57d392728f3c5f9..dc542e0a3055a6abb63314ee6dd20ecc451c7d2d 100644 (file)
@@ -25,6 +25,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -50,6 +53,7 @@ struct response_type {
 };
 #define PCIXCC_RESPONSE_TYPE_ICA  0
 #define PCIXCC_RESPONSE_TYPE_XCRB 1
+#define PCIXCC_RESPONSE_TYPE_EP11 2
 
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
@@ -358,6 +362,91 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
        return 0;
 }
 
+static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev,
+                                      struct ap_message *ap_msg,
+                                      struct ep11_urb *xcRB)
+{
+       unsigned int lfmt;
+
+       static struct type6_hdr static_type6_ep11_hdr = {
+               .type           =  0x06,
+               .rqid           = {0x00, 0x01},
+               .function_code  = {0x00, 0x00},
+               .agent_id[0]    =  0x58,        /* {'X'} */
+               .agent_id[1]    =  0x43,        /* {'C'} */
+               .offset1        =  0x00000058,
+       };
+
+       struct {
+               struct type6_hdr hdr;
+               struct ep11_cprb cprbx;
+               unsigned char   pld_tag;        /* fixed value 0x30 */
+               unsigned char   pld_lenfmt;     /* payload length format */
+       } __packed * msg = ap_msg->message;
+
+       struct pld_hdr {
+               unsigned char   func_tag;       /* fixed value 0x4 */
+               unsigned char   func_len;       /* fixed value 0x4 */
+               unsigned int    func_val;       /* function ID     */
+               unsigned char   dom_tag;        /* fixed value 0x4 */
+               unsigned char   dom_len;        /* fixed value 0x4 */
+               unsigned int    dom_val;        /* domain id       */
+       } __packed * payload_hdr;
+
+       /* length checks */
+       ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len;
+       if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE -
+                                  (sizeof(struct type6_hdr)))
+               return -EINVAL;
+
+       if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE -
+                                   (sizeof(struct type86_fmt2_msg)))
+               return -EINVAL;
+
+       /* prepare type6 header */
+       msg->hdr = static_type6_ep11_hdr;
+       msg->hdr.ToCardLen1   = xcRB->req_len;
+       msg->hdr.FromCardLen1 = xcRB->resp_len;
+
+       /* Import CPRB data from the ioctl input parameter */
+       if (copy_from_user(&(msg->cprbx.cprb_len),
+                          (char *)xcRB->req, xcRB->req_len)) {
+               return -EFAULT;
+       }
+
+       /*
+        The target domain field within the cprb body/payload block will be
+        replaced by the usage domain for non-management commands only.
+        Therefore we check the first bit of the 'flags' parameter for
+        management command indication.
+          0 - non management command
+          1 - management command
+       */
+       if (!((msg->cprbx.flags & 0x80) == 0x80)) {
+               msg->cprbx.target_id = (unsigned int)
+                                       AP_QID_QUEUE(zdev->ap_dev->qid);
+
+               if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
+                       switch (msg->pld_lenfmt & 0x03) {
+                       case 1:
+                               lfmt = 2;
+                               break;
+                       case 2:
+                               lfmt = 3;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               } else {
+                       lfmt = 1; /* length format #1 */
+                 }
+               payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt);
+               payload_hdr->dom_val = (unsigned int)
+                                       AP_QID_QUEUE(zdev->ap_dev->qid);
+       }
+       return 0;
+}
+
 /**
  * Copy results from a type 86 ICA reply message back to user space.
  *
@@ -377,6 +466,12 @@ struct type86x_reply {
        char text[0];
 } __packed;
 
+struct type86_ep11_reply {
+       struct type86_hdr hdr;
+       struct type86_fmt2_ext fmt2;
+       struct ep11_cprb cprbx;
+} __packed;
+
 static int convert_type86_ica(struct zcrypt_device *zdev,
                          struct ap_message *reply,
                          char __user *outputdata,
@@ -440,6 +535,11 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
                if (service_rc == 8 && service_rs == 72)
                        return -EINVAL;
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online,
+                              msg->hdr.reply_code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
        data = msg->text;
@@ -503,6 +603,33 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev,
        return 0;
 }
 
+/**
+ * Copy results from a type 86 EP11 XCRB reply message back to user space.
+ *
+ * @zdev: crypto device pointer
+ * @reply: reply AP message.
+ * @xcRB: pointer to EP11 user request block
+ *
+ * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
+ */
+static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev,
+                                   struct ap_message *reply,
+                                   struct ep11_urb *xcRB)
+{
+       struct type86_fmt2_msg *msg = reply->message;
+       char *data = reply->message;
+
+       if (xcRB->resp_len < msg->fmt2.count1)
+               return -EINVAL;
+
+       /* Copy response CPRB to user */
+       if (copy_to_user((char *)xcRB->resp,
+                        data + msg->fmt2.offset1, msg->fmt2.count1))
+               return -EFAULT;
+       xcRB->resp_len = msg->fmt2.count1;
+       return 0;
+}
+
 static int convert_type86_rng(struct zcrypt_device *zdev,
                          struct ap_message *reply,
                          char *buffer)
@@ -551,6 +678,10 @@ static int convert_response_ica(struct zcrypt_device *zdev,
                 * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
@@ -579,10 +710,40 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
        default: /* Unknown response type, this should NEVER EVER happen */
                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
 
+static int convert_response_ep11_xcrb(struct zcrypt_device *zdev,
+       struct ap_message *reply, struct ep11_urb *xcRB)
+{
+       struct type86_ep11_reply *msg = reply->message;
+
+       /* Response type byte is the second byte in the response. */
+       switch (((unsigned char *)reply->message)[1]) {
+       case TYPE82_RSP_CODE:
+       case TYPE87_RSP_CODE:
+               return convert_error(zdev, reply);
+       case TYPE86_RSP_CODE:
+               if (msg->hdr.reply_code)
+                       return convert_error(zdev, reply);
+               if (msg->cprbx.cprb_ver_id == 0x04)
+                       return convert_type86_ep11_xcrb(zdev, reply, xcRB);
+       /* Fall through, no break, incorrect cprb version is an unknown resp.*/
+       default: /* Unknown response type, this should NEVER EVER happen */
+               zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
+               return -EAGAIN; /* repeat the request on a different device. */
+       }
+}
+
 static int convert_response_rng(struct zcrypt_device *zdev,
                                 struct ap_message *reply,
                                 char *data)
@@ -602,6 +763,10 @@ static int convert_response_rng(struct zcrypt_device *zdev,
                 * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
@@ -657,6 +822,51 @@ out:
        complete(&(resp_type->work));
 }
 
+/**
+ * This function is called from the AP bus code after a crypto request
+ * "msg" has finished with the reply message "reply".
+ * It is called from tasklet context.
+ * @ap_dev: pointer to the AP device
+ * @msg: pointer to the AP message
+ * @reply: pointer to the AP reply message
+ */
+static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
+                                        struct ap_message *msg,
+                                        struct ap_message *reply)
+{
+       static struct error_hdr error_reply = {
+               .type = TYPE82_RSP_CODE,
+               .reply_code = REP82_ERROR_MACHINE_FAILURE,
+       };
+       struct response_type *resp_type =
+               (struct response_type *)msg->private;
+       struct type86_ep11_reply *t86r;
+       int length;
+
+       /* Copy the reply message to the request message buffer. */
+       if (IS_ERR(reply)) {
+               memcpy(msg->message, &error_reply, sizeof(error_reply));
+               goto out;
+       }
+       t86r = reply->message;
+       if (t86r->hdr.type == TYPE86_RSP_CODE &&
+           t86r->cprbx.cprb_ver_id == 0x04) {
+               switch (resp_type->type) {
+               case PCIXCC_RESPONSE_TYPE_EP11:
+                       length = t86r->fmt2.offset1 + t86r->fmt2.count1;
+                       length = min(MSGTYPE06_MAX_MSG_SIZE, length);
+                       memcpy(msg->message, reply->message, length);
+                       break;
+               default:
+                       memcpy(msg->message, &error_reply, sizeof(error_reply));
+               }
+       } else {
+               memcpy(msg->message, reply->message, sizeof(error_reply));
+         }
+out:
+       complete(&(resp_type->work));
+}
+
 static atomic_t zcrypt_step = ATOMIC_INIT(0);
 
 /**
@@ -781,6 +991,46 @@ out_free:
        return rc;
 }
 
+/**
+ * The request distributor calls this function if it picked the CEX4P
+ * device to handle a send_ep11_cprb request.
+ * @zdev: pointer to zcrypt_device structure that identifies the
+ *       CEX4P device to the request distributor
+ * @xcRB: pointer to the ep11 user request block
+ */
+static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
+                                               struct ep11_urb *xcrb)
+{
+       struct ap_message ap_msg;
+       struct response_type resp_type = {
+               .type = PCIXCC_RESPONSE_TYPE_EP11,
+       };
+       int rc;
+
+       ap_init_message(&ap_msg);
+       ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
+       if (!ap_msg.message)
+               return -ENOMEM;
+       ap_msg.receive = zcrypt_msgtype6_receive_ep11;
+       ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
+                               atomic_inc_return(&zcrypt_step);
+       ap_msg.private = &resp_type;
+       rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb);
+       if (rc)
+               goto out_free;
+       init_completion(&resp_type.work);
+       ap_queue_message(zdev->ap_dev, &ap_msg);
+       rc = wait_for_completion_interruptible(&resp_type.work);
+       if (rc == 0)
+               rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
+       else /* Signal pending. */
+               ap_cancel_message(zdev->ap_dev, &ap_msg);
+
+out_free:
+       kzfree(ap_msg.message);
+       return rc;
+}
+
 /**
  * The request distributor calls this function if it picked the PCIXCC/CEX2C
  * device to generate random data.
@@ -839,10 +1089,19 @@ static struct zcrypt_ops zcrypt_msgtype6_ops = {
        .rng = zcrypt_msgtype6_rng,
 };
 
+static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = {
+       .owner = THIS_MODULE,
+       .variant = MSGTYPE06_VARIANT_EP11,
+       .rsa_modexpo = NULL,
+       .rsa_modexpo_crt = NULL,
+       .send_ep11_cprb = zcrypt_msgtype6_send_ep11_cprb,
+};
+
 int __init zcrypt_msgtype6_init(void)
 {
        zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops);
        zcrypt_msgtype_register(&zcrypt_msgtype6_ops);
+       zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops);
        return 0;
 }
 
@@ -850,6 +1109,7 @@ void __exit zcrypt_msgtype6_exit(void)
 {
        zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops);
        zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops);
+       zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops);
 }
 
 module_init(zcrypt_msgtype6_init);
index 1e500d3c073571fe764bd1111cd8a2a7b10e7751..207247570623709c946f3a7708d3e3bfc7a0313e 100644 (file)
@@ -32,6 +32,7 @@
 #define MSGTYPE06_NAME                 "zcrypt_msgtype6"
 #define MSGTYPE06_VARIANT_DEFAULT      0
 #define MSGTYPE06_VARIANT_NORNG                1
+#define MSGTYPE06_VARIANT_EP11         2
 
 #define MSGTYPE06_MAX_MSG_SIZE         (12*1024)
 
@@ -99,6 +100,7 @@ struct type86_hdr {
 } __packed;
 
 #define TYPE86_RSP_CODE 0x86
+#define TYPE87_RSP_CODE 0x87
 #define TYPE86_FMT2    0x02
 
 struct type86_fmt2_ext {
index f2b71d8df01f0c1e42e75bd7b0f9786bbf881cae..7a743f4c646c0e46dadcaed195acc9bccf1bf183 100644 (file)
@@ -24,6 +24,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -199,6 +202,10 @@ static int convert_type84(struct zcrypt_device *zdev,
        if (t84h->len < sizeof(*t84h) + outputdatalength) {
                /* The result is too short, the PCICA card may not do that.. */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online, t84h->code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
        BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE);
@@ -223,6 +230,10 @@ static int convert_response(struct zcrypt_device *zdev,
                                      outputdata, outputdatalength);
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 0d90a4334055efcc22ae73a290c53d83fcee8530..4d14c04b746e14ebe656ae08bc14843aee093a45 100644 (file)
@@ -24,6 +24,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gfp.h>
@@ -372,6 +375,11 @@ static int convert_type86(struct zcrypt_device *zdev,
                if (service_rc == 8 && service_rs == 72)
                        return -EINVAL;
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online,
+                              msg->hdr.reply_code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
        data = msg->text;
@@ -425,6 +433,10 @@ static int convert_response(struct zcrypt_device *zdev,
                /* no break, incorrect cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 5e1e12c0cf4220796112d2d6dd9d9e102fdf537d..0a7325361d2958dceeae99da5959e518f8490985 100644 (file)
@@ -2025,7 +2025,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twa_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index c845bdbeb6c06f971923300e7f8e11182d18d84c..4de346017e9ff91b43aed80d48231ac60f23a4e3 100644 (file)
@@ -1600,7 +1600,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twl_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index b9276d10b25c2e277c05e1b6e48e196a11b38fa4..752624e6bc0022807c6265539cad6d8b42d1611f 100644 (file)
@@ -2279,7 +2279,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,  
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = tw_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index 30fa38a0ad39a33102f1cd4656b4d800c498ae07..9176bfbd574586ab04a62786253271b1a1636006 100644 (file)
@@ -201,7 +201,7 @@ static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
        instance->irq = IRQ_AMIGA_PORTS;
        instance->unique_id = z->slotaddr;
 
-       regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start);
+       regs = ZTWO_VADDR(z->resource.start);
        regs->DAWR = DAWR_A2091;
 
        wdregs.SASR = &regs->SASR;
index c0f4f4290dd60dbeb836f547b097ca8b7141eaaf..dd5b64726ddc3c5f9dcee231501630c66424b9ab 100644 (file)
@@ -220,7 +220,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
 
        instance->irq = IRQ_AMIGA_PORTS;
 
-       regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start);
+       regs = ZTWO_VADDR(res->start);
        regs->DAWR = DAWR_A3000;
 
        wdregs.SASR = &regs->SASR;
index 70c521f79f7c26fbc92b65645b780e927c7fcac3..f5a2ab41543bd0bd9006a3af5687085343a25220 100644 (file)
@@ -56,7 +56,7 @@ static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
        scsi_addr = res->start + A4000T_SCSI_OFFSET;
 
        /* Fill in the required pieces of hostdata */
-       hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr);
+       hostdata->base = ZTWO_VADDR(scsi_addr);
        hostdata->clock = 50;
        hostdata->chip710 = 1;
        hostdata->dmode_extra = DMODE_FC2;
index f0d432c139d0cecedf51295562c858d22a9f44f0..4921ed19a027f819b731271c4804be74d2426e5a 100644 (file)
@@ -1081,6 +1081,7 @@ static struct scsi_host_template aac_driver_template = {
 #endif
        .use_clustering                 = ENABLE_CLUSTERING,
        .emulated                       = 1,
+       .no_write_same                  = 1,
 };
 
 static void __aac_shutdown(struct aac_dev * aac)
index 97fd450aff09315194233e7a8ea1f06b566248ef..4f6a30b8e5f99bb3cba345bfec806cdc4972b9f3 100644 (file)
@@ -137,6 +137,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
        .cmd_per_lun            = ARCMSR_MAX_CMD_PERLUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = arcmsr_host_attrs,
+       .no_write_same          = 1,
 };
 static struct pci_device_id arcmsr_device_id_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
index 94d5d0102f7dcc4da5754591a828b47699cec644..42bcb970445a8a7212fafa1aa7285639d5c7d8a3 100644 (file)
@@ -296,6 +296,7 @@ wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
 struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
                                            u16 vf_id, wwn_t lpwwn);
 
+void bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, char *symname);
 void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
                            struct bfa_lport_info_s *port_info);
 void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
index 2f61a5af36581bce4db052d09d7024352063f0a4..f5e4e61a0fd7ba5bd461e0f79bd2f333317bf74a 100644 (file)
@@ -1097,6 +1097,17 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
        bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
 }
 
+void
+bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port,
+                               char *symname)
+{
+       strcpy(port->port_cfg.sym_name.symname, symname);
+
+       if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
+               bfa_fcs_lport_ns_util_send_rspn_id(
+                       BFA_FCS_GET_NS_FROM_PORT(port), NULL);
+}
+
 /*
  *  fcs_lport_api
  */
@@ -5140,9 +5151,6 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
        u8 *psymbl = &symbl[0];
        int len;
 
-       if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
-               return;
-
        /* Avoid sending RSPN in the following states. */
        if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
index e9a681d31223cffca67210615a45c6813f1d56af..40be670a1cbc865c4b39694d10e86584f0dc6321 100644 (file)
@@ -593,11 +593,8 @@ bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
                return;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       if (strlen(sym_name) > 0) {
-               strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name);
-               bfa_fcs_lport_ns_util_send_rspn_id(
-                       BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL);
-       }
+       if (strlen(sym_name) > 0)
+               bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
 
index ee4fa40a50b131597a3e1b6960bffc17191f2d03..ce5ef0190bad3f99f7459a859ce0ca0a1e947246 100644 (file)
@@ -4684,6 +4684,7 @@ static struct scsi_host_template gdth_template = {
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .unchecked_isa_dma      = 1,
         .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 #ifdef CONFIG_ISA
index 2203ac281103b964917f47c1095d6c6a233ec7bf..3b6f83ffddc4e87c59057d0f7eb8a4ded51f11f4 100644 (file)
@@ -310,7 +310,7 @@ static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
        if (!request_mem_region(address, 256, "wd33c93"))
                return -EBUSY;
 
-       regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address));
+       regs = ZTWO_VADDR(address);
 
        error = check_wd33c93(regs);
        if (error)
index f334859024c0652e3ce9bd197c66ca39b877af65..f2c5005f312af9aabeb25f8831ee17b5f28f6a42 100644 (file)
@@ -395,6 +395,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
        shost->eh_deadline = shost_eh_deadline * HZ;
+       shost->no_write_same = sht->no_write_same;
 
        if (sht->supported_mode == MODE_UNKNOWN)
                /* means we didn't set it ... default to INITIATOR */
index 22f6432eb4755a20af732e8c4d4060e9fbb9e909..20a5e6ecf945fab55a982840d6921046b4c552bf 100644 (file)
@@ -561,6 +561,7 @@ static struct scsi_host_template hpsa_driver_template = {
        .sdev_attrs = hpsa_sdev_attrs,
        .shost_attrs = hpsa_shost_attrs,
        .max_sectors = 8192,
+       .no_write_same = 1,
 };
 
 
@@ -1288,7 +1289,7 @@ static void complete_scsi_command(struct CommandList *cp)
                                        "has check condition: aborted command: "
                                        "ASC: 0x%x, ASCQ: 0x%x\n",
                                        cp, asc, ascq);
-                               cmd->result = DID_SOFT_ERROR << 16;
+                               cmd->result |= DID_SOFT_ERROR << 16;
                                break;
                        }
                        /* Must be some other type of check condition */
@@ -4925,7 +4926,7 @@ reinit_after_soft_reset:
        hpsa_hba_inquiry(h);
        hpsa_register_scsi(h);  /* hook ourselves into SCSI subsystem */
        start_controller_lockup_detector(h);
-       return 1;
+       return 0;
 
 clean4:
        hpsa_free_sg_chain_blocks(h);
index 36ac1c34ce97eb53374f55451b8b42f4752b88f2..573f4128b6b68018f43a3263d166232ef39601fc 100644 (file)
@@ -6305,7 +6305,8 @@ static struct scsi_host_template driver_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = ipr_ioa_attrs,
        .sdev_attrs = ipr_dev_attrs,
-       .proc_name = IPR_NAME
+       .proc_name = IPR_NAME,
+       .no_write_same = 1,
 };
 
 /**
index 8d5ea8a1e5a6f33ab8235b300417d7ba352f84f7..52a216f21ae579644b97c093e89e12306a265595 100644 (file)
@@ -374,6 +374,7 @@ static struct scsi_host_template ips_driver_template = {
        .sg_tablesize           = IPS_MAX_SG,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 
index 161c98efade9b9f290c04588e4638df0f3c421ac..d2895836f9fa4c00fec1a46d993074ecb3edeaea 100644 (file)
@@ -211,7 +211,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
                qc->tf.nsect = 0;
        }
 
-       ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
+       ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis);
        task->uldd_task = qc;
        if (ata_is_atapi(qc->tf.protocol)) {
                memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
index 90c95a3385d18bb52f93093da10c8d400514f712..816db12ef5d555159226c5eb618b110ebb790776 100644 (file)
@@ -4244,6 +4244,7 @@ static struct scsi_host_template megaraid_template = {
        .eh_device_reset_handler        = megaraid_reset,
        .eh_bus_reset_handler           = megaraid_reset,
        .eh_host_reset_handler          = megaraid_reset,
+       .no_write_same                  = 1,
 };
 
 static int
index d1a4b82836ea6936f55504e33bcaabb5db9adbee..e2237a97cb9d314b485869cc37da7e3de8062531 100644 (file)
@@ -367,6 +367,7 @@ static struct scsi_host_template megaraid_template_g = {
        .eh_host_reset_handler          = megaraid_reset_handler,
        .change_queue_depth             = megaraid_change_queue_depth,
        .use_clustering                 = ENABLE_CLUSTERING,
+       .no_write_same                  = 1,
        .sdev_attrs                     = megaraid_sdev_attrs,
        .shost_attrs                    = megaraid_shost_attrs,
 };
index 0a743a5d16477a5e168f02a77a99e90f201caac3..c99812bf2a732f7180c291f3dcc23b5eda81a74c 100644 (file)
@@ -2148,6 +2148,7 @@ static struct scsi_host_template megasas_template = {
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
        .change_queue_depth = megasas_change_queue_depth,
+       .no_write_same = 1,
 };
 
 /**
index f16ece91b94ac73de979eda5496925c1d253b37b..0a1296a87d66d5919859ea586a8637109b537c50 100644 (file)
@@ -3403,6 +3403,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
        port->port_state =  portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPC;
        PM8001_MSG_DBG(pm8001_ha,
                pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
                port_id, phy_id));
@@ -3483,6 +3484,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
                " phy id = %d\n", port_id, phy_id));
        port->port_state =  portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPC;
        port->port_attached = 1;
        pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
index 6d91e2446542c78290dfba8f9e846380ccda3067..e4867e690c846db4ab2954644b959cc044f39f83 100644 (file)
 #define LINKRATE_30                    (0x02 << 8)
 #define LINKRATE_60                    (0x04 << 8)
 
+/* for phy state */
+
+#define PHY_STATE_LINK_UP_SPC          0x1
+
 /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
 #define GSM_SM_BASE                    0x4F0000
 struct mpi_msg_hdr{
index 34f5f5ffef056ec2e86e44726dd99c13ae204877..73a120d81b4dacf7c22e3b99c07458680dacbaf5 100644 (file)
@@ -175,20 +175,16 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 static void pm8001_tasklet(unsigned long opaque)
 {
        struct pm8001_hba_info *pm8001_ha;
-       u32 vec;
-       pm8001_ha = (struct pm8001_hba_info *)opaque;
+       struct isr_param *irq_vector;
+
+       irq_vector = (struct isr_param *)opaque;
+       pm8001_ha = irq_vector->drv_inst;
        if (unlikely(!pm8001_ha))
                BUG_ON(1);
-       vec = pm8001_ha->int_vector;
-       PM8001_CHIP_DISP->isr(pm8001_ha, vec);
+       PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 }
 #endif
 
-static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
-{
-       return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
-}
-
 /**
  * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
  * It obtains the vector number and calls the equivalent bottom
@@ -198,18 +194,20 @@ static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
  */
 static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
 {
-       struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
-       u8 outq = *(u8 *)opaque;
+       struct isr_param *irq_vector;
+       struct pm8001_hba_info *pm8001_ha;
        irqreturn_t ret = IRQ_HANDLED;
+       irq_vector = (struct isr_param *)opaque;
+       pm8001_ha = irq_vector->drv_inst;
+
        if (unlikely(!pm8001_ha))
                return IRQ_NONE;
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
-       pm8001_ha->int_vector = outq;
 #ifdef PM8001_USE_TASKLET
-       tasklet_schedule(&pm8001_ha->tasklet);
+       tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]);
 #else
-       ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
+       ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 #endif
        return ret;
 }
@@ -230,9 +228,8 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
 
-       pm8001_ha->int_vector = 0;
 #ifdef PM8001_USE_TASKLET
-       tasklet_schedule(&pm8001_ha->tasklet);
+       tasklet_schedule(&pm8001_ha->tasklet[0]);
 #else
        ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
 #endif
@@ -457,7 +454,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 {
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
-
+       int j;
 
        pm8001_ha = sha->lldd_ha;
        if (!pm8001_ha)
@@ -480,12 +477,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
                pm8001_ha->iomb_size = IOMB_SIZE_SPC;
 
 #ifdef PM8001_USE_TASKLET
-       /**
-       * default tasklet for non msi-x interrupt handler/first msi-x
-       * interrupt handler
-       **/
-       tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                       (unsigned long)pm8001_ha);
+       /* Tasklet for non msi-x interrupt handler */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+                       (unsigned long)&(pm8001_ha->irq_vector[0]));
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+                               (unsigned long)&(pm8001_ha->irq_vector[j]));
 #endif
        pm8001_ioremap(pm8001_ha);
        if (!pm8001_alloc(pm8001_ha, ent))
@@ -733,19 +732,20 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
                        "pci_enable_msix request ret:%d no of intr %d\n",
                                        rc, pm8001_ha->number_of_intr));
 
-               for (i = 0; i < number_of_intr; i++)
-                       pm8001_ha->outq[i] = i;
 
                for (i = 0; i < number_of_intr; i++) {
                        snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
                                        DRV_NAME"%d", i);
+                       pm8001_ha->irq_vector[i].irq_id = i;
+                       pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
+
                        if (request_irq(pm8001_ha->msix_entries[i].vector,
                                pm8001_interrupt_handler_msix, flag,
-                               intr_drvname[i], &pm8001_ha->outq[i])) {
+                               intr_drvname[i], &(pm8001_ha->irq_vector[i]))) {
                                for (j = 0; j < i; j++)
                                        free_irq(
                                        pm8001_ha->msix_entries[j].vector,
-                                       &pm8001_ha->outq[j]);
+                                       &(pm8001_ha->irq_vector[i]));
                                pci_disable_msix(pm8001_ha->pdev);
                                break;
                        }
@@ -907,7 +907,7 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
-       int i;
+       int i, j;
        pm8001_ha = sha->lldd_ha;
        sas_unregister_ha(sha);
        sas_remove_host(pm8001_ha->shost);
@@ -921,13 +921,18 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                free_irq(pm8001_ha->msix_entries[i].vector,
-                               &pm8001_ha->outq[i]);
+                               &(pm8001_ha->irq_vector[i]));
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
 #endif
 #ifdef PM8001_USE_TASKLET
-       tasklet_kill(&pm8001_ha->tasklet);
+       /* For non-msix and msix interrupts */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_kill(&pm8001_ha->tasklet[0]);
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_kill(&pm8001_ha->tasklet[j]);
 #endif
        pm8001_free(pm8001_ha);
        kfree(sha->sas_phy);
@@ -948,7 +953,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
-       int i;
+       int  i, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        flush_workqueue(pm8001_wq);
@@ -964,13 +969,18 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                free_irq(pm8001_ha->msix_entries[i].vector,
-                               &pm8001_ha->outq[i]);
+                               &(pm8001_ha->irq_vector[i]));
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
 #endif
 #ifdef PM8001_USE_TASKLET
-       tasklet_kill(&pm8001_ha->tasklet);
+       /* For non-msix and msix interrupts */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_kill(&pm8001_ha->tasklet[0]);
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_kill(&pm8001_ha->tasklet[j]);
 #endif
        device_state = pci_choose_state(pdev, state);
        pm8001_printk("pdev=0x%p, slot=%s, entering "
@@ -993,7 +1003,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
        int rc;
-       u8 i = 0;
+       u8 i = 0, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        device_state = pdev->current_state;
@@ -1033,10 +1043,14 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        if (rc)
                goto err_out_disable;
 #ifdef PM8001_USE_TASKLET
-       /* default tasklet for non msi-x interrupt handler/first msi-x
-       * interrupt handler */
-       tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                       (unsigned long)pm8001_ha);
+       /*  Tasklet for non msi-x interrupt handler */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+                       (unsigned long)&(pm8001_ha->irq_vector[0]));
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+                               (unsigned long)&(pm8001_ha->irq_vector[j]));
 #endif
        PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
        if (pm8001_ha->chip_id != chip_8001) {
@@ -1169,6 +1183,7 @@ module_exit(pm8001_exit);
 MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
 MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
 MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
+MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
 MODULE_DESCRIPTION(
                "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 "
                "SAS/SATA controller driver");
index f4eb18e5163152b414fc8b0a08b4a07a7f844111..f50ac44b950e5f0fbd12772689a03c5aaebfea87 100644 (file)
@@ -1098,15 +1098,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
        struct pm8001_tmf_task tmf_task;
        struct pm8001_device *pm8001_dev = dev->lldd_dev;
        struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
+       DECLARE_COMPLETION_ONSTACK(completion_setstate);
        if (dev_is_sata(dev)) {
                struct sas_phy *phy = sas_get_local_phy(dev);
                rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
                        dev, 1, 0);
                rc = sas_phy_reset(phy, 1);
                sas_put_local_phy(phy);
+               pm8001_dev->setds_completion = &completion_setstate;
                rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
                        pm8001_dev, 0x01);
-               msleep(2000);
+               wait_for_completion(&completion_setstate);
        } else {
                tmf_task.tmf = TMF_LU_RESET;
                rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
index 6037d477a183241c0010d73a00580c3667f3aaa9..6c5fd5ee22d30cf5f1ef0b38cbcc8666f46b0d79 100644 (file)
@@ -466,6 +466,10 @@ struct pm8001_hba_memspace {
        u64                     membase;
        u32                     memsize;
 };
+struct isr_param {
+       struct pm8001_hba_info *drv_inst;
+       u32 irq_id;
+};
 struct pm8001_hba_info {
        char                    name[PM8001_NAME_LENGTH];
        struct list_head        list;
@@ -519,14 +523,13 @@ struct pm8001_hba_info {
        int                     number_of_intr;/*will be used in remove()*/
 #endif
 #ifdef PM8001_USE_TASKLET
-       struct tasklet_struct   tasklet;
+       struct tasklet_struct   tasklet[PM8001_MAX_MSIX_VEC];
 #endif
        u32                     logging_level;
        u32                     fw_status;
        u32                     smp_exp_mode;
-       u32                     int_vector;
        const struct firmware   *fw_image;
-       u8                      outq[PM8001_MAX_MSIX_VEC];
+       struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
 };
 
 struct pm8001_work {
index 8987b1706216436ef36392eb329e56320547ab23..c950dc5c99432967891c093d7bddb0bb24186e7e 100644 (file)
@@ -2894,6 +2894,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
        port->port_state = portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
                "portid:%d; phyid:%d; linkrate:%d; "
                "portstate:%x; devicetype:%x\n",
@@ -2978,6 +2979,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                                port_id, phy_id, link_rate, portstate));
 
        port->port_state = portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        port->port_attached = 1;
        pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
index c86816bea4243354d8864a5422778996ebec215e..9970a385795d16c5328ca6c7711ebf146e02c63c 100644 (file)
 #define SAS_DOPNRJT_RTRY_TMO            128
 #define SAS_COPNRJT_RTRY_TMO            128
 
+/* for phy state */
+#define PHY_STATE_LINK_UP_SPCV         0x2
 /*
   Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
   Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
index bd6f743d87a78af19c698d38d70291723fd28dfb..be8ce54f99b247bcba427a16c2f4873b987329c8 100644 (file)
@@ -1404,11 +1404,22 @@ enum {
 };
 #define PMCRAID_AEN_CMD_MAX (__PMCRAID_AEN_CMD_MAX - 1)
 
+static struct genl_multicast_group pmcraid_mcgrps[] = {
+       { .name = "events", /* not really used - see ID discussion below */ },
+};
+
 static struct genl_family pmcraid_event_family = {
-       .id = GENL_ID_GENERATE,
+       /*
+        * Due to prior multicast group abuse (the code having assumed that
+        * the family ID can be used as a multicast group ID) we need to
+        * statically allocate a family (and thus group) ID.
+        */
+       .id = GENL_ID_PMCRAID,
        .name = "pmcraid",
        .version = 1,
-       .maxattr = PMCRAID_AEN_ATTR_MAX
+       .maxattr = PMCRAID_AEN_ATTR_MAX,
+       .mcgrps = pmcraid_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(pmcraid_mcgrps),
 };
 
 /**
@@ -1511,9 +1522,8 @@ static int pmcraid_notify_aen(
                return result;
        }
 
-       result =
-               genlmsg_multicast(&pmcraid_event_family, skb, 0,
-                                 pmcraid_event_family.id, GFP_ATOMIC);
+       result = genlmsg_multicast(&pmcraid_event_family, skb,
+                                  0, 0, GFP_ATOMIC);
 
        /* If there are no listeners, genlmsg_multicast may return non-zero
         * value.
@@ -4315,6 +4325,7 @@ static struct scsi_host_template pmcraid_host_template = {
        .this_id = -1,
        .sg_tablesize = PMCRAID_MAX_IOADLS,
        .max_sectors = PMCRAID_IOA_MAX_SECTORS,
+       .no_write_same = 1,
        .cmd_per_lun = PMCRAID_MAX_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = pmcraid_host_attrs,
index 596480022b0a4b88eb7a3d855e472200d5ab4fef..38a1257e76e1ec432c6cc81893b54a27ee30081a 100644 (file)
@@ -471,7 +471,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
                schedule_delayed_work(&tgt->sess_del_work, 0);
        else
                schedule_delayed_work(&tgt->sess_del_work,
-                   jiffies - sess->expires);
+                   sess->expires - jiffies);
 }
 
 /* ha->hardware_lock supposed to be held on entry */
@@ -550,13 +550,14 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
        struct scsi_qla_host *vha = tgt->vha;
        struct qla_hw_data *ha = vha->hw;
        struct qla_tgt_sess *sess;
-       unsigned long flags;
+       unsigned long flags, elapsed;
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
        while (!list_empty(&tgt->del_sess_list)) {
                sess = list_entry(tgt->del_sess_list.next, typeof(*sess),
                    del_list_entry);
-               if (time_after_eq(jiffies, sess->expires)) {
+               elapsed = jiffies;
+               if (time_after_eq(elapsed, sess->expires)) {
                        qlt_undelete_sess(sess);
 
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
@@ -566,7 +567,7 @@ static void qlt_del_sess_work_fn(struct delayed_work *work)
                        ha->tgt.tgt_ops->put_sess(sess);
                } else {
                        schedule_delayed_work(&tgt->sess_del_work,
-                           jiffies - sess->expires);
+                           sess->expires - elapsed);
                        break;
                }
        }
@@ -4290,6 +4291,7 @@ int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn,
                if (rc != 0) {
                        ha->tgt.tgt_ops = NULL;
                        ha->tgt.target_lport_ptr = NULL;
+                       scsi_host_put(host);
                }
                mutex_unlock(&qla_tgt_mutex);
                return rc;
index e6c4bff04339cb1975637a92bb3842601e1e158f..69725f7c32c1bc5b6c6dbfb93756aa4770b5d17e 100644 (file)
@@ -2659,6 +2659,12 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        struct scsi_device *sdev = sdkp->device;
 
+       if (sdev->host->no_write_same) {
+               sdev->no_write_same = 1;
+
+               return;
+       }
+
        if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
                /* too large values might cause issues with arcmsr */
                int vpd_buf_len = 64;
index 1a28f5632797ed2da2f27c0752013e3c7e4dde5d..17d7404272400dd1a76989a3965e0c4b85343036 100644 (file)
@@ -1697,6 +1697,7 @@ static struct scsi_host_template scsi_driver = {
        .use_clustering =       DISABLE_CLUSTERING,
        /* Make sure we dont get a sg segment crosses a page boundary */
        .dma_boundary =         PAGE_SIZE-1,
+       .no_write_same =        1,
 };
 
 enum {
index cbf3476c68cd3511e13592296198da53ddcc441d..aff31991aea9808f5f98180cb126be87be12db26 100644 (file)
@@ -104,7 +104,7 @@ static int zorro7xx_init_one(struct zorro_dev *z,
        if (ioaddr > 0x01000000)
                hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
        else
-               hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr);
+               hostdata->base = ZTWO_VADDR(ioaddr);
 
        hostdata->clock = 50;
        hostdata->chip710 = 1;
index 3ed666fe840a0cdbaf1a2a2c6cd75670dd25fb48..9025edd7dc45fde131c7c9c6004ce5434829c785 100644 (file)
@@ -377,7 +377,7 @@ out_master_put:
 
 static int bcm2835_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
 
        free_irq(bs->irq, master);
index 80d56b214eb51af96ceb9e9d55ffea6bbb2d7302..469ecd8763581c3628c033e00adc47699e033f12 100644 (file)
@@ -435,7 +435,7 @@ out:
 
 static int bcm63xx_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        /* reset spi block */
index 9602bbd8d7eac061fffb5543704fc9d68a48f135..87676587d783551e120f5478f9b522c7add7df31 100644 (file)
@@ -557,7 +557,7 @@ free_master:
 
 static int mpc512x_psc_spi_do_remove(struct device *dev)
 {
-       struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
        clk_disable_unprepare(mps->clk_mclk);
index 73afb56c08cc26826d468ad4aaacdce3a7e7043f..3adebfa22e3d785b6bf7ffb2149e77652039c3c3 100644 (file)
@@ -565,7 +565,7 @@ static int mxs_spi_remove(struct platform_device *pdev)
        struct mxs_spi *spi;
        struct mxs_ssp *ssp;
 
-       master = spi_master_get(platform_get_drvdata(pdev));
+       master = platform_get_drvdata(pdev);
        spi = spi_master_get_devdata(master);
        ssp = &spi->ssp;
 
index cb0e1f1137adb65384188ce31651171cb3f5f311..7765b1999537a08e5c6d95eed39bdea4c8c9c9dd 100644 (file)
@@ -1073,6 +1073,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
        { "INT33C0", 0 },
        { "INT33C1", 0 },
+       { "INT3430", 0 },
+       { "INT3431", 0 },
        { "80860F0E", 0 },
        { },
 };
@@ -1291,6 +1293,9 @@ static int pxa2xx_spi_resume(struct device *dev)
        /* Enable the SSP clock */
        clk_prepare_enable(ssp->clk);
 
+       /* Restore LPSS private register bits */
+       lpss_ssp_setup(drv_data);
+
        /* Start the queue running */
        status = spi_master_resume(drv_data->master);
        if (status != 0) {
index 58449ad4ad0d3a83eb273b49f292909078519ca1..9e829cee73572bab01eae87f3e4a219a8e76c98f 100644 (file)
@@ -885,14 +885,13 @@ static void rspi_release_dma(struct rspi_data *rspi)
 
 static int rspi_remove(struct platform_device *pdev)
 {
-       struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
+       struct rspi_data *rspi = platform_get_drvdata(pdev);
 
        spi_unregister_master(rspi->master);
        rspi_release_dma(rspi);
        free_irq(platform_get_irq(pdev, 0), rspi);
        clk_put(rspi->clk);
        iounmap(rspi->addr);
-       spi_master_put(rspi->master);
 
        return 0;
 }
index 0b71270fbf67ba671dd43f116db48de30076514c..4396bd44854063d9488cfd5dadc863c40c9e1dbf 100644 (file)
@@ -161,7 +161,7 @@ static int ti_qspi_setup(struct spi_device *spi)
                        qspi->spi_max_frequency, clk_div);
 
        ret = pm_runtime_get_sync(qspi->dev);
-       if (ret) {
+       if (ret < 0) {
                dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
                return ret;
        }
@@ -459,11 +459,10 @@ static int ti_qspi_probe(struct platform_device *pdev)
        if (!of_property_read_u32(np, "num-cs", &num_cs))
                master->num_chipselect = num_cs;
 
-       platform_set_drvdata(pdev, master);
-
        qspi = spi_master_get_devdata(master);
        qspi->master = master;
        qspi->dev = &pdev->dev;
+       platform_set_drvdata(pdev, qspi);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -517,10 +516,26 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
-       struct  ti_qspi *qspi = platform_get_drvdata(pdev);
+       struct spi_master *master;
+       struct ti_qspi *qspi;
+       int ret;
+
+       master = platform_get_drvdata(pdev);
+       qspi = spi_master_get_devdata(master);
+
+       ret = pm_runtime_get_sync(qspi->dev);
+       if (ret < 0) {
+               dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
+               return ret;
+       }
 
        ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
 
+       pm_runtime_put(qspi->dev);
+       pm_runtime_disable(&pdev->dev);
+
+       spi_unregister_master(master);
+
        return 0;
 }
 
index 637cce2b8bdde8d3f37c8134a5f3aee7c4adead8..18c9bb2b5f39108793a32a2b71624f0e59434712 100644 (file)
@@ -425,7 +425,7 @@ exit:
 
 static int txx9spi_remove(struct platform_device *dev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+       struct spi_master *master = platform_get_drvdata(dev);
        struct txx9spi *c = spi_master_get_devdata(master);
 
        destroy_workqueue(c->workqueue);
index 18cc625d887f796aed4b082eb2366262aec8aaa8..349ebba4b1992afdf703e689022dfbf67b07f626 100644 (file)
@@ -1415,7 +1415,7 @@ int devm_spi_register_master(struct device *dev, struct spi_master *master)
                return -ENOMEM;
 
        ret = spi_register_master(master);
-       if (ret != 0) {
+       if (!ret) {
                *ptr = master;
                devres_add(dev, ptr);
        } else {
index 53fee2f9a498866c6a19d3d6c3ca1d078fd7206e..8dfdd2732bdc329b3865c010d0afdb8e1e248337 100644 (file)
@@ -39,7 +39,8 @@ static INT bcm_close(struct net_device *dev)
        return 0;
 }
 
-static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        return ClassifyPacket(netdev_priv(dev), skb);
 }
index 8f02bf66e20b2002b3b52655919a89f95c0fcad9..4964d2a2fc7d54ba099541b3f9c2c61be4799936 100644 (file)
@@ -446,7 +446,7 @@ int comedi_load_firmware(struct comedi_device *dev,
                release_firmware(fw);
        }
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 EXPORT_SYMBOL_GPL(comedi_load_firmware);
 
index 432e3f9c3301ecc7ce6f6d633913bf1e1e85f4e4..c55f234b29e6052e541dc7b7043d0a877682b4cb 100644 (file)
@@ -63,7 +63,8 @@ enum pci_8255_boardid {
        BOARD_ADLINK_PCI7296,
        BOARD_CB_PCIDIO24,
        BOARD_CB_PCIDIO24H,
-       BOARD_CB_PCIDIO48H,
+       BOARD_CB_PCIDIO48H_OLD,
+       BOARD_CB_PCIDIO48H_NEW,
        BOARD_CB_PCIDIO96H,
        BOARD_NI_PCIDIO96,
        BOARD_NI_PCIDIO96B,
@@ -106,11 +107,16 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = {
                .dio_badr       = 2,
                .n_8255         = 1,
        },
-       [BOARD_CB_PCIDIO48H] = {
+       [BOARD_CB_PCIDIO48H_OLD] = {
                .name           = "cb_pci-dio48h",
                .dio_badr       = 1,
                .n_8255         = 2,
        },
+       [BOARD_CB_PCIDIO48H_NEW] = {
+               .name           = "cb_pci-dio48h",
+               .dio_badr       = 2,
+               .n_8255         = 2,
+       },
        [BOARD_CB_PCIDIO96H] = {
                .name           = "cb_pci-dio96h",
                .dio_badr       = 2,
@@ -263,7 +269,10 @@ static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = {
        { PCI_VDEVICE(ADLINK, 0x7296), BOARD_ADLINK_PCI7296 },
        { PCI_VDEVICE(CB, 0x0028), BOARD_CB_PCIDIO24 },
        { PCI_VDEVICE(CB, 0x0014), BOARD_CB_PCIDIO24H },
-       { PCI_VDEVICE(CB, 0x000b), BOARD_CB_PCIDIO48H },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, 0x0000, 0x0000),
+         .driver_data = BOARD_CB_PCIDIO48H_OLD },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_CB, 0x000b, PCI_VENDOR_ID_CB, 0x000b),
+         .driver_data = BOARD_CB_PCIDIO48H_NEW },
        { PCI_VDEVICE(CB, 0x0017), BOARD_CB_PCIDIO96H },
        { PCI_VDEVICE(NI, 0x0160), BOARD_NI_PCIDIO96 },
        { PCI_VDEVICE(NI, 0x1630), BOARD_NI_PCIDIO96B },
index 99421f90d1895f6a0691d4443c457f5aac2335db..0485d7f398672a61045367b7ac85a267b34b6e8d 100644 (file)
@@ -451,7 +451,12 @@ done:
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
                        BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
                .scan_index = idx,                                      \
-               .scan_type = IIO_ST('s', 16, 16, IIO_BE),               \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 16,                                 \
+                       .storagebits = 16,                              \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
        }
 
 static const struct iio_chan_spec hmc5843_channels[] = {
index 6bd015ac9d683474a034924f8ffec3e752e1d382..96e4eee344ef602174acec2ce27cf57bfb0ce128 100644 (file)
@@ -88,8 +88,9 @@ static int imx_drm_driver_unload(struct drm_device *drm)
 
        imx_drm_device_put();
 
-       drm_mode_config_cleanup(imxdrm->drm);
+       drm_vblank_cleanup(imxdrm->drm);
        drm_kms_helper_poll_fini(imxdrm->drm);
+       drm_mode_config_cleanup(imxdrm->drm);
 
        return 0;
 }
@@ -199,8 +200,8 @@ static void imx_drm_driver_preclose(struct drm_device *drm,
        if (!file->is_master)
                return;
 
-       for (i = 0; i < 4; i++)
-               imx_drm_disable_vblank(drm , i);
+       for (i = 0; i < MAX_CRTC; i++)
+               imx_drm_disable_vblank(drm, i);
 }
 
 static const struct file_operations imx_drm_driver_fops = {
@@ -376,8 +377,6 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        struct imx_drm_device *imxdrm = __imx_drm_device();
        int ret;
 
-       drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc,
-                       imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
        ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
        if (ret)
                return ret;
@@ -385,6 +384,9 @@ static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc)
        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;
@@ -428,11 +430,11 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
        ret = drm_mode_group_init_legacy_group(imxdrm->drm,
                        &imxdrm->drm->primary->mode_group);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        ret = drm_vblank_init(imxdrm->drm, MAX_CRTC);
        if (ret)
-               goto err_init;
+               goto err_kms;
 
        /*
         * with vblank_disable_allowed = true, vblank interrupt will be disabled
@@ -441,12 +443,19 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
         */
        imxdrm->drm->vblank_disable_allowed = true;
 
-       if (!imx_drm_device_get())
+       if (!imx_drm_device_get()) {
                ret = -EINVAL;
+               goto err_vblank;
+       }
 
-       ret = 0;
+       mutex_unlock(&imxdrm->mutex);
+       return 0;
 
-err_init:
+err_vblank:
+       drm_vblank_cleanup(drm);
+err_kms:
+       drm_kms_helper_poll_fini(drm);
+       drm_mode_config_cleanup(drm);
        mutex_unlock(&imxdrm->mutex);
 
        return ret;
@@ -492,6 +501,15 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 
        mutex_lock(&imxdrm->mutex);
 
+       /*
+        * The vblank arrays are dimensioned by MAX_CRTC - we can't
+        * pass IDs greater than this to those functions.
+        */
+       if (imxdrm->pipes >= MAX_CRTC) {
+               ret = -EINVAL;
+               goto err_busy;
+       }
+
        if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
@@ -528,6 +546,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
        return 0;
 
 err_register:
+       list_del(&imx_drm_crtc->list);
        kfree(imx_drm_crtc);
 err_alloc:
 err_busy:
index 680f4c8fa0815481a410621eb616879dbb149109..2c44fef8d58b327df92e97667f0661c45e3e57d6 100644 (file)
@@ -114,7 +114,6 @@ struct imx_tve {
        struct drm_encoder encoder;
        struct imx_drm_encoder *imx_drm_encoder;
        struct device *dev;
-       spinlock_t enable_lock; /* serializes tve_enable/disable */
        spinlock_t lock;        /* register lock */
        bool enabled;
        int mode;
@@ -146,10 +145,8 @@ __releases(&tve->lock)
 
 static void tve_enable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (!tve->enabled) {
                tve->enabled = true;
                clk_prepare_enable(tve->clk);
@@ -169,23 +166,18 @@ static void tve_enable(struct imx_tve *tve)
                             TVE_CD_SM_IEN |
                             TVE_CD_LM_IEN |
                             TVE_CD_MON_END_IEN);
-
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static void tve_disable(struct imx_tve *tve)
 {
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&tve->enable_lock, flags);
        if (tve->enabled) {
                tve->enabled = false;
                ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
                                         TVE_IPU_CLK_EN | TVE_EN, 0);
                clk_disable_unprepare(tve->clk);
        }
-       spin_unlock_irqrestore(&tve->enable_lock, flags);
 }
 
 static int tve_setup_tvout(struct imx_tve *tve)
@@ -601,7 +593,6 @@ static int imx_tve_probe(struct platform_device *pdev)
 
        tve->dev = &pdev->dev;
        spin_lock_init(&tve->lock);
-       spin_lock_init(&tve->enable_lock);
 
        ddc_node = of_parse_phandle(np, "ddc", 0);
        if (ddc_node) {
index 7a22ce619ed264ba536de785650700b02f6d3ef3..97ca6924dbb3fce7b5db813aefb781adb273187a 100644 (file)
@@ -996,35 +996,35 @@ static const struct ipu_platform_reg client_reg[] = {
        },
 };
 
+static DEFINE_MUTEX(ipu_client_id_mutex);
 static int ipu_client_id;
 
-static int ipu_add_subdevice_pdata(struct device *dev,
-               const struct ipu_platform_reg *reg)
-{
-       struct platform_device *pdev;
-
-       pdev = platform_device_register_data(dev, reg->name, ipu_client_id++,
-                       &reg->pdata, sizeof(struct ipu_platform_reg));
-
-       return PTR_ERR_OR_ZERO(pdev);
-}
-
 static int ipu_add_client_devices(struct ipu_soc *ipu)
 {
-       int ret;
-       int i;
+       struct device *dev = ipu->dev;
+       unsigned i;
+       int id, ret;
+
+       mutex_lock(&ipu_client_id_mutex);
+       id = ipu_client_id;
+       ipu_client_id += ARRAY_SIZE(client_reg);
+       mutex_unlock(&ipu_client_id_mutex);
 
        for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
                const struct ipu_platform_reg *reg = &client_reg[i];
-               ret = ipu_add_subdevice_pdata(ipu->dev, reg);
-               if (ret)
+               struct platform_device *pdev;
+
+               pdev = platform_device_register_data(dev, reg->name,
+                       id++, &reg->pdata, sizeof(reg->pdata));
+
+               if (IS_ERR(pdev))
                        goto err_register;
        }
 
        return 0;
 
 err_register:
-       platform_device_unregister_children(to_platform_device(ipu->dev));
+       platform_device_unregister_children(to_platform_device(dev));
 
        return ret;
 }
index 235d2b1ec593c4dfba7a83c4eb5fd0f578e0c5c4..eedffed17e391d3243443c443ff9338bf494c440 100644 (file)
@@ -306,7 +306,8 @@ static netdev_tx_t xlr_net_start_xmit(struct sk_buff *skb,
        return NETDEV_TX_OK;
 }
 
-static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb)
+static u16 xlr_net_select_queue(struct net_device *ndev, struct sk_buff *skb,
+                               void *accel_priv)
 {
        return (u16)smp_processor_id();
 }
index 17659bb04befc24fabded5439be74aba9fdcb5d1..dd69e344e4099c852ffd0bd5ef11ef859a0e274c 100644 (file)
@@ -652,7 +652,8 @@ static unsigned int rtw_classify8021d(struct sk_buff *skb)
        return dscp >> 5;
 }
 
-static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb)
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+                           void *accel_priv)
 {
        struct adapter  *padapter = rtw_netdev_priv(dev);
        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
index 1aa4a3fd0f1ba3b023367974593897ba1077df18..56e355b3e7fa00b5dd6a8ca4929071cc5cdaca09 100644 (file)
@@ -258,7 +258,8 @@ err:
 /* This function maps kernel space memory to user space memory. */
 static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-       u32 status;
+       struct omap_dsp_platform_data *pdata =
+                                       omap_dspbridge_dev->dev.platform_data;
 
        /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -268,13 +269,9 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
                vma->vm_start, vma->vm_end, vma->vm_page_prot,
                vma->vm_flags);
 
-       status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                                vma->vm_end - vma->vm_start,
-                                vma->vm_page_prot);
-       if (status != 0)
-               status = -EAGAIN;
-
-       return status;
+       return vm_iomap_memory(vma,
+                              pdata->phys_mempool_base,
+                              pdata->phys_mempool_size);
 }
 
 static const struct file_operations bridge_fops = {
index d70e9119e906cba0c0f38da61948ce745bc5d6e5..00867190413c78d1f3226348e5c68718077c0b9f 100644 (file)
@@ -465,6 +465,7 @@ int iscsit_del_np(struct iscsi_np *np)
                 */
                send_sig(SIGINT, np->np_thread, 1);
                kthread_stop(np->np_thread);
+               np->np_thread = NULL;
        }
 
        np->np_transport->iscsit_free_np(np);
@@ -823,24 +824,22 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
             (hdr->flags & ISCSI_FLAG_CMD_WRITE)) && !hdr->data_length) {
                /*
-                * Vmware ESX v3.0 uses a modified Cisco Initiator (v3.4.2)
-                * that adds support for RESERVE/RELEASE.  There is a bug
-                * add with this new functionality that sets R/W bits when
-                * neither CDB carries any READ or WRITE datapayloads.
+                * From RFC-3720 Section 10.3.1:
+                *
+                * "Either or both of R and W MAY be 1 when either the
+                *  Expected Data Transfer Length and/or Bidirectional Read
+                *  Expected Data Transfer Length are 0"
+                *
+                * For this case, go ahead and clear the unnecssary bits
+                * to avoid any confusion with ->data_direction.
                 */
-               if ((hdr->cdb[0] == 0x16) || (hdr->cdb[0] == 0x17)) {
-                       hdr->flags &= ~ISCSI_FLAG_CMD_READ;
-                       hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
-                       goto done;
-               }
+               hdr->flags &= ~ISCSI_FLAG_CMD_READ;
+               hdr->flags &= ~ISCSI_FLAG_CMD_WRITE;
 
-               pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
+               pr_warn("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
                        " set when Expected Data Transfer Length is 0 for"
-                       " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
-               return iscsit_add_reject_cmd(cmd,
-                                            ISCSI_REASON_BOOKMARK_INVALID, buf);
+                       " CDB: 0x%02x, Fixing up flags\n", hdr->cdb[0]);
        }
-done:
 
        if (!(hdr->flags & ISCSI_FLAG_CMD_READ) &&
            !(hdr->flags & ISCSI_FLAG_CMD_WRITE) && (hdr->data_length != 0)) {
index e3318edb233dbe91b8e35f9fe1a7fff58508fb6b..1c0088fe9e99368c2dfb50b378dee6033cd42cab 100644 (file)
@@ -474,7 +474,8 @@ static ssize_t __iscsi_##prefix##_store_##name(                             \
                                                                        \
        if (!capable(CAP_SYS_ADMIN))                                    \
                return -EPERM;                                          \
-                                                                       \
+       if (count >= sizeof(auth->name))                                \
+               return -EINVAL;                                         \
        snprintf(auth->name, sizeof(auth->name), "%s", page);           \
        if (!strncmp("NULL", auth->name, 4))                            \
                auth->naf_flags &= ~flags;                              \
index 4eb93b2b6473bcce92f912908a0790485db15e85..e29279e6b577dd564e8271f95c171838ead5ca39 100644 (file)
@@ -1403,11 +1403,6 @@ old_sess_out:
 
 out:
        stop = kthread_should_stop();
-       if (!stop && signal_pending(current)) {
-               spin_lock_bh(&np->np_thread_lock);
-               stop = (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN);
-               spin_unlock_bh(&np->np_thread_lock);
-       }
        /* Wait for another socket.. */
        if (!stop)
                return 1;
@@ -1415,7 +1410,6 @@ exit:
        iscsi_stop_login_thread_timer(np);
        spin_lock_bh(&np->np_thread_lock);
        np->np_thread_state = ISCSI_NP_THREAD_EXIT;
-       np->np_thread = NULL;
        spin_unlock_bh(&np->np_thread_lock);
 
        return 0;
index 207b340498a3645231dbb2ae449e48f052e3313f..d06de84b069bb0c283495bdf09da4b3e9b96ba2f 100644 (file)
@@ -1106,6 +1106,11 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
        dev->dev_attrib.block_size = block_size;
        pr_debug("dev[%p]: SE Device block_size changed to %u\n",
                        dev, block_size);
+
+       if (dev->dev_attrib.max_bytes_per_io)
+               dev->dev_attrib.hw_max_sectors =
+                       dev->dev_attrib.max_bytes_per_io / block_size;
+
        return 0;
 }
 
index 0e34cda3271e9bb3291b06a934c1ef7136488811..78241a53b555fc5600d0a6ffe7b8d8b4e15687d0 100644 (file)
@@ -66,9 +66,8 @@ static int fd_attach_hba(struct se_hba *hba, u32 host_id)
        pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
                " Target Core Stack %s\n", hba->hba_id, FD_VERSION,
                TARGET_CORE_MOD_VERSION);
-       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic"
-               " MaxSectors: %u\n",
-               hba->hba_id, fd_host->fd_host_id, FD_MAX_SECTORS);
+       pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n",
+               hba->hba_id, fd_host->fd_host_id);
 
        return 0;
 }
@@ -220,7 +219,8 @@ static int fd_configure_device(struct se_device *dev)
        }
 
        dev->dev_attrib.hw_block_size = fd_dev->fd_block_size;
-       dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS;
+       dev->dev_attrib.max_bytes_per_io = FD_MAX_BYTES;
+       dev->dev_attrib.hw_max_sectors = FD_MAX_BYTES / fd_dev->fd_block_size;
        dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH;
 
        if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) {
index 37ffc5bd23992a5f1e1124b2c6eba9889e7119ff..d7772c167685fecc89caf699884198b9a9d9f999 100644 (file)
@@ -7,7 +7,10 @@
 #define FD_DEVICE_QUEUE_DEPTH  32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE           512
-#define FD_MAX_SECTORS         2048
+/*
+ * Limited by the number of iovecs (2048) per vfs_[writev,readv] call
+ */
+#define FD_MAX_BYTES           8388608
 
 #define RRF_EMULATE_CDB                0x01
 #define RRF_GOT_LBA            0x02
index f697f8baec5418d13484904bf3730880f90639fd..2a573de19a9fdceea07d233f15a699be6c10c770 100644 (file)
@@ -278,7 +278,6 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
        acl->dynamic_node_acl = 1;
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
@@ -406,7 +405,6 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
        acl->se_tpg = tpg;
        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
-       spin_lock_init(&acl->stats_lock);
 
        tpg->se_tpg_tfo->set_default_node_attributes(acl);
 
@@ -658,15 +656,9 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
        spin_lock_init(&lun->lun_sep_lock);
        init_completion(&lun->lun_ref_comp);
 
-       ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
-       if (ret < 0)
-               return ret;
-
        ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
-       if (ret < 0) {
-               percpu_ref_cancel_init(&lun->lun_ref);
+       if (ret < 0)
                return ret;
-       }
 
        return 0;
 }
index 8f181b3f842b3b04b12d972da58d8f238b6a7a00..d833c8f5b465d4a96e5ee0d34de8758e1035169e 100644 (file)
@@ -438,14 +438,12 @@ static int clamp_thread(void *arg)
                         */
                        local_touch_nmi();
                        stop_critical_timings();
-                       __monitor((void *)&current_thread_info()->flags, 0, 0);
-                       cpu_relax(); /* allow HT sibling to run */
-                       __mwait(eax, ecx);
+                       mwait_idle_with_hints(eax, ecx);
                        start_critical_timings();
                        atomic_inc(&idle_wakeup_counter);
                }
                tick_nohz_idle_exit();
-               preempt_enable_no_resched();
+               preempt_enable();
        }
        del_timer_sync(&wakeup_timer);
        clear_bit(cpunr, cpu_clamping_mask);
index 0f74945af624962266803ce242ef10509906a6a4..34aacaaae14ab9b595ea41744504c2cbc65b9ff3 100644 (file)
@@ -93,6 +93,7 @@ struct n_tty_data {
        size_t canon_head;
        size_t echo_head;
        size_t echo_commit;
+       size_t echo_mark;
        DECLARE_BITMAP(char_map, 256);
 
        /* private to n_tty_receive_overrun (single-threaded) */
@@ -336,6 +337,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
 {
        ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
        ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
+       ldata->echo_mark = 0;
        ldata->line_start = 0;
 
        ldata->erasing = 0;
@@ -787,6 +789,7 @@ static void commit_echoes(struct tty_struct *tty)
        size_t head;
 
        head = ldata->echo_head;
+       ldata->echo_mark = head;
        old = ldata->echo_commit - ldata->echo_tail;
 
        /* Process committed echoes if the accumulated # of bytes
@@ -810,10 +813,12 @@ static void process_echoes(struct tty_struct *tty)
        struct n_tty_data *ldata = tty->disc_data;
        size_t echoed;
 
-       if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail)
+       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
+           ldata->echo_mark == ldata->echo_tail)
                return;
 
        mutex_lock(&ldata->output_lock);
+       ldata->echo_commit = ldata->echo_mark;
        echoed = __process_echoes(tty);
        mutex_unlock(&ldata->output_lock);
 
@@ -821,11 +826,13 @@ static void process_echoes(struct tty_struct *tty)
                tty->ops->flush_chars(tty);
 }
 
+/* NB: echo_mark and echo_head should be equivalent here */
 static void flush_echoes(struct tty_struct *tty)
 {
        struct n_tty_data *ldata = tty->disc_data;
 
-       if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head)
+       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
+           ldata->echo_commit == ldata->echo_head)
                return;
 
        mutex_lock(&ldata->output_lock);
index 4658e3e0ec4256d9b2e31f890ea72822abf47f93..06525f10e3641bc2140b140a50d8b994acd662d3 100644 (file)
@@ -96,7 +96,8 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
@@ -132,7 +133,8 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR) {
                int tries = 1000;
                while (tries--) {
-                       if (value == p->serial_in(p, UART_LCR))
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
                                return;
                        dw8250_force_idle(p);
                        writel(value, p->membase + (UART_LCR << p->regshift));
@@ -455,6 +457,8 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
 static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT33C4", 0 },
        { "INT33C5", 0 },
+       { "INT3434", 0 },
+       { "INT3435", 0 },
        { "80860F0A", 0 },
        { },
 };
index e46e9f3f19b90d34476b60a2e21aa656fc3c8fae..f619ad5b5eaefc891b6857c03edd942492198e18 100644 (file)
@@ -240,6 +240,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                        continue;
                        }
 
+#ifdef SUPPORT_SYSRQ
                        /*
                         * uart_handle_sysrq_char() doesn't work if
                         * spinlocked, for some reason
@@ -253,6 +254,7 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id)
                                }
                                spin_lock(&port->lock);
                        }
+#endif
 
                        port->icount.rx++;
 
index 22fad8ad5ac206c4cf22f820e9a4cf5c3f6cd8bd..d8a55e87877f06f3141602e4f08cdcb668c465b0 100644 (file)
@@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem)
        return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
+/*
+ * ldsem_cmpxchg() updates @*old with the last-known sem->count value.
+ * Returns 1 if count was successfully changed; @*old will have @new value.
+ * Returns 0 if count was not changed; @*old will have most recent sem->count
+ */
 static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem)
 {
-       long tmp = *old;
-       *old = atomic_long_cmpxchg(&sem->count, *old, new);
-       return *old == tmp;
+       long tmp = atomic_long_cmpxchg(&sem->count, *old, new);
+       if (tmp == *old) {
+               *old = new;
+               return 1;
+       } else {
+               *old = tmp;
+               return 0;
+       }
 }
 
 /*
index 67beb84449304d987c68a544c02b9c6e428dce1a..f7beb6eb40c714ae71309807b94b55a643501a9f 100644 (file)
@@ -653,6 +653,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
                return -EINVAL;
        mem = idev->info->mem + mi;
 
+       if (mem->addr & ~PAGE_MASK)
+               return -ENODEV;
        if (vma->vm_end - vma->vm_start > mem->size)
                return -EINVAL;
 
index 5d8981c5235e50e42776cfb9f672977c11a61ef0..6e73f8cd60e513ca44de8d6bd00fe69085e4453f 100644 (file)
@@ -642,6 +642,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                        : CI_ROLE_GADGET;
        }
 
+       /* only update vbus status for peripheral */
+       if (ci->role == CI_ROLE_GADGET)
+               ci_handle_vbus_change(ci);
+
        ret = ci_role_start(ci, ci->role);
        if (ret) {
                dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
index 59e6020ea7539e5e331364ac067c9a16f27855ba..526cd77563d8a89c29f5444901ee3ba366b1575a 100644 (file)
@@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci)
        return ret;
 
 disable_reg:
-       regulator_disable(ci->platdata->reg_vbus);
+       if (ci->platdata->reg_vbus)
+               regulator_disable(ci->platdata->reg_vbus);
 
 put_hcd:
        usb_put_hcd(hcd);
index b34c81969cba672a7e880f405f2445adf36b7e6f..69d20fbb38a26a32357cc9f5d7fc4f81efa08cca 100644 (file)
@@ -1795,9 +1795,6 @@ static int udc_start(struct ci_hdrc *ci)
        pm_runtime_no_callbacks(&ci->gadget.dev);
        pm_runtime_enable(&ci->gadget.dev);
 
-       /* Update ci->vbus_active */
-       ci_handle_vbus_change(ci);
-
        return retval;
 
 destroy_eps:
index 3e7560f004f86d7153ed3ea0eeabed09dabf6b47..e8404319ca68b93d7b1d05b881b4d1bed8d1ded8 100644 (file)
@@ -1515,6 +1515,8 @@ static int acm_reset_resume(struct usb_interface *intf)
 
 static const struct usb_device_id acm_ids[] = {
        /* quirky and broken devices */
+       { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
+       .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
index 4d387596f3f0a6e531caa1a9049a383d605091b4..0b23a8639311b182ee9e2afddcec1cb888269257 100644 (file)
@@ -854,13 +854,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on)
 {
        /* need autopm_get/put here to ensure the usbcore sees the new value */
        int rv = usb_autopm_get_interface(intf);
-       if (rv < 0)
-               goto err;
 
        intf->needs_remote_wakeup = on;
-       usb_autopm_put_interface(intf);
-err:
-       return rv;
+       if (!rv)
+               usb_autopm_put_interface(intf);
+       return 0;
 }
 
 static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
index a7c04e24ca484deb233db5dcfd995b73427c4cc0..bd9dc3504b5149b2ff5091d67bb514a92cbc0a88 100644 (file)
@@ -4832,8 +4832,9 @@ static void hub_events(void)
                                        hub->ports[i - 1]->child;
 
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
-                               if (!udev || !(portstatus &
-                                               USB_PORT_STAT_CONNECTION)) {
+                               if (!udev ||
+                                   !(portstatus & USB_PORT_STAT_CONNECTION) ||
+                                   udev->state == USB_STATE_NOTATTACHED) {
                                        status = hub_port_reset(hub, i,
                                                        NULL, HUB_BH_RESET_TIME,
                                                        true);
index 74f9cf02da070a6d1c23b643a56f76e3264fb8cd..a49217ae35333846bb76912666f0efa12bca6813 100644 (file)
@@ -455,9 +455,6 @@ static int dwc3_probe(struct platform_device *pdev)
        if (IS_ERR(regs))
                return PTR_ERR(regs);
 
-       usb_phy_set_suspend(dwc->usb2_phy, 0);
-       usb_phy_set_suspend(dwc->usb3_phy, 0);
-
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
 
@@ -488,6 +485,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err0;
        }
 
+       usb_phy_set_suspend(dwc->usb2_phy, 0);
+       usb_phy_set_suspend(dwc->usb3_phy, 0);
+
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
@@ -569,6 +569,8 @@ err2:
        dwc3_event_buffers_cleanup(dwc);
 
 err1:
+       usb_phy_set_suspend(dwc->usb2_phy, 1);
+       usb_phy_set_suspend(dwc->usb3_phy, 1);
        dwc3_core_exit(dwc);
 
 err0:
index 95f7649c71a78745692a63bafd1527daacda52e3..21a352079bc25fdd0fe33ddba1a3191b29b812f0 100644 (file)
@@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                        dep = dwc3_wIndex_to_dep(dwc, wIndex);
                        if (!dep)
                                return -EINVAL;
+                       if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
+                               break;
                        ret = __dwc3_gadget_ep_set_halt(dep, set);
                        if (ret)
                                return -EINVAL;
index 5452c0fce36074d4238e3553bb00d879d8df9ac3..02e44fcaf205e3eaf4a69e706c41d6e081c6c1e5 100644 (file)
@@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               if (dep->flags & DWC3_EP_WEDGE)
-                       return 0;
-
                ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
                        DWC3_DEPCMD_CLEARSTALL, &params);
                if (ret)
@@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                                        value ? "set" : "clear",
                                        dep->name);
                else
-                       dep->flags &= ~DWC3_EP_STALL;
+                       dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
        }
 
        return ret;
index a91e6422f93021f912042298a99cdde36362b09b..f66d96ad1f51eb96d1806187dbb564675a02b8f0 100644 (file)
@@ -682,6 +682,7 @@ config USB_CONFIGFS_PHONET
 config USB_CONFIGFS_MASS_STORAGE
        boolean "Mass storage"
        depends on USB_CONFIGFS
+       depends on BLOCK
        select USB_F_MASS_STORAGE
        help
          The Mass Storage Gadget acts as a USB Mass Storage disk drive.
index 3e7ae707f691c4b0cf4b701024d8df0af4a5bb69..2018ba1a2172d4bb26faea20c34e44653070e91f 100644 (file)
@@ -593,6 +593,7 @@ static void reset_config(struct usb_composite_dev *cdev)
                bitmap_zero(f->endpoints, 32);
        }
        cdev->config = NULL;
+       cdev->delayed_status = 0;
 }
 
 static int set_config(struct usb_composite_dev *cdev,
index 774e8b89cdb593bf951b5c82e97c169f921a6130..241fc873ffa4569fcc98a3a93ff98e3f07339d72 100644 (file)
@@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void)
 {
        struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
        if (unlikely(!ffs))
-               return 0;
+               return NULL;
 
        ENTER();
 
index a03ba2c83589ee15f9c1880d17f1aa133eb47f29..b963939088606e7e9252ec1f55d42ff9fdd1dcd3 100644 (file)
@@ -523,7 +523,7 @@ static int fsg_setup(struct usb_function *f,
                 */
                DBG(fsg, "bulk reset request\n");
                raise_exception(fsg->common, FSG_STATE_RESET);
-               return DELAYED_STATUS;
+               return USB_GADGET_DELAYED_STATUS;
 
        case US_BULK_GET_MAX_LUN:
                if (ctrl->bRequestType !=
@@ -602,13 +602,14 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
        return true;
 }
 
-static int sleep_thread(struct fsg_common *common)
+static int sleep_thread(struct fsg_common *common, bool can_freeze)
 {
        int     rc = 0;
 
        /* Wait until a signal arrives or we are woken up */
        for (;;) {
-               try_to_freeze();
+               if (can_freeze)
+                       try_to_freeze();
                set_current_state(TASK_INTERRUPTIBLE);
                if (signal_pending(current)) {
                        rc = -EINTR;
@@ -682,7 +683,7 @@ static int do_read(struct fsg_common *common)
                /* Wait for the next buffer to become available */
                bh = common->next_buffhd_to_fill;
                while (bh->state != BUF_STATE_EMPTY) {
-                       rc = sleep_thread(common);
+                       rc = sleep_thread(common, false);
                        if (rc)
                                return rc;
                }
@@ -937,7 +938,7 @@ static int do_write(struct fsg_common *common)
                }
 
                /* Wait for something to happen */
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, false);
                if (rc)
                        return rc;
        }
@@ -1504,7 +1505,7 @@ static int throw_away_data(struct fsg_common *common)
                }
 
                /* Otherwise wait for something to happen */
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -1625,7 +1626,7 @@ static int send_status(struct fsg_common *common)
        /* Wait for the next buffer to become available */
        bh = common->next_buffhd_to_fill;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -1828,7 +1829,7 @@ static int do_scsi_command(struct fsg_common *common)
        bh = common->next_buffhd_to_fill;
        common->next_buffhd_to_drain = bh;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2174,7 +2175,7 @@ static int get_next_command(struct fsg_common *common)
        /* Wait for the next buffer to become available */
        bh = common->next_buffhd_to_fill;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2193,7 +2194,7 @@ static int get_next_command(struct fsg_common *common)
 
        /* Wait for the CBW to arrive */
        while (bh->state != BUF_STATE_FULL) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2379,7 +2380,7 @@ static void handle_exception(struct fsg_common *common)
                        }
                        if (num_active == 0)
                                break;
-                       if (sleep_thread(common))
+                       if (sleep_thread(common, true))
                                return;
                }
 
@@ -2516,7 +2517,7 @@ static int fsg_main_thread(void *common_)
                }
 
                if (!common->running) {
-                       sleep_thread(common);
+                       sleep_thread(common, true);
                        continue;
                }
 
@@ -3111,7 +3112,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
                                          fsg->common->can_stall);
                if (ret)
                        return ret;
-               fsg_common_set_inquiry_string(fsg->common, 0, 0);
+               fsg_common_set_inquiry_string(fsg->common, NULL, NULL);
                ret = fsg_common_run_thread(fsg->common);
                if (ret)
                        return ret;
index 0ac6064aa3b86b6cd2376324ac9996f8ece1c0a0..409a3c45a36af1ec596ad4d9bf2c117c9f493444 100644 (file)
@@ -54,6 +54,7 @@
  */
 #ifdef CONFIG_ARCH_PXA
 #include <mach/pxa25x-udc.h>
+#include <mach/hardware.h>
 #endif
 
 #ifdef CONFIG_ARCH_LUBBOCK
index 9875d9c0823f7c554744a40acb0a70897dde0bc6..e20bc109fdd70f43eec9e1572d3fa8f75e6ba423 100644 (file)
@@ -1180,6 +1180,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
 }
 
 static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
+static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
 
 /**
  * s3c_hsotg_process_control - process a control request
@@ -1221,6 +1222,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
        if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
                switch (ctrl->bRequest) {
                case USB_REQ_SET_ADDRESS:
+                       s3c_hsotg_disconnect(hsotg);
                        dcfg = readl(hsotg->regs + DCFG);
                        dcfg &= ~DCFG_DevAddr_MASK;
                        dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
@@ -1245,7 +1247,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
        /* as a fallback, try delivering it to the driver to deal with */
 
        if (ret == 0 && hsotg->driver) {
+               spin_unlock(&hsotg->lock);
                ret = hsotg->driver->setup(&hsotg->gadget, ctrl);
+               spin_lock(&hsotg->lock);
                if (ret < 0)
                        dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
        }
@@ -1308,10 +1312,12 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
                return;
        }
 
+       spin_lock(&hsotg->lock);
        if (req->actual == 0)
                s3c_hsotg_enqueue_setup(hsotg);
        else
                s3c_hsotg_process_control(hsotg, req->buf);
+       spin_unlock(&hsotg->lock);
 }
 
 /**
@@ -2533,7 +2539,6 @@ irq_retry:
                writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
 
                call_gadget(hsotg, suspend);
-               s3c_hsotg_disconnect(hsotg);
        }
 
        if (gintsts & GINTSTS_WkUpInt) {
index c74c2fdbd56eda5683a13995a96b6221711c30ef..70c891469f574ebd1d7719fc05bcf838d1d6e3cb 100644 (file)
@@ -119,10 +119,6 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
        return curlun->filp != NULL;
 }
 
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE    256
-#define DELAYED_STATUS (EP0_BUFSIZE + 999)     /* An impossibly large value */
-
 /* Default size of buffer length. */
 #define FSG_BUFLEN     ((u32)16384)
 
index 6c3d7950d2a9e56d5231938493127c0964f04221..0f8aad78b54f7095a26b6e413a22ff5ae1e016df 100644 (file)
@@ -370,7 +370,7 @@ err:
        return -ENOMEM;
 }
 
-void bot_cleanup_old_alt(struct f_uas *fu)
+static void bot_cleanup_old_alt(struct f_uas *fu)
 {
        if (!(fu->flags & USBG_ENABLED))
                return;
index 0dd07ae1555ddf066312e0ff4e8182a02f27a3d6..f49b0b61ecc8163941447e8ba5b719982951531e 100644 (file)
@@ -91,17 +91,17 @@ static struct usb_zero_options gzero_options = {
  * functional coverage for the "USBCV" test harness from USB-IF.
  * It's always set if OTG mode is enabled.
  */
-unsigned autoresume = DEFAULT_AUTORESUME;
+static unsigned autoresume = DEFAULT_AUTORESUME;
 module_param(autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
 
 /* Maximum Autoresume time */
-unsigned max_autoresume;
+static unsigned max_autoresume;
 module_param(max_autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup");
 
 /* Interval between two remote wakeups */
-unsigned autoresume_interval_ms;
+static unsigned autoresume_interval_ms;
 module_param(autoresume_interval_ms, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume_interval_ms,
                "milliseconds to increase successive wakeup delays");
index 418444ebb1b8bb1fd1862fc9233c7562c5c40d81..8c356af79409f9ef4647d141bc6aa5146791496b 100644 (file)
@@ -136,23 +136,27 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        struct ohci_hcd *ohci;
        int retval;
        struct usb_hcd *hcd = NULL;
-
-       if (pdev->num_resources != 2) {
-               pr_debug("hcd probe: invalid num_resources");
-               return -ENODEV;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int irq;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_dbg(dev, "hcd probe: missing memory resource\n");
+               return -ENXIO;
        }
 
-       if ((pdev->resource[0].flags != IORESOURCE_MEM)
-                       || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-               pr_debug("hcd probe: invalid resource type\n");
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_dbg(dev, "hcd probe: missing irq resource\n");
+               return irq;
        }
 
        hcd = usb_create_hcd(driver, &pdev->dev, "at91");
        if (!hcd)
                return -ENOMEM;
-       hcd->rsrc_start = pdev->resource[0].start;
-       hcd->rsrc_len = resource_size(&pdev->resource[0]);
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len = resource_size(res);
 
        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
                pr_debug("request_mem_region failed\n");
@@ -199,7 +203,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        ohci->num_ports = board->ports;
        at91_start_hc(pdev);
 
-       retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval == 0)
                return retval;
 
index e89ac4d4b87e5be4d4a134e389dbdfa20931eb9c..9b7435f0dcd6b432f0c7fa9fcc096817e7141712 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index b8dffd59eb256e52786328e5e4f1919846a80d9c..73f5208714a4a4d8270bd85acd1ec625fb9abf71 100644 (file)
@@ -128,7 +128,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * any other sleep) on Haswell machines with LPT and LPT-LP
                 * with the new Intel BIOS
                 */
-               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+               /* Limit the quirk to only known vendors, as this triggers
+                * yet another BIOS bug on some other machines
+                * https://bugzilla.kernel.org/show_bug.cgi?id=66171
+                */
+               if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
+                       xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
index 1e2f3f4958436fb120b81d41632ad7e7c76fb5b5..53c2e296467fcabbb8139361f6b422829f97cae4 100644 (file)
@@ -2973,8 +2973,58 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
        }
 
        while (1) {
-               if (room_on_ring(xhci, ep_ring, num_trbs))
-                       break;
+               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 -ENOMEM;
+                       }
+
+                       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 (ep_ring == xhci->cmd_ring) {
                        xhci_err(xhci, "Do not support expand command ring\n");
index 0a43329569d178de72a5c8ee619e7206c360c51c..4d4499b8044971a8db410579f7965e9b6d862c38 100644 (file)
@@ -1809,7 +1809,6 @@ static void musb_free(struct musb *musb)
                        disable_irq_wake(musb->nIrq);
                free_irq(musb->nIrq, musb);
        }
-       cancel_work_sync(&musb->irq_work);
 
        musb_host_free(musb);
 }
@@ -1896,6 +1895,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_platform_disable(musb);
        musb_generic_disable(musb);
 
+       /* Init IRQ workqueue before request_irq */
+       INIT_WORK(&musb->irq_work, musb_irq_work);
+
        /* setup musb parts of the core (especially endpoints) */
        status = musb_core_init(plat->config->multipoint
                        ? MUSB_CONTROLLER_MHDRC
@@ -1905,9 +1907,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
 
-       /* Init IRQ workqueue before request_irq */
-       INIT_WORK(&musb->irq_work, musb_irq_work);
-
        /* attach to the IRQ */
        if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
                dev_err(dev, "request_irq %d failed!\n", nIrq);
@@ -1981,6 +1980,7 @@ fail4:
        musb_host_cleanup(musb);
 
 fail3:
+       cancel_work_sync(&musb->irq_work);
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 fail2_5:
@@ -2043,6 +2043,7 @@ static int musb_remove(struct platform_device *pdev)
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 
+       cancel_work_sync(&musb->irq_work);
        musb_free(musb);
        device_init_wakeup(dev, 0);
        return 0;
index ff9d6de2b7465c949d54ae4801108a3800f4be3f..a12bd30401e076fe0e502789e300c05ecc770bb1 100644 (file)
@@ -38,6 +38,7 @@ struct cppi41_dma_channel {
        u32 prog_len;
        u32 transferred;
        u32 packet_sz;
+       struct list_head tx_check;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -47,6 +48,8 @@ struct cppi41_dma_controller {
        struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS];
        struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS];
        struct musb *musb;
+       struct hrtimer early_tx;
+       struct list_head early_tx_list;
        u32 rx_mode;
        u32 tx_mode;
        u32 auto_req;
@@ -96,31 +99,27 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
        cppi41_channel->usb_toggle = toggle;
 }
 
-static void cppi41_dma_callback(void *private_data)
+static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
 {
-       struct dma_channel *channel = private_data;
-       struct cppi41_dma_channel *cppi41_channel = channel->private_data;
-       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
-       struct musb *musb = hw_ep->musb;
-       unsigned long flags;
-       struct dma_tx_state txstate;
-       u32 transferred;
+       u8              epnum = hw_ep->epnum;
+       struct musb     *musb = hw_ep->musb;
+       void __iomem    *epio = musb->endpoints[epnum].regs;
+       u16             csr;
 
-       spin_lock_irqsave(&musb->lock, flags);
+       csr = musb_readw(epio, MUSB_TXCSR);
+       if (csr & MUSB_TXCSR_TXPKTRDY)
+               return false;
+       return true;
+}
 
-       dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
-                       &txstate);
-       transferred = cppi41_channel->prog_len - txstate.residue;
-       cppi41_channel->transferred += transferred;
+static void cppi41_dma_callback(void *private_data);
 
-       dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
-               hw_ep->epnum, cppi41_channel->transferred,
-               cppi41_channel->total_len);
+static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
+{
+       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+       struct musb *musb = hw_ep->musb;
 
-       update_rx_toggle(cppi41_channel);
-
-       if (cppi41_channel->transferred == cppi41_channel->total_len ||
-                       transferred < cppi41_channel->packet_sz) {
+       if (!cppi41_channel->prog_len) {
 
                /* done, complete */
                cppi41_channel->channel.actual_len =
@@ -150,13 +149,11 @@ static void cppi41_dma_callback(void *private_data)
                                remain_bytes,
                                direction,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (WARN_ON(!dma_desc)) {
-                       spin_unlock_irqrestore(&musb->lock, flags);
+               if (WARN_ON(!dma_desc))
                        return;
-               }
 
                dma_desc->callback = cppi41_dma_callback;
-               dma_desc->callback_param = channel;
+               dma_desc->callback_param = &cppi41_channel->channel;
                cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
                dma_async_issue_pending(dc);
 
@@ -166,6 +163,117 @@ static void cppi41_dma_callback(void *private_data)
                        musb_writew(epio, MUSB_RXCSR, csr);
                }
        }
+}
+
+static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
+{
+       struct cppi41_dma_controller *controller;
+       struct cppi41_dma_channel *cppi41_channel, *n;
+       struct musb *musb;
+       unsigned long flags;
+       enum hrtimer_restart ret = HRTIMER_NORESTART;
+
+       controller = container_of(timer, struct cppi41_dma_controller,
+                       early_tx);
+       musb = controller->musb;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list,
+                       tx_check) {
+               bool empty;
+               struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+
+               empty = musb_is_tx_fifo_empty(hw_ep);
+               if (empty) {
+                       list_del_init(&cppi41_channel->tx_check);
+                       cppi41_trans_done(cppi41_channel);
+               }
+       }
+
+       if (!list_empty(&controller->early_tx_list)) {
+               ret = HRTIMER_RESTART;
+               hrtimer_forward_now(&controller->early_tx,
+                               ktime_set(0, 150 * NSEC_PER_USEC));
+       }
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return ret;
+}
+
+static void cppi41_dma_callback(void *private_data)
+{
+       struct dma_channel *channel = private_data;
+       struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+       struct musb *musb = hw_ep->musb;
+       unsigned long flags;
+       struct dma_tx_state txstate;
+       u32 transferred;
+       bool empty;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
+                       &txstate);
+       transferred = cppi41_channel->prog_len - txstate.residue;
+       cppi41_channel->transferred += transferred;
+
+       dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
+               hw_ep->epnum, cppi41_channel->transferred,
+               cppi41_channel->total_len);
+
+       update_rx_toggle(cppi41_channel);
+
+       if (cppi41_channel->transferred == cppi41_channel->total_len ||
+                       transferred < cppi41_channel->packet_sz)
+               cppi41_channel->prog_len = 0;
+
+       empty = musb_is_tx_fifo_empty(hw_ep);
+       if (empty) {
+               cppi41_trans_done(cppi41_channel);
+       } else {
+               struct cppi41_dma_controller *controller;
+               /*
+                * On AM335x it has been observed that the TX interrupt fires
+                * too early that means the TXFIFO is not yet empty but the DMA
+                * engine says that it is done with the transfer. We don't
+                * receive a FIFO empty interrupt so the only thing we can do is
+                * to poll for the bit. On HS it usually takes 2us, on FS around
+                * 110us - 150us depending on the transfer size.
+                * We spin on HS (no longer than than 25us and setup a timer on
+                * FS to check for the bit and complete the transfer.
+                */
+               controller = cppi41_channel->controller;
+
+               if (musb->g.speed == USB_SPEED_HIGH) {
+                       unsigned wait = 25;
+
+                       do {
+                               empty = musb_is_tx_fifo_empty(hw_ep);
+                               if (empty)
+                                       break;
+                               wait--;
+                               if (!wait)
+                                       break;
+                               udelay(1);
+                       } while (1);
+
+                       empty = musb_is_tx_fifo_empty(hw_ep);
+                       if (empty) {
+                               cppi41_trans_done(cppi41_channel);
+                               goto out;
+                       }
+               }
+               list_add_tail(&cppi41_channel->tx_check,
+                               &controller->early_tx_list);
+               if (!hrtimer_active(&controller->early_tx)) {
+                       hrtimer_start_range_ns(&controller->early_tx,
+                               ktime_set(0, 140 * NSEC_PER_USEC),
+                               40 * NSEC_PER_USEC,
+                               HRTIMER_MODE_REL);
+               }
+       }
+out:
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
@@ -364,6 +472,8 @@ static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
                WARN_ON(1);
                return 1;
        }
+       if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK)
+               return 0;
        if (cppi41_channel->is_tx)
                return 1;
        /* AM335x Advisory 1.0.13. No workaround for device RX mode */
@@ -388,6 +498,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
        if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
                return 0;
 
+       list_del_init(&cppi41_channel->tx_check);
        if (is_tx) {
                csr = musb_readw(epio, MUSB_TXCSR);
                csr &= ~MUSB_TXCSR_DMAENAB;
@@ -495,6 +606,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
                cppi41_channel->controller = controller;
                cppi41_channel->port_num = port;
                cppi41_channel->is_tx = is_tx;
+               INIT_LIST_HEAD(&cppi41_channel->tx_check);
 
                musb_dma = &cppi41_channel->channel;
                musb_dma->private_data = cppi41_channel;
@@ -520,6 +632,7 @@ void dma_controller_destroy(struct dma_controller *c)
        struct cppi41_dma_controller *controller = container_of(c,
                        struct cppi41_dma_controller, controller);
 
+       hrtimer_cancel(&controller->early_tx);
        cppi41_dma_controller_stop(controller);
        kfree(controller);
 }
@@ -539,6 +652,9 @@ struct dma_controller *dma_controller_create(struct musb *musb,
        if (!controller)
                goto kzalloc_fail;
 
+       hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       controller->early_tx.function = cppi41_recheck_tx_req;
+       INIT_LIST_HEAD(&controller->early_tx_list);
        controller->musb = musb;
 
        controller->controller.channel_alloc = cppi41_dma_channel_allocate;
index d2d3a173b31503b54f9071e9af48f4878567856f..32fb057c03f58e25f401bdb49755e2cdc2637e86 100644 (file)
@@ -1796,7 +1796,11 @@ int musb_gadget_setup(struct musb *musb)
 
        /* this "gadget" abstracts/virtualizes the controller */
        musb->g.name = musb_driver_name;
+#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE)
        musb->g.is_otg = 1;
+#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET)
+       musb->g.is_otg = 0;
+#endif
 
        musb_g_init_endpoints(musb);
 
index 08e2f39027ec00ae0a7c5ae07b46fdd1cdbfae8f..2b41c636a52a7a1ecf3ae0e3df622d141307c038 100644 (file)
@@ -19,8 +19,9 @@ config AB8500_USB
          in host mode, low speed.
 
 config FSL_USB2_OTG
-       bool "Freescale USB OTG Transceiver Driver"
+       tristate "Freescale USB OTG Transceiver Driver"
        depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
+       depends on USB
        select USB_OTG
        select USB_PHY
        help
@@ -29,6 +30,7 @@ config FSL_USB2_OTG
 config ISP1301_OMAP
        tristate "Philips ISP1301 with OMAP OTG"
        depends on I2C && ARCH_OMAP_OTG
+       depends on USB
        select USB_PHY
        help
          If you say yes here you get support for the Philips ISP1301
index 6370e50649d7f732c640fd65879c26d82ec5f994..0e3c60cb669a63c7a1d1bb7bd673f212f854c425 100644 (file)
@@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
                return am_phy->id;
        }
 
-       ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
-                       USB_PHY_TYPE_USB2, 0, false);
+       ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL);
        if (ret)
                return ret;
 
@@ -66,8 +65,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, am_phy);
 
        return 0;
-
-       return ret;
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
index fce3a9e9bb5d282ff6b1a64492ad6a55c90e654f..aa6d37b3378ad65ff26e336031173a9ae52d2287 100644 (file)
@@ -48,8 +48,9 @@ void usb_nop_xceiv_register(void)
        if (pd)
                return;
        pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
-       if (!pd) {
+       if (IS_ERR(pd)) {
                pr_err("Unable to register generic usb transceiver\n");
+               pd = NULL;
                return;
        }
 }
@@ -150,10 +151,40 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 }
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc)
+               struct usb_phy_gen_xceiv_platform_data *pdata)
 {
+       enum usb_phy_type type = USB_PHY_TYPE_USB2;
        int err;
 
+       u32 clk_rate = 0;
+       bool needs_vcc = false;
+
+       nop->reset_active_low = true;   /* default behaviour */
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+               enum of_gpio_flags flags = 0;
+
+               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+                       clk_rate = 0;
+
+               needs_vcc = of_property_read_bool(node, "vcc-supply");
+               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
+                                                               0, &flags);
+               if (nop->gpio_reset == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+       } else if (pdata) {
+               type = pdata->type;
+               clk_rate = pdata->clk_rate;
+               needs_vcc = pdata->needs_vcc;
+               nop->gpio_reset = pdata->gpio_reset;
+       } else {
+               nop->gpio_reset = -1;
+       }
+
        nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
                        GFP_KERNEL);
        if (!nop->phy.otg)
@@ -218,43 +249,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
 static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct usb_phy_gen_xceiv_platform_data *pdata =
-                       dev_get_platdata(&pdev->dev);
        struct usb_phy_gen_xceiv        *nop;
-       enum usb_phy_type       type = USB_PHY_TYPE_USB2;
        int err;
-       u32 clk_rate = 0;
-       bool needs_vcc = false;
 
        nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
        if (!nop)
                return -ENOMEM;
 
-       nop->reset_active_low = true;   /* default behaviour */
-
-       if (dev->of_node) {
-               struct device_node *node = dev->of_node;
-               enum of_gpio_flags flags;
-
-               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
-                       clk_rate = 0;
-
-               needs_vcc = of_property_read_bool(node, "vcc-supply");
-               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
-                                                               0, &flags);
-               if (nop->gpio_reset == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
-
-       } else if (pdata) {
-               type = pdata->type;
-               clk_rate = pdata->clk_rate;
-               needs_vcc = pdata->needs_vcc;
-               nop->gpio_reset = pdata->gpio_reset;
-       }
-
-       err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc);
+       err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev));
        if (err)
                return err;
 
@@ -271,8 +273,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, nop);
 
        return 0;
-
-       return err;
 }
 
 static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
index d2a220d81734ad5be296f56c3b416aa321bfb63e..38a81f307b8220bc5dfc81487a9fb420e397ccd1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PHY_GENERIC_H_
 #define _PHY_GENERIC_H_
 
+#include <linux/usb/usb_phy_gen_xceiv.h>
+
 struct usb_phy_gen_xceiv {
        struct usb_phy phy;
        struct device *dev;
@@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy);
 void usb_gen_phy_shutdown(struct usb_phy *phy);
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc);
+               struct usb_phy_gen_xceiv_platform_data *pdata);
 
 #endif
index fdd33b44dbd31b929eb13a2c0bd138570ccebc37..545844b7e7962f809f33812d9167f039b5fbc8d1 100644 (file)
@@ -164,7 +164,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 
        mxs_phy->clk = clk;
 
-       platform_set_drvdata(pdev, &mxs_phy->phy);
+       platform_set_drvdata(pdev, mxs_phy);
 
        ret = usb_add_phy_dev(&mxs_phy->phy);
        if (ret)
index a99a6953f11cc1988272b9ae2d4e917073eb458f..db3ab34cddb4cbc6be6df4e66596b11186235477 100644 (file)
@@ -107,10 +107,10 @@ static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv)
        clk_prepare_enable(priv->clk);
 
        /* Set USB channels in the USBHS UGCTRL2 register */
-       val = ioread32(priv->base);
+       val = ioread32(priv->base + USBHS_UGCTRL2_REG);
        val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS);
        val |= priv->ugctrl2;
-       iowrite32(val, priv->base);
+       iowrite32(val, priv->base + USBHS_UGCTRL2_REG);
 }
 
 /* Shutdown USB channels */
index 82232acf1ab61b17cfbe9d084c3ed2188d554b18..bbe4f8e6e8d7492be10cc54cfe2f37e8001f2db6 100644 (file)
@@ -876,7 +876,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
 
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                resource_size(res));
-       if (!tegra_phy->regs) {
+       if (!tegra_phy->pad_regs) {
                dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
                return -ENOMEM;
        }
index 30e8a61552d4d0526d999c0b49651593f04a5530..bad57ce77ba508e0f6ff8c07fa516e9477606a3c 100644 (file)
@@ -127,7 +127,8 @@ static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
 
 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 {
-       u8 data, ret = 0;
+       u8 data;
+       int ret;
 
        ret = twl_i2c_read_u8(module, &data, address);
        if (ret >= 0)
index 9ced8937a8f3a699dad340e1e9ea62c9d706dc69..fb0d537435eb221019babe694aafefd25b9e90cc 100644 (file)
@@ -2123,6 +2123,20 @@ static void ftdi_set_termios(struct tty_struct *tty,
                termios->c_cflag |= CRTSCTS;
        }
 
+       /*
+        * All FTDI UART chips are limited to CS7/8. We won't pretend to
+        * support CS5/6 and revert the CSIZE setting instead.
+        */
+       if ((C_CSIZE(tty) != CS8) && (C_CSIZE(tty) != CS7)) {
+               dev_warn(ddev, "requested CSIZE setting not supported\n");
+
+               termios->c_cflag &= ~CSIZE;
+               if (old_termios)
+                       termios->c_cflag |= old_termios->c_cflag & CSIZE;
+               else
+                       termios->c_cflag |= CS8;
+       }
+
        cflag = termios->c_cflag;
 
        if (!old_termios)
@@ -2159,19 +2173,16 @@ no_skip:
        } else {
                urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
        }
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS7:
-                       urb_value |= 7;
-                       dev_dbg(ddev, "Setting CS7\n");
-                       break;
-               case CS8:
-                       urb_value |= 8;
-                       dev_dbg(ddev, "Setting CS8\n");
-                       break;
-               default:
-                       dev_err(ddev, "CSIZE was set but not CS7-CS8\n");
-               }
+       switch (cflag & CSIZE) {
+       case CS7:
+               urb_value |= 7;
+               dev_dbg(ddev, "Setting CS7\n");
+               break;
+       default:
+       case CS8:
+               urb_value |= 8;
+               dev_dbg(ddev, "Setting CS8\n");
+               break;
        }
 
        /* This is needed by the break command since it uses the same command
index 2b01ec8651c296e3f016bf2421040da6f1bbbc98..b63ce023f96f1ab7284e218ca68219da5f952440 100644 (file)
@@ -173,16 +173,8 @@ retry:
                clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
                return result;
        }
-       /*
-        * Try sending off another urb, unless called from completion handler
-        * (in which case there will be no free urb or no data).
-        */
-       if (mem_flags != GFP_ATOMIC)
-               goto retry;
 
-       clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
-
-       return 0;
+       goto retry;     /* try sending off another urb */
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_start);
 
@@ -208,7 +200,7 @@ int usb_serial_generic_write(struct tty_struct *tty,
                return 0;
 
        count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
-       result = usb_serial_generic_write_start(port, GFP_KERNEL);
+       result = usb_serial_generic_write_start(port, GFP_ATOMIC);
        if (result)
                return result;
 
index e5bdd987b9e8f7e260fc95c48b142742026999fa..a69da83604c03da3219c2340264cff08b456a404 100644 (file)
@@ -1813,25 +1813,25 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
        iflag = tty->termios.c_iflag;
 
        /* Change the number of bits */
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       lData = LCR_BITS_5;
-                       break;
+       switch (cflag & CSIZE) {
+       case CS5:
+               lData = LCR_BITS_5;
+               break;
 
-               case CS6:
-                       lData = LCR_BITS_6;
-                       break;
+       case CS6:
+               lData = LCR_BITS_6;
+               break;
 
-               case CS7:
-                       lData = LCR_BITS_7;
-                       break;
-               default:
-               case CS8:
-                       lData = LCR_BITS_8;
-                       break;
-               }
+       case CS7:
+               lData = LCR_BITS_7;
+               break;
+
+       default:
+       case CS8:
+               lData = LCR_BITS_8;
+               break;
        }
+
        /* Change the Parity bit */
        if (cflag & PARENB) {
                if (cflag & PARODD) {
index c3d94853b4ab7a2dd13d8f6dea0009f55795ba56..cc7a24154490b29ebb39d4b9d3e72785c4320285 100644 (file)
@@ -85,6 +85,7 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4505                   0x1464
 #define HUAWEI_PRODUCT_K3765                   0x1465
 #define HUAWEI_PRODUCT_K4605                   0x14C6
+#define HUAWEI_PRODUCT_E173S6                  0x1C07
 
 #define QUANTA_VENDOR_ID                       0x0408
 #define QUANTA_PRODUCT_Q101                    0xEA02
@@ -250,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
 #define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AC2726                     0xfff1
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -572,6 +574,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) },
@@ -634,6 +638,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) },
@@ -688,6 +696,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
@@ -742,6 +754,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) },
@@ -796,6 +812,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) },
@@ -850,6 +870,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) },
@@ -904,6 +928,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) },
@@ -1426,6 +1454,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
index 1e6de4cd079d6a2c0e3b4b3c7679d6145bcf6f2c..1e3318dfa1cb569fcbd78ed2079ef026f33a8d16 100644 (file)
@@ -361,23 +361,21 @@ static void pl2303_set_termios(struct tty_struct *tty,
                            0, 0, buf, 7, 100);
        dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);
 
-       if (C_CSIZE(tty)) {
-               switch (C_CSIZE(tty)) {
-               case CS5:
-                       buf[6] = 5;
-                       break;
-               case CS6:
-                       buf[6] = 6;
-                       break;
-               case CS7:
-                       buf[6] = 7;
-                       break;
-               default:
-               case CS8:
-                       buf[6] = 8;
-               }
-               dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
+       switch (C_CSIZE(tty)) {
+       case CS5:
+               buf[6] = 5;
+               break;
+       case CS6:
+               buf[6] = 6;
+               break;
+       case CS7:
+               buf[6] = 7;
+               break;
+       default:
+       case CS8:
+               buf[6] = 8;
        }
+       dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
 
        /* For reference buf[0]:buf[3] baud rate value */
        pl2303_encode_baudrate(tty, port, &buf[0]);
index 4abac28b5992a1f128005f5f7df103118a39b081..5b793c352267751ecd43cce1c7fae9e5a7fac624 100644 (file)
@@ -348,22 +348,20 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
        }
 
        /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       buf[1] |= SET_UART_FORMAT_SIZE_5;
-                       break;
-               case CS6:
-                       buf[1] |= SET_UART_FORMAT_SIZE_6;
-                       break;
-               case CS7:
-                       buf[1] |= SET_UART_FORMAT_SIZE_7;
-                       break;
-               default:
-               case CS8:
-                       buf[1] |= SET_UART_FORMAT_SIZE_8;
-                       break;
-               }
+       switch (cflag & CSIZE) {
+       case CS5:
+               buf[1] |= SET_UART_FORMAT_SIZE_5;
+               break;
+       case CS6:
+               buf[1] |= SET_UART_FORMAT_SIZE_6;
+               break;
+       case CS7:
+               buf[1] |= SET_UART_FORMAT_SIZE_7;
+               break;
+       default:
+       case CS8:
+               buf[1] |= SET_UART_FORMAT_SIZE_8;
+               break;
        }
 
        /* Set Stop bit2 : 0:1bit 1:2bit */
index fca4c752a4ed233199d82a787c0ebfbfff32e71c..eae2c873b39ff7dbb2ecd8d7624a1e2aec14e8ca 100644 (file)
@@ -281,8 +281,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x19d2, 0xfffd) },
        { USB_DEVICE(0x19d2, 0xfffc) },
        { USB_DEVICE(0x19d2, 0xfffb) },
-       /* AC2726, AC8710_V3 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
+       /* AC8710_V3 */
        { USB_DEVICE(0x19d2, 0xfff6) },
        { USB_DEVICE(0x19d2, 0xfff7) },
        { USB_DEVICE(0x19d2, 0xfff8) },
index e538b72c4e3af2d09153614952e12101eac03520..f14e7929ba2278dae601788ab4f07ae657e2e2bb 100644 (file)
@@ -97,18 +97,12 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work);
 
 static void wusb_dev_free(struct wusb_dev *wusb_dev)
 {
-       if (wusb_dev) {
-               kfree(wusb_dev->set_gtk_req);
-               usb_free_urb(wusb_dev->set_gtk_urb);
-               kfree(wusb_dev);
-       }
+       kfree(wusb_dev);
 }
 
 static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 {
        struct wusb_dev *wusb_dev;
-       struct urb *urb;
-       struct usb_ctrlrequest *req;
 
        wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL);
        if (wusb_dev == NULL)
@@ -118,22 +112,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 
        INIT_WORK(&wusb_dev->devconnect_acked_work, wusbhc_devconnect_acked_work);
 
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (urb == NULL)
-               goto err;
-       wusb_dev->set_gtk_urb = urb;
-
-       req = kmalloc(sizeof(*req), GFP_KERNEL);
-       if (req == NULL)
-               goto err;
-       wusb_dev->set_gtk_req = req;
-
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-       req->bRequest = USB_REQ_SET_DESCRIPTOR;
-       req->wValue = cpu_to_le16(USB_DT_KEY << 8 | wusbhc->gtk_index);
-       req->wIndex = 0;
-       req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength);
-
        return wusb_dev;
 err:
        wusb_dev_free(wusb_dev);
@@ -411,9 +389,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
 /*
  * Refresh the list of keep alives to emit in the MMC
  *
- * Some devices don't respond to keep alives unless they've been
- * authenticated, so skip unauthenticated devices.
- *
  * We only publish the first four devices that have a coming timeout
  * condition. Then when we are done processing those, we go for the
  * next ones. We ignore the ones that have timed out already (they'll
@@ -448,7 +423,7 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc)
 
                if (wusb_dev == NULL)
                        continue;
-               if (wusb_dev->usb_dev == NULL || !wusb_dev->usb_dev->authenticated)
+               if (wusb_dev->usb_dev == NULL)
                        continue;
 
                if (time_after(jiffies, wusb_dev->entry_ts + tt)) {
@@ -524,11 +499,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr)
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
+static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr)
 {
+       struct wusb_dev *wusb_dev;
+
        mutex_lock(&wusbhc->mutex);
-       wusb_dev->entry_ts = jiffies;
-       __wusbhc_keep_alive(wusbhc);
+       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+       if (wusb_dev == NULL) {
+               dev_dbg(wusbhc->dev, "ignoring DN_Alive from unconnected device %02x\n",
+                       srcaddr);
+       } else {
+               wusb_dev->entry_ts = jiffies;
+               __wusbhc_keep_alive(wusbhc);
+       }
        mutex_unlock(&wusbhc->mutex);
 }
 
@@ -582,14 +565,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
+static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr)
 {
        struct device *dev = wusbhc->dev;
-
-       dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr);
+       struct wusb_dev *wusb_dev;
 
        mutex_lock(&wusbhc->mutex);
-       __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx));
+       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+       if (wusb_dev == NULL) {
+               dev_dbg(dev, "ignoring DN DISCONNECT from unconnected device %02x\n",
+                       srcaddr);
+       } else {
+               dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n",
+                       wusb_dev->addr);
+               __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc,
+                       wusb_dev->port_idx));
+       }
        mutex_unlock(&wusbhc->mutex);
 }
 
@@ -611,30 +602,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
                      struct wusb_dn_hdr *dn_hdr, size_t size)
 {
        struct device *dev = wusbhc->dev;
-       struct wusb_dev *wusb_dev;
 
        if (size < sizeof(struct wusb_dn_hdr)) {
                dev_err(dev, "DN data shorter than DN header (%d < %d)\n",
                        (int)size, (int)sizeof(struct wusb_dn_hdr));
                return;
        }
-
-       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
-       if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) {
-               dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n",
-                       dn_hdr->bType, srcaddr);
-               return;
-       }
-
        switch (dn_hdr->bType) {
        case WUSB_DN_CONNECT:
                wusbhc_handle_dn_connect(wusbhc, dn_hdr, size);
                break;
        case WUSB_DN_ALIVE:
-               wusbhc_handle_dn_alive(wusbhc, wusb_dev);
+               wusbhc_handle_dn_alive(wusbhc, srcaddr);
                break;
        case WUSB_DN_DISCONNECT:
-               wusbhc_handle_dn_disconnect(wusbhc, wusb_dev);
+               wusbhc_handle_dn_disconnect(wusbhc, srcaddr);
                break;
        case WUSB_DN_MASAVAILCHANGED:
        case WUSB_DN_RWAKE:
index dd88441c8f7891e0d242e1107d6ff585a30999e4..4c40d0dbf53d45c35ae5b05798f1f09566ffc29e 100644 (file)
 #include <linux/export.h>
 #include "wusbhc.h"
 
-static void wusbhc_set_gtk_callback(struct urb *urb);
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work);
+static void wusbhc_gtk_rekey_work(struct work_struct *work);
 
 int wusbhc_sec_create(struct wusbhc *wusbhc)
 {
        wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data);
        wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY;
        wusbhc->gtk.descr.bReserved = 0;
+       wusbhc->gtk_index = 0;
 
-       wusbhc->gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK,
-                                          WUSB_KEY_INDEX_ORIGINATOR_HOST);
-
-       INIT_WORK(&wusbhc->gtk_rekey_done_work, wusbhc_gtk_rekey_done_work);
+       INIT_WORK(&wusbhc->gtk_rekey_work, wusbhc_gtk_rekey_work);
 
        return 0;
 }
@@ -113,7 +110,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
        wusbhc_generate_gtk(wusbhc);
 
        result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
-                                &wusbhc->gtk.descr.bKeyData, key_size);
+                               &wusbhc->gtk.descr.bKeyData, key_size);
        if (result < 0)
                dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n",
                        result);
@@ -129,7 +126,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
  */
 void wusbhc_sec_stop(struct wusbhc *wusbhc)
 {
-       cancel_work_sync(&wusbhc->gtk_rekey_done_work);
+       cancel_work_sync(&wusbhc->gtk_rekey_work);
 }
 
 
@@ -185,12 +182,14 @@ static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value)
 static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
        struct usb_device *usb_dev = wusb_dev->usb_dev;
+       u8 key_index = wusb_key_index(wusbhc->gtk_index,
+               WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST);
 
        return usb_control_msg(
                usb_dev, usb_sndctrlpipe(usb_dev, 0),
                USB_REQ_SET_DESCRIPTOR,
                USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-               USB_DT_KEY << 8 | wusbhc->gtk_index, 0,
+               USB_DT_KEY << 8 | key_index, 0,
                &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
                1000);
 }
@@ -520,24 +519,55 @@ error_kzalloc:
  * Once all connected and authenticated devices have received the new
  * GTK, switch the host to using it.
  */
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work)
+static void wusbhc_gtk_rekey_work(struct work_struct *work)
 {
-       struct wusbhc *wusbhc = container_of(work, struct wusbhc, gtk_rekey_done_work);
+       struct wusbhc *wusbhc = container_of(work,
+                                       struct wusbhc, gtk_rekey_work);
        size_t key_size = sizeof(wusbhc->gtk.data);
+       int port_idx;
+       struct wusb_dev *wusb_dev, *wusb_dev_next;
+       LIST_HEAD(rekey_list);
 
        mutex_lock(&wusbhc->mutex);
+       /* generate the new key */
+       wusbhc_generate_gtk(wusbhc);
+       /* roll the gtk index. */
+       wusbhc->gtk_index = (wusbhc->gtk_index + 1) % (WUSB_KEY_INDEX_MAX + 1);
+       /*
+        * Save all connected devices on a list while holding wusbhc->mutex and
+        * take a reference to each one.  Then submit the set key request to
+        * them after releasing the lock in order to avoid a deadlock.
+        */
+       for (port_idx = 0; port_idx < wusbhc->ports_max; port_idx++) {
+               wusb_dev = wusbhc->port[port_idx].wusb_dev;
+               if (!wusb_dev || !wusb_dev->usb_dev
+                       || !wusb_dev->usb_dev->authenticated)
+                       continue;
 
-       if (--wusbhc->pending_set_gtks == 0)
-               wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size);
-
+               wusb_dev_get(wusb_dev);
+               list_add_tail(&wusb_dev->rekey_node, &rekey_list);
+       }
        mutex_unlock(&wusbhc->mutex);
-}
 
-static void wusbhc_set_gtk_callback(struct urb *urb)
-{
-       struct wusbhc *wusbhc = urb->context;
+       /* Submit the rekey requests without holding wusbhc->mutex. */
+       list_for_each_entry_safe(wusb_dev, wusb_dev_next, &rekey_list,
+               rekey_node) {
+               list_del_init(&wusb_dev->rekey_node);
+               dev_dbg(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d\n",
+                       __func__, wusb_dev->port_idx);
+
+               if (wusb_dev_set_gtk(wusbhc, wusb_dev) < 0) {
+                       dev_err(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d failed\n",
+                               __func__, wusb_dev->port_idx);
+               }
+               wusb_dev_put(wusb_dev);
+       }
 
-       queue_work(wusbd, &wusbhc->gtk_rekey_done_work);
+       /* Switch the host controller to use the new GTK. */
+       mutex_lock(&wusbhc->mutex);
+       wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
+               &wusbhc->gtk.descr.bKeyData, key_size);
+       mutex_unlock(&wusbhc->mutex);
 }
 
 /**
@@ -553,26 +583,12 @@ static void wusbhc_set_gtk_callback(struct urb *urb)
  */
 void wusbhc_gtk_rekey(struct wusbhc *wusbhc)
 {
-       static const size_t key_size = sizeof(wusbhc->gtk.data);
-       int p;
-
-       wusbhc_generate_gtk(wusbhc);
-
-       for (p = 0; p < wusbhc->ports_max; p++) {
-               struct wusb_dev *wusb_dev;
-
-               wusb_dev = wusbhc->port[p].wusb_dev;
-               if (!wusb_dev || !wusb_dev->usb_dev || !wusb_dev->usb_dev->authenticated)
-                       continue;
-
-               usb_fill_control_urb(wusb_dev->set_gtk_urb, wusb_dev->usb_dev,
-                                    usb_sndctrlpipe(wusb_dev->usb_dev, 0),
-                                    (void *)wusb_dev->set_gtk_req,
-                                    &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
-                                    wusbhc_set_gtk_callback, wusbhc);
-               if (usb_submit_urb(wusb_dev->set_gtk_urb, GFP_KERNEL) == 0)
-                       wusbhc->pending_set_gtks++;
-       }
-       if (wusbhc->pending_set_gtks == 0)
-               wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size);
+       /*
+        * We need to submit a URB to the downstream WUSB devices in order to
+        * change the group key.  This can't be done while holding the
+        * wusbhc->mutex since that is also taken in the urb_enqueue routine
+        * and will cause a deadlock.  Instead, queue a work item to do
+        * it when the lock is not held
+        */
+       queue_work(wusbd, &wusbhc->gtk_rekey_work);
 }
index 711b1952b114ab09322a2b11289cf7aa5fe0d433..6bd3b819a6b56b2c37f552ba5177f71df80cd626 100644 (file)
@@ -97,6 +97,7 @@ struct wusb_dev {
        struct kref refcnt;
        struct wusbhc *wusbhc;
        struct list_head cack_node;     /* Connect-Ack list */
+       struct list_head rekey_node;    /* GTK rekey list */
        u8 port_idx;
        u8 addr;
        u8 beacon_type:4;
@@ -107,8 +108,6 @@ struct wusb_dev {
        struct usb_wireless_cap_descriptor *wusb_cap_descr;
        struct uwb_mas_bm availability;
        struct work_struct devconnect_acked_work;
-       struct urb *set_gtk_urb;
-       struct usb_ctrlrequest *set_gtk_req;
        struct usb_device *usb_dev;
 };
 
@@ -296,8 +295,7 @@ struct wusbhc {
        } __attribute__((packed)) gtk;
        u8 gtk_index;
        u32 gtk_tkid;
-       struct work_struct gtk_rekey_done_work;
-       int pending_set_gtks;
+       struct work_struct gtk_rekey_work;
 
        struct usb_encryption_descriptor *ccm1_etd;
 };
index 0dac36ce09d6d74b7b33af1c15a70faffa72e792..518f790ef88a6d319e4d7fd806557c61741363dd 100644 (file)
@@ -3710,7 +3710,7 @@ default_chipset:
        if (!videomemory) {
                dev_warn(&pdev->dev,
                         "Unable to map videomem cached writethrough\n");
-               info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
+               info->screen_base = ZTWO_VADDR(info->fix.smem_start);
        } else
                info->screen_base = (char *)videomemory;
 
index 8521051cf946f0025a9cab15e4f8f880ac841016..cd961622f9c1aac941f33fb0053f192010cd6c09 100644 (file)
@@ -131,6 +131,7 @@ static const struct platform_device_id atmel_lcdfb_devtypes[] = {
                /* terminator */
        }
 };
+MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes);
 
 static struct atmel_lcdfb_config *
 atmel_lcdfb_get_config(struct platform_device *pdev)
index 5aab9b9dc2109be565005d77cbfed962046434b3..d992aa5eb3f0dc6557b23b4ec3e4868301c5ede8 100644 (file)
@@ -2256,7 +2256,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
 
        info->fix.mmio_start = regbase;
        cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
-                                           : (caddr_t)ZTWO_VADDR(regbase);
+                                           : ZTWO_VADDR(regbase);
        if (!cinfo->regbase) {
                dev_err(info->device, "Cannot map registers\n");
                error = -EIO;
@@ -2266,7 +2266,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
        info->fix.smem_start = rambase;
        info->screen_size = ramsize;
        info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
-                                              : (caddr_t)ZTWO_VADDR(rambase);
+                                              : ZTWO_VADDR(rambase);
        if (!info->screen_base) {
                dev_err(info->device, "Cannot map video RAM\n");
                error = -EIO;
index 50c857477e4f1fff39527a4570fc4bf16a640c5e..65041e15fd598ec465c76369fe62cab480746655 100644 (file)
@@ -624,15 +624,15 @@ static int kyrofb_ioctl(struct fb_info *info,
                        return -EINVAL;
                }
        case KYRO_IOCTL_UVSTRIDE:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
                        return -EFAULT;
                break;
        case KYRO_IOCTL_STRIDE:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
                        return -EFAULT;
                break;
        case KYRO_IOCTL_OVERLAY_OFFSET:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
                        return -EFAULT;
                break;
        }
index 5bd2eb8d4f394b2122bf42bb1a1c42a71f440efe..cda7587cbc86ec0e2a6fa8a2ca90038ff71e155b 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/fb.h>
 
 #include <asm/setup.h>
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/io.h>
 
index 9dbea22234015b39845410dd1e651d61e06beb55..7d44d669d5b6decc8f986de2be5a120d408efb3a 100644 (file)
@@ -91,6 +91,15 @@ extern boot_infos_t *boot_infos;
 #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
 
+#define FB_RIGHT_POS(p, bpp)         (fb_be_math(p) ? 0 : (32 - (bpp)))
+
+static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value)
+{
+       u32 bpp = info->var.bits_per_pixel;
+
+       return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp);
+}
+
     /*
      *  Set a single color register. The values supplied are already
      *  rounded down to the hardware's capabilities (according to the
@@ -120,7 +129,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                        mask <<= info->var.transp.offset;
                        value |= mask;
                }
-               pal[regno] = value;
+               pal[regno] = offb_cmap_byteswap(info, value);
                return 0;
        }
 
@@ -301,7 +310,7 @@ static struct fb_ops offb_ops = {
 static void __iomem *offb_map_reg(struct device_node *np, int index,
                                  unsigned long offset, unsigned long size)
 {
-       const u32 *addrp;
+       const __be32 *addrp;
        u64 asize, taddr;
        unsigned int flags;
 
@@ -369,7 +378,11 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
                }
                of_node_put(pciparent);
        } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) {
-               const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#ifdef __BIG_ENDIAN
+               const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#else
+               const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 };
+#endif
                u64 io_addr = of_translate_address(dp, io_of_addr);
                if (io_addr != OF_BAD_ADDR) {
                        par->cmap_adr = ioremap(io_addr + 0x3c8, 2);
@@ -535,7 +548,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        unsigned int flags, rsize, addr_prop = 0;
        unsigned long max_size = 0;
        u64 rstart, address = OF_BAD_ADDR;
-       const u32 *pp, *addrp, *up;
+       const __be32 *pp, *addrp, *up;
        u64 asize;
        int foreign_endian = 0;
 
@@ -551,25 +564,25 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        if (pp == NULL)
                pp = of_get_property(dp, "depth", &len);
        if (pp && len == sizeof(u32))
-               depth = *pp;
+               depth = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-width", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "width", &len);
        if (pp && len == sizeof(u32))
-               width = *pp;
+               width = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-height", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "height", &len);
        if (pp && len == sizeof(u32))
-               height = *pp;
+               height = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-linebytes", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "linebytes", &len);
        if (pp && len == sizeof(u32) && (*pp != 0xffffffffu))
-               pitch = *pp;
+               pitch = be32_to_cpup(pp);
        else
                pitch = width * ((depth + 7) / 8);
 
index e6d56f714ae498ef896f77f1ece977cbf906c345..d94f35dbd5369e83a50265c78b421aac2ab300c7 100644 (file)
@@ -526,6 +526,8 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
        struct omap_dss_device *in = ddata->in;
        int r;
 
+       mutex_lock(&ddata->mutex);
+
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
        in->ops.sdi->set_timings(in, &ddata->videomode);
@@ -614,10 +616,7 @@ static int acx565akm_enable(struct omap_dss_device *dssdev)
        if (omapdss_device_is_enabled(dssdev))
                return 0;
 
-       mutex_lock(&ddata->mutex);
        r = acx565akm_panel_power_on(dssdev);
-       mutex_unlock(&ddata->mutex);
-
        if (r)
                return r;
 
index e0f098562a74b87eee790de505a8483a8a2024b7..a297de5cc859934209099e74fc54880a5f0620f3 100644 (file)
@@ -569,6 +569,7 @@ EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
  * Power management
  */
 
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
 static int sh_mobile_meram_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -611,6 +612,7 @@ static int sh_mobile_meram_resume(struct device *dev)
                meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */
 
 static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
                            sh_mobile_meram_suspend,
index e287ebc47817da5e8dccd66ce40d028d92bb6c73..97cb9bd1d1ddb75f48abe8546c555f6160b7a0b1 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/cuda.h>
 #include <asm/io.h>
 #ifdef CONFIG_MAC
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #else
 #include <asm/prom.h>
index b30e5a439d1f968679c4b0ce80eb918f7e1678b5..a8f2b280f796337df10aa430688f859bdf47b12f 100644 (file)
@@ -293,8 +293,7 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                        + sizeof(u32) * 16, GFP_KERNEL);
        if (!fbi) {
                dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-               ret = -ENOMEM;
-               goto failed;
+               return -ENOMEM;
        }
 
        strcpy(fbi->fb.fix.id, "VT8500 LCD");
@@ -327,15 +326,13 @@ static int vt8500lcd_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "no I/O memory resource defined\n");
-               ret = -ENODEV;
-               goto failed_fbi;
+               return -ENODEV;
        }
 
        res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
        if (res == NULL) {
                dev_err(&pdev->dev, "failed to request I/O memory\n");
-               ret = -EBUSY;
-               goto failed_fbi;
+               return -EBUSY;
        }
 
        fbi->regbase = ioremap(res->start, resource_size(res));
@@ -346,17 +343,19 @@ static int vt8500lcd_probe(struct platform_device *pdev)
        }
 
        disp_timing = of_get_display_timings(pdev->dev.of_node);
-       if (!disp_timing)
-               return -EINVAL;
+       if (!disp_timing) {
+               ret = -EINVAL;
+               goto failed_free_io;
+       }
 
        ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
                                                        OF_USE_NATIVE_MODE);
        if (ret)
-               return ret;
+               goto failed_free_io;
 
        ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
        if (ret)
-               return ret;
+               goto failed_free_io;
 
        /* try allocating the framebuffer */
        fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
@@ -364,7 +363,8 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                                GFP_KERNEL);
        if (!fb_mem_virt) {
                pr_err("%s: Failed to allocate framebuffer\n", __func__);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto failed_free_io;
        }
 
        fbi->fb.fix.smem_start  = fb_mem_phys;
@@ -447,9 +447,6 @@ failed_free_io:
        iounmap(fbi->regbase);
 failed_free_res:
        release_mem_region(res->start, resource_size(res));
-failed_fbi:
-       kfree(fbi);
-failed:
        return ret;
 }
 
index c444654fc33fb6f7e858824eb8ed816186bf3bda..5c4a95b516cf9e576884c8f84e566f03b396facb 100644 (file)
@@ -285,7 +285,7 @@ static void update_balloon_size(struct virtio_balloon *vb)
 {
        __le32 actual = cpu_to_le32(vb->num_pages);
 
-       virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages,
+       virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual,
                      &actual);
 }
 
index a6a2cebb25879242b8408b1537838a67d932b2b3..cafa973c43be7af984fb9d39456b1d36b8913ea8 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
-#include <linux/miscdevice.h>
 
 #define PM_RSTC                                0x1c
 #define PM_WDOG                                0x24
index 833e813118489216a8a27901f749f0765bd03e8f..d1d07f2f69df7cf61cd838feaa89650c22908098 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/module.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/timer.h>
 #include <linux/io.h>
index 70a240297c6d22f2a7d170a731f70320512f478a..07f88f54e5c03008159a5a276056340e65058086 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/watchdog.h>
-#include <linux/miscdevice.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
index 2de486a7eea18a058808cbb33a0ec0fa5f3a650b..3aa50cfa335fda1576950451a492a92336da41cd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index a1a3638c579c857c382ec9c253e5f69424e1dbbb..20dc73844737a99cf30aa6852f6bfceb06d04984 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
index 6d4f3998e1f6c08e7158fdf1068b3a94c3bad448..bdb3f4a5b27c760b5c7509f957213037e234e2be 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
index 44edca66d564195a8e20b54f20c8b4cc389eca2c..f7722a42467632030b4d36dc608e1af7cf497002 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
index 1bdcc313e1d9f713dc24c8b4cf7e2f7e9c312574..5bec20f5dc2db29ec5294bbdf03ee7b8106cb21a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 53d37fea183e1b5be5f2f18093a1c4021e632bc9..d92c2d5859ce9f67c4af0f2c61fcbe6c8c396e74 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/miscdevice.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 
index 3b9fff9dcf654ba6abfb09f970a7d288147d7083..131193a7acdfd0bb07660095e0ff57c500eed6cb 100644 (file)
@@ -409,8 +409,9 @@ static int __init sc1200wdt_init(void)
 #if defined CONFIG_PNP
        /* now that the user has specified an IO port and we haven't detected
         * any devices, disable pnp support */
+       if (isapnp)
+               pnp_unregister_driver(&scl200wdt_pnp_driver);
        isapnp = 0;
-       pnp_unregister_driver(&scl200wdt_pnp_driver);
 #endif
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
index f9b8e06f355808e763ca7a1f7f2e4511fe33c88f..af3528f84d65469196d2a409dbcfc531a09e57c6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/pm_runtime.h>
 #include <linux/fs.h>
index ef2638fee4a8f7037c1f7c342ec1be1347ee3957..c04a1aa158e25762fcbe2b161052beaf56897d7f 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
index d667f6b51d35f93aba02547f82653f3dbb189aa4..bb64ae3f47da58079ac816bde0d5c9abac5f0bff 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 #include <linux/stmp3xxx_rtc_wdt.h>
index 0fd0e8ae62a833b462b29bd09f8f5e7666e437bf..6a447e321dd0c3cf076169d7eac3c7b887a4b96b 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index e029b5768f2c1379279f034dc24c892b52fc0ec3..5aed9d7ad47e6ee81e96b4f16b15aa653a6a9482 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
 #include <linux/err.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
index 55ea73f7c70b52e49ca3b4f2b40f5baa064928e9..4c02e2b9410377d9e6b77fe1bc2b50d929774551 100644 (file)
@@ -350,17 +350,19 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
 
                pfn = page_to_pfn(page);
 
-               set_phys_to_machine(pfn, frame_list[i]);
-
 #ifdef CONFIG_XEN_HAVE_PVMMU
-               /* Link back into the page tables if not highmem. */
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       int ret;
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               mfn_pte(frame_list[i], PAGE_KERNEL),
-                               0);
-                       BUG_ON(ret);
+               if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+                       set_phys_to_machine(pfn, frame_list[i]);
+
+                       /* Link back into the page tables if not highmem. */
+                       if (!PageHighMem(page)) {
+                               int ret;
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               mfn_pte(frame_list[i], PAGE_KERNEL),
+                                               0);
+                               BUG_ON(ret);
+                       }
                }
 #endif
 
@@ -378,7 +380,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
        enum bp_state state = BP_DONE;
        unsigned long  pfn, i;
        struct page   *page;
-       struct page   *scratch_page;
        int ret;
        struct xen_memory_reservation reservation = {
                .address_bits = 0,
@@ -411,27 +412,29 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
+#ifdef CONFIG_XEN_HAVE_PVMMU
                /*
                 * Ballooned out frames are effectively replaced with
                 * a scratch frame.  Ensure direct mappings and the
                 * p2m are consistent.
                 */
-               scratch_page = get_balloon_scratch_page();
-#ifdef CONFIG_XEN_HAVE_PVMMU
-               if (xen_pv_domain() && !PageHighMem(page)) {
-                       ret = HYPERVISOR_update_va_mapping(
-                               (unsigned long)__va(pfn << PAGE_SHIFT),
-                               pfn_pte(page_to_pfn(scratch_page),
-                                       PAGE_KERNEL_RO), 0);
-                       BUG_ON(ret);
-               }
-#endif
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                        unsigned long p;
+                       struct page   *scratch_page = get_balloon_scratch_page();
+
+                       if (!PageHighMem(page)) {
+                               ret = HYPERVISOR_update_va_mapping(
+                                               (unsigned long)__va(pfn << PAGE_SHIFT),
+                                               pfn_pte(page_to_pfn(scratch_page),
+                                                       PAGE_KERNEL_RO), 0);
+                               BUG_ON(ret);
+                       }
                        p = page_to_pfn(scratch_page);
                        __set_phys_to_machine(pfn, pfn_to_mfn(p));
+
+                       put_balloon_scratch_page();
                }
-               put_balloon_scratch_page();
+#endif
 
                balloon_append(pfn_to_page(pfn));
        }
@@ -627,15 +630,17 @@ static int __init balloon_init(void)
        if (!xen_domain())
                return -ENODEV;
 
-       for_each_online_cpu(cpu)
-       {
-               per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
-               if (per_cpu(balloon_scratch_page, cpu) == NULL) {
-                       pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
-                       return -ENOMEM;
+       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+               for_each_online_cpu(cpu)
+               {
+                       per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL);
+                       if (per_cpu(balloon_scratch_page, cpu) == NULL) {
+                               pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu);
+                               return -ENOMEM;
+                       }
                }
+               register_cpu_notifier(&balloon_cpu_notifier);
        }
-       register_cpu_notifier(&balloon_cpu_notifier);
 
        pr_info("Initialising balloon driver\n");
 
index 62ccf5424ba857e0fe11bb22187bb7dd5d3dad6c..aa846a48f4009eaac8271a8a653716c27aa1dc01 100644 (file)
@@ -930,9 +930,10 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                ret = m2p_add_override(mfn, pages[i], kmap_ops ?
                                       &kmap_ops[i] : NULL);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+ out:
        if (lazy)
                arch_leave_lazy_mmu_mode();
 
@@ -969,9 +970,10 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                ret = m2p_remove_override(pages[i], kmap_ops ?
                                       &kmap_ops[i] : NULL);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+ out:
        if (lazy)
                arch_leave_lazy_mmu_mode();
 
@@ -1174,7 +1176,8 @@ static int gnttab_setup(void)
                gnttab_shared.addr = xen_remap(xen_hvm_resume_frames,
                                                PAGE_SIZE * max_nr_gframes);
                if (gnttab_shared.addr == NULL) {
-                       pr_warn("Failed to ioremap gnttab share frames!\n");
+                       pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n",
+                                       xen_hvm_resume_frames);
                        return -ENOMEM;
                }
        }
index 8e74590fa1bb5d9149e17550c3f4ec7b74142983..569a13b9e856de5c3900050d583844f401243e96 100644 (file)
@@ -533,12 +533,17 @@ static void privcmd_close(struct vm_area_struct *vma)
 {
        struct page **pages = vma->vm_private_data;
        int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       int rc;
 
        if (!xen_feature(XENFEAT_auto_translated_physmap) || !numpgs || !pages)
                return;
 
-       xen_unmap_domain_mfn_range(vma, numpgs, pages);
-       free_xenballooned_pages(numpgs, pages);
+       rc = xen_unmap_domain_mfn_range(vma, numpgs, pages);
+       if (rc == 0)
+               free_xenballooned_pages(numpgs, pages);
+       else
+               pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n",
+                       numpgs, rc);
        kfree(pages);
 }
 
index a224bc74b6b9d34fa5c45f41408a3ed1138098f4..1eac0731c349f2067b42dea6e01f292453096d4b 100644 (file)
@@ -555,6 +555,11 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
                                sg_dma_len(sgl) = 0;
                                return 0;
                        }
+                       xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
+                                               map & ~PAGE_MASK,
+                                               sg->length,
+                                               dir,
+                                               attrs);
                        sg->dma_address = xen_phys_to_bus(map);
                } else {
                        /* we are not interested in the dma_addr returned by
index f62172603215ed433a32f7945603c95bf05783c2..7dc5332ff9842bfe1f119f4ff003056430959ec3 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for the Zorro bus specific drivers.
 #
 
-obj-$(CONFIG_ZORRO)    += zorro.o zorro-driver.o zorro-sysfs.o names.o
+obj-$(CONFIG_ZORRO)    += zorro.o zorro-driver.o zorro-sysfs.o
 obj-$(CONFIG_PROC_FS)  += proc.o
+obj-$(CONFIG_ZORRO_NAMES) +=  names.o
 
 hostprogs-y            := gen-devlist
 
index e8517c3d8e82df3d9b34f9049a29bdedd0a61b0e..6f3fd9903ac387f8d354c843ae88950b45bcfcfb 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/zorro.h>
 
 
-#ifdef CONFIG_ZORRO_NAMES
-
 struct zorro_prod_info {
        __u16 prod;
        unsigned short seen;
@@ -69,7 +67,6 @@ void __init zorro_name_device(struct zorro_dev *dev)
        } while (--i);
 
        /* Couldn't find either the manufacturer nor the product */
-       sprintf(name, "Zorro device %08x", dev->id);
        return;
 
        match_manuf: {
@@ -98,11 +95,3 @@ void __init zorro_name_device(struct zorro_dev *dev)
                }
        }
 }
-
-#else
-
-void __init zorro_name_device(struct zorro_dev *dev)
-{
-}
-
-#endif
index ea1ce822a8e0437120184a8e559bd0495860c7b7..6ac2579da0ebb1355450474204807701e47e2e08 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/export.h>
+
+#include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/setup.h>
@@ -41,10 +43,10 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *
        /* Construct a ConfigDev */
        memset(&cd, 0, sizeof(cd));
        cd.cd_Rom = z->rom;
-       cd.cd_SlotAddr = z->slotaddr;
-       cd.cd_SlotSize = z->slotsize;
-       cd.cd_BoardAddr = (void *)zorro_resource_start(z);
-       cd.cd_BoardSize = zorro_resource_len(z);
+       cd.cd_SlotAddr = cpu_to_be16(z->slotaddr);
+       cd.cd_SlotSize = cpu_to_be16(z->slotsize);
+       cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z));
+       cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z));
 
        if (copy_to_user(buf, (void *)&cd + pos, nbytes))
                return -EFAULT;
index ac1db7f1bcab7731e9366cfc4bce832c4258cd35..eacae1434b73fd7472e2d81b5b86ebc214f3e6af 100644 (file)
@@ -161,11 +161,12 @@ static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
 }
 
 struct bus_type zorro_bus_type = {
-       .name   = "zorro",
-       .match  = zorro_bus_match,
-       .uevent = zorro_uevent,
-       .probe  = zorro_device_probe,
-       .remove = zorro_device_remove,
+       .name     = "zorro",
+       .dev_name = "zorro",
+       .match    = zorro_bus_match,
+       .uevent   = zorro_uevent,
+       .probe    = zorro_device_probe,
+       .remove   = zorro_device_remove,
 };
 EXPORT_SYMBOL(zorro_bus_type);
 
index 26f7184ef9e1a19cb47890bcbfaa124c6c34912b..36b210f9b6b29621fa9e410db063d3df53d7fb75 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
+#include <asm/byteorder.h>
+
 #include "zorro.h"
 
 
@@ -33,10 +35,20 @@ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
 zorro_config_attr(id, id, "0x%08x\n");
 zorro_config_attr(type, rom.er_Type, "0x%02x\n");
-zorro_config_attr(serial, rom.er_SerialNumber, "0x%08x\n");
 zorro_config_attr(slotaddr, slotaddr, "0x%04x\n");
 zorro_config_attr(slotsize, slotsize, "0x%04x\n");
 
+static ssize_t
+show_serial(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct zorro_dev *z;
+
+       z = to_zorro_dev(dev);
+       return sprintf(buf, "0x%08x\n", be32_to_cpu(z->rom.er_SerialNumber));
+}
+
+static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
+
 static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct zorro_dev *z = to_zorro_dev(dev);
@@ -60,10 +72,10 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj,
        /* Construct a ConfigDev */
        memset(&cd, 0, sizeof(cd));
        cd.cd_Rom = z->rom;
-       cd.cd_SlotAddr = z->slotaddr;
-       cd.cd_SlotSize = z->slotsize;
-       cd.cd_BoardAddr = (void *)zorro_resource_start(z);
-       cd.cd_BoardSize = zorro_resource_len(z);
+       cd.cd_SlotAddr = cpu_to_be16(z->slotaddr);
+       cd.cd_SlotSize = cpu_to_be16(z->slotsize);
+       cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z));
+       cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z));
 
        return memory_read_from_buffer(buf, count, &off, &cd, sizeof(cd));
 }
index 858c9714b2f390a26e1a1450f196d7abf6e14340..707c1a5a031703ba1b7e8de9f87e71103d217a18 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <asm/amigahw.h>
 
@@ -29,7 +30,8 @@
      */
 
 unsigned int zorro_num_autocon;
-struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
+struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata;
+struct zorro_dev *zorro_autocon;
 
 
     /*
@@ -38,6 +40,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
 
 struct zorro_bus {
        struct device dev;
+       struct zorro_dev devices[0];
 };
 
 
@@ -125,18 +128,22 @@ static struct resource __init *zorro_find_parent_resource(
 static int __init amiga_zorro_probe(struct platform_device *pdev)
 {
        struct zorro_bus *bus;
+       struct zorro_dev_init *zi;
        struct zorro_dev *z;
        struct resource *r;
        unsigned int i;
        int error;
 
        /* Initialize the Zorro bus */
-       bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+       bus = kzalloc(sizeof(*bus) +
+                     zorro_num_autocon * sizeof(bus->devices[0]),
+                     GFP_KERNEL);
        if (!bus)
                return -ENOMEM;
 
+       zorro_autocon = bus->devices;
        bus->dev.parent = &pdev->dev;
-       dev_set_name(&bus->dev, "zorro");
+       dev_set_name(&bus->dev, zorro_bus_type.name);
        error = device_register(&bus->dev);
        if (error) {
                pr_err("Zorro: Error registering zorro_bus\n");
@@ -151,15 +158,23 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)
 
        /* First identify all devices ... */
        for (i = 0; i < zorro_num_autocon; i++) {
+               zi = &zorro_autocon_init[i];
                z = &zorro_autocon[i];
-               z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8);
+
+               z->rom = zi->rom;
+               z->id = (be16_to_cpu(z->rom.er_Manufacturer) << 16) |
+                       (z->rom.er_Product << 8);
                if (z->id == ZORRO_PROD_GVP_EPC_BASE) {
                        /* GVP quirk */
-                       unsigned long magic = zorro_resource_start(z)+0x8000;
+                       unsigned long magic = zi->boardaddr + 0x8000;
                        z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK;
                }
+               z->slotaddr = zi->slotaddr;
+               z->slotsize = zi->slotsize;
                sprintf(z->name, "Zorro device %08x", z->id);
                zorro_name_device(z);
+               z->resource.start = zi->boardaddr;
+               z->resource.end = zi->boardaddr + zi->boardsize - 1;
                z->resource.name = z->name;
                r = zorro_find_parent_resource(pdev, z);
                error = request_resource(r, &z->resource);
@@ -167,9 +182,9 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)
                        dev_err(&bus->dev,
                                "Address space collision on device %s %pR\n",
                                z->name, &z->resource);
-               dev_set_name(&z->dev, "%02x", i);
                z->dev.parent = &bus->dev;
                z->dev.bus = &zorro_bus_type;
+               z->dev.id = i;
        }
 
        /* ... then register them */
index b682d5ccd63f74b1be7aae6db188270318891f14..34119fb4e5601603edbd139563f539b3548963c9 100644 (file)
@@ -1,4 +1,9 @@
 
+#ifdef CONFIG_ZORRO_NAMES
 extern void zorro_name_device(struct zorro_dev *z);
+#else
+static inline void zorro_name_device(struct zorro_dev *dev) { }
+#endif
+
 extern int zorro_create_sysfs_dev_files(struct zorro_dev *z);
 
index 08159ed13649cacbec1825065e24b2b5b61be267..062a5f6a1448c6cff1cd1dc09e84db3f0d59cc27 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -244,9 +244,14 @@ static void aio_free_ring(struct kioctx *ctx)
        int i;
 
        for (i = 0; i < ctx->nr_pages; i++) {
+               struct page *page;
                pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
                                page_count(ctx->ring_pages[i]));
-               put_page(ctx->ring_pages[i]);
+               page = ctx->ring_pages[i];
+               if (!page)
+                       continue;
+               ctx->ring_pages[i] = NULL;
+               put_page(page);
        }
 
        put_aio_ring_file(ctx);
@@ -280,18 +285,38 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
        unsigned long flags;
        int rc;
 
+       rc = 0;
+
+       /* Make sure the old page hasn't already been changed */
+       spin_lock(&mapping->private_lock);
+       ctx = mapping->private_data;
+       if (ctx) {
+               pgoff_t idx;
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               idx = old->index;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       if (ctx->ring_pages[idx] != old)
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
+               spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       } else
+               rc = -EINVAL;
+       spin_unlock(&mapping->private_lock);
+
+       if (rc != 0)
+               return rc;
+
        /* Writeback must be complete */
        BUG_ON(PageWriteback(old));
-       put_page(old);
+       get_page(new);
 
-       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1);
        if (rc != MIGRATEPAGE_SUCCESS) {
-               get_page(old);
+               put_page(new);
                return rc;
        }
 
-       get_page(new);
-
        /* We can potentially race against kioctx teardown here.  Use the
         * address_space's private data lock to protect the mapping's
         * private_data.
@@ -303,13 +328,24 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
                spin_lock_irqsave(&ctx->completion_lock, flags);
                migrate_page_copy(new, old);
                idx = old->index;
-               if (idx < (pgoff_t)ctx->nr_pages)
-                       ctx->ring_pages[idx] = new;
+               if (idx < (pgoff_t)ctx->nr_pages) {
+                       /* And only do the move if things haven't changed */
+                       if (ctx->ring_pages[idx] == old)
+                               ctx->ring_pages[idx] = new;
+                       else
+                               rc = -EAGAIN;
+               } else
+                       rc = -EINVAL;
                spin_unlock_irqrestore(&ctx->completion_lock, flags);
        } else
                rc = -EBUSY;
        spin_unlock(&mapping->private_lock);
 
+       if (rc == MIGRATEPAGE_SUCCESS)
+               put_page(old);
+       else
+               put_page(new);
+
        return rc;
 }
 #endif
@@ -326,7 +362,7 @@ static int aio_setup_ring(struct kioctx *ctx)
        struct aio_ring *ring;
        unsigned nr_events = ctx->max_reqs;
        struct mm_struct *mm = current->mm;
-       unsigned long size, populate;
+       unsigned long size, unused;
        int nr_pages;
        int i;
        struct file *file;
@@ -347,6 +383,20 @@ static int aio_setup_ring(struct kioctx *ctx)
                return -EAGAIN;
        }
 
+       ctx->aio_ring_file = file;
+       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
+                       / sizeof(struct io_event);
+
+       ctx->ring_pages = ctx->internal_pages;
+       if (nr_pages > AIO_RING_PAGES) {
+               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
+                                         GFP_KERNEL);
+               if (!ctx->ring_pages) {
+                       put_aio_ring_file(ctx);
+                       return -ENOMEM;
+               }
+       }
+
        for (i = 0; i < nr_pages; i++) {
                struct page *page;
                page = find_or_create_page(file->f_inode->i_mapping,
@@ -358,17 +408,14 @@ static int aio_setup_ring(struct kioctx *ctx)
                SetPageUptodate(page);
                SetPageDirty(page);
                unlock_page(page);
+
+               ctx->ring_pages[i] = page;
        }
-       ctx->aio_ring_file = file;
-       nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
-                       / sizeof(struct io_event);
+       ctx->nr_pages = i;
 
-       ctx->ring_pages = ctx->internal_pages;
-       if (nr_pages > AIO_RING_PAGES) {
-               ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
-                                         GFP_KERNEL);
-               if (!ctx->ring_pages)
-                       return -ENOMEM;
+       if (unlikely(i != nr_pages)) {
+               aio_free_ring(ctx);
+               return -EAGAIN;
        }
 
        ctx->mmap_size = nr_pages * PAGE_SIZE;
@@ -377,9 +424,9 @@ static int aio_setup_ring(struct kioctx *ctx)
        down_write(&mm->mmap_sem);
        ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
                                       PROT_READ | PROT_WRITE,
-                                      MAP_SHARED | MAP_POPULATE, 0, &populate);
+                                      MAP_SHARED, 0, &unused);
+       up_write(&mm->mmap_sem);
        if (IS_ERR((void *)ctx->mmap_base)) {
-               up_write(&mm->mmap_sem);
                ctx->mmap_size = 0;
                aio_free_ring(ctx);
                return -EAGAIN;
@@ -387,27 +434,6 @@ static int aio_setup_ring(struct kioctx *ctx)
 
        pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
 
-       /* We must do this while still holding mmap_sem for write, as we
-        * need to be protected against userspace attempting to mremap()
-        * or munmap() the ring buffer.
-        */
-       ctx->nr_pages = get_user_pages(current, mm, ctx->mmap_base, nr_pages,
-                                      1, 0, ctx->ring_pages, NULL);
-
-       /* Dropping the reference here is safe as the page cache will hold
-        * onto the pages for us.  It is also required so that page migration
-        * can unmap the pages and get the right reference count.
-        */
-       for (i = 0; i < ctx->nr_pages; i++)
-               put_page(ctx->ring_pages[i]);
-
-       up_write(&mm->mmap_sem);
-
-       if (unlikely(ctx->nr_pages != nr_pages)) {
-               aio_free_ring(ctx);
-               return -EAGAIN;
-       }
-
        ctx->user_id = ctx->mmap_base;
        ctx->nr_events = nr_events; /* trusted copy */
 
@@ -645,12 +671,13 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
            aio_nr + nr_events < aio_nr) {
                spin_unlock(&aio_nr_lock);
                err = -EAGAIN;
-               goto err;
+               goto err_ctx;
        }
        aio_nr += ctx->max_reqs;
        spin_unlock(&aio_nr_lock);
 
-       percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->users);    /* io_setup() will drop this ref */
+       percpu_ref_get(&ctx->reqs);     /* free_ioctx_users() will drop this */
 
        err = ioctx_add_table(ctx, mm);
        if (err)
@@ -662,6 +689,8 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 
 err_cleanup:
        aio_nr_sub(ctx->max_reqs);
+err_ctx:
+       aio_free_ring(ctx);
 err:
        free_percpu(ctx->cpu);
        free_percpu(ctx->reqs.pcpu_count);
index b50764bef1410c2750b17d943ae3597899b3ee9e..131d82800b3af45778cb8651f5c559bd57cec437 100644 (file)
@@ -333,7 +333,6 @@ static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
 static int btrfsic_read_block(struct btrfsic_state *state,
                              struct btrfsic_block_data_ctx *block_ctx);
 static void btrfsic_dump_database(struct btrfsic_state *state);
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err);
 static int btrfsic_test_for_metadata(struct btrfsic_state *state,
                                     char **datav, unsigned int num_pages);
 static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
@@ -1687,7 +1686,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
        for (i = 0; i < num_pages;) {
                struct bio *bio;
                unsigned int j;
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
                if (!bio) {
@@ -1698,8 +1696,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                }
                bio->bi_bdev = block_ctx->dev->bdev;
                bio->bi_sector = dev_bytenr >> 9;
-               bio->bi_end_io = btrfsic_complete_bio_end_io;
-               bio->bi_private = &complete;
 
                for (j = i; j < num_pages; j++) {
                        ret = bio_add_page(bio, block_ctx->pagev[j],
@@ -1712,12 +1708,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                               "btrfsic: error, failed to add a single page!\n");
                        return -1;
                }
-               submit_bio(READ, bio);
-
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-
-               if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+               if (submit_bio_wait(READ, bio)) {
                        printk(KERN_INFO
                               "btrfsic: read error at logical %llu dev %s!\n",
                               block_ctx->start, block_ctx->dev->name);
@@ -1740,11 +1731,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
        return block_ctx->len;
 }
 
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static void btrfsic_dump_database(struct btrfsic_state *state)
 {
        struct list_head *elem_all;
@@ -3008,14 +2994,12 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh)
        return submit_bh(rw, bh);
 }
 
-void btrfsic_submit_bio(int rw, struct bio *bio)
+static void __btrfsic_submit_bio(int rw, struct bio *bio)
 {
        struct btrfsic_dev_state *dev_state;
 
-       if (!btrfsic_is_initialized) {
-               submit_bio(rw, bio);
+       if (!btrfsic_is_initialized)
                return;
-       }
 
        mutex_lock(&btrfsic_mutex);
        /* since btrfsic_submit_bio() is also called before
@@ -3106,10 +3090,20 @@ void btrfsic_submit_bio(int rw, struct bio *bio)
        }
 leave:
        mutex_unlock(&btrfsic_mutex);
+}
 
+void btrfsic_submit_bio(int rw, struct bio *bio)
+{
+       __btrfsic_submit_bio(rw, bio);
        submit_bio(rw, bio);
 }
 
+int btrfsic_submit_bio_wait(int rw, struct bio *bio)
+{
+       __btrfsic_submit_bio(rw, bio);
+       return submit_bio_wait(rw, bio);
+}
+
 int btrfsic_mount(struct btrfs_root *root,
                  struct btrfs_fs_devices *fs_devices,
                  int including_extent_data, u32 print_mask)
index 8b59175cc50243c7bd525c91b265fa0f329f6af1..13b8566c97ab433f7455eeb6762942d5e623d16a 100644 (file)
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
 int btrfsic_submit_bh(int rw, struct buffer_head *bh);
 void btrfsic_submit_bio(int rw, struct bio *bio);
+int btrfsic_submit_bio_wait(int rw, struct bio *bio);
 #else
 #define btrfsic_submit_bh submit_bh
 #define btrfsic_submit_bio submit_bio
+#define btrfsic_submit_bio_wait submit_bio_wait
 #endif
 
 int btrfsic_mount(struct btrfs_root *root,
index 45d98d01028f7cdac43461a7acd42f5e17599f32..9c01509dd8abfb0fddc5480b7f4cb3b73002aad4 100644 (file)
@@ -767,20 +767,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
        if (!path)
                return -ENOMEM;
 
-       if (metadata) {
-               key.objectid = bytenr;
-               key.type = BTRFS_METADATA_ITEM_KEY;
-               key.offset = offset;
-       } else {
-               key.objectid = bytenr;
-               key.type = BTRFS_EXTENT_ITEM_KEY;
-               key.offset = offset;
-       }
-
        if (!trans) {
                path->skip_locking = 1;
                path->search_commit_root = 1;
        }
+
+search_again:
+       key.objectid = bytenr;
+       key.offset = offset;
+       if (metadata)
+               key.type = BTRFS_METADATA_ITEM_KEY;
+       else
+               key.type = BTRFS_EXTENT_ITEM_KEY;
+
 again:
        ret = btrfs_search_slot(trans, root->fs_info->extent_root,
                                &key, path, 0, 0);
@@ -788,7 +787,6 @@ again:
                goto out_free;
 
        if (ret > 0 && metadata && key.type == BTRFS_METADATA_ITEM_KEY) {
-               metadata = 0;
                if (path->slots[0]) {
                        path->slots[0]--;
                        btrfs_item_key_to_cpu(path->nodes[0], &key,
@@ -855,7 +853,7 @@ again:
                        mutex_lock(&head->mutex);
                        mutex_unlock(&head->mutex);
                        btrfs_put_delayed_ref(&head->node);
-                       goto again;
+                       goto search_again;
                }
                if (head->extent_op && head->extent_op->update_flags)
                        extent_flags |= head->extent_op->flags_to_set;
index 8e457fca0a0ba5c04afb84414ccd640821a640d1..ff43802a7c886088e37c5c1c16427f2b522cad30 100644 (file)
@@ -1952,11 +1952,6 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec,
        return err;
 }
 
-static void repair_io_failure_callback(struct bio *bio, int err)
-{
-       complete(bio->bi_private);
-}
-
 /*
  * this bypasses the standard btrfs submit functions deliberately, as
  * the standard behavior is to write all copies in a raid setup. here we only
@@ -1973,7 +1968,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
 {
        struct bio *bio;
        struct btrfs_device *dev;
-       DECLARE_COMPLETION_ONSTACK(compl);
        u64 map_length = 0;
        u64 sector;
        struct btrfs_bio *bbio = NULL;
@@ -1990,8 +1984,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio)
                return -EIO;
-       bio->bi_private = &compl;
-       bio->bi_end_io = repair_io_failure_callback;
        bio->bi_size = 0;
        map_length = length;
 
@@ -2012,10 +2004,8 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        }
        bio->bi_bdev = dev->bdev;
        bio_add_page(bio, page, length, start - page_offset(page));
-       btrfsic_submit_bio(WRITE_SYNC, bio);
-       wait_for_completion(&compl);
 
-       if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+       if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
                /* try to remap that extent elsewhere? */
                bio_put(bio);
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
index a111622598b0b23f82c84352e6b782361e079526..21da5762b0b1b33d193f3bd7f664995a43062bd6 100644 (file)
@@ -2121,7 +2121,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
 
        err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
        if (err == -EINTR)
-               goto out;
+               goto out_drop_write;
        dentry = lookup_one_len(vol_args->name, parent, namelen);
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
@@ -2284,6 +2284,7 @@ out_dput:
        dput(dentry);
 out_unlock_dir:
        mutex_unlock(&dir->i_mutex);
+out_drop_write:
        mnt_drop_write_file(file);
 out:
        kfree(vol_args);
index ce459a7cb16dae48e233587cb28d271c4403f297..429c73c374b84f9bcd468067221bf99e0b9f67db 100644 (file)
@@ -571,7 +571,9 @@ static int is_cowonly_root(u64 root_objectid)
            root_objectid == BTRFS_CHUNK_TREE_OBJECTID ||
            root_objectid == BTRFS_DEV_TREE_OBJECTID ||
            root_objectid == BTRFS_TREE_LOG_OBJECTID ||
-           root_objectid == BTRFS_CSUM_TREE_OBJECTID)
+           root_objectid == BTRFS_CSUM_TREE_OBJECTID ||
+           root_objectid == BTRFS_UUID_TREE_OBJECTID ||
+           root_objectid == BTRFS_QUOTA_TREE_OBJECTID)
                return 1;
        return 0;
 }
@@ -1264,10 +1266,10 @@ static int __must_check __add_reloc_root(struct btrfs_root *root)
 }
 
 /*
- * helper to update/delete the 'address of tree root -> reloc tree'
+ * helper to delete the 'address of tree root -> reloc tree'
  * mapping
  */
-static int __update_reloc_root(struct btrfs_root *root, int del)
+static void __del_reloc_root(struct btrfs_root *root)
 {
        struct rb_node *rb_node;
        struct mapping_node *node = NULL;
@@ -1275,7 +1277,7 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
 
        spin_lock(&rc->reloc_root_tree.lock);
        rb_node = tree_search(&rc->reloc_root_tree.rb_root,
-                             root->commit_root->start);
+                             root->node->start);
        if (rb_node) {
                node = rb_entry(rb_node, struct mapping_node, rb_node);
                rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
@@ -1283,23 +1285,45 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
        spin_unlock(&rc->reloc_root_tree.lock);
 
        if (!node)
-               return 0;
+               return;
        BUG_ON((struct btrfs_root *)node->data != root);
 
-       if (!del) {
-               spin_lock(&rc->reloc_root_tree.lock);
-               node->bytenr = root->node->start;
-               rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
-                                     node->bytenr, &node->rb_node);
-               spin_unlock(&rc->reloc_root_tree.lock);
-               if (rb_node)
-                       backref_tree_panic(rb_node, -EEXIST, node->bytenr);
-       } else {
-               spin_lock(&root->fs_info->trans_lock);
-               list_del_init(&root->root_list);
-               spin_unlock(&root->fs_info->trans_lock);
-               kfree(node);
+       spin_lock(&root->fs_info->trans_lock);
+       list_del_init(&root->root_list);
+       spin_unlock(&root->fs_info->trans_lock);
+       kfree(node);
+}
+
+/*
+ * helper to update the 'address of tree root -> reloc tree'
+ * mapping
+ */
+static int __update_reloc_root(struct btrfs_root *root, u64 new_bytenr)
+{
+       struct rb_node *rb_node;
+       struct mapping_node *node = NULL;
+       struct reloc_control *rc = root->fs_info->reloc_ctl;
+
+       spin_lock(&rc->reloc_root_tree.lock);
+       rb_node = tree_search(&rc->reloc_root_tree.rb_root,
+                             root->node->start);
+       if (rb_node) {
+               node = rb_entry(rb_node, struct mapping_node, rb_node);
+               rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
        }
+       spin_unlock(&rc->reloc_root_tree.lock);
+
+       if (!node)
+               return 0;
+       BUG_ON((struct btrfs_root *)node->data != root);
+
+       spin_lock(&rc->reloc_root_tree.lock);
+       node->bytenr = new_bytenr;
+       rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
+                             node->bytenr, &node->rb_node);
+       spin_unlock(&rc->reloc_root_tree.lock);
+       if (rb_node)
+               backref_tree_panic(rb_node, -EEXIST, node->bytenr);
        return 0;
 }
 
@@ -1420,7 +1444,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
 {
        struct btrfs_root *reloc_root;
        struct btrfs_root_item *root_item;
-       int del = 0;
        int ret;
 
        if (!root->reloc_root)
@@ -1432,11 +1455,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
        if (root->fs_info->reloc_ctl->merge_reloc_tree &&
            btrfs_root_refs(root_item) == 0) {
                root->reloc_root = NULL;
-               del = 1;
+               __del_reloc_root(reloc_root);
        }
 
-       __update_reloc_root(reloc_root, del);
-
        if (reloc_root->commit_root != reloc_root->node) {
                btrfs_set_root_node(root_item, reloc_root->node);
                free_extent_buffer(reloc_root->commit_root);
@@ -2287,7 +2308,7 @@ void free_reloc_roots(struct list_head *list)
        while (!list_empty(list)) {
                reloc_root = list_entry(list->next, struct btrfs_root,
                                        root_list);
-               __update_reloc_root(reloc_root, 1);
+               __del_reloc_root(reloc_root);
                free_extent_buffer(reloc_root->node);
                free_extent_buffer(reloc_root->commit_root);
                kfree(reloc_root);
@@ -2332,7 +2353,7 @@ again:
 
                        ret = merge_reloc_root(rc, root);
                        if (ret) {
-                               __update_reloc_root(reloc_root, 1);
+                               __del_reloc_root(reloc_root);
                                free_extent_buffer(reloc_root->node);
                                free_extent_buffer(reloc_root->commit_root);
                                kfree(reloc_root);
@@ -2388,6 +2409,13 @@ out:
                btrfs_std_error(root->fs_info, ret);
                if (!list_empty(&reloc_roots))
                        free_reloc_roots(&reloc_roots);
+
+               /* new reloc root may be added */
+               mutex_lock(&root->fs_info->reloc_mutex);
+               list_splice_init(&rc->reloc_roots, &reloc_roots);
+               mutex_unlock(&root->fs_info->reloc_mutex);
+               if (!list_empty(&reloc_roots))
+                       free_reloc_roots(&reloc_roots);
        }
 
        BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
@@ -4522,6 +4550,11 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
        BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
               root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
 
+       if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
+               if (buf == root->node)
+                       __update_reloc_root(root, cow->start);
+       }
+
        level = btrfs_header_level(buf);
        if (btrfs_header_generation(buf) <=
            btrfs_root_last_snapshot(&root->root_item))
index 561e2f16ba3e3ff3b0be72b12b4a052b86082d2a..1fd3f33c330abe930fbd03de1deb5968e32fd7b5 100644 (file)
@@ -208,7 +208,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                                         int is_metadata, int have_csum,
                                         const u8 *csum, u64 generation,
                                         u16 csum_size);
-static void scrub_complete_bio_end_io(struct bio *bio, int err);
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good,
                                             int force_write);
@@ -1294,7 +1293,6 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
        for (page_num = 0; page_num < sblock->page_count; page_num++) {
                struct bio *bio;
                struct scrub_page *page = sblock->pagev[page_num];
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                if (page->dev->bdev == NULL) {
                        page->io_error = 1;
@@ -1311,18 +1309,11 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
                }
                bio->bi_bdev = page->dev->bdev;
                bio->bi_sector = page->physical >> 9;
-               bio->bi_end_io = scrub_complete_bio_end_io;
-               bio->bi_private = &complete;
 
                bio_add_page(bio, page->page, PAGE_SIZE, 0);
-               btrfsic_submit_bio(READ, bio);
-
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-
-               page->io_error = !test_bit(BIO_UPTODATE, &bio->bi_flags);
-               if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+               if (btrfsic_submit_bio_wait(READ, bio))
                        sblock->no_io_error_seen = 0;
+
                bio_put(bio);
        }
 
@@ -1391,11 +1382,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                sblock->checksum_error = 1;
 }
 
-static void scrub_complete_bio_end_io(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good,
                                             int force_write)
@@ -1430,7 +1416,6 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
            sblock_bad->checksum_error || page_bad->io_error) {
                struct bio *bio;
                int ret;
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                if (!page_bad->dev->bdev) {
                        printk_ratelimited(KERN_WARNING
@@ -1443,19 +1428,14 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
                        return -EIO;
                bio->bi_bdev = page_bad->dev->bdev;
                bio->bi_sector = page_bad->physical >> 9;
-               bio->bi_end_io = scrub_complete_bio_end_io;
-               bio->bi_private = &complete;
 
                ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0);
                if (PAGE_SIZE != ret) {
                        bio_put(bio);
                        return -EIO;
                }
-               btrfsic_submit_bio(WRITE, bio);
 
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-               if (!bio_flagged(bio, BIO_UPTODATE)) {
+               if (btrfsic_submit_bio_wait(WRITE, bio)) {
                        btrfs_dev_stat_inc_and_print(page_bad->dev,
                                BTRFS_DEV_STAT_WRITE_ERRS);
                        btrfs_dev_replace_stats_inc(
@@ -3375,7 +3355,6 @@ static int write_page_nocow(struct scrub_ctx *sctx,
        struct bio *bio;
        struct btrfs_device *dev;
        int ret;
-       DECLARE_COMPLETION_ONSTACK(compl);
 
        dev = sctx->wr_ctx.tgtdev;
        if (!dev)
@@ -3392,8 +3371,6 @@ static int write_page_nocow(struct scrub_ctx *sctx,
                spin_unlock(&sctx->stat_lock);
                return -ENOMEM;
        }
-       bio->bi_private = &compl;
-       bio->bi_end_io = scrub_complete_bio_end_io;
        bio->bi_size = 0;
        bio->bi_sector = physical_for_dev_replace >> 9;
        bio->bi_bdev = dev->bdev;
@@ -3404,10 +3381,8 @@ leave_with_eio:
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
                return -EIO;
        }
-       btrfsic_submit_bio(WRITE_SYNC, bio);
-       wait_for_completion(&compl);
 
-       if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+       if (btrfsic_submit_bio_wait(WRITE_SYNC, bio))
                goto leave_with_eio;
 
        bio_put(bio);
index 6837fe87f3a6bb9f471f54c596e0d98fe67059a3..945d1db98f26968ec051a6ff6116f971f18e7303 100644 (file)
@@ -4723,8 +4723,8 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        }
 
        if (!access_ok(VERIFY_READ, arg->clone_sources,
-                       sizeof(*arg->clone_sources *
-                       arg->clone_sources_count))) {
+                       sizeof(*arg->clone_sources) *
+                       arg->clone_sources_count)) {
                ret = -EFAULT;
                goto out;
        }
index 2d8ac1bf0cf9b9d613215000758cbfa312b4962e..d71a11d13dfaa8b3065222c87ce964d8ba28e5b5 100644 (file)
@@ -432,7 +432,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        } else {
                                printk(KERN_INFO "btrfs: setting nodatacow\n");
                        }
-                       info->compress_type = BTRFS_COMPRESS_NONE;
                        btrfs_clear_opt(info->mount_opt, COMPRESS);
                        btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                        btrfs_set_opt(info->mount_opt, NODATACOW);
@@ -461,7 +460,6 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                btrfs_set_fs_incompat(info, COMPRESS_LZO);
                        } else if (strncmp(args[0].from, "no", 2) == 0) {
                                compress_type = "no";
-                               info->compress_type = BTRFS_COMPRESS_NONE;
                                btrfs_clear_opt(info->mount_opt, COMPRESS);
                                btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                                compress_force = false;
@@ -474,9 +472,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
                                pr_info("btrfs: force %s compression\n",
                                        compress_type);
-                       } else
+                       } else if (btrfs_test_opt(root, COMPRESS)) {
                                pr_info("btrfs: use %s compression\n",
                                        compress_type);
+                       }
                        break;
                case Opt_ssd:
                        printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
index 1e561c059539542e83a118edb003ffabca08506b..ec3ba43b9faae73fba6d6352da9515a812ec9f36 100644 (file)
@@ -210,9 +210,13 @@ static int readpage_nounlock(struct file *filp, struct page *page)
        if (err < 0) {
                SetPageError(page);
                goto out;
-       } else if (err < PAGE_CACHE_SIZE) {
+       } else {
+               if (err < PAGE_CACHE_SIZE) {
                /* zero fill remainder of page */
-               zero_user_segment(page, err, PAGE_CACHE_SIZE);
+                       zero_user_segment(page, err, PAGE_CACHE_SIZE);
+               } else {
+                       flush_dcache_page(page);
+               }
        }
        SetPageUptodate(page);
 
index 9a8e396aed89a43a0c824c3b682f96ac817ebc1c..278fd28912880b5cc09989ed7dcb8e7fbbfcb3ef 100644 (file)
@@ -978,7 +978,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
        struct ceph_mds_reply_inode *ininfo;
        struct ceph_vino vino;
        struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
-       int i = 0;
        int err = 0;
 
        dout("fill_trace %p is_dentry %d is_target %d\n", req,
@@ -1039,6 +1038,29 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                }
        }
 
+       if (rinfo->head->is_target) {
+               vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
+               vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
+
+               in = ceph_get_inode(sb, vino);
+               if (IS_ERR(in)) {
+                       err = PTR_ERR(in);
+                       goto done;
+               }
+               req->r_target_inode = in;
+
+               err = fill_inode(in, &rinfo->targeti, NULL,
+                               session, req->r_request_started,
+                               (le32_to_cpu(rinfo->head->result) == 0) ?
+                               req->r_fmode : -1,
+                               &req->r_caps_reservation);
+               if (err < 0) {
+                       pr_err("fill_inode badness %p %llx.%llx\n",
+                               in, ceph_vinop(in));
+                       goto done;
+               }
+       }
+
        /*
         * ignore null lease/binding on snapdir ENOENT, or else we
         * will have trouble splicing in the virtual snapdir later
@@ -1108,7 +1130,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                             ceph_dentry(req->r_old_dentry)->offset);
 
                        dn = req->r_old_dentry;  /* use old_dentry */
-                       in = dn->d_inode;
                }
 
                /* null dentry? */
@@ -1130,44 +1151,28 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                }
 
                /* attach proper inode */
-               ininfo = rinfo->targeti.in;
-               vino.ino = le64_to_cpu(ininfo->ino);
-               vino.snap = le64_to_cpu(ininfo->snapid);
-               in = dn->d_inode;
-               if (!in) {
-                       in = ceph_get_inode(sb, vino);
-                       if (IS_ERR(in)) {
-                               pr_err("fill_trace bad get_inode "
-                                      "%llx.%llx\n", vino.ino, vino.snap);
-                               err = PTR_ERR(in);
-                               d_drop(dn);
-                               goto done;
-                       }
+               if (!dn->d_inode) {
+                       ihold(in);
                        dn = splice_dentry(dn, in, &have_lease, true);
                        if (IS_ERR(dn)) {
                                err = PTR_ERR(dn);
                                goto done;
                        }
                        req->r_dentry = dn;  /* may have spliced */
-                       ihold(in);
-               } else if (ceph_ino(in) == vino.ino &&
-                          ceph_snap(in) == vino.snap) {
-                       ihold(in);
-               } else {
+               } else if (dn->d_inode && dn->d_inode != in) {
                        dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
-                            dn, in, ceph_ino(in), ceph_snap(in),
-                            vino.ino, vino.snap);
+                            dn, dn->d_inode, ceph_vinop(dn->d_inode),
+                            ceph_vinop(in));
                        have_lease = false;
-                       in = NULL;
                }
 
                if (have_lease)
                        update_dentry_lease(dn, rinfo->dlease, session,
                                            req->r_request_started);
                dout(" final dn %p\n", dn);
-               i++;
-       } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
-                  req->r_op == CEPH_MDS_OP_MKSNAP) && !req->r_aborted) {
+       } else if (!req->r_aborted &&
+                  (req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
+                   req->r_op == CEPH_MDS_OP_MKSNAP)) {
                struct dentry *dn = req->r_dentry;
 
                /* fill out a snapdir LOOKUPSNAP dentry */
@@ -1177,52 +1182,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                ininfo = rinfo->targeti.in;
                vino.ino = le64_to_cpu(ininfo->ino);
                vino.snap = le64_to_cpu(ininfo->snapid);
-               in = ceph_get_inode(sb, vino);
-               if (IS_ERR(in)) {
-                       pr_err("fill_inode get_inode badness %llx.%llx\n",
-                              vino.ino, vino.snap);
-                       err = PTR_ERR(in);
-                       d_delete(dn);
-                       goto done;
-               }
                dout(" linking snapped dir %p to dn %p\n", in, dn);
+               ihold(in);
                dn = splice_dentry(dn, in, NULL, true);
                if (IS_ERR(dn)) {
                        err = PTR_ERR(dn);
                        goto done;
                }
                req->r_dentry = dn;  /* may have spliced */
-               ihold(in);
-               rinfo->head->is_dentry = 1;  /* fool notrace handlers */
-       }
-
-       if (rinfo->head->is_target) {
-               vino.ino = le64_to_cpu(rinfo->targeti.in->ino);
-               vino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
-
-               if (in == NULL || ceph_ino(in) != vino.ino ||
-                   ceph_snap(in) != vino.snap) {
-                       in = ceph_get_inode(sb, vino);
-                       if (IS_ERR(in)) {
-                               err = PTR_ERR(in);
-                               goto done;
-                       }
-               }
-               req->r_target_inode = in;
-
-               err = fill_inode(in,
-                                &rinfo->targeti, NULL,
-                                session, req->r_request_started,
-                                (le32_to_cpu(rinfo->head->result) == 0) ?
-                                req->r_fmode : -1,
-                                &req->r_caps_reservation);
-               if (err < 0) {
-                       pr_err("fill_inode badness %p %llx.%llx\n",
-                              in, ceph_vinop(in));
-                       goto done;
-               }
        }
-
 done:
        dout("fill_trace done err=%d\n", err);
        return err;
@@ -1272,7 +1240,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
        struct qstr dname;
        struct dentry *dn;
        struct inode *in;
-       int err = 0, i;
+       int err = 0, ret, i;
        struct inode *snapdir = NULL;
        struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
        struct ceph_dentry_info *di;
@@ -1305,6 +1273,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                        ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir);
        }
 
+       /* FIXME: release caps/leases if error occurs */
        for (i = 0; i < rinfo->dir_nr; i++) {
                struct ceph_vino vino;
 
@@ -1329,9 +1298,10 @@ retry_lookup:
                                err = -ENOMEM;
                                goto out;
                        }
-                       err = ceph_init_dentry(dn);
-                       if (err < 0) {
+                       ret = ceph_init_dentry(dn);
+                       if (ret < 0) {
                                dput(dn);
+                               err = ret;
                                goto out;
                        }
                } else if (dn->d_inode &&
@@ -1351,9 +1321,6 @@ retry_lookup:
                        spin_unlock(&parent->d_lock);
                }
 
-               di = dn->d_fsdata;
-               di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
-
                /* inode */
                if (dn->d_inode) {
                        in = dn->d_inode;
@@ -1366,26 +1333,39 @@ retry_lookup:
                                err = PTR_ERR(in);
                                goto out;
                        }
-                       dn = splice_dentry(dn, in, NULL, false);
-                       if (IS_ERR(dn))
-                               dn = NULL;
                }
 
                if (fill_inode(in, &rinfo->dir_in[i], NULL, session,
                               req->r_request_started, -1,
                               &req->r_caps_reservation) < 0) {
                        pr_err("fill_inode badness on %p\n", in);
+                       if (!dn->d_inode)
+                               iput(in);
+                       d_drop(dn);
                        goto next_item;
                }
-               if (dn)
-                       update_dentry_lease(dn, rinfo->dir_dlease[i],
-                                           req->r_session,
-                                           req->r_request_started);
+
+               if (!dn->d_inode) {
+                       dn = splice_dentry(dn, in, NULL, false);
+                       if (IS_ERR(dn)) {
+                               err = PTR_ERR(dn);
+                               dn = NULL;
+                               goto next_item;
+                       }
+               }
+
+               di = dn->d_fsdata;
+               di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
+
+               update_dentry_lease(dn, rinfo->dir_dlease[i],
+                                   req->r_session,
+                                   req->r_request_started);
 next_item:
                if (dn)
                        dput(dn);
        }
-       req->r_did_prepopulate = true;
+       if (err == 0)
+               req->r_did_prepopulate = true;
 
 out:
        if (snapdir) {
index aa3397620342d20beba92abc732845273d3663ca..2c29db6a247e4788256461100bed11ac79648d26 100644 (file)
@@ -477,9 +477,10 @@ extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
                        const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
 extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
-extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-               const unsigned char *path,
-               struct cifs_sb_info *cifs_sb, unsigned int xid);
+extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                             struct cifs_sb_info *cifs_sb,
+                             struct cifs_fattr *fattr,
+                             const unsigned char *path);
 extern int mdfour(unsigned char *, unsigned char *, int);
 extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
                        const struct nls_table *codepage);
index 124aa0230c1b8738edb8d04ca5d764f0a6cc5b12..d707edb6b852695f0de3993c9ef9cd12a3f909f3 100644 (file)
@@ -4010,7 +4010,7 @@ QFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4179,7 +4179,7 @@ UnixQFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4263,7 +4263,7 @@ UnixQPathInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
index 11ff5f116b20e663bf5e0428a940b437d9b232aa..a514e0a65f69b5936fbd60934b33938666f70dd0 100644 (file)
@@ -193,7 +193,7 @@ check_name(struct dentry *direntry)
 static int
 cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
               struct tcon_link *tlink, unsigned oflags, umode_t mode,
-              __u32 *oplock, struct cifs_fid *fid, int *created)
+              __u32 *oplock, struct cifs_fid *fid)
 {
        int rc = -ENOENT;
        int create_options = CREATE_NOT_DIR;
@@ -349,7 +349,6 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
                                .device = 0,
                };
 
-               *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        args.uid = current_fsuid();
                        if (inode->i_mode & S_ISGID)
@@ -480,13 +479,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
        cifs_add_pending_open(&fid, tlink, &open);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, opened);
+                           &oplock, &fid);
 
        if (rc) {
                cifs_del_pending_open(&open);
                goto out;
        }
 
+       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               *opened |= FILE_CREATED;
+
        rc = finish_open(file, direntry, generic_file_open, opened);
        if (rc) {
                if (server->ops->close)
@@ -529,7 +531,6 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
        struct TCP_Server_Info *server;
        struct cifs_fid fid;
        __u32 oplock;
-       int created = FILE_CREATED;
 
        cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p\n",
                 inode, direntry->d_name.name, direntry);
@@ -546,7 +547,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                server->ops->new_lease_key(&fid);
 
        rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
-                           &oplock, &fid, &created);
+                           &oplock, &fid);
        if (!rc && server->ops->close)
                server->ops->close(xid, tcon, &fid);
 
index 36f9ebb93ceba676c363cdf7b973f3936a9dde8f..49719b8228e58bd44b373fd4b39d844be9e2043b 100644 (file)
@@ -383,7 +383,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                              full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
@@ -799,7 +800,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                          full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
index cc0234710ddbb780cae5037b717a93d8a7d3d54d..92aee08483a52e100011fb05e1fcfc5255b340ac 100644 (file)
@@ -354,34 +354,30 @@ open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
 
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-                  const unsigned char *path,
-                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                  const unsigned char *path)
 {
-       int rc = 0;
+       int rc;
        u8 *buf = NULL;
        unsigned int link_len = 0;
        unsigned int bytes_read = 0;
-       struct cifs_tcon *ptcon;
 
        if (!CIFSCouldBeMFSymlink(fattr))
                /* it's not a symlink */
                return 0;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-       if (!buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!buf)
+               return -ENOMEM;
 
-       ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
-       if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
-               rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
-                                                &bytes_read, cifs_sb, xid);
+       if (tcon->ses->server->ops->query_mf_symlink)
+               rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
+                                               &bytes_read, cifs_sb, xid);
        else
-               goto out;
+               rc = -ENOSYS;
 
-       if (rc != 0)
+       if (rc)
                goto out;
 
        if (bytes_read == 0) /* not a symlink */
index 4bdb300b16e2e940bab8eeb07417b7f87914815f..cb4a10690868263cb58e28012ee8f9abc4880da5 100644 (file)
@@ -192,7 +192,7 @@ static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char
                if (!tcount)
                        return 0;
        }
-       mask = ~(~0ul << tcount*8);
+       mask = bytemask_from_count(tcount);
        return unlikely(!!((a ^ b) & mask));
 }
 
@@ -3061,8 +3061,13 @@ char *d_path(const struct path *path, char *buf, int buflen)
         * thus don't need to be hashed.  They also don't need a name until a
         * user wants to identify the object in /proc/pid/fd/.  The little hack
         * below allows us to generate a name for these objects on demand:
+        *
+        * Some pseudo inodes are mountable.  When they are mounted
+        * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
+        * and instead have d_path return the mounted path.
         */
-       if (path->dentry->d_op && path->dentry->d_op->d_dname)
+       if (path->dentry->d_op && path->dentry->d_op->d_dname &&
+           (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
                return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
        rcu_read_lock();
index 79b65c3b9e876f1087ccbcf7908a47c18efbbad9..af903128891cfa0365f7fac36ba8fc052cc584a4 100644 (file)
@@ -1852,8 +1852,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                goto error_tgt_fput;
 
        /* Check if EPOLLWAKEUP is allowed */
-       if ((epds.events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
-               epds.events &= ~EPOLLWAKEUP;
+       ep_take_care_of_epollwakeup(&epds);
 
        /*
         * We have to check that the file structure underneath the file descriptor
@@ -1908,10 +1907,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                        }
                }
        }
-       if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
-               tep = tf.file->private_data;
-               mutex_lock_nested(&tep->mtx, 1);
-       }
 
        /*
         * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
index 288534920fe5cc4960f99ae636777344c5d42db6..20d6697bd6386560a679dda5e8b8592a65d63798 100644 (file)
@@ -1493,6 +1493,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
                                sb->s_blocksize - offset : towrite;
 
                tmp_bh.b_state = 0;
+               tmp_bh.b_size = sb->s_blocksize;
                err = ext2_get_block(inode, blk, &tmp_bh, 1);
                if (err < 0)
                        goto out;
index e6185031c1ccb5d7ef6c35185d77e5b06d648a5d..ece55565b9cd35575c454d44656c63321d89e0f9 100644 (file)
@@ -268,6 +268,16 @@ struct ext4_io_submit {
 /* Translate # of blks to # of clusters */
 #define EXT4_NUM_B2C(sbi, blks)        (((blks) + (sbi)->s_cluster_ratio - 1) >> \
                                 (sbi)->s_cluster_bits)
+/* Mask out the low bits to get the starting block of the cluster */
+#define EXT4_PBLK_CMASK(s, pblk) ((pblk) &                             \
+                                 ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_CMASK(s, lblk) ((lblk) &                             \
+                                 ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
+/* Get the cluster offset */
+#define EXT4_PBLK_COFF(s, pblk) ((pblk) &                              \
+                                ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
+#define EXT4_LBLK_COFF(s, lblk) ((lblk) &                              \
+                                ((ext4_lblk_t) (s)->s_cluster_ratio - 1))
 
 /*
  * Structure of a blocks group descriptor
index 17ac112ab1012bd88ff32d145f27a29f025efdde..3fe29de832c825e390b8d59d818b5ec37a8eb61f 100644 (file)
@@ -259,6 +259,15 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                if (WARN_ON_ONCE(err)) {
                        ext4_journal_abort_handle(where, line, __func__, bh,
                                                  handle, err);
+                       ext4_error_inode(inode, where, line,
+                                        bh->b_blocknr,
+                                        "journal_dirty_metadata failed: "
+                                        "handle type %u started at line %u, "
+                                        "credits %u/%u, errcode %d",
+                                        handle->h_type,
+                                        handle->h_line_no,
+                                        handle->h_requested_credits,
+                                        handle->h_buffer_credits, err);
                }
        } else {
                if (inode)
index 35f65cf4f318d72bce4e79995ddbc85d0e4bbfa3..3384dc4bed4034921beffb84783327024e4cf22e 100644 (file)
@@ -360,8 +360,10 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
 {
        ext4_fsblk_t block = ext4_ext_pblock(ext);
        int len = ext4_ext_get_actual_len(ext);
+       ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
+       ext4_lblk_t last = lblock + len - 1;
 
-       if (len == 0)
+       if (lblock > last)
                return 0;
        return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -387,11 +389,26 @@ static int ext4_valid_extent_entries(struct inode *inode,
        if (depth == 0) {
                /* leaf entries */
                struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+               struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+               ext4_fsblk_t pblock = 0;
+               ext4_lblk_t lblock = 0;
+               ext4_lblk_t prev = 0;
+               int len = 0;
                while (entries) {
                        if (!ext4_valid_extent(inode, ext))
                                return 0;
+
+                       /* Check for overlapping extents */
+                       lblock = le32_to_cpu(ext->ee_block);
+                       len = ext4_ext_get_actual_len(ext);
+                       if ((lblock <= prev) && prev) {
+                               pblock = ext4_ext_pblock(ext);
+                               es->s_last_error_block = cpu_to_le64(pblock);
+                               return 0;
+                       }
                        ext++;
                        entries--;
+                       prev = lblock + len - 1;
                }
        } else {
                struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
@@ -1834,8 +1851,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
        depth = ext_depth(inode);
        if (!path[depth].p_ext)
                goto out;
-       b2 = le32_to_cpu(path[depth].p_ext->ee_block);
-       b2 &= ~(sbi->s_cluster_ratio - 1);
+       b2 = EXT4_LBLK_CMASK(sbi, le32_to_cpu(path[depth].p_ext->ee_block));
 
        /*
         * get the next allocated block if the extent in the path
@@ -1845,7 +1861,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,
                b2 = ext4_ext_next_allocated_block(path);
                if (b2 == EXT_MAX_BLOCKS)
                        goto out;
-               b2 &= ~(sbi->s_cluster_ratio - 1);
+               b2 = EXT4_LBLK_CMASK(sbi, b2);
        }
 
        /* check for wrap through zero on extent logical start block*/
@@ -2504,7 +2520,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
                 * extent, we have to mark the cluster as used (store negative
                 * cluster number in partial_cluster).
                 */
-               unaligned = pblk & (sbi->s_cluster_ratio - 1);
+               unaligned = EXT4_PBLK_COFF(sbi, pblk);
                if (unaligned && (ee_len == num) &&
                    (*partial_cluster != -((long long)EXT4_B2C(sbi, pblk))))
                        *partial_cluster = EXT4_B2C(sbi, pblk);
@@ -2598,7 +2614,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                         * accidentally freeing it later on
                         */
                        pblk = ext4_ext_pblock(ex);
-                       if (pblk & (sbi->s_cluster_ratio - 1))
+                       if (EXT4_PBLK_COFF(sbi, pblk))
                                *partial_cluster =
                                        -((long long)EXT4_B2C(sbi, pblk));
                        ex--;
@@ -3753,7 +3769,7 @@ int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
 {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        ext4_lblk_t lblk_start, lblk_end;
-       lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
+       lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
        lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
 
        return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
@@ -3812,9 +3828,9 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        trace_ext4_get_reserved_cluster_alloc(inode, lblk_start, num_blks);
 
        /* Check towards left side */
-       c_offset = lblk_start & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start);
        if (c_offset) {
-               lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
+               lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start);
                lblk_to = lblk_from + c_offset - 1;
 
                if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
@@ -3822,7 +3838,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
        }
 
        /* Now check towards right. */
-       c_offset = (lblk_start + num_blks) & (sbi->s_cluster_ratio - 1);
+       c_offset = EXT4_LBLK_COFF(sbi, lblk_start + num_blks);
        if (allocated_clusters && c_offset) {
                lblk_from = lblk_start + num_blks;
                lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
@@ -4030,7 +4046,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
                                     struct ext4_ext_path *path)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       ext4_lblk_t c_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       ext4_lblk_t c_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ext4_lblk_t ex_cluster_start, ex_cluster_end;
        ext4_lblk_t rr_cluster_start;
        ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
@@ -4048,8 +4064,7 @@ static int get_implied_cluster_alloc(struct super_block *sb,
            (rr_cluster_start == ex_cluster_start)) {
                if (rr_cluster_start == ex_cluster_end)
                        ee_start += ee_len - 1;
-               map->m_pblk = (ee_start & ~(sbi->s_cluster_ratio - 1)) +
-                       c_offset;
+               map->m_pblk = EXT4_PBLK_CMASK(sbi, ee_start) + c_offset;
                map->m_len = min(map->m_len,
                                 (unsigned) sbi->s_cluster_ratio - c_offset);
                /*
@@ -4203,7 +4218,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         */
        map->m_flags &= ~EXT4_MAP_FROM_CLUSTER;
        newex.ee_block = cpu_to_le32(map->m_lblk);
-       cluster_offset = map->m_lblk & (sbi->s_cluster_ratio-1);
+       cluster_offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
 
        /*
         * If we are doing bigalloc, check to see if the extent returned
@@ -4271,7 +4286,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
         * needed so that future calls to get_implied_cluster_alloc()
         * work correctly.
         */
-       offset = map->m_lblk & (sbi->s_cluster_ratio - 1);
+       offset = EXT4_LBLK_COFF(sbi, map->m_lblk);
        ar.len = EXT4_NUM_B2C(sbi, offset+allocated);
        ar.goal -= offset;
        ar.logical -= offset;
index 0757634741187a568cc2255187bcd2cf250d852b..61d49ff22c81f844cb8bc6324ad3aa70d649fb7b 100644 (file)
@@ -1206,7 +1206,6 @@ static int ext4_journalled_write_end(struct file *file,
  */
 static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1218,7 +1217,6 @@ static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1238,10 +1236,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                return -ENOSPC;
        }
        ei->i_reserved_meta_blocks += md_needed;
@@ -1255,7 +1249,6 @@ repeat:
  */
 static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
 {
-       int retries = 0;
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int md_needed;
@@ -1277,7 +1270,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock)
         * in order to allocate nrblocks
         * worse case is one extent per block
         */
-repeat:
        spin_lock(&ei->i_block_reservation_lock);
        /*
         * ext4_calc_metadata_amount() has side effects, which we have
@@ -1297,10 +1289,6 @@ repeat:
                ei->i_da_metadata_calc_len = save_len;
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
-               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       cond_resched();
-                       goto repeat;
-               }
                dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
                return -ENOSPC;
        }
index 4d113efa024c8439f4000a0fa59ed643f2489166..04a5c7504be9d6dbe55174d451f559064a7a05cf 100644 (file)
@@ -3442,6 +3442,9 @@ static void ext4_mb_pa_callback(struct rcu_head *head)
 {
        struct ext4_prealloc_space *pa;
        pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu);
+
+       BUG_ON(atomic_read(&pa->pa_count));
+       BUG_ON(pa->pa_deleted == 0);
        kmem_cache_free(ext4_pspace_cachep, pa);
 }
 
@@ -3455,11 +3458,13 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
        ext4_group_t grp;
        ext4_fsblk_t grp_blk;
 
-       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
-               return;
-
        /* in this short window concurrent discard can set pa_deleted */
        spin_lock(&pa->pa_lock);
+       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
+               spin_unlock(&pa->pa_lock);
+               return;
+       }
+
        if (pa->pa_deleted == 1) {
                spin_unlock(&pa->pa_lock);
                return;
@@ -4121,7 +4126,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
        ext4_get_group_no_and_offset(sb, goal, &group, &block);
 
        /* set up allocation goals */
-       ac->ac_b_ex.fe_logical = ar->logical & ~(sbi->s_cluster_ratio - 1);
+       ac->ac_b_ex.fe_logical = EXT4_LBLK_CMASK(sbi, ar->logical);
        ac->ac_status = AC_STATUS_CONTINUE;
        ac->ac_sb = sb;
        ac->ac_inode = ar->inode;
@@ -4663,7 +4668,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
         * blocks at the beginning or the end unless we are explicitly
         * requested to avoid doing so.
         */
-       overflow = block & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_PBLK_COFF(sbi, block);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
                        overflow = sbi->s_cluster_ratio - overflow;
@@ -4677,7 +4682,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
                        count += overflow;
                }
        }
-       overflow = count & (sbi->s_cluster_ratio - 1);
+       overflow = EXT4_LBLK_COFF(sbi, count);
        if (overflow) {
                if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
                        if (count > overflow)
index c977f4e4e63be6c4cf3b477f628e4fc7d323d1f5..1f7784de05b6c6afad4d7437202ceb6efeec3399 100644 (file)
@@ -792,7 +792,7 @@ static void ext4_put_super(struct super_block *sb)
        }
 
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        ext4_release_system_zone(sb);
        ext4_mb_release(sb);
        ext4_ext_release(sb);
@@ -3316,10 +3316,18 @@ int ext4_calculate_overhead(struct super_block *sb)
 }
 
 
-static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
+static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
 
+       /*
+        * There's no need to reserve anything when we aren't using extents.
+        * The space estimates are exact, there are no unwritten extents,
+        * hole punching doesn't need new metadata... This is needed especially
+        * to keep ext2/3 backward compatibility.
+        */
+       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+               return 0;
        /*
         * By default we reserve 2% or 4096 clusters, whichever is smaller.
         * This should cover the situations where we can not afford to run
@@ -3328,7 +3336,8 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
         * allocation would require 1, or 2 blocks, higher numbers are
         * very rare.
         */
-       resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
+       resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
+                       EXT4_SB(sb)->s_cluster_bits;
 
        do_div(resv_clusters, 50);
        resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
@@ -4071,10 +4080,10 @@ no_journal:
                         "available");
        }
 
-       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi));
+       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
-                        "reserved pool", ext4_calculate_resv_clusters(sbi));
+                        "reserved pool", ext4_calculate_resv_clusters(sb));
                goto failed_mount4a;
        }
 
@@ -4184,7 +4193,7 @@ failed_mount_wq:
        }
 failed_mount3:
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        if (sbi->s_flex_groups)
                ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
index 1f4a10ece2f1249d5ae9991bfdde4874019b3462..e0259a163f98e69000c28bdb78fcf2b77c2bed2d 100644 (file)
@@ -516,13 +516,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
        }
        WARN_ON(inode->i_state & I_SYNC);
        /*
-        * Skip inode if it is clean. We don't want to mess with writeback
-        * lists in this function since flusher thread may be doing for example
-        * sync in parallel and if we move the inode, it could get skipped. So
-        * here we make sure inode is on some writeback list and leave it there
-        * unless we have completely cleaned the inode.
+        * Skip inode if it is clean and we have no outstanding writeback in
+        * WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
+        * function since flusher thread may be doing for example sync in
+        * parallel and if we move the inode, it could get skipped. So here we
+        * make sure inode is on some writeback list and leave it there unless
+        * we have completely cleaned the inode.
         */
-       if (!(inode->i_state & I_DIRTY))
+       if (!(inode->i_state & I_DIRTY) &&
+           (wbc->sync_mode != WB_SYNC_ALL ||
+            !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
                goto out;
        inode->i_state |= I_SYNC;
        spin_unlock(&inode->i_lock);
index b7fc035a6943cc40f649f1cca7be5858fbcf1cbc..73f3e4ee403793e1ae39c75b5d652f64c6a4b52a 100644 (file)
@@ -986,6 +986,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
+       struct address_space *mapping = inode->i_mapping;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int rv;
@@ -1006,6 +1007,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
        if (rv != 1)
                goto out; /* dio not valid, fall back to buffered i/o */
 
+       /*
+        * Now since we are holding a deferred (CW) lock at this point, you
+        * might be wondering why this is ever needed. There is a case however
+        * where we've granted a deferred local lock against a cached exclusive
+        * glock. That is ok provided all granted local locks are deferred, but
+        * it also means that it is possible to encounter pages which are
+        * cached and possibly also mapped. So here we check for that and sort
+        * them out ahead of the dio. The glock state machine will take care of
+        * everything else.
+        *
+        * If in fact the cached glock state (gl->gl_state) is deferred (CW) in
+        * the first place, mapping->nr_pages will always be zero.
+        */
+       if (mapping->nrpages) {
+               loff_t lstart = offset & (PAGE_CACHE_SIZE - 1);
+               loff_t len = iov_length(iov, nr_segs);
+               loff_t end = PAGE_ALIGN(offset + len) - 1;
+
+               rv = 0;
+               if (len == 0)
+                       goto out;
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len);
+               rv = filemap_write_and_wait_range(mapping, lstart, end);
+               if (rv)
+                       return rv;
+               truncate_inode_pages_range(mapping, lstart, end);
+       }
+
        rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                  offset, nr_segs, gfs2_get_block_direct,
                                  NULL, NULL, 0);
index c8420f7e4db604da3663da61c5ae4556b6439783..6f7a47c052592145d7601c0e9ab0341c4dd8c4d7 100644 (file)
@@ -1655,6 +1655,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
        struct task_struct *gh_owner = NULL;
        char flags_buf[32];
 
+       rcu_read_lock();
        if (gh->gh_owner_pid)
                gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
        gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
@@ -1664,6 +1665,7 @@ static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
                       gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
                       gh_owner ? gh_owner->comm : "(ended)",
                       (void *)gh->gh_ip);
+       rcu_read_unlock();
        return 0;
 }
 
index db908f697139cfffbca462d3a7528e13139576b5..f88dcd92501098e4a9bca28724da34e8df5a0154 100644 (file)
@@ -192,8 +192,11 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
        if (ip && !S_ISREG(ip->i_inode.i_mode))
                ip = NULL;
-       if (ip && test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
-               unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+       if (ip) {
+               if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags))
+                       unmap_shared_mapping_range(ip->i_inode.i_mapping, 0, 0);
+               inode_dio_wait(&ip->i_inode);
+       }
        if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
                return;
 
@@ -410,6 +413,9 @@ static int inode_go_lock(struct gfs2_holder *gh)
                        return error;
        }
 
+       if (gh->gh_state != LM_ST_DEFERRED)
+               inode_dio_wait(&ip->i_inode);
+
        if ((ip->i_diskflags & GFS2_DIF_TRUNC_IN_PROG) &&
            (gl->gl_state == LM_ST_EXCLUSIVE) &&
            (gh->gh_state == LM_ST_EXCLUSIVE)) {
index 610613fb65b552dccfdf9853ac96d2f667bd36d4..9dcb9777a5f80eb32bcfce88aca3a8026776f047 100644 (file)
@@ -551,10 +551,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct buffer_head *bh = bd->bd_bh;
        struct gfs2_glock *gl = bd->bd_gl;
 
-       gfs2_remove_from_ail(bd);
-       bd->bd_bh = NULL;
        bh->b_private = NULL;
        bd->bd_blkno = bh->b_blocknr;
+       gfs2_remove_from_ail(bd); /* drops ref on bh */
+       bd->bd_bh = NULL;
        bd->bd_ops = &gfs2_revoke_lops;
        sdp->sd_log_num_revoke++;
        atomic_inc(&gl->gl_revokes);
index 932415050540e2a1bdefc6d957e68ef7a0d82d01..52f177be3bf861309ed2439d33da7617bba8dba8 100644 (file)
@@ -258,6 +258,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
        struct address_space *mapping = bh->b_page->mapping;
        struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
        struct gfs2_bufdata *bd = bh->b_private;
+       int was_pinned = 0;
 
        if (test_clear_buffer_pinned(bh)) {
                trace_gfs2_pin(bd, 0);
@@ -273,12 +274,16 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
                        tr->tr_num_databuf_rm++;
                }
                tr->tr_touched = 1;
+               was_pinned = 1;
                brelse(bh);
        }
        if (bd) {
                spin_lock(&sdp->sd_ail_lock);
                if (bd->bd_tr) {
                        gfs2_trans_add_revoke(sdp, bd);
+               } else if (was_pinned) {
+                       bh->b_private = NULL;
+                       kmem_cache_free(gfs2_bufdata_cachep, bd);
                }
                spin_unlock(&sdp->sd_ail_lock);
        }
index 82303b4749582cd3c00d402a9f42b9972b1de677..52fa88314f5cdf8ef98ed95e44791a5065cbfccd 100644 (file)
@@ -1366,8 +1366,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        if (IS_ERR(s))
                goto error_bdev;
 
-       if (s->s_root)
+       if (s->s_root) {
+               /*
+                * s_umount nests inside bd_mutex during
+                * __invalidate_device().  blkdev_put() acquires
+                * bd_mutex and can't be called under s_umount.  Drop
+                * s_umount temporarily.  This is safe as we're
+                * holding an active reference.
+                */
+               up_write(&s->s_umount);
                blkdev_put(bdev, mode);
+               down_write(&s->s_umount);
+       }
 
        memset(&args, 0, sizeof(args));
        args.ar_quota = GFS2_QUOTA_DEFAULT;
index b51a6079108d1d4fa4a696b222a63c6634b0a36c..e9a97a0d431480616043410a51567730bebafda3 100644 (file)
@@ -24,13 +24,6 @@ struct hfsplus_wd {
        u16 embed_count;
 };
 
-static void hfsplus_end_io_sync(struct bio *bio, int err)
-{
-       if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       complete(bio->bi_private);
-}
-
 /*
  * hfsplus_submit_bio - Perfrom block I/O
  * @sb: super block of volume for I/O
@@ -53,7 +46,6 @@ static void hfsplus_end_io_sync(struct bio *bio, int err)
 int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
                void *buf, void **data, int rw)
 {
-       DECLARE_COMPLETION_ONSTACK(wait);
        struct bio *bio;
        int ret = 0;
        u64 io_size;
@@ -73,8 +65,6 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
        bio = bio_alloc(GFP_NOIO, 1);
        bio->bi_sector = sector;
        bio->bi_bdev = sb->s_bdev;
-       bio->bi_end_io = hfsplus_end_io_sync;
-       bio->bi_private = &wait;
 
        if (!(rw & WRITE) && data)
                *data = (u8 *)buf + offset;
@@ -93,12 +83,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
                buf = (u8 *)buf + len;
        }
 
-       submit_bio(rw, bio);
-       wait_for_completion(&wait);
-
-       if (!bio_flagged(bio, BIO_UPTODATE))
-               ret = -EIO;
-
+       ret = submit_bio_wait(rw, bio);
 out:
        bio_put(bio);
        return ret < 0 ? ret : 0;
index 52032647dd4a32f7c8efaea95227634071f8d7d3..5fa344afb49ae8642be889ce2b3f69d176af548e 100644 (file)
@@ -702,7 +702,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        read_lock(&journal->j_state_lock);
 #ifdef CONFIG_JBD2_DEBUG
        if (!tid_geq(journal->j_commit_request, tid)) {
-               printk(KERN_EMERG
+               printk(KERN_ERR
                       "%s: error: j_commit_request=%d, tid=%d\n",
                       __func__, journal->j_commit_request, tid);
        }
@@ -718,10 +718,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        }
        read_unlock(&journal->j_state_lock);
 
-       if (unlikely(is_journal_aborted(journal))) {
-               printk(KERN_EMERG "journal commit I/O error\n");
+       if (unlikely(is_journal_aborted(journal)))
                err = -EIO;
-       }
        return err;
 }
 
@@ -1527,13 +1525,13 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
            JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                /* Can't have checksum v1 and v2 on at the same time! */
-               printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
+               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
                       "at the same time!\n");
                goto out;
        }
 
        if (!jbd2_verify_csum_type(journal, sb)) {
-               printk(KERN_ERR "JBD: Unknown checksum type\n");
+               printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
        }
 
@@ -1541,7 +1539,7 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
                if (IS_ERR(journal->j_chksum_driver)) {
-                       printk(KERN_ERR "JBD: Cannot load crc32c driver.\n");
+                       printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
                        err = PTR_ERR(journal->j_chksum_driver);
                        journal->j_chksum_driver = NULL;
                        goto out;
@@ -1550,7 +1548,7 @@ static int journal_get_superblock(journal_t *journal)
 
        /* Check superblock checksum */
        if (!jbd2_superblock_csum_verify(journal, sb)) {
-               printk(KERN_ERR "JBD: journal checksum error\n");
+               printk(KERN_ERR "JBD2: journal checksum error\n");
                goto out;
        }
 
@@ -1836,7 +1834,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                        journal->j_chksum_driver = crypto_alloc_shash("crc32c",
                                                                      0, 0);
                        if (IS_ERR(journal->j_chksum_driver)) {
-                               printk(KERN_ERR "JBD: Cannot load crc32c "
+                               printk(KERN_ERR "JBD2: Cannot load crc32c "
                                       "driver.\n");
                                journal->j_chksum_driver = NULL;
                                return 0;
@@ -2645,7 +2643,7 @@ static void __exit journal_exit(void)
 #ifdef CONFIG_JBD2_DEBUG
        int n = atomic_read(&nr_journal_heads);
        if (n)
-               printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
+               printk(KERN_ERR "JBD2: leaked %d journal_heads!\n", n);
 #endif
        jbd2_remove_jbd_stats_proc_entry();
        jbd2_journal_destroy_caches();
index 3929c50428b1a289d4024fcbe673276f63ff97c0..3b6bb19d60b17abceadec4c38df5d3570c0fcba9 100644 (file)
@@ -594,7 +594,7 @@ static int do_one_pass(journal_t *journal,
                                                be32_to_cpu(tmp->h_sequence))) {
                                                brelse(obh);
                                                success = -EIO;
-                                               printk(KERN_ERR "JBD: Invalid "
+                                               printk(KERN_ERR "JBD2: Invalid "
                                                       "checksum recovering "
                                                       "block %llu in log\n",
                                                       blocknr);
index 7aa9a32573bba885d166e484c367bffc06bcd9e2..8360674c85bcb98af88d6aaff3ee4c46fe6f31bf 100644 (file)
@@ -932,7 +932,7 @@ repeat:
                                        jbd2_alloc(jh2bh(jh)->b_size,
                                                         GFP_NOFS);
                                if (!frozen_buffer) {
-                                       printk(KERN_EMERG
+                                       printk(KERN_ERR
                                               "%s: OOM for frozen_buffer\n",
                                               __func__);
                                        JBUFFER_TRACE(jh, "oom!");
@@ -1166,7 +1166,7 @@ repeat:
        if (!jh->b_committed_data) {
                committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
-                       printk(KERN_EMERG "%s: No memory for committed data\n",
+                       printk(KERN_ERR "%s: No memory for committed data\n",
                                __func__);
                        err = -ENOMEM;
                        goto out;
@@ -1290,7 +1290,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                 * once a transaction -bzzz
                 */
                jh->b_modified = 1;
-               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+               if (handle->h_buffer_credits <= 0) {
+                       ret = -ENOSPC;
+                       goto out_unlock_bh;
+               }
                handle->h_buffer_credits--;
        }
 
@@ -1305,7 +1308,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "fastpath");
                if (unlikely(jh->b_transaction !=
                             journal->j_running_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_running_transaction (%p, %u)",
                               journal->j_devname,
@@ -1332,7 +1335,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "already on other transaction");
                if (unlikely(jh->b_transaction !=
                             journal->j_committing_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_committing_transaction (%p, %u)",
                               journal->j_devname,
@@ -1345,7 +1348,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                        ret = -EINVAL;
                }
                if (unlikely(jh->b_next_transaction != transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_next_transaction (%llu, %p, %u) != "
                               "transaction (%p, %u)",
                               journal->j_devname,
@@ -1373,7 +1376,6 @@ out_unlock_bh:
        jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
-       WARN_ON(ret);   /* All errors are bugs, so dump the stack */
        return ret;
 }
 
index 550475ca6a0e0ec35c82d90b10372f2e4434fe90..0f95f0d0b3133e9b3129e3807a842438e162a245 100644 (file)
 
 #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
 
-static void request_complete(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static int sync_request(struct page *page, struct block_device *bdev, int rw)
 {
        struct bio bio;
        struct bio_vec bio_vec;
-       struct completion complete;
 
        bio_init(&bio);
        bio.bi_max_vecs = 1;
@@ -35,13 +29,8 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw)
        bio.bi_size = PAGE_SIZE;
        bio.bi_bdev = bdev;
        bio.bi_sector = page->index * (PAGE_SIZE >> 9);
-       init_completion(&complete);
-       bio.bi_private = &complete;
-       bio.bi_end_io = request_complete;
 
-       submit_bio(rw, &bio);
-       wait_for_completion(&complete);
-       return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+       return submit_bio_wait(rw, &bio);
 }
 
 static int bdev_readpage(void *_sb, struct page *page)
index c53d3a9547f9295408fa3cfe0d5abfb72023e29e..3531deebad3084104e6a9fca7116ba68890ad5af 100644 (file)
@@ -1598,11 +1598,6 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
  *   do a "get_unaligned()" if this helps and is sufficiently
  *   fast.
  *
- * - Little-endian machines (so that we can generate the mask
- *   of low bytes efficiently). Again, we *could* do a byte
- *   swapping load on big-endian architectures if that is not
- *   expensive enough to make the optimization worthless.
- *
  * - non-CONFIG_DEBUG_PAGEALLOC configurations (so that we
  *   do not trap on the (extremely unlikely) case of a page
  *   crossing operation.
@@ -1646,7 +1641,7 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
                if (!len)
                        goto done;
        }
-       mask = ~(~0ul << len*8);
+       mask = bytemask_from_count(len);
        hash += mask & a;
 done:
        return fold_hash(hash);
index ac2ce8a766e1a9c6250cdac616f9a951dddee45e..be32ebccdeb166a0c4eb85c4459d68a3d2555fab 100644 (file)
@@ -2886,7 +2886,7 @@ bool fs_fully_visible(struct file_system_type *type)
                        struct inode *inode = child->mnt_mountpoint->d_inode;
                        if (!S_ISDIR(inode->i_mode))
                                goto next;
-                       if (inode->i_nlink != 2)
+                       if (inode->i_nlink > 2)
                                goto next;
                }
                visible = true;
index 8485978993e85bcbda9772b55a2ed26f5442a228..9838fb020473c935817b34da4a1127b4c75af3fe 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
+#include "../nfs4_fs.h"
 #include "../pnfs.h"
 #include "../netns.h"
 
index 9c3e117c3ed1f04c5dd1650f70a3aa4ca2fd7d8c..4d01614425658adade20f579ec7f10e44c5d5a15 100644 (file)
@@ -44,7 +44,7 @@
 static inline sector_t normalize(sector_t s, int base)
 {
        sector_t tmp = s; /* Since do_div modifies its argument */
-       return s - do_div(tmp, base);
+       return s - sector_div(tmp, base);
 }
 
 static inline sector_t normalize_up(sector_t s, int base)
index fc0f95ec73587f9fbcfa7fca24438da29012b5b9..d25f10fb4926b09dc39ac3f6f62a433d4bcdc58b 100644 (file)
@@ -46,7 +46,9 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
 #include <linux/sunrpc/cache.h>
 #include <linux/sunrpc/svcauth.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
+#include <linux/nfs_fs.h>
 
+#include "nfs4_fs.h"
 #include "dns_resolve.h"
 #include "cache_lib.h"
 #include "netns.h"
index 18ab2da4eeb65dbf7c8f7d7b578a35fc5251b0b6..00ad1c2b217ded2338c0ac4154681f83963581ab 100644 (file)
@@ -312,7 +312,7 @@ struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags)
 }
 EXPORT_SYMBOL_GPL(nfs4_label_alloc);
 #else
-void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        struct nfs4_label *label)
 {
 }
index bca6a3e3c49ce58e9cdfa1552e25afce2158584e..8b5cc04a86115e05f0a2e98e9b02a0b307b1b910 100644 (file)
@@ -269,6 +269,21 @@ extern const u32 nfs41_maxgetdevinfo_overhead;
 extern struct rpc_procinfo nfs4_procedures[];
 #endif
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
+static inline void nfs4_label_free(struct nfs4_label *label)
+{
+       if (label) {
+               kfree(label->label);
+               kfree(label);
+       }
+       return;
+}
+#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) {}
+#endif /* CONFIG_NFS_V4_SECURITY_LABEL */
+
 /* proc.c */
 void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
 extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
index 3ce79b04522eb19b2ecee294c3a59a2b0c49b4b9..5609edc742a0fc42568c73e7d26b4c2feb336c33 100644 (file)
@@ -9,6 +9,14 @@
 #ifndef __LINUX_FS_NFS_NFS4_FS_H
 #define __LINUX_FS_NFS_NFS4_FS_H
 
+#if defined(CONFIG_NFS_V4_2)
+#define NFS4_MAX_MINOR_VERSION 2
+#elif defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MINOR_VERSION 1
+#else
+#define NFS4_MAX_MINOR_VERSION 0
+#endif
+
 #if IS_ENABLED(CONFIG_NFS_V4)
 
 #define NFS4_MAX_LOOP_ON_RECOVER (10)
index 659990c0109e3173298b92385d585be566e161de..15052b81df4245e4f797adb0d0b2e523338b23cc 100644 (file)
@@ -2518,9 +2518,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                                                     calldata->roc_barrier);
                        nfs_set_open_stateid(state, &calldata->res.stateid, 0);
                        renew_lease(server, calldata->timestamp);
-                       nfs4_close_clear_stateid_flags(state,
-                                       calldata->arg.fmode);
                        break;
+               case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_OLD_STATEID:
                case -NFS4ERR_BAD_STATEID:
@@ -2528,9 +2527,13 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                        if (calldata->arg.fmode == 0)
                                break;
                default:
-                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
+                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
                                rpc_restart_call_prepare(task);
+                               goto out_release;
+                       }
        }
+       nfs4_close_clear_stateid_flags(state, calldata->arg.fmode);
+out_release:
        nfs_release_seqid(calldata->arg.seqid);
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
        dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
@@ -4802,7 +4805,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        dprintk("%s ERROR %d, Reset session\n", __func__,
                                task->tk_status);
                        nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
-                       goto restart_call;
+                       goto wait_on_recovery;
 #endif /* CONFIG_NFS_V4_1 */
                case -NFS4ERR_DELAY:
                        nfs_inc_server_stats(server, NFSIOS_DELAY);
@@ -4987,11 +4990,17 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 
        trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
        switch (task->tk_status) {
-       case -NFS4ERR_STALE_STATEID:
-       case -NFS4ERR_EXPIRED:
        case 0:
                renew_lease(data->res.server, data->timestamp);
                break;
+       case -NFS4ERR_ADMIN_REVOKED:
+       case -NFS4ERR_DELEG_REVOKED:
+       case -NFS4ERR_BAD_STATEID:
+       case -NFS4ERR_OLD_STATEID:
+       case -NFS4ERR_STALE_STATEID:
+       case -NFS4ERR_EXPIRED:
+               task->tk_status = 0;
+               break;
        default:
                if (nfs4_async_handle_error(task, data->res.server, NULL) ==
                                -EAGAIN) {
@@ -7589,7 +7598,14 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
                return;
 
        server = NFS_SERVER(lrp->args.inode);
-       if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+       switch (task->tk_status) {
+       default:
+               task->tk_status = 0;
+       case 0:
+               break;
+       case -NFS4ERR_DELAY:
+               if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN)
+                       break;
                rpc_restart_call_prepare(task);
                return;
        }
index 9186c7ce0b141b187a8b127a6608005a05ad53d1..b6af150c96b8cdf616950c1bd0f4f8403eeae5c8 100644 (file)
@@ -131,6 +131,13 @@ nfsd_reply_cache_alloc(void)
        return rp;
 }
 
+static void
+nfsd_reply_cache_unhash(struct svc_cacherep *rp)
+{
+       hlist_del_init(&rp->c_hash);
+       list_del_init(&rp->c_lru);
+}
+
 static void
 nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
 {
@@ -417,7 +424,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
                rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
                if (nfsd_cache_entry_expired(rp) ||
                    num_drc_entries >= max_drc_entries) {
-                       lru_put_end(rp);
+                       nfsd_reply_cache_unhash(rp);
                        prune_cache_entries();
                        goto search_cache;
                }
index 9f6b486b6c01a0e6711ca5930e78474d0739e35e..a1a191634abc1729f94a443ab4eac4cdddaaf54c 100644 (file)
@@ -1440,17 +1440,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
 
                nilfs_clear_logs(&sci->sc_segbufs);
 
-               err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
-               if (unlikely(err))
-                       return err;
-
                if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
                        err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
                                                        sci->sc_freesegs,
                                                        sci->sc_nfreesegs,
                                                        NULL);
                        WARN_ON(err); /* do not happen */
+                       sci->sc_stage.flags &= ~NILFS_CF_SUFREED;
                }
+
+               err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
+               if (unlikely(err))
+                       return err;
+
                nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);
                sci->sc_stage = prev_stage;
        }
index d2c45e14e6d8126e41bc6c463a509e68946e9fa4..0e0752ef27159f6183dabc1749e49fca8494319a 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -726,11 +726,25 @@ pipe_poll(struct file *filp, poll_table *wait)
        return mask;
 }
 
+static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
+{
+       int kill = 0;
+
+       spin_lock(&inode->i_lock);
+       if (!--pipe->files) {
+               inode->i_pipe = NULL;
+               kill = 1;
+       }
+       spin_unlock(&inode->i_lock);
+
+       if (kill)
+               free_pipe_info(pipe);
+}
+
 static int
 pipe_release(struct inode *inode, struct file *file)
 {
-       struct pipe_inode_info *pipe = inode->i_pipe;
-       int kill = 0;
+       struct pipe_inode_info *pipe = file->private_data;
 
        __pipe_lock(pipe);
        if (file->f_mode & FMODE_READ)
@@ -743,17 +757,9 @@ pipe_release(struct inode *inode, struct file *file)
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
-       spin_lock(&inode->i_lock);
-       if (!--pipe->files) {
-               inode->i_pipe = NULL;
-               kill = 1;
-       }
-       spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
 
-       if (kill)
-               free_pipe_info(pipe);
-
+       put_pipe_info(inode, pipe);
        return 0;
 }
 
@@ -1014,7 +1020,6 @@ static int fifo_open(struct inode *inode, struct file *filp)
 {
        struct pipe_inode_info *pipe;
        bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
-       int kill = 0;
        int ret;
 
        filp->f_version = 0;
@@ -1130,15 +1135,9 @@ err_wr:
        goto err;
 
 err:
-       spin_lock(&inode->i_lock);
-       if (!--pipe->files) {
-               inode->i_pipe = NULL;
-               kill = 1;
-       }
-       spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
-       if (kill)
-               free_pipe_info(pipe);
+
+       put_pipe_info(inode, pipe);
        return ret;
 }
 
index 28955d4b7218e95a6ba7666111459b0382450786..124fc43c709088a46b26c90a16e251a2fd7c4f66 100644 (file)
@@ -292,16 +292,20 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
 {
        struct proc_dir_entry *pde = PDE(file_inode(file));
        unsigned long rv = -EIO;
-       unsigned long (*get_area)(struct file *, unsigned long, unsigned long,
-                                 unsigned long, unsigned long) = NULL;
+
        if (use_pde(pde)) {
+               typeof(proc_reg_get_unmapped_area) *get_area;
+
+               get_area = pde->proc_fops->get_unmapped_area;
 #ifdef CONFIG_MMU
-               get_area = current->mm->get_unmapped_area;
+               if (!get_area)
+                       get_area = current->mm->get_unmapped_area;
 #endif
-               if (pde->proc_fops->get_unmapped_area)
-                       get_area = pde->proc_fops->get_unmapped_area;
+
                if (get_area)
                        rv = get_area(file, orig_addr, len, pgoff, flags);
+               else
+                       rv = orig_addr;
                unuse_pde(pde);
        }
        return rv;
index b8e93a40a5d3342767a26959858d24f2a24274c0..78c3c2097787a1be2ea2bd1757a6c6e5554df72c 100644 (file)
@@ -443,8 +443,11 @@ int pstore_register(struct pstore_info *psi)
                pstore_get_records(0);
 
        kmsg_dump_register(&pstore_dumper);
-       pstore_register_console();
-       pstore_register_ftrace();
+
+       if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
+               pstore_register_console();
+               pstore_register_ftrace();
+       }
 
        if (pstore_update_ms >= 0) {
                pstore_timer.expires = jiffies +
index 2943b2bfae482ac83d352f317af4c074ce6597ae..62a0de6632e1aa3c8de599e19db3f8d7e2a383e2 100644 (file)
@@ -84,6 +84,9 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
                 */
                res = squashfs_read_cache(target_page, block, bsize, pages,
                                                                page);
+               if (res < 0)
+                       goto mark_errored;
+
                goto out;
        }
 
@@ -119,7 +122,7 @@ mark_errored:
         * dealt with by the caller
         */
        for (i = 0; i < pages; i++) {
-               if (page[i] == target_page)
+               if (page[i] == NULL || page[i] == target_page)
                        continue;
                flush_dcache_page(page[i]);
                SetPageError(page[i]);
index b94f93685093edb4f2d189238989d3024fffa246..35e7d08fe629dfcb79553bcdcdf39af03b5e4960 100644 (file)
@@ -609,7 +609,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
        struct sysfs_open_file *of;
-       bool has_read, has_write, has_mmap;
+       bool has_read, has_write;
        int error = -EACCES;
 
        /* need attr_sd for attr and ops, its parent for kobj */
@@ -621,7 +621,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = battr->read || battr->mmap;
                has_write = battr->write || battr->mmap;
-               has_mmap = battr->mmap;
        } else {
                const struct sysfs_ops *ops = sysfs_file_ops(attr_sd);
 
@@ -633,7 +632,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = ops->show;
                has_write = ops->store;
-               has_mmap = false;
        }
 
        /* check perms and supported operations */
@@ -661,9 +659,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
         * open file has a separate mutex, it's okay as long as those don't
         * happen on the same file.  At this point, we can't easily give
         * each file a separate locking class.  Let's differentiate on
-        * whether the file has mmap or not for now.
+        * whether the file is bin or not for now.
         */
-       if (has_mmap)
+       if (sysfs_is_bin(attr_sd))
                mutex_init(&of->mutex);
        else
                mutex_init(&of->mutex);
index 739e0a52dedadea67eb595f4b03619ce3e3383a3..5549d69ddb45a2038ece8e24085e0f9ef6ce9984 100644 (file)
@@ -110,7 +110,7 @@ xfs_attr3_rmt_verify(
        if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt))
                return false;
        if (be32_to_cpu(rmt->rm_offset) +
-                               be32_to_cpu(rmt->rm_bytes) >= XATTR_SIZE_MAX)
+                               be32_to_cpu(rmt->rm_bytes) > XATTR_SIZE_MAX)
                return false;
        if (rmt->rm_owner == 0)
                return false;
index 3ef11b22e7505c380feb6597113d5b150f7b1afb..3b2c14b6f0fb13efd7a3aa89abc05d0a8334a5ff 100644 (file)
@@ -1635,7 +1635,7 @@ xfs_bmap_last_extent(
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
  * at, or past the EOF.
  */
 STATIC int
@@ -1650,9 +1650,14 @@ xfs_bmap_isaeof(
        bma->aeof = 0;
        error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
                                     &is_empty);
-       if (error || is_empty)
+       if (error)
                return error;
 
+       if (is_empty) {
+               bma->aeof = 1;
+               return 0;
+       }
+
        /*
         * Check if we are allocation or past the last extent, or at least into
         * the last delayed allocated extent.
@@ -3643,10 +3648,19 @@ xfs_bmap_btalloc(
        int             isaligned;
        int             tryagain;
        int             error;
+       int             stripe_align;
 
        ASSERT(ap->length);
 
        mp = ap->ip->i_mount;
+
+       /* stripe alignment for allocation is determined by mount parameters */
+       stripe_align = 0;
+       if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
+               stripe_align = mp->m_swidth;
+       else if (mp->m_dalign)
+               stripe_align = mp->m_dalign;
+
        align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
        if (unlikely(align)) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3655,6 +3669,8 @@ xfs_bmap_btalloc(
                ASSERT(!error);
                ASSERT(ap->length);
        }
+
+
        nullfb = *ap->firstblock == NULLFSBLOCK;
        fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
        if (nullfb) {
@@ -3730,7 +3746,7 @@ xfs_bmap_btalloc(
         */
        if (!ap->flist->xbf_low && ap->aeof) {
                if (!ap->offset) {
-                       args.alignment = mp->m_dalign;
+                       args.alignment = stripe_align;
                        atype = args.type;
                        isaligned = 1;
                        /*
@@ -3755,13 +3771,13 @@ xfs_bmap_btalloc(
                         * of minlen+alignment+slop doesn't go up
                         * between the calls.
                         */
-                       if (blen > mp->m_dalign && blen <= args.maxlen)
-                               nextminlen = blen - mp->m_dalign;
+                       if (blen > stripe_align && blen <= args.maxlen)
+                               nextminlen = blen - stripe_align;
                        else
                                nextminlen = args.minlen;
-                       if (nextminlen + mp->m_dalign > args.minlen + 1)
+                       if (nextminlen + stripe_align > args.minlen + 1)
                                args.minalignslop =
-                                       nextminlen + mp->m_dalign -
+                                       nextminlen + stripe_align -
                                        args.minlen - 1;
                        else
                                args.minalignslop = 0;
@@ -3783,7 +3799,7 @@ xfs_bmap_btalloc(
                 */
                args.type = atype;
                args.fsbno = ap->blkno;
-               args.alignment = mp->m_dalign;
+               args.alignment = stripe_align;
                args.minlen = nextminlen;
                args.minalignslop = 0;
                isaligned = 1;
index 5887e41c0323ae85f867cc9bc83bbdf8c1e41cd1..82e0dab46ee52cc991a7130d8f671e011eef10a3 100644 (file)
@@ -287,6 +287,7 @@ xfs_bmapi_allocate(
        INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
        queue_work(xfs_alloc_wq, &args->work);
        wait_for_completion(&done);
+       destroy_work_on_stack(&args->work);
        return args->result;
 }
 
@@ -1187,7 +1188,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNWRITE(bp);
                XFS_BUF_READ(bp);
                XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
@@ -1200,7 +1206,12 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNDONE(bp);
                XFS_BUF_UNREAD(bp);
                XFS_BUF_WRITE(bp);
-               xfsbdstrat(mp, bp);
+
+               if (XFS_FORCED_SHUTDOWN(mp)) {
+                       error = XFS_ERROR(EIO);
+                       break;
+               }
+               xfs_buf_iorequest(bp);
                error = xfs_buf_iowait(bp);
                if (error) {
                        xfs_buf_ioerror_alert(bp,
index c7f0b77dcb0090046b84eda27c68d870af25d45a..afe7645e4b2b8b7746665ed35a0d55da6ce11e3b 100644 (file)
@@ -698,7 +698,11 @@ xfs_buf_read_uncached(
        bp->b_flags |= XBF_READ;
        bp->b_ops = ops;
 
-       xfsbdstrat(target->bt_mount, bp);
+       if (XFS_FORCED_SHUTDOWN(target->bt_mount)) {
+               xfs_buf_relse(bp);
+               return NULL;
+       }
+       xfs_buf_iorequest(bp);
        xfs_buf_iowait(bp);
        return bp;
 }
@@ -1089,7 +1093,7 @@ xfs_bioerror(
  * This is meant for userdata errors; metadata bufs come with
  * iodone functions attached, so that we can track down errors.
  */
-STATIC int
+int
 xfs_bioerror_relse(
        struct xfs_buf  *bp)
 {
@@ -1152,7 +1156,7 @@ xfs_bwrite(
        ASSERT(xfs_buf_islocked(bp));
 
        bp->b_flags |= XBF_WRITE;
-       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
+       bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL);
 
        xfs_bdstrat_cb(bp);
 
@@ -1164,25 +1168,6 @@ xfs_bwrite(
        return error;
 }
 
-/*
- * Wrapper around bdstrat so that we can stop data from going to disk in case
- * we are shutting down the filesystem.  Typically user data goes thru this
- * path; one of the exceptions is the superblock.
- */
-void
-xfsbdstrat(
-       struct xfs_mount        *mp,
-       struct xfs_buf          *bp)
-{
-       if (XFS_FORCED_SHUTDOWN(mp)) {
-               trace_xfs_bdstrat_shut(bp, _RET_IP_);
-               xfs_bioerror_relse(bp);
-               return;
-       }
-
-       xfs_buf_iorequest(bp);
-}
-
 STATIC void
 _xfs_buf_ioend(
        xfs_buf_t               *bp,
@@ -1516,6 +1501,12 @@ xfs_wait_buftarg(
                        struct xfs_buf *bp;
                        bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
                        list_del_init(&bp->b_lru);
+                       if (bp->b_flags & XBF_WRITE_FAIL) {
+                               xfs_alert(btp->bt_mount,
+"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
+"Please run xfs_repair to determine the extent of the problem.",
+                                       (long long)bp->b_bn);
+                       }
                        xfs_buf_rele(bp);
                }
                if (loop++ != 0)
@@ -1799,7 +1790,7 @@ __xfs_buf_delwri_submit(
 
        blk_start_plug(&plug);
        list_for_each_entry_safe(bp, n, io_list, b_list) {
-               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC);
+               bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL);
                bp->b_flags |= XBF_WRITE;
 
                if (!wait) {
index e65683361017745eff61e245ee72896d2e6ff8df..1cf21a4a9f221de465299bf820fa710c3b3aa40e 100644 (file)
@@ -45,6 +45,7 @@ typedef enum {
 #define XBF_ASYNC       (1 << 4) /* initiator will not wait for completion */
 #define XBF_DONE        (1 << 5) /* all pages in the buffer uptodate */
 #define XBF_STALE       (1 << 6) /* buffer has been staled, do not find it */
+#define XBF_WRITE_FAIL  (1 << 24)/* async writes have failed on this buffer */
 
 /* I/O hints for the BIO layer */
 #define XBF_SYNCIO      (1 << 10)/* treat this buffer as synchronous I/O */
@@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t;
        { XBF_ASYNC,            "ASYNC" }, \
        { XBF_DONE,             "DONE" }, \
        { XBF_STALE,            "STALE" }, \
+       { XBF_WRITE_FAIL,       "WRITE_FAIL" }, \
        { XBF_SYNCIO,           "SYNCIO" }, \
        { XBF_FUA,              "FUA" }, \
        { XBF_FLUSH,            "FLUSH" }, \
@@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t;
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
        { _XBF_COMPOUND,        "COMPOUND" }
 
+
 /*
  * Internal state flags.
  */
@@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *);
 
 /* Buffer Read and Write Routines */
 extern int xfs_bwrite(struct xfs_buf *bp);
-
-extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
-
 extern void xfs_buf_ioend(xfs_buf_t *, int);
 extern void xfs_buf_ioerror(xfs_buf_t *, int);
 extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
@@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 #define xfs_buf_zero(bp, off, len) \
            xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
 
+extern int xfs_bioerror_relse(struct xfs_buf *);
+
 static inline int xfs_buf_geterror(xfs_buf_t *bp)
 {
        return bp ? bp->b_error : ENOMEM;
@@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void);
 
 #define XFS_BUF_ZEROFLAGS(bp) \
        ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \
-                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
+                           XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \
+                           XBF_WRITE_FAIL))
 
 void xfs_buf_stale(struct xfs_buf *bp);
 #define XFS_BUF_UNSTALE(bp)    ((bp)->b_flags &= ~XBF_STALE)
index a64f67ba25d3c99c748e1d4a8f84f7648e3dd651..2227b9b050bb30248d986b343dd33e42c7978529 100644 (file)
@@ -496,6 +496,14 @@ xfs_buf_item_unpin(
        }
 }
 
+/*
+ * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30
+ * seconds so as to not spam logs too much on repeated detection of the same
+ * buffer being bad..
+ */
+
+DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
+
 STATIC uint
 xfs_buf_item_push(
        struct xfs_log_item     *lip,
@@ -524,6 +532,14 @@ xfs_buf_item_push(
 
        trace_xfs_buf_item_push(bip);
 
+       /* has a previous flush failed due to IO errors? */
+       if ((bp->b_flags & XBF_WRITE_FAIL) &&
+           ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
+               xfs_warn(bp->b_target->bt_mount,
+"Detected failing async write on buffer block 0x%llx. Retrying async write.\n",
+                        (long long)bp->b_bn);
+       }
+
        if (!xfs_buf_delwri_queue(bp, buffer_list))
                rval = XFS_ITEM_FLUSHING;
        xfs_buf_unlock(bp);
@@ -1096,8 +1112,9 @@ xfs_buf_iodone_callbacks(
 
                xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
 
-               if (!XFS_BUF_ISSTALE(bp)) {
-                       bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE;
+               if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) {
+                       bp->b_flags |= XBF_WRITE | XBF_ASYNC |
+                                      XBF_DONE | XBF_WRITE_FAIL;
                        xfs_buf_iorequest(bp);
                } else {
                        xfs_buf_relse(bp);
index 56369d4509d5603cff44adeb17902324a547f48b..48c7d18f68c3fb23a89a31a955fc9250fbd63108 100644 (file)
@@ -2067,12 +2067,12 @@ xfs_dir2_node_lookup(
  */
 int                                            /* error */
 xfs_dir2_node_removename(
-       xfs_da_args_t           *args)          /* operation arguments */
+       struct xfs_da_args      *args)          /* operation arguments */
 {
-       xfs_da_state_blk_t      *blk;           /* leaf block */
+       struct xfs_da_state_blk *blk;           /* leaf block */
        int                     error;          /* error return value */
        int                     rval;           /* operation return value */
-       xfs_da_state_t          *state;         /* btree cursor */
+       struct xfs_da_state     *state;         /* btree cursor */
 
        trace_xfs_dir2_node_removename(args);
 
@@ -2084,19 +2084,18 @@ xfs_dir2_node_removename(
        state->mp = args->dp->i_mount;
        state->blocksize = state->mp->m_dirblksize;
        state->node_ents = state->mp->m_dir_node_ents;
-       /*
-        * Look up the entry we're deleting, set up the cursor.
-        */
+
+       /* Look up the entry we're deleting, set up the cursor. */
        error = xfs_da3_node_lookup_int(state, &rval);
        if (error)
-               rval = error;
-       /*
-        * Didn't find it, upper layer screwed up.
-        */
+               goto out_free;
+
+       /* Didn't find it, upper layer screwed up. */
        if (rval != EEXIST) {
-               xfs_da_state_free(state);
-               return rval;
+               error = rval;
+               goto out_free;
        }
+
        blk = &state->path.blk[state->path.active - 1];
        ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
        ASSERT(state->extravalid);
@@ -2107,7 +2106,7 @@ xfs_dir2_node_removename(
        error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
                &state->extrablk, &rval);
        if (error)
-               return error;
+               goto out_free;
        /*
         * Fix the hash values up the btree.
         */
@@ -2122,6 +2121,7 @@ xfs_dir2_node_removename(
         */
        if (!error)
                error = xfs_dir2_node_to_leaf(state);
+out_free:
        xfs_da_state_free(state);
        return error;
 }
index 8367d6dc18c9df7f51cd565e11395cba24929a53..4f11ef0111395bbb7775407e9039e92cad0a932d 100644 (file)
@@ -157,7 +157,7 @@ xfs_ioc_trim(
        struct xfs_mount                *mp,
        struct fstrim_range __user      *urange)
 {
-       struct request_queue    *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
+       struct request_queue    *q = bdev_get_queue(mp->m_ddev_targp->bt_bdev);
        unsigned int            granularity = q->limits.discard_granularity;
        struct fstrim_range     range;
        xfs_daddr_t             start, end, minlen;
@@ -180,7 +180,8 @@ xfs_ioc_trim(
         * matter as trimming blocks is an advisory interface.
         */
        if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) ||
-           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)))
+           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)) ||
+           range.len < mp->m_sb.sb_blocksize)
                return -XFS_ERROR(EINVAL);
 
        start = BTOBB(range.start);
index a6e54b3319bd0f5deb573623f332486590fbe165..02fb943cbf22b36b4e6da8c66b03be8839dc03d4 100644 (file)
@@ -220,6 +220,8 @@ xfs_growfs_data_private(
         */
        nfree = 0;
        for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
+               __be32  *agfl_bno;
+
                /*
                 * AG freespace header block
                 */
@@ -279,8 +281,10 @@ xfs_growfs_data_private(
                        agfl->agfl_seqno = cpu_to_be32(agno);
                        uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid);
                }
+
+               agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, bp);
                for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
-                       agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
+                       agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
 
                error = xfs_bwrite(bp);
                xfs_buf_relse(bp);
index 4d613401a5e056a08dd2f8b21b77833bfe14cbc6..33ad9a77791f7ebbf3f8762e0c9df1af637c5328 100644 (file)
@@ -442,7 +442,8 @@ xfs_attrlist_by_handle(
                return -XFS_ERROR(EPERM);
        if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
                return -XFS_ERROR(EFAULT);
-       if (al_hreq.buflen > XATTR_LIST_MAX)
+       if (al_hreq.buflen < sizeof(struct attrlist) ||
+           al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
        /*
index e8fb1231db8124dc08b2ffbcc551d6bfa1bc21f5..a7992f8de9d3fa53a63ab2d3250f0c4933caded9 100644 (file)
@@ -356,7 +356,8 @@ xfs_compat_attrlist_by_handle(
        if (copy_from_user(&al_hreq, arg,
                           sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
                return -XFS_ERROR(EFAULT);
-       if (al_hreq.buflen > XATTR_LIST_MAX)
+       if (al_hreq.buflen < sizeof(struct attrlist) ||
+           al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
        /*
index 27e0e544e9635ba47281279c68670f7e568a7a58..104455b8046c4bd9ea11855c917b7b46c4573361 100644 (file)
@@ -618,7 +618,8 @@ xfs_setattr_nonsize(
                }
                if (!gid_eq(igid, gid)) {
                        if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
-                               ASSERT(!XFS_IS_PQUOTA_ON(mp));
+                               ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
+                                      !XFS_IS_PQUOTA_ON(mp));
                                ASSERT(mask & ATTR_GID);
                                ASSERT(gdqp);
                                olddquot2 = xfs_qm_vop_chown(tp, ip,
index b6b669df40f3ab335e75cd3a67903601be0128a4..eae16920655b4569af25e9567682019ba301533d 100644 (file)
@@ -193,7 +193,10 @@ xlog_bread_noalign(
        bp->b_io_length = nbblks;
        bp->b_error = 0;
 
-       xfsbdstrat(log->l_mp, bp);
+       if (XFS_FORCED_SHUTDOWN(log->l_mp))
+               return XFS_ERROR(EIO);
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error)
                xfs_buf_ioerror_alert(bp, __func__);
@@ -4397,7 +4400,13 @@ xlog_do_recover(
        XFS_BUF_READ(bp);
        XFS_BUF_UNASYNC(bp);
        bp->b_ops = &xfs_sb_buf_ops;
-       xfsbdstrat(log->l_mp, bp);
+
+       if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
+               xfs_buf_relse(bp);
+               return XFS_ERROR(EIO);
+       }
+
+       xfs_buf_iorequest(bp);
        error = xfs_buf_iowait(bp);
        if (error) {
                xfs_buf_ioerror_alert(bp, __func__);
index 14a4996cfec6cb4fbeaa1d3f8432548ebb57d48b..dd88f0e27bd8ce1119d2606c256117d4d2488b9c 100644 (file)
@@ -134,8 +134,6 @@ xfs_qm_dqpurge(
 {
        struct xfs_mount        *mp = dqp->q_mount;
        struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       struct xfs_dquot        *gdqp = NULL;
-       struct xfs_dquot        *pdqp = NULL;
 
        xfs_dqlock(dqp);
        if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -143,21 +141,6 @@ xfs_qm_dqpurge(
                return EAGAIN;
        }
 
-       /*
-        * If this quota has a hint attached, prepare for releasing it now.
-        */
-       gdqp = dqp->q_gdquot;
-       if (gdqp) {
-               xfs_dqlock(gdqp);
-               dqp->q_gdquot = NULL;
-       }
-
-       pdqp = dqp->q_pdquot;
-       if (pdqp) {
-               xfs_dqlock(pdqp);
-               dqp->q_pdquot = NULL;
-       }
-
        dqp->dq_flags |= XFS_DQ_FREEING;
 
        xfs_dqflock(dqp);
@@ -206,11 +189,47 @@ xfs_qm_dqpurge(
        XFS_STATS_DEC(xs_qm_dquot_unused);
 
        xfs_qm_dqdestroy(dqp);
+       return 0;
+}
+
+/*
+ * Release the group or project dquot pointers the user dquots maybe carrying
+ * around as a hint, and proceed to purge the user dquot cache if requested.
+*/
+STATIC int
+xfs_qm_dqpurge_hints(
+       struct xfs_dquot        *dqp,
+       void                    *data)
+{
+       struct xfs_dquot        *gdqp = NULL;
+       struct xfs_dquot        *pdqp = NULL;
+       uint                    flags = *((uint *)data);
+
+       xfs_dqlock(dqp);
+       if (dqp->dq_flags & XFS_DQ_FREEING) {
+               xfs_dqunlock(dqp);
+               return EAGAIN;
+       }
+
+       /* If this quota has a hint attached, prepare for releasing it now */
+       gdqp = dqp->q_gdquot;
+       if (gdqp)
+               dqp->q_gdquot = NULL;
+
+       pdqp = dqp->q_pdquot;
+       if (pdqp)
+               dqp->q_pdquot = NULL;
+
+       xfs_dqunlock(dqp);
 
        if (gdqp)
-               xfs_qm_dqput(gdqp);
+               xfs_qm_dqrele(gdqp);
        if (pdqp)
-               xfs_qm_dqput(pdqp);
+               xfs_qm_dqrele(pdqp);
+
+       if (flags & XFS_QMOPT_UQUOTA)
+               return xfs_qm_dqpurge(dqp, NULL);
+
        return 0;
 }
 
@@ -222,8 +241,18 @@ xfs_qm_dqpurge_all(
        struct xfs_mount        *mp,
        uint                    flags)
 {
-       if (flags & XFS_QMOPT_UQUOTA)
-               xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL);
+       /*
+        * We have to release group/project dquot hint(s) from the user dquot
+        * at first if they are there, otherwise we would run into an infinite
+        * loop while walking through radix tree to purge other type of dquots
+        * since their refcount is not zero if the user dquot refers to them
+        * as hint.
+        *
+        * Call the special xfs_qm_dqpurge_hints() will end up go through the
+        * general xfs_qm_dqpurge() against user dquot cache if requested.
+        */
+       xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags);
+
        if (flags & XFS_QMOPT_GQUOTA)
                xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL);
        if (flags & XFS_QMOPT_PQUOTA)
@@ -2082,24 +2111,21 @@ xfs_qm_vop_create_dqattach(
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
-       if (udqp) {
+       if (udqp && XFS_IS_UQUOTA_ON(mp)) {
                ASSERT(ip->i_udquot == NULL);
-               ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
 
                ip->i_udquot = xfs_qm_dqhold(udqp);
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (gdqp) {
+       if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
                ASSERT(ip->i_gdquot == NULL);
-               ASSERT(XFS_IS_GQUOTA_ON(mp));
                ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
                ip->i_gdquot = xfs_qm_dqhold(gdqp);
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (pdqp) {
+       if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(ip->i_pdquot == NULL);
-               ASSERT(XFS_IS_PQUOTA_ON(mp));
                ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
 
                ip->i_pdquot = xfs_qm_dqhold(pdqp);
index c035d11b7734196c4fd689121d945e598a8d6d7a..647b6f1d8923fee484ada5eea3e2e68d47df8286 100644 (file)
@@ -314,7 +314,18 @@ xfs_trans_read_buf_map(
                        ASSERT(bp->b_iodone == NULL);
                        XFS_BUF_READ(bp);
                        bp->b_ops = ops;
-                       xfsbdstrat(tp->t_mountp, bp);
+
+                       /*
+                        * XXX(hch): clean up the error handling here to be less
+                        * of a mess..
+                        */
+                       if (XFS_FORCED_SHUTDOWN(mp)) {
+                               trace_xfs_bdstrat_shut(bp, _RET_IP_);
+                               xfs_bioerror_relse(bp);
+                       } else {
+                               xfs_buf_iorequest(bp);
+                       }
+
                        error = xfs_buf_iowait(bp);
                        if (error) {
                                xfs_buf_ioerror_alert(bp, __func__);
index c602c7718421ded2f2bbe50f1e76edc39ac2b6f2..ddabed1f51c22227df9fdc1a7d050ca3b395b470 100644 (file)
@@ -169,7 +169,8 @@ struct acpi_device_flags {
        u32 ejectable:1;
        u32 power_manageable:1;
        u32 match_driver:1;
-       u32 reserved:27;
+       u32 no_hotplug:1;
+       u32 reserved:26;
 };
 
 /* File System */
@@ -344,6 +345,7 @@ extern struct kobject *acpi_kobj;
 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
 void acpi_bus_private_data_handler(acpi_handle, void *);
 int acpi_bus_get_private_data(acpi_handle, void **);
+void acpi_bus_no_hotplug(acpi_handle handle);
 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
index 639d7a4d033bc2a0dc2413003d9209540504ebe3..6f692f8ac664565eda7f0e2f7a551d1f5ebc1df4 100644 (file)
@@ -1,4 +1,5 @@
-/* Generic barrier definitions, based on MN10300 definitions.
+/*
+ * Generic barrier definitions, originally based on MN10300 definitions.
  *
  * It should be possible to use these on really simple architectures,
  * but it serves more as a starting point for new ports.
 
 #ifndef __ASSEMBLY__
 
-#define nop() asm volatile ("nop")
+#include <linux/compiler.h>
+
+#ifndef nop
+#define nop()  asm volatile ("nop")
+#endif
 
 /*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
+ * Force strict CPU ordering. And yes, this is required on UP too when we're
+ * talking to devices.
  *
- * This implementation only contains a compiler barrier.
+ * Fall back to compiler barriers if nothing better is provided.
  */
 
-#define mb()   asm volatile ("": : :"memory")
+#ifndef mb
+#define mb()   barrier()
+#endif
+
+#ifndef rmb
 #define rmb()  mb()
-#define wmb()  asm volatile ("": : :"memory")
+#endif
+
+#ifndef wmb
+#define wmb()  mb()
+#endif
+
+#ifndef read_barrier_depends
+#define read_barrier_depends()         do { } while (0)
+#endif
 
 #ifdef CONFIG_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
+#define smp_read_barrier_depends()     read_barrier_depends()
 #else
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
 #define smp_wmb()      barrier()
+#define smp_read_barrier_depends()     do { } while (0)
+#endif
+
+#ifndef set_mb
+#define set_mb(var, value)  do { (var) = (value); mb(); } while (0)
 #endif
 
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+#define smp_store_release(p, v)                                                \
+do {                                                                   \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ACCESS_ONCE(*p) = (v);                                          \
+} while (0)
 
-#define read_barrier_depends()         do {} while (0)
-#define smp_read_barrier_depends()     do {} while (0)
+#define smp_load_acquire(p)                                            \
+({                                                                     \
+       typeof(*p) ___p1 = ACCESS_ONCE(*p);                             \
+       compiletime_assert_atomic_type(*p);                             \
+       smp_mb();                                                       \
+       ___p1;                                                          \
+})
 
 #endif /* !__ASSEMBLY__ */
 #endif /* __ASM_GENERIC_BARRIER_H */
index f330d28e4d0eaf4d8e681bb905f52ff72465bea7..db09234589409760b91cb9e696472a3e828476f9 100644 (file)
@@ -217,7 +217,7 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 #endif
 
 #ifndef pte_accessible
-# define pte_accessible(pte)           ((void)(pte),1)
+# define pte_accessible(mm, pte)       ((void)(pte), 1)
 #endif
 
 #ifndef flush_tlb_fix_spurious_fault
@@ -599,11 +599,10 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        barrier();
 #endif
-       if (pmd_none(pmdval))
+       if (pmd_none(pmdval) || pmd_trans_huge(pmdval))
                return 1;
        if (unlikely(pmd_bad(pmdval))) {
-               if (!pmd_trans_huge(pmdval))
-                       pmd_clear_bad(pmd);
+               pmd_clear_bad(pmd);
                return 1;
        }
        return 0;
index ddf2b420ac8f81621ec9dd088e8379f8b686cd94..1cd3f5d767a81b18b8c3950701506e3f8bfcfc6c 100644 (file)
@@ -3,13 +3,11 @@
 
 #include <linux/thread_info.h>
 
-/*
- * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
- * that think a non-zero value indicates we cannot preempt.
- */
+#define PREEMPT_ENABLED        (0)
+
 static __always_inline int preempt_count(void)
 {
-       return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED;
+       return current_thread_info()->preempt_count;
 }
 
 static __always_inline int *preempt_count_ptr(void)
@@ -17,11 +15,6 @@ static __always_inline int *preempt_count_ptr(void)
        return &current_thread_info()->preempt_count;
 }
 
-/*
- * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the
- * alternative is loosing a reschedule. Better schedule too often -- also this
- * should be a very rare operation.
- */
 static __always_inline void preempt_count_set(int pc)
 {
        *preempt_count_ptr() = pc;
@@ -41,28 +34,17 @@ static __always_inline void preempt_count_set(int pc)
        task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
 } while (0)
 
-/*
- * We fold the NEED_RESCHED bit into the preempt count such that
- * preempt_enable() can decrement and test for needing to reschedule with a
- * single instruction.
- *
- * We invert the actual bit, so that when the decrement hits 0 we know we both
- * need to resched (the bit is cleared) and can resched (no preempt count).
- */
-
 static __always_inline void set_preempt_need_resched(void)
 {
-       *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED;
 }
 
 static __always_inline void clear_preempt_need_resched(void)
 {
-       *preempt_count_ptr() |= PREEMPT_NEED_RESCHED;
 }
 
 static __always_inline bool test_preempt_need_resched(void)
 {
-       return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED);
+       return false;
 }
 
 /*
@@ -81,7 +63,12 @@ static __always_inline void __preempt_count_sub(int val)
 
 static __always_inline bool __preempt_count_dec_and_test(void)
 {
-       return !--*preempt_count_ptr();
+       /*
+        * Because of load-store architectures cannot do per-cpu atomic
+        * operations; we cannot use PREEMPT_NEED_RESCHED because it might get
+        * lost.
+        */
+       return !--*preempt_count_ptr() && tif_need_resched();
 }
 
 /*
@@ -89,7 +76,7 @@ static __always_inline bool __preempt_count_dec_and_test(void)
  */
 static __always_inline bool should_resched(void)
 {
-       return unlikely(!*preempt_count_ptr());
+       return unlikely(!preempt_count() && tif_need_resched());
 }
 
 #ifdef CONFIG_PREEMPT
index 3f21f1b72e45db6db5e8ef7ec75fb790ce6184a9..d3909effd7256ee1334910f72ab57becccff93f9 100644 (file)
@@ -49,4 +49,12 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct
        return (val + c->high_bits) & ~rhs;
 }
 
+#ifndef zero_bytemask
+#ifdef CONFIG_64BIT
+#define zero_bytemask(mask)    (~0ul << fls64(mask))
+#else
+#define zero_bytemask(mask)    (~0ul << fls(mask))
+#endif /* CONFIG_64BIT */
+#endif /* zero_bytemask */
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
index 13621cc8cf4c454f546a6fbb33fb5e85e8b1b1aa..6a626a507b8ca2d9c1a167b0758c7d7d3604013e 100644 (file)
@@ -36,6 +36,7 @@ static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num,
 {
        sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0);
        sg1[num - 1].page_link &= ~0x02;
+       sg1[num - 1].page_link |= 0x01;
 }
 
 static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
@@ -43,7 +44,7 @@ static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
        if (sg_is_last(sg))
                return NULL;
 
-       return (++sg)->length ? sg : (void *)sg_page(sg);
+       return (++sg)->length ? sg : sg_chain_ptr(sg);
 }
 
 static inline void scatterwalk_crypto_chain(struct scatterlist *head,
index 87578c109e4869bbecf5cce3a7530a0c2fb80637..49376aec2fbb8a9e054b9605fd9de36e4cd39c5f 100644 (file)
        {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
-       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
+       {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\
        {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
index 9a193b84238a30c97814fcee82148739a5a82b30..a89df3be16863302dcedde84da6f0dbc278fde8c 100644 (file)
@@ -41,10 +41,10 @@ struct assoc_array_ops {
        /* Is this the object we're looking for? */
        bool (*compare_object)(const void *object, const void *index_key);
 
-       /* How different are two objects, to a bit position in their keys? (or
-        * -1 if they're the same)
+       /* How different is an object from an index key, to a bit position in
+        * their keys? (or -1 if they're the same)
         */
-       int (*diff_objects)(const void *a, const void *b);
+       int (*diff_objects)(const void *object, const void *index_key);
 
        /* Method to free an object. */
        void (*free_object)(void *object);
index 669fef5c745a3fe98145a87d21a588cb64835c15..3e0fbe44176328193cf849fd039d70e91694a4ca 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <uapi/linux/auxvec.h>
 
-#define AT_VECTOR_SIZE_BASE 19 /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 20 /* NEW_AUX_ENT entries in auxiliary table */
   /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
 #endif /* _LINUX_AUXVEC_H */
index 27b1bcffe40853e8e1f6c1f629525c94ec2a343e..86c12c93e3cf6ce9c1db4085b9ee986d2c1e5b9a 100644 (file)
@@ -1,9 +1,35 @@
 #ifndef _LINUX_BH_H
 #define _LINUX_BH_H
 
-extern void local_bh_disable(void);
+#include <linux/preempt.h>
+#include <linux/preempt_mask.h>
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+extern void __local_bh_disable_ip(unsigned long ip, unsigned int cnt);
+#else
+static __always_inline void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
+{
+       preempt_count_add(cnt);
+       barrier();
+}
+#endif
+
+static inline void local_bh_disable(void)
+{
+       __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
+}
+
 extern void _local_bh_enable(void);
-extern void local_bh_enable(void);
-extern void local_bh_enable_ip(unsigned long ip);
+extern void __local_bh_enable_ip(unsigned long ip, unsigned int cnt);
+
+static inline void local_bh_enable_ip(unsigned long ip)
+{
+       __local_bh_enable_ip(ip, SOFTIRQ_DISABLE_OFFSET);
+}
+
+static inline void local_bh_enable(void)
+{
+       __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
+}
 
 #endif /* _LINUX_BH_H */
index 973ce10c40b651faa5d9e06f41eb49fefa492eab..dc1bd3dcf11fd6b72f93c5d3d9b674957bb705a0 100644 (file)
@@ -28,8 +28,6 @@
 
 #endif
 
-#define uninitialized_var(x) x
-
 #ifndef __HAVE_BUILTIN_BSWAP16__
 /* icc has this, but it's called _bswap16 */
 #define __HAVE_BUILTIN_BSWAP16__
index 92669cd182a6daca2550e2de8e4b8c7e2fd65a59..fe7a686dfd8dc3b87dcc35d0bdd3e50a47324014 100644 (file)
@@ -298,6 +298,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
 #endif
 
+/* Is this type a native word size -- useful for atomic operations */
+#ifndef __native_word
+# define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+#endif
+
 /* Compile time object size, -1 for unknown */
 #ifndef __compiletime_object_size
 # define __compiletime_object_size(obj) -1
@@ -337,6 +342,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 #define compiletime_assert(condition, msg) \
        _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
 
+#define compiletime_assert_atomic_type(t)                              \
+       compiletime_assert(__native_word(t),                            \
+               "Need native word sized stores/loads for atomicity.")
+
 /*
  * Prevent the compiler from merging or refetching accesses.  The compiler
  * is also forbidden from reordering successive instances of ACCESS_ONCE(),
index 158158704c30e75820913051283c6533ce669a4b..37b81bd51ec0e48ce7ec9c24608aeca3ca92ad36 100644 (file)
@@ -17,13 +17,13 @@ extern void __context_tracking_task_switch(struct task_struct *prev,
 
 static inline void user_enter(void)
 {
-       if (static_key_false(&context_tracking_enabled))
+       if (context_tracking_is_enabled())
                context_tracking_user_enter();
 
 }
 static inline void user_exit(void)
 {
-       if (static_key_false(&context_tracking_enabled))
+       if (context_tracking_is_enabled())
                context_tracking_user_exit();
 }
 
@@ -31,7 +31,7 @@ static inline enum ctx_state exception_enter(void)
 {
        enum ctx_state prev_ctx;
 
-       if (!static_key_false(&context_tracking_enabled))
+       if (!context_tracking_is_enabled())
                return 0;
 
        prev_ctx = this_cpu_read(context_tracking.state);
@@ -42,7 +42,7 @@ static inline enum ctx_state exception_enter(void)
 
 static inline void exception_exit(enum ctx_state prev_ctx)
 {
-       if (static_key_false(&context_tracking_enabled)) {
+       if (context_tracking_is_enabled()) {
                if (prev_ctx == IN_USER)
                        context_tracking_user_enter();
        }
@@ -51,7 +51,7 @@ static inline void exception_exit(enum ctx_state prev_ctx)
 static inline void context_tracking_task_switch(struct task_struct *prev,
                                                struct task_struct *next)
 {
-       if (static_key_false(&context_tracking_enabled))
+       if (context_tracking_is_enabled())
                __context_tracking_task_switch(prev, next);
 }
 #else
index 0f1979d0674f86e5ab006b9a0639fe9436a9e4bb..97a81225d037396fb8faae2fa0b3189ee045f7cb 100644 (file)
@@ -22,15 +22,20 @@ struct context_tracking {
 extern struct static_key context_tracking_enabled;
 DECLARE_PER_CPU(struct context_tracking, context_tracking);
 
-static inline bool context_tracking_in_user(void)
+static inline bool context_tracking_is_enabled(void)
 {
-       return __this_cpu_read(context_tracking.state) == IN_USER;
+       return static_key_false(&context_tracking_enabled);
 }
 
-static inline bool context_tracking_active(void)
+static inline bool context_tracking_cpu_is_enabled(void)
 {
        return __this_cpu_read(context_tracking.active);
 }
+
+static inline bool context_tracking_in_user(void)
+{
+       return __this_cpu_read(context_tracking.state) == IN_USER;
+}
 #else
 static inline bool context_tracking_in_user(void) { return false; }
 static inline bool context_tracking_active(void) { return false; }
index fe68a5a985831eca65d3880fb69094fbb91dbde0..7032518f85424bb081d9f6a713fec67d45873d77 100644 (file)
@@ -6,6 +6,8 @@
 #include <linux/proc_fs.h>
 #include <linux/elf.h>
 
+#include <asm/pgtable.h> /* for pgprot_t */
+
 #define ELFCORE_ADDR_MAX       (-1ULL)
 #define ELFCORE_ADDR_ERR       (-2ULL)
 
index 57e87e749a484cbf09a2f9f21fac3d3f52574df9..bf72e9ac6de01d1b1783b0b4adfd441c9c9ac58c 100644 (file)
@@ -29,8 +29,10 @@ struct vfsmount;
 /* The hash is always the low bits of hash_len */
 #ifdef __LITTLE_ENDIAN
  #define HASH_LEN_DECLARE u32 hash; u32 len;
+ #define bytemask_from_count(cnt)      (~(~0ul << (cnt)*8))
 #else
  #define HASH_LEN_DECLARE u32 len; u32 hash;
+ #define bytemask_from_count(cnt)      (~(~0ul >> (cnt)*8))
 #endif
 
 /*
index dbdffe8d44693afc648d0e0755fa86e0d0d629fe..8e6c20af11a2c835b2489875513845161abb362c 100644 (file)
@@ -35,6 +35,34 @@ extern void edac_atomic_assert_error(void);
 extern struct bus_type *edac_get_sysfs_subsys(void);
 extern void edac_put_sysfs_subsys(void);
 
+enum {
+       EDAC_REPORTING_ENABLED,
+       EDAC_REPORTING_DISABLED,
+       EDAC_REPORTING_FORCE
+};
+
+extern int edac_report_status;
+#ifdef CONFIG_EDAC
+static inline int get_edac_report_status(void)
+{
+       return edac_report_status;
+}
+
+static inline void set_edac_report_status(int new)
+{
+       edac_report_status = new;
+}
+#else
+static inline int get_edac_report_status(void)
+{
+       return EDAC_REPORTING_DISABLED;
+}
+
+static inline void set_edac_report_status(int new)
+{
+}
+#endif
+
 static inline void opstate_init(void)
 {
        switch (edac_op_state) {
index bc5687d0f3157c9d8d39342d4e69db1734baff16..0a819e7a60c961246c529570fedf7717dd6c3c7c 100644 (file)
@@ -556,6 +556,9 @@ extern struct efi {
        unsigned long hcdp;             /* HCDP table */
        unsigned long uga;              /* UGA table */
        unsigned long uv_systab;        /* UV system table */
+       unsigned long fw_vendor;        /* fw_vendor */
+       unsigned long runtime;          /* runtime table */
+       unsigned long config_table;     /* config tables */
        efi_get_time_t *get_time;
        efi_set_time_t *set_time;
        efi_get_wakeup_time_t *get_wakeup_time;
@@ -653,6 +656,7 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_RUNTIME_SERVICES   3       /* Can we use runtime services? */
 #define EFI_MEMMAP             4       /* Can we use EFI memory map? */
 #define EFI_64BIT              5       /* Is the firmware 64-bit? */
+#define EFI_ARCH_1             6       /* First arch-specific bit */
 
 #ifdef CONFIG_EFI
 # ifdef CONFIG_X86
@@ -801,6 +805,8 @@ struct efivar_entry {
        struct efi_variable var;
        struct list_head list;
        struct kobject kobj;
+       bool scanning;
+       bool deleting;
 };
 
 
@@ -866,6 +872,21 @@ void efivar_run_worker(void);
 #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
 int efivars_sysfs_init(void);
 
+#define EFIVARS_DATA_SIZE_MAX 1024
+
 #endif /* CONFIG_EFI_VARS */
 
+#ifdef CONFIG_EFI_RUNTIME_MAP
+int efi_runtime_map_init(struct kobject *);
+void efi_runtime_map_setup(void *, int, u32);
+#else
+static inline int efi_runtime_map_init(struct kobject *kobj)
+{
+       return 0;
+}
+
+static inline void
+efi_runtime_map_setup(void *map, int nr_entries, u32 desc_size) {}
+#endif
+
 #endif /* _LINUX_EFI_H */
index 9abbe630c456775b19cc999f36887efa94bbdd41..8c9b7a1c4138b87a79833bc400370a13e94cf270 100644 (file)
@@ -248,6 +248,9 @@ struct ftrace_event_call {
 #ifdef CONFIG_PERF_EVENTS
        int                             perf_refcount;
        struct hlist_head __percpu      *perf_events;
+
+       int     (*perf_perm)(struct ftrace_event_call *,
+                            struct perf_event *);
 #endif
 };
 
@@ -317,6 +320,19 @@ struct ftrace_event_file {
        }                                                               \
        early_initcall(trace_init_flags_##name);
 
+#define __TRACE_EVENT_PERF_PERM(name, expr...)                         \
+       static int perf_perm_##name(struct ftrace_event_call *tp_event, \
+                                   struct perf_event *p_event)         \
+       {                                                               \
+               return ({ expr; });                                     \
+       }                                                               \
+       static int __init trace_init_perf_perm_##name(void)             \
+       {                                                               \
+               event_##name.perf_perm = &perf_perm_##name;             \
+               return 0;                                               \
+       }                                                               \
+       early_initcall(trace_init_perf_perm_##name);
+
 #define PERF_MAX_TRACE_SIZE    2048
 
 #define MAX_FILTER_STR_VAL     256     /* Should handle KSYM_SYMBOL_LEN */
index 82eac610ce1a77ba944ee99d4afe6c921690b3c5..3ea2cf6b0e6ce444f732e489fbf97c8a44969515 100644 (file)
@@ -2,9 +2,12 @@
 #define __LINUX_GPIO_DRIVER_H
 
 #include <linux/types.h>
+#include <linux/module.h>
 
 struct device;
 struct gpio_desc;
+struct of_phandle_args;
+struct device_node;
 struct seq_file;
 
 /**
index d9cf963ac832475ffeb04c3385d1576b054fbb79..12d5f972f23f46cf1dbf83c0e7fc93333cf49015 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/lockdep.h>
 #include <linux/ftrace_irq.h>
 #include <linux/vtime.h>
+#include <asm/hardirq.h>
 
 
 extern void synchronize_irq(unsigned int irq);
index 206a2af6b62b176fbbb16e2cca923053edc5877a..b914ca3f57ba4469264034cd521bf2cdc43b0cfb 100644 (file)
@@ -42,6 +42,8 @@ struct hid_sensor_hub_attribute_info {
        s32 units;
        s32 unit_expo;
        s32 size;
+       s32 logical_minimum;
+       s32 logical_maximum;
 };
 
 /**
index 4f945d3ed49fc7a511affdc307ea84aff60565cb..8323775ac21d0a86d2bda5a9ee93d2cfad181f78 100644 (file)
 #define HID_USAGE_SENSOR_PROP_REPORT_STATE                     0x200316
 #define HID_USAGE_SENSOR_PROY_POWER_STATE                      0x200319
 
+/* Power state enumerations */
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM               0x00
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM           0x01
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM            0x02
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM    0x03
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM      0x04
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM            0x05
+
+/* Report State enumerations */
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM           0x00
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM          0x01
+
 #endif
index 9649ff0c63f8d0bb5253cd08b3f32499986b4cfd..bd7e987522221f42b7042cc242abc8ca31a72996 100644 (file)
@@ -142,7 +142,10 @@ static inline int dequeue_hwpoisoned_huge_page(struct page *page)
        return 0;
 }
 
-#define isolate_huge_page(p, l) false
+static inline bool isolate_huge_page(struct page *page, struct list_head *list)
+{
+       return false;
+}
 #define putback_active_hugepage(p)     do {} while (0)
 #define is_hugepage_active(x)  false
 
index eff50e062be850189ed9e78a9b6058a5eea49b74..d9c8dbd3373f90d298ac66001ccdd13fa6f54ddf 100644 (file)
@@ -445,7 +445,7 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
 static inline struct i2c_adapter *
 i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
 {
-#if IS_ENABLED(I2C_MUX)
+#if IS_ENABLED(CONFIG_I2C_MUX)
        struct device *parent = adapter->dev.parent;
 
        if (parent != NULL && parent->type == &i2c_adapter_type)
index b0ed422e4e4a09f059eef7cb2018dee374801084..f0e52383a00108b973413b552e112a65f84a2669 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/user_namespace.h>
 #include <linux/securebits.h>
 #include <linux/seqlock.h>
+#include <linux/rbtree.h>
 #include <net/net_namespace.h>
 #include <linux/sched/rt.h>
 
@@ -154,6 +155,14 @@ extern struct task_group root_task_group;
 
 #define INIT_TASK_COMM "swapper"
 
+#ifdef CONFIG_RT_MUTEXES
+# define INIT_RT_MUTEXES(tsk)                                          \
+       .pi_waiters = RB_ROOT,                                          \
+       .pi_waiters_leftmost = NULL,
+#else
+# define INIT_RT_MUTEXES(tsk)
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -221,6 +230,7 @@ extern struct task_group root_task_group;
        INIT_TRACE_RECURSION                                            \
        INIT_TASK_RCU_PREEMPT(tsk)                                      \
        INIT_CPUSET_SEQ(tsk)                                            \
+       INIT_RT_MUTEXES(tsk)                                            \
        INIT_VTIME(tsk)                                                 \
 }
 
index 5d89d1b808a6cc896f22332c477126c3d2f2b563..c56c350324e4b4670ef8d31397a1a777b9c08578 100644 (file)
@@ -4,6 +4,7 @@
 #include <uapi/linux/ipv6.h>
 
 #define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
+#define ipv6_authlen(p) (((p)->hdrlen+2) << 2)
 /*
  * This structure contains configuration options per IPv6 link.
  */
index 714ba08dc09265922fe8ab81dee1caadc12a9100..e374e369fb2f4c9eb5ace48679376550d5ee633c 100644 (file)
@@ -14,6 +14,6 @@ enum irqreturn {
 };
 
 typedef enum irqreturn irqreturn_t;
-#define IRQ_RETVAL(x)  ((x) != IRQ_NONE)
+#define IRQ_RETVAL(x)  ((x) ? IRQ_HANDLED : IRQ_NONE)
 
 #endif
index d4e98d13eff4bda01b08313986b63135cc80ee2b..2aa3d4b000e6f62c209d594bfdd9c3cde2dd68e7 100644 (file)
@@ -193,7 +193,8 @@ extern int _cond_resched(void);
                (__x < 0) ? -__x : __x;         \
        })
 
-#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP)
+#if defined(CONFIG_MMU) && \
+       (defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP))
 void might_fault(void);
 #else
 static inline void might_fault(void) { }
@@ -393,6 +394,15 @@ extern int panic_on_oops;
 extern int panic_on_unrecovered_nmi;
 extern int panic_on_io_nmi;
 extern int sysctl_panic_on_stackoverflow;
+/*
+ * Only to be used by arch init code. If the user over-wrote the default
+ * CONFIG_PANIC_TIMEOUT, honor it.
+ */
+static inline void set_arch_panic_timeout(int timeout, int arch_default_timeout)
+{
+       if (panic_timeout == arch_default_timeout)
+               panic_timeout = timeout;
+}
 extern const char *print_tainted(void);
 enum lockdep_ok {
        LOCKDEP_STILL_OK,
index d78d28a733b15afdc25a620ca5925f6619f82a2c..5fd33dc1fe3ad265d352ed48f3a8cdeec0ca646e 100644 (file)
@@ -198,6 +198,9 @@ extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 extern size_t vmcoreinfo_size;
 extern size_t vmcoreinfo_max_size;
 
+/* flag to track if kexec reboot is in progress */
+extern bool kexec_in_progress;
+
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
                unsigned long long *crash_size, unsigned long long *crash_base);
 int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
index 0e23c26485f457cf2380818a18b00c1175bc02ae..9b503376738fac8e25e9fa71b286b4c341295d76 100644 (file)
@@ -418,6 +418,7 @@ enum {
        ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
        ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
        ATA_HORKAGE_ATAPI_DMADIR = (1 << 18),   /* device requires dmadir */
+       ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19),    /* don't use queued TRIM */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index c8929c3832db26d00d80f96e524afbb0e75c4df1..4bfde0e99ed5169d7220204c39070faa387f57ab 100644 (file)
@@ -19,7 +19,7 @@
 
 #define USE_CMPXCHG_LOCKREF \
        (IS_ENABLED(CONFIG_ARCH_USE_CMPXCHG_LOCKREF) && \
-        IS_ENABLED(CONFIG_SMP) && !BLOATED_SPINLOCKS)
+        IS_ENABLED(CONFIG_SMP) && SPINLOCK_SIZE <= 4)
 
 struct lockref {
        union {
index 69ed5f5e9f6e4a83f8c9226cb92d6ba7eafa17bd..c45c089bfdaca9a91f32832102ff32291444884f 100644 (file)
@@ -133,4 +133,34 @@ __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
        return ret;
 }
 
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+       return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+       u32 ah, al;
+       u64 ret;
+
+       al = a;
+       ah = a >> 32;
+
+       ret = ((u64)al * mul) >> shift;
+       if (ah)
+               ret += ((u64)ah * mul) << (32 - shift);
+
+       return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#endif
+
 #endif /* _LINUX_MATH64_H */
index 2d0c9071bcfb795a4f34cdc44b1e88abae394c5e..cab2dd27907661e9c312e03088e398cc06c89a20 100644 (file)
@@ -39,7 +39,8 @@ enum sec_device_type {
 struct sec_pmic_dev {
        struct device *dev;
        struct sec_platform_data *pdata;
-       struct regmap *regmap;
+       struct regmap *regmap_pmic;
+       struct regmap *regmap_rtc;
        struct i2c_client *i2c;
        struct i2c_client *rtc;
 
index ad05ce60c1c97a052c11713f18532836829831cc..2e5b194b9b1900b9d5304cbdb52f14aac576b85e 100644 (file)
@@ -22,6 +22,8 @@
 #define PHY_ID_KSZ8021         0x00221555
 #define PHY_ID_KSZ8031         0x00221556
 #define PHY_ID_KSZ8041         0x00221510
+/* undocumented */
+#define PHY_ID_KSZ8041RNLI     0x00221537
 #define PHY_ID_KSZ8051         0x00221550
 /* same id: ks8001 Rev. A/B, and ks8721 Rev 3. */
 #define PHY_ID_KSZ8001         0x0022161A
index f5096b58b20d3ef64618e18ca37e1083b97af252..f015c059e159f1f8cad2da7b88dd26cdcbfd637d 100644 (file)
@@ -55,7 +55,8 @@ extern int migrate_huge_page_move_mapping(struct address_space *mapping,
                                  struct page *newpage, struct page *page);
 extern int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode);
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count);
 #else
 
 static inline void putback_lru_pages(struct list_head *l) {}
@@ -90,10 +91,19 @@ static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
 #endif /* CONFIG_MIGRATION */
 
 #ifdef CONFIG_NUMA_BALANCING
+extern bool pmd_trans_migrating(pmd_t pmd);
+extern void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd);
 extern int migrate_misplaced_page(struct page *page,
                                  struct vm_area_struct *vma, int node);
 extern bool migrate_ratelimited(int node);
 #else
+static inline bool pmd_trans_migrating(pmd_t pmd)
+{
+       return false;
+}
+static inline void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+}
 static inline int migrate_misplaced_page(struct page *page,
                                         struct vm_area_struct *vma, int node)
 {
index 1cedd000cf293f4486575b87086b01e2ee1b26e5..35527173cf50c71baeba5f549007c5903bc8ea06 100644 (file)
@@ -1317,7 +1317,7 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
 #endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
 
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
 extern bool ptlock_alloc(struct page *page);
 extern void ptlock_free(struct page *page);
 
@@ -1325,7 +1325,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return page->ptl;
 }
-#else /* BLOATED_SPINLOCKS */
+#else /* ALLOC_SPLIT_PTLOCKS */
 static inline bool ptlock_alloc(struct page *page)
 {
        return true;
@@ -1339,7 +1339,7 @@ static inline spinlock_t *ptlock_ptr(struct page *page)
 {
        return &page->ptl;
 }
-#endif /* BLOATED_SPINLOCKS */
+#endif /* ALLOC_SPLIT_PTLOCKS */
 
 static inline spinlock_t *pte_lockptr(struct mm_struct *mm, pmd_t *pmd)
 {
index bd299418a934e21b99c303af82a7c2f427bbf915..290901a8c1de9f0193ae3e2c640c070623431081 100644 (file)
@@ -26,6 +26,7 @@ struct address_space;
 #define USE_SPLIT_PTE_PTLOCKS  (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
 #define USE_SPLIT_PMD_PTLOCKS  (USE_SPLIT_PTE_PTLOCKS && \
                IS_ENABLED(CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK))
+#define ALLOC_SPLIT_PTLOCKS    (SPINLOCK_SIZE > BITS_PER_LONG/8)
 
 /*
  * Each physical page in the system has a struct page associated with
@@ -155,7 +156,7 @@ struct page {
                                                 * system if PG_buddy is set.
                                                 */
 #if USE_SPLIT_PTE_PTLOCKS
-#if BLOATED_SPINLOCKS
+#if ALLOC_SPLIT_PTLOCKS
                spinlock_t *ptl;
 #else
                spinlock_t ptl;
@@ -442,6 +443,14 @@ struct mm_struct {
 
        /* numa_scan_seq prevents two threads setting pte_numa */
        int numa_scan_seq;
+#endif
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+       /*
+        * An operation with batched TLB flushing is going on. Anything that
+        * can move process memory needs to flush the TLB when moving a
+        * PROT_NONE or PROT_NUMA mapped page.
+        */
+       bool tlb_flush_pending;
 #endif
        struct uprobes_state uprobes_state;
 };
@@ -459,4 +468,45 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm)
        return mm->cpu_vm_mask_var;
 }
 
+#if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
+/*
+ * Memory barriers to keep this state in sync are graciously provided by
+ * the page table locks, outside of which no page table modifications happen.
+ * The barriers below prevent the compiler from re-ordering the instructions
+ * around the memory barriers that are already present in the code.
+ */
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       return mm->tlb_flush_pending;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+       mm->tlb_flush_pending = true;
+
+       /*
+        * Guarantee that the tlb_flush_pending store does not leak into the
+        * critical section updating the page tables
+        */
+       smp_mb__before_spinlock();
+}
+/* Clearing is done after a TLB flush, which also provides a barrier. */
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+       barrier();
+       mm->tlb_flush_pending = false;
+}
+#else
+static inline bool mm_tlb_flush_pending(struct mm_struct *mm)
+{
+       return false;
+}
+static inline void set_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+static inline void clear_tlb_flush_pending(struct mm_struct *mm)
+{
+}
+#endif
+
 #endif /* _LINUX_MM_TYPES_H */
index 4bcee94cef9314c44dfaa94fb17d3c905fefee08..69be3e6079c8c9320cff6598b8ba33ff1cdfb1f8 100644 (file)
@@ -181,7 +181,7 @@ struct proto_ops {
                                      int offset, size_t size, int flags);
        ssize_t         (*splice_read)(struct socket *sock,  loff_t *ppos,
                                       struct pipe_inode_info *pipe, size_t len, unsigned int flags);
-       void            (*set_peek_off)(struct sock *sk, int val);
+       int             (*set_peek_off)(struct sock *sk, int val);
 };
 
 #define DECLARE_SOCKADDR(type, dst, src)       \
index 7f0ed423a3606f1cc13e09a00d332dc4a45f924b..ce2a1f5f9a1e0226d933d28606823239e4467526 100644 (file)
@@ -769,7 +769,8 @@ struct netdev_phys_port_id {
  *        (can also return NETDEV_TX_LOCKED iff NETIF_F_LLTX)
  *     Required can not be NULL.
  *
- * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb);
+ * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
+ *                         void *accel_priv);
  *     Called to decide which queue to when device supports multiple
  *     transmit queues.
  *
@@ -990,7 +991,8 @@ struct net_device_ops {
        netdev_tx_t             (*ndo_start_xmit) (struct sk_buff *skb,
                                                   struct net_device *dev);
        u16                     (*ndo_select_queue)(struct net_device *dev,
-                                                   struct sk_buff *skb);
+                                                   struct sk_buff *skb,
+                                                   void *accel_priv);
        void                    (*ndo_change_rx_flags)(struct net_device *dev,
                                                       int flags);
        void                    (*ndo_set_rx_mode)(struct net_device *dev);
@@ -1255,7 +1257,7 @@ struct net_device {
        unsigned char           perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
        unsigned char           addr_assign_type; /* hw address assignment type */
        unsigned char           addr_len;       /* hardware address length      */
-       unsigned char           neigh_priv_len;
+       unsigned short          neigh_priv_len;
        unsigned short          dev_id;         /* Used to differentiate devices
                                                 * that share the same link
                                                 * layer address
@@ -1529,7 +1531,8 @@ 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);
+                                   struct sk_buff *skb,
+                                   void *accel_priv);
 u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
 
 /*
@@ -1819,6 +1822,7 @@ int dev_close(struct net_device *dev);
 void dev_disable_lro(struct net_device *dev);
 int dev_loopback_xmit(struct sk_buff *newskb);
 int dev_queue_xmit(struct sk_buff *skb);
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
 int register_netdevice(struct net_device *dev);
 void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
 void unregister_netdevice_many(struct list_head *head);
@@ -1912,6 +1916,15 @@ static inline int dev_parse_header(const struct sk_buff *skb,
        return dev->header_ops->parse(skb, haddr);
 }
 
+static inline int dev_rebuild_header(struct sk_buff *skb)
+{
+       const struct net_device *dev = skb->dev;
+
+       if (!dev->header_ops || !dev->header_ops->rebuild)
+               return 0;
+       return dev->header_ops->rebuild(skb);
+}
+
 typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
 int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
 static inline int unregister_gifconf(unsigned int family)
@@ -2417,7 +2430,7 @@ int dev_change_carrier(struct net_device *, bool new_carrier);
 int dev_get_phys_port_id(struct net_device *dev,
                         struct netdev_phys_port_id *ppid);
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv);
+                       struct netdev_queue *txq);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 
 extern int             netdev_budget;
@@ -3008,6 +3021,19 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
        dev->gso_max_size = size;
 }
 
+static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
+                                       int pulled_hlen, u16 mac_offset,
+                                       int mac_len)
+{
+       skb->protocol = protocol;
+       skb->encapsulation = 1;
+       skb_push(skb, pulled_hlen);
+       skb_reset_transport_header(skb);
+       skb->mac_header = mac_offset;
+       skb->network_header = skb->mac_header + mac_len;
+       skb->mac_len = mac_len;
+}
+
 static inline bool netif_is_macvlan(struct net_device *dev)
 {
        return dev->priv_flags & IFF_MACVLAN;
index c1637062c1ce138129a87dd571a5ea7cd2b53abd..12c2cb947df579bca8e55c46c5a58cf449f084fb 100644 (file)
@@ -413,16 +413,6 @@ enum lock_type4 {
 #define NFS4_VERSION 4
 #define NFS4_MINOR_VERSION 0
 
-#if defined(CONFIG_NFS_V4_2)
-#define NFS4_MAX_MINOR_VERSION 2
-#else
-#if defined(CONFIG_NFS_V4_1)
-#define NFS4_MAX_MINOR_VERSION 1
-#else
-#define NFS4_MAX_MINOR_VERSION 0
-#endif /* CONFIG_NFS_V4_1 */
-#endif /* CONFIG_NFS_V4_2 */
-
 #define NFS4_DEBUG 1
 
 /* Index of predefined Linux client operations */
index 14a48207a304ec65dda6ac8af22e0e0825b8fa6b..48997374eaf04eac0d52b8bf8d60c61c35944df3 100644 (file)
@@ -506,24 +506,6 @@ extern const struct inode_operations nfs_referral_inode_operations;
 extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
-/*
- * linux/fs/nfs/nfs4proc.c
- */
-#ifdef CONFIG_NFS_V4_SECURITY_LABEL
-extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
-static inline void nfs4_label_free(struct nfs4_label *label)
-{
-       if (label) {
-               kfree(label->label);
-               kfree(label);
-       }
-       return;
-}
-#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) {}
-#endif
-
 /*
  * linux/fs/nfs/unlink.c
  */
index 1084a15175e04ff0bc715e3e429aab7027d279f8..a13d6825e586972835ba2b3d53ac4ab504ba5369 100644 (file)
@@ -960,6 +960,7 @@ void pci_update_resource(struct pci_dev *dev, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+bool pci_device_is_present(struct pci_dev *pdev);
 
 /* ROM control related routines */
 int pci_enable_rom(struct pci_dev *pdev);
@@ -1567,65 +1568,65 @@ enum pci_fixup_pass {
 /* Anonymous variables would be nice... */
 #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,        \
                                  class_shift, hook)                    \
-       static const struct pci_fixup __pci_fixup_##name __used         \
+       static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used       \
        __attribute__((__section__(#section), aligned((sizeof(void *)))))    \
                = { vendor, device, class, class_shift, hook };
 
 #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device, class,    \
+               resume##hook, vendor, device, class,    \
                class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(vendor, device, class,    \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_SUSPEND(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device, class,   \
+               suspend##hook, vendor, device, class,   \
                class_shift, hook)
 
 #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device,           \
+               resume##hook, vendor, device,           \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook)           \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device,          \
+               suspend##hook, vendor, device,          \
                PCI_ANY_ID, 0, hook)
 
 #ifdef CONFIG_PCI_QUIRKS
index 57e890abe1f09220c777b5403c782cd6792872d6..a5fc7d01aad61049164f920f90a6f20df1cbc22d 100644 (file)
@@ -69,6 +69,7 @@
        __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;                    \
        extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;            \
        __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;                   \
+       extern __PCPU_ATTRS(sec) __typeof__(type) name;                 \
        __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak                 \
        __typeof__(type) name
 #else
index 2e069d1288df5f04e6982243d7cac0f7455cd31d..e56b07f5c9b67f0119d874b60a8a6bed9fda7e99 100644 (file)
@@ -320,6 +320,7 @@ struct perf_event {
        struct list_head                migrate_entry;
 
        struct hlist_node               hlist_entry;
+       struct list_head                active_entry;
        int                             nr_siblings;
        int                             group_flags;
        struct perf_event               *group_leader;
index c167e4429bc705a6fc58faa6709917065b518547..0e3cce130fe26f812fb46e99c936b698f8433e3b 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/arch/arm/plat-s3c/include/plat/hwmon.h
- *
+/*
  * Copyright 2005 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *     http://armlinux.simtec.co.uk/
@@ -11,8 +10,8 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_ARCH_ADC_HWMON_H
-#define __ASM_ARCH_ADC_HWMON_H __FILE__
+#ifndef __HWMON_S3C_H__
+#define __HWMON_S3C_H__
 
 /**
  * s3c_hwmon_chcfg - channel configuration
@@ -47,5 +46,4 @@ struct s3c_hwmon_pdata {
  */
 extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd);
 
-#endif /* __ASM_ARCH_ADC_HWMON_H */
-
+#endif /* __HWMON_S3C_H__ */
index e2a41dd7690cceaaf320c7bad68184e60f0c7911..8da8f94ee15c1a01757796942fd2e74ac5b81f2c 100644 (file)
@@ -11,6 +11,9 @@
  * For further information, see the Documentation/hwmon/max197 file.
  */
 
+#ifndef _PDATA_MAX197_H
+#define _PDATA_MAX197_H
+
 /**
  * struct max197_platform_data - MAX197 connectivity info
  * @convert:   Function used to start a conversion with control byte ctrl.
@@ -19,3 +22,5 @@
 struct max197_platform_data {
        int (*convert)(u8 ctrl);
 };
+
+#endif /* _PDATA_MAX197_H */
index 33e0fd27225e03a06aac63e08de8cfb36adb49fc..12289c1e9413f57ece424438795dc27e341aa5d8 100644 (file)
@@ -12,6 +12,9 @@
  * For further information, see the Documentation/hwmon/sht15 file.
  */
 
+#ifndef _PDATA_SHT15_H
+#define _PDATA_SHT15_H
+
 /**
  * struct sht15_platform_data - sht15 connectivity info
  * @gpio_data:         no. of gpio to which bidirectional data line is
@@ -31,3 +34,5 @@ struct sht15_platform_data {
        bool no_otp_reload;
        bool low_resolution;
 };
+
+#endif /* _PDATA_SHT15_H */
index a3d9dc8c2c006a02cd7677a6e4a6ac10dac69910..59749fc48328181452537d226f632559371a7147 100644 (file)
@@ -64,7 +64,11 @@ do { \
 } while (0)
 
 #else
-#define preempt_enable() preempt_enable_no_resched()
+#define preempt_enable() \
+do { \
+       barrier(); \
+       preempt_count_dec(); \
+} while (0)
 #define preempt_check_resched() do { } while (0)
 #endif
 
@@ -93,7 +97,11 @@ do { \
                __preempt_schedule_context(); \
 } while (0)
 #else
-#define preempt_enable_notrace() preempt_enable_no_resched_notrace()
+#define preempt_enable_notrace() \
+do { \
+       barrier(); \
+       __preempt_count_dec(); \
+} while (0)
 #endif
 
 #else /* !CONFIG_PREEMPT_COUNT */
@@ -116,6 +124,31 @@ do { \
 
 #endif /* CONFIG_PREEMPT_COUNT */
 
+#ifdef MODULE
+/*
+ * Modules have no business playing preemption tricks.
+ */
+#undef sched_preempt_enable_no_resched
+#undef preempt_enable_no_resched
+#undef preempt_enable_no_resched_notrace
+#undef preempt_check_resched
+#endif
+
+#ifdef CONFIG_PREEMPT
+#define preempt_set_need_resched() \
+do { \
+       set_preempt_need_resched(); \
+} while (0)
+#define preempt_fold_need_resched() \
+do { \
+       if (tif_need_resched()) \
+               set_preempt_need_resched(); \
+} while (0)
+#else
+#define preempt_set_need_resched() do { } while (0)
+#define preempt_fold_need_resched() do { } while (0)
+#endif
+
 #ifdef CONFIG_PREEMPT_NOTIFIERS
 
 struct preempt_notifier;
index d169820203dd825e54bd35479954e162509e78d8..dbeec4d4a3beafb0d6123944f108981879c3137e 100644 (file)
@@ -2,7 +2,6 @@
 #define LINUX_PREEMPT_MASK_H
 
 #include <linux/preempt.h>
-#include <asm/hardirq.h>
 
 /*
  * We put the hardirq and softirq counter into the preemption
 # define PREEMPT_CHECK_OFFSET 0
 #endif
 
+/*
+ * The preempt_count offset needed for things like:
+ *
+ *  spin_lock_bh()
+ *
+ * Which need to disable both preemption (CONFIG_PREEMPT_COUNT) and
+ * softirqs, such that unlock sequences of:
+ *
+ *  spin_unlock();
+ *  local_bh_enable();
+ *
+ * Work as expected.
+ */
+#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_CHECK_OFFSET)
+
 /*
  * Are we running in atomic context?  WARNING: this macro cannot
  * always detect atomic context; in particular, it cannot know about
index abd437d0a8a7eeac72297ad5306ca071993d8f58..ece0c6bbfcc5617f394092ec027f39ce3abc629d 100644 (file)
@@ -51,6 +51,7 @@ struct pstore_info {
        char            *buf;
        size_t          bufsize;
        struct mutex    read_mutex;     /* serialize open/read/close */
+       int             flags;
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
@@ -70,6 +71,8 @@ struct pstore_info {
        void            *data;
 };
 
+#define        PSTORE_FLAGS_FRAGILE    1
+
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
 extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
index 45a0a9e81478c41187088d6ce3fb9762f070e335..dbaf9908411217c57a257309c5949e8d4b76ff5b 100644 (file)
@@ -55,8 +55,8 @@ static inline void __list_add_rcu(struct list_head *new,
        next->prev = new;
 }
 #else
-extern void __list_add_rcu(struct list_head *new,
-               struct list_head *prev, struct list_head *next);
+void __list_add_rcu(struct list_head *new,
+                   struct list_head *prev, struct list_head *next);
 #endif
 
 /**
index 39cbb889e20da020c8936aae8124601b718e05a5..3e355c688618e66391d535de3e183bf9c9ec8cba 100644 (file)
@@ -50,13 +50,13 @@ extern int rcutorture_runnable; /* for sysctl */
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
 
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
-extern void rcutorture_record_test_transition(void);
-extern void rcutorture_record_progress(unsigned long vernum);
-extern void do_trace_rcu_torture_read(const char *rcutorturename,
-                                     struct rcu_head *rhp,
-                                     unsigned long secs,
-                                     unsigned long c_old,
-                                     unsigned long c);
+void rcutorture_record_test_transition(void);
+void rcutorture_record_progress(unsigned long vernum);
+void do_trace_rcu_torture_read(const char *rcutorturename,
+                              struct rcu_head *rhp,
+                              unsigned long secs,
+                              unsigned long c_old,
+                              unsigned long c);
 #else
 static inline void rcutorture_record_test_transition(void)
 {
@@ -65,11 +65,11 @@ static inline void rcutorture_record_progress(unsigned long vernum)
 {
 }
 #ifdef CONFIG_RCU_TRACE
-extern void do_trace_rcu_torture_read(const char *rcutorturename,
-                                     struct rcu_head *rhp,
-                                     unsigned long secs,
-                                     unsigned long c_old,
-                                     unsigned long c);
+void do_trace_rcu_torture_read(const char *rcutorturename,
+                              struct rcu_head *rhp,
+                              unsigned long secs,
+                              unsigned long c_old,
+                              unsigned long c);
 #else
 #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
        do { } while (0)
@@ -118,8 +118,8 @@ extern void do_trace_rcu_torture_read(const char *rcutorturename,
  * if CPU A and CPU B are the same CPU (but again only if the system has
  * more than one CPU).
  */
-extern void call_rcu(struct rcu_head *head,
-                             void (*func)(struct rcu_head *head));
+void call_rcu(struct rcu_head *head,
+             void (*func)(struct rcu_head *head));
 
 #else /* #ifdef CONFIG_PREEMPT_RCU */
 
@@ -149,8 +149,8 @@ extern void call_rcu(struct rcu_head *head,
  * See the description of call_rcu() for more detailed information on
  * memory ordering guarantees.
  */
-extern void call_rcu_bh(struct rcu_head *head,
-                       void (*func)(struct rcu_head *head));
+void call_rcu_bh(struct rcu_head *head,
+                void (*func)(struct rcu_head *head));
 
 /**
  * call_rcu_sched() - Queue an RCU for invocation after sched grace period.
@@ -171,16 +171,16 @@ extern void call_rcu_bh(struct rcu_head *head,
  * See the description of call_rcu() for more detailed information on
  * memory ordering guarantees.
  */
-extern void call_rcu_sched(struct rcu_head *head,
-                          void (*func)(struct rcu_head *rcu));
+void call_rcu_sched(struct rcu_head *head,
+                   void (*func)(struct rcu_head *rcu));
 
-extern void synchronize_sched(void);
+void synchronize_sched(void);
 
 #ifdef CONFIG_PREEMPT_RCU
 
-extern void __rcu_read_lock(void);
-extern void __rcu_read_unlock(void);
-extern void rcu_read_unlock_special(struct task_struct *t);
+void __rcu_read_lock(void);
+void __rcu_read_unlock(void);
+void rcu_read_unlock_special(struct task_struct *t);
 void synchronize_rcu(void);
 
 /*
@@ -216,19 +216,19 @@ static inline int rcu_preempt_depth(void)
 #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
 
 /* Internal to kernel */
-extern void rcu_init(void);
-extern void rcu_sched_qs(int cpu);
-extern void rcu_bh_qs(int cpu);
-extern void rcu_check_callbacks(int cpu, int user);
+void rcu_init(void);
+void rcu_sched_qs(int cpu);
+void rcu_bh_qs(int cpu);
+void rcu_check_callbacks(int cpu, int user);
 struct notifier_block;
-extern void rcu_idle_enter(void);
-extern void rcu_idle_exit(void);
-extern void rcu_irq_enter(void);
-extern void rcu_irq_exit(void);
+void rcu_idle_enter(void);
+void rcu_idle_exit(void);
+void rcu_irq_enter(void);
+void rcu_irq_exit(void);
 
 #ifdef CONFIG_RCU_USER_QS
-extern void rcu_user_enter(void);
-extern void rcu_user_exit(void);
+void rcu_user_enter(void);
+void rcu_user_exit(void);
 #else
 static inline void rcu_user_enter(void) { }
 static inline void rcu_user_exit(void) { }
@@ -262,7 +262,7 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev,
        } while (0)
 
 #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
-extern bool __rcu_is_watching(void);
+bool __rcu_is_watching(void);
 #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */
 
 /*
@@ -289,8 +289,8 @@ void wait_rcu_gp(call_rcu_func_t crf);
  * initialization.
  */
 #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
-extern void init_rcu_head_on_stack(struct rcu_head *head);
-extern void destroy_rcu_head_on_stack(struct rcu_head *head);
+void init_rcu_head_on_stack(struct rcu_head *head);
+void destroy_rcu_head_on_stack(struct rcu_head *head);
 #else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 static inline void init_rcu_head_on_stack(struct rcu_head *head)
 {
@@ -325,6 +325,7 @@ static inline void rcu_lock_release(struct lockdep_map *map)
 extern struct lockdep_map rcu_lock_map;
 extern struct lockdep_map rcu_bh_lock_map;
 extern struct lockdep_map rcu_sched_lock_map;
+extern struct lockdep_map rcu_callback_map;
 extern int debug_lockdep_rcu_enabled(void);
 
 /**
@@ -362,7 +363,7 @@ static inline int rcu_read_lock_held(void)
  * rcu_read_lock_bh_held() is defined out of line to avoid #include-file
  * hell.
  */
-extern int rcu_read_lock_bh_held(void);
+int rcu_read_lock_bh_held(void);
 
 /**
  * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
@@ -448,7 +449,7 @@ static inline int rcu_read_lock_sched_held(void)
 
 #ifdef CONFIG_PROVE_RCU
 
-extern int rcu_my_thread_group_empty(void);
+int rcu_my_thread_group_empty(void);
 
 /**
  * rcu_lockdep_assert - emit lockdep splat if specified condition not met
@@ -548,10 +549,48 @@ static inline void rcu_preempt_sleep_check(void)
                smp_read_barrier_depends(); \
                (_________p1); \
        })
-#define __rcu_assign_pointer(p, v, space) \
+
+/**
+ * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
+ * @v: The value to statically initialize with.
+ */
+#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
+
+/**
+ * rcu_assign_pointer() - assign to RCU-protected pointer
+ * @p: pointer to assign to
+ * @v: value to assign (publish)
+ *
+ * Assigns the specified value to the specified RCU-protected
+ * pointer, ensuring that any concurrent RCU readers will see
+ * any prior initialization.
+ *
+ * Inserts memory barriers on architectures that require them
+ * (which is most of them), and also prevents the compiler from
+ * reordering the code that initializes the structure after the pointer
+ * assignment.  More importantly, this call documents which pointers
+ * will be dereferenced by RCU read-side code.
+ *
+ * In some special cases, you may use RCU_INIT_POINTER() instead
+ * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
+ * to the fact that it does not constrain either the CPU or the compiler.
+ * That said, using RCU_INIT_POINTER() when you should have used
+ * rcu_assign_pointer() is a very bad thing that results in
+ * impossible-to-diagnose memory corruption.  So please be careful.
+ * See the RCU_INIT_POINTER() comment header for details.
+ *
+ * Note that rcu_assign_pointer() evaluates each of its arguments only
+ * once, appearances notwithstanding.  One of the "extra" evaluations
+ * is in typeof() and the other visible only to sparse (__CHECKER__),
+ * neither of which actually execute the argument.  As with most cpp
+ * macros, this execute-arguments-only-once property is important, so
+ * 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(); \
-               (p) = (typeof(*v) __force space *)(v); \
+               ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
        } while (0)
 
 
@@ -889,32 +928,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
        preempt_enable_notrace();
 }
 
-/**
- * rcu_assign_pointer() - assign to RCU-protected pointer
- * @p: pointer to assign to
- * @v: value to assign (publish)
- *
- * Assigns the specified value to the specified RCU-protected
- * pointer, ensuring that any concurrent RCU readers will see
- * any prior initialization.
- *
- * Inserts memory barriers on architectures that require them
- * (which is most of them), and also prevents the compiler from
- * reordering the code that initializes the structure after the pointer
- * assignment.  More importantly, this call documents which pointers
- * will be dereferenced by RCU read-side code.
- *
- * In some special cases, you may use RCU_INIT_POINTER() instead
- * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
- * to the fact that it does not constrain either the CPU or the compiler.
- * That said, using RCU_INIT_POINTER() when you should have used
- * rcu_assign_pointer() is a very bad thing that results in
- * impossible-to-diagnose memory corruption.  So please be careful.
- * See the RCU_INIT_POINTER() comment header for details.
- */
-#define rcu_assign_pointer(p, v) \
-       __rcu_assign_pointer((p), (v), __rcu)
-
 /**
  * RCU_INIT_POINTER() - initialize an RCU protected pointer
  *
@@ -949,7 +962,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  */
 #define RCU_INIT_POINTER(p, v) \
        do { \
-               p = (typeof(*v) __force __rcu *)(v); \
+               p = RCU_INITIALIZER(v); \
        } while (0)
 
 /**
@@ -958,7 +971,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * GCC-style initialization for an RCU-protected pointer in a structure field.
  */
 #define RCU_POINTER_INITIALIZER(p, v) \
-               .p = (typeof(*v) __force __rcu *)(v)
+               .p = RCU_INITIALIZER(v)
 
 /*
  * Does the specified offset indicate that the corresponding rcu_head
@@ -1005,7 +1018,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
        __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
 
 #ifdef CONFIG_RCU_NOCB_CPU
-extern bool rcu_is_nocb_cpu(int 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 */
@@ -1013,8 +1026,8 @@ static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
 
 /* Only for use by adaptive-ticks code. */
 #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
-extern bool rcu_sys_is_idle(void);
-extern void rcu_sysidle_force_exit(void);
+bool rcu_sys_is_idle(void);
+void rcu_sysidle_force_exit(void);
 #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
 
 static inline bool rcu_sys_is_idle(void)
index 09ebcbe9fd780932e2dee223daaa8426395e77d8..6f01771b571c00eede5aaae145fdcf7382e61cd9 100644 (file)
@@ -125,7 +125,7 @@ static inline void exit_rcu(void)
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 extern int rcu_scheduler_active __read_mostly;
-extern void rcu_scheduler_starting(void);
+void rcu_scheduler_starting(void);
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 static inline void rcu_scheduler_starting(void)
 {
index 4b9c8154874269d66cc3fa1312bc6e53d2584669..72137ee8c603b2c0c45ea7f729211e12cfad3941 100644 (file)
@@ -30,9 +30,9 @@
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
-extern void rcu_note_context_switch(int cpu);
-extern int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
-extern void rcu_cpu_stall_reset(void);
+void rcu_note_context_switch(int cpu);
+int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
+void rcu_cpu_stall_reset(void);
 
 /*
  * Note a virtualization-based context switch.  This is simply a
@@ -44,9 +44,9 @@ static inline void rcu_virt_note_context_switch(int cpu)
        rcu_note_context_switch(cpu);
 }
 
-extern void synchronize_rcu_bh(void);
-extern void synchronize_sched_expedited(void);
-extern void synchronize_rcu_expedited(void);
+void synchronize_rcu_bh(void);
+void synchronize_sched_expedited(void);
+void synchronize_rcu_expedited(void);
 
 void kfree_call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
 
@@ -71,25 +71,25 @@ static inline void synchronize_rcu_bh_expedited(void)
        synchronize_sched_expedited();
 }
 
-extern void rcu_barrier(void);
-extern void rcu_barrier_bh(void);
-extern void rcu_barrier_sched(void);
+void rcu_barrier(void);
+void rcu_barrier_bh(void);
+void rcu_barrier_sched(void);
 
 extern unsigned long rcutorture_testseq;
 extern unsigned long rcutorture_vernum;
-extern long rcu_batches_completed(void);
-extern long rcu_batches_completed_bh(void);
-extern long rcu_batches_completed_sched(void);
+long rcu_batches_completed(void);
+long rcu_batches_completed_bh(void);
+long rcu_batches_completed_sched(void);
 
-extern void rcu_force_quiescent_state(void);
-extern void rcu_bh_force_quiescent_state(void);
-extern void rcu_sched_force_quiescent_state(void);
+void rcu_force_quiescent_state(void);
+void rcu_bh_force_quiescent_state(void);
+void rcu_sched_force_quiescent_state(void);
 
-extern void exit_rcu(void);
+void exit_rcu(void);
 
-extern void rcu_scheduler_starting(void);
+void rcu_scheduler_starting(void);
 extern int rcu_scheduler_active __read_mostly;
 
-extern bool rcu_is_watching(void);
+bool rcu_is_watching(void);
 
 #endif /* __LINUX_RCUTREE_H */
index 8e00f9f6f96395b3e209192259b6af58f7078143..9e7db9e73cc13ffc04d05b02c9c5ea0d877be7e9 100644 (file)
@@ -43,6 +43,7 @@ extern int unregister_reboot_notifier(struct notifier_block *);
  * Architecture-specific implementations of sys_reboot commands.
  */
 
+extern void migrate_to_reboot_cpu(void);
 extern void machine_restart(char *cmd);
 extern void machine_halt(void);
 extern void machine_power_off(void);
index de17134244f3b6eb35f70abb907d994b1b5e578d..3aed8d737e1a870a8e1727a50af5108e9dbb87cf 100644 (file)
@@ -13,7 +13,7 @@
 #define __LINUX_RT_MUTEX_H
 
 #include <linux/linkage.h>
-#include <linux/plist.h>
+#include <linux/rbtree.h>
 #include <linux/spinlock_types.h>
 
 extern int max_lock_depth; /* for sysctl */
@@ -22,12 +22,14 @@ extern int max_lock_depth; /* for sysctl */
  * The rt_mutex structure
  *
  * @wait_lock: spinlock to protect the structure
- * @wait_list: pilist head to enqueue waiters in priority order
+ * @waiters:   rbtree root to enqueue waiters in priority order
+ * @waiters_leftmost: top waiter
  * @owner:     the mutex owner
  */
 struct rt_mutex {
        raw_spinlock_t          wait_lock;
-       struct plist_head       wait_list;
+       struct rb_root          waiters;
+       struct rb_node          *waiters_leftmost;
        struct task_struct      *owner;
 #ifdef CONFIG_DEBUG_RT_MUTEXES
        int                     save_state;
@@ -66,7 +68,7 @@ struct hrtimer_sleeper;
 
 #define __RT_MUTEX_INITIALIZER(mutexname) \
        { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
-       , .wait_list = PLIST_HEAD_INIT(mutexname.wait_list) \
+       , .waiters = RB_ROOT \
        , .owner = NULL \
        __DEBUG_RT_MUTEX_INITIALIZER(mutexname)}
 
@@ -98,12 +100,4 @@ extern int rt_mutex_trylock(struct rt_mutex *lock);
 
 extern void rt_mutex_unlock(struct rt_mutex *lock);
 
-#ifdef CONFIG_RT_MUTEXES
-# define INIT_RT_MUTEXES(tsk)                                          \
-       .pi_waiters     = PLIST_HEAD_INIT(tsk.pi_waiters),      \
-       INIT_RT_MUTEX_DEBUG(tsk)
-#else
-# define INIT_RT_MUTEXES(tsk)
-#endif
-
 #endif
index 939428ad25acb506297c1726faaee83d60d047c4..8e3e66ac0a5215d221042e15e631fb2fe2fb51d1 100644 (file)
@@ -24,6 +24,11 @@ extern int rtnl_trylock(void);
 extern int rtnl_is_locked(void);
 #ifdef CONFIG_PROVE_LOCKING
 extern int lockdep_rtnl_is_held(void);
+#else
+static inline int lockdep_rtnl_is_held(void)
+{
+       return 1;
+}
 #endif /* #ifdef CONFIG_PROVE_LOCKING */
 
 /**
index 9c9f0495d37c0d41643a24c25e8447e4ee90d576..5b9b84b204070f8e6780e3836ea3c9efdc4a1e61 100644 (file)
@@ -172,8 +172,7 @@ static inline void __raw_read_lock_irq(rwlock_t *lock)
 
 static inline void __raw_read_lock_bh(rwlock_t *lock)
 {
-       local_bh_disable();
-       preempt_disable();
+       __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
        rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_);
        LOCK_CONTENDED(lock, do_raw_read_trylock, do_raw_read_lock);
 }
@@ -200,8 +199,7 @@ static inline void __raw_write_lock_irq(rwlock_t *lock)
 
 static inline void __raw_write_lock_bh(rwlock_t *lock)
 {
-       local_bh_disable();
-       preempt_disable();
+       __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
        rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
 }
@@ -250,8 +248,7 @@ static inline void __raw_read_unlock_bh(rwlock_t *lock)
 {
        rwlock_release(&lock->dep_map, 1, _RET_IP_);
        do_raw_read_unlock(lock);
-       preempt_enable_no_resched();
-       local_bh_enable_ip((unsigned long)__builtin_return_address(0));
+       __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
 }
 
 static inline void __raw_write_unlock_irqrestore(rwlock_t *lock,
@@ -275,8 +272,7 @@ static inline void __raw_write_unlock_bh(rwlock_t *lock)
 {
        rwlock_release(&lock->dep_map, 1, _RET_IP_);
        do_raw_write_unlock(lock);
-       preempt_enable_no_resched();
-       local_bh_enable_ip((unsigned long)__builtin_return_address(0));
+       __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
 }
 
 #endif /* __LINUX_RWLOCK_API_SMP_H */
index 7e35d4b9e14a45cba37fd8a7f234e5a3a50ec4b5..ffccdad050b5b89d086b70a906843b3c23861984 100644 (file)
@@ -16,6 +16,7 @@ struct sched_param {
 #include <linux/types.h>
 #include <linux/timex.h>
 #include <linux/jiffies.h>
+#include <linux/plist.h>
 #include <linux/rbtree.h>
 #include <linux/thread_info.h>
 #include <linux/cpumask.h>
@@ -56,6 +57,70 @@ struct sched_param {
 
 #include <asm/processor.h>
 
+#define SCHED_ATTR_SIZE_VER0   48      /* sizeof first published struct */
+
+/*
+ * Extended scheduling parameters data structure.
+ *
+ * This is needed because the original struct sched_param can not be
+ * altered without introducing ABI issues with legacy applications
+ * (e.g., in sched_getparam()).
+ *
+ * However, the possibility of specifying more than just a priority for
+ * the tasks may be useful for a wide variety of application fields, e.g.,
+ * multimedia, streaming, automation and control, and many others.
+ *
+ * This variant (sched_attr) is meant at describing a so-called
+ * sporadic time-constrained task. In such model a task is specified by:
+ *  - the activation period or minimum instance inter-arrival time;
+ *  - the maximum (or average, depending on the actual scheduling
+ *    discipline) computation time of all instances, a.k.a. runtime;
+ *  - the deadline (relative to the actual activation time) of each
+ *    instance.
+ * Very briefly, a periodic (sporadic) task asks for the execution of
+ * some specific computation --which is typically called an instance--
+ * (at most) every period. Moreover, each instance typically lasts no more
+ * than the runtime and must be completed by time instant t equal to
+ * the instance activation time + the deadline.
+ *
+ * This is reflected by the actual fields of the sched_attr structure:
+ *
+ *  @size              size of the structure, for fwd/bwd compat.
+ *
+ *  @sched_policy      task's scheduling policy
+ *  @sched_flags       for customizing the scheduler behaviour
+ *  @sched_nice                task's nice value      (SCHED_NORMAL/BATCH)
+ *  @sched_priority    task's static priority (SCHED_FIFO/RR)
+ *  @sched_deadline    representative of the task's deadline
+ *  @sched_runtime     representative of the task's runtime
+ *  @sched_period      representative of the task's period
+ *
+ * Given this task model, there are a multiplicity of scheduling algorithms
+ * and policies, that can be used to ensure all the tasks will make their
+ * timing constraints.
+ *
+ * As of now, the SCHED_DEADLINE policy (sched_dl scheduling class) is the
+ * only user of this new interface. More information about the algorithm
+ * available in the scheduling class file or in Documentation/.
+ */
+struct sched_attr {
+       u32 size;
+
+       u32 sched_policy;
+       u64 sched_flags;
+
+       /* SCHED_NORMAL, SCHED_BATCH */
+       s32 sched_nice;
+
+       /* SCHED_FIFO, SCHED_RR */
+       u32 sched_priority;
+
+       /* SCHED_DEADLINE */
+       u64 sched_runtime;
+       u64 sched_deadline;
+       u64 sched_period;
+};
+
 struct exec_domain;
 struct futex_pi_state;
 struct robust_list_head;
@@ -168,7 +233,6 @@ extern char ___assert_task_state[1 - 2*!!(
 
 #define task_is_traced(task)   ((task->state & __TASK_TRACED) != 0)
 #define task_is_stopped(task)  ((task->state & __TASK_STOPPED) != 0)
-#define task_is_dead(task)     ((task)->exit_state != 0)
 #define task_is_stopped_or_traced(task)        \
                        ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
 #define task_contributes_to_load(task) \
@@ -440,8 +504,6 @@ struct task_cputime {
                .sum_exec_runtime = 0,                          \
        }
 
-#define PREEMPT_ENABLED                (PREEMPT_NEED_RESCHED)
-
 #ifdef CONFIG_PREEMPT_COUNT
 #define PREEMPT_DISABLED       (1 + PREEMPT_ENABLED)
 #else
@@ -831,8 +893,6 @@ struct sched_domain {
        unsigned int balance_interval;  /* initialise to 1. units in ms. */
        unsigned int nr_balance_failed; /* initialise to 0 */
 
-       u64 last_update;
-
        /* idle_balance() stats */
        u64 max_newidle_lb_cost;
        unsigned long next_decay_max_lb_cost;
@@ -934,7 +994,8 @@ struct pipe_inode_info;
 struct uts_namespace;
 
 struct load_weight {
-       unsigned long weight, inv_weight;
+       unsigned long weight;
+       u32 inv_weight;
 };
 
 struct sched_avg {
@@ -1032,6 +1093,51 @@ struct sched_rt_entity {
 #endif
 };
 
+struct sched_dl_entity {
+       struct rb_node  rb_node;
+
+       /*
+        * Original scheduling parameters. Copied here from sched_attr
+        * during sched_setscheduler2(), they will remain the same until
+        * the next sched_setscheduler2().
+        */
+       u64 dl_runtime;         /* maximum runtime for each instance    */
+       u64 dl_deadline;        /* relative deadline of each instance   */
+       u64 dl_period;          /* separation of two instances (period) */
+       u64 dl_bw;              /* dl_runtime / dl_deadline             */
+
+       /*
+        * Actual scheduling parameters. Initialized with the values above,
+        * they are continously updated during task execution. Note that
+        * the remaining runtime could be < 0 in case we are in overrun.
+        */
+       s64 runtime;            /* remaining runtime for this instance  */
+       u64 deadline;           /* absolute deadline for this instance  */
+       unsigned int flags;     /* specifying the scheduler behaviour   */
+
+       /*
+        * Some bool flags:
+        *
+        * @dl_throttled tells if we exhausted the runtime. If so, the
+        * task has to wait for a replenishment to be performed at the
+        * next firing of dl_timer.
+        *
+        * @dl_new tells if a new instance arrived. If so we must
+        * start executing it with full runtime and reset its absolute
+        * deadline;
+        *
+        * @dl_boosted tells if we are boosted due to DI. If so we are
+        * outside bandwidth enforcement mechanism (but only until we
+        * exit the critical section).
+        */
+       int dl_throttled, dl_new, dl_boosted;
+
+       /*
+        * Bandwidth enforcement timer. Each -deadline task has its
+        * own bandwidth to be enforced, thus we need one timer per task.
+        */
+       struct hrtimer dl_timer;
+};
 
 struct rcu_node;
 
@@ -1068,6 +1174,7 @@ struct task_struct {
 #ifdef CONFIG_CGROUP_SCHED
        struct task_group *sched_task_group;
 #endif
+       struct sched_dl_entity dl;
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
        /* list of struct preempt_notifier: */
@@ -1101,6 +1208,7 @@ struct task_struct {
        struct list_head tasks;
 #ifdef CONFIG_SMP
        struct plist_node pushable_tasks;
+       struct rb_node pushable_dl_tasks;
 #endif
 
        struct mm_struct *mm, *active_mm;
@@ -1252,9 +1360,12 @@ struct task_struct {
 
 #ifdef CONFIG_RT_MUTEXES
        /* PI waiters blocked on a rt_mutex held by this task */
-       struct plist_head pi_waiters;
+       struct rb_root pi_waiters;
+       struct rb_node *pi_waiters_leftmost;
        /* Deadlock detection and priority inheritance handling */
        struct rt_mutex_waiter *pi_blocked_on;
+       /* Top pi_waiters task */
+       struct task_struct *pi_top_task;
 #endif
 
 #ifdef CONFIG_DEBUG_MUTEXES
@@ -1883,7 +1994,9 @@ static inline void sched_clock_idle_wakeup_event(u64 delta_ns)
  * but then during bootup it turns out that sched_clock()
  * is reliable after all:
  */
-extern int sched_clock_stable;
+extern int sched_clock_stable(void);
+extern void set_sched_clock_stable(void);
+extern void clear_sched_clock_stable(void);
 
 extern void sched_clock_tick(void);
 extern void sched_clock_idle_sleep_event(void);
@@ -1962,6 +2075,8 @@ extern int sched_setscheduler(struct task_struct *, int,
                              const struct sched_param *);
 extern int sched_setscheduler_nocheck(struct task_struct *, int,
                                      const struct sched_param *);
+extern int sched_setattr(struct task_struct *,
+                        const struct sched_attr *);
 extern struct task_struct *idle_task(int cpu);
 /**
  * is_idle_task - is the specified task an idle task?
@@ -2041,7 +2156,7 @@ extern void wake_up_new_task(struct task_struct *tsk);
 #else
  static inline void kick_process(struct task_struct *tsk) { }
 #endif
-extern void sched_fork(unsigned long clone_flags, struct task_struct *p);
+extern int sched_fork(unsigned long clone_flags, struct task_struct *p);
 extern void sched_dead(struct task_struct *p);
 
 extern void proc_caches_init(void);
@@ -2630,6 +2745,21 @@ static inline bool __must_check current_clr_polling_and_test(void)
 }
 #endif
 
+static inline void current_clr_polling(void)
+{
+       __current_clr_polling();
+
+       /*
+        * Ensure we check TIF_NEED_RESCHED after we clear the polling bit.
+        * Once the bit is cleared, we'll get IPIs with every new
+        * TIF_NEED_RESCHED and the IPI handler, scheduler_ipi(), will also
+        * fold.
+        */
+       smp_mb(); /* paired with resched_task() */
+
+       preempt_fold_need_resched();
+}
+
 static __always_inline bool need_resched(void)
 {
        return unlikely(tif_need_resched());
diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h
new file mode 100644 (file)
index 0000000..9d303b8
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _SCHED_DEADLINE_H
+#define _SCHED_DEADLINE_H
+
+/*
+ * SCHED_DEADLINE tasks has negative priorities, reflecting
+ * the fact that any of them has higher prio than RT and
+ * NORMAL/BATCH tasks.
+ */
+
+#define MAX_DL_PRIO            0
+
+static inline int dl_prio(int prio)
+{
+       if (unlikely(prio < MAX_DL_PRIO))
+               return 1;
+       return 0;
+}
+
+static inline int dl_task(struct task_struct *p)
+{
+       return dl_prio(p->prio);
+}
+
+#endif /* _SCHED_DEADLINE_H */
index 440434df36274db0c93678549c11bb644fed1d34..34e4ebea8fce79efa8f1528747db18b7a11f75b4 100644 (file)
@@ -35,6 +35,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 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)
 {
@@ -45,6 +46,10 @@ static inline int rt_mutex_getprio(struct task_struct *p)
 {
        return p->normal_prio;
 }
+static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
+{
+       return NULL;
+}
 # define rt_mutex_adjust_pi(p)         do { } while (0)
 static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
 {
index 41467f8ff8ec8c7c5766021abe00e358f63e93cc..31e0193cb0c5b06c505742c3ec21e41a902ea6ed 100644 (file)
@@ -48,7 +48,6 @@ extern unsigned int sysctl_numa_balancing_scan_delay;
 extern unsigned int sysctl_numa_balancing_scan_period_min;
 extern unsigned int sysctl_numa_balancing_scan_period_max;
 extern unsigned int sysctl_numa_balancing_scan_size;
-extern unsigned int sysctl_numa_balancing_settle_count;
 
 #ifdef CONFIG_SCHED_DEBUG
 extern unsigned int sysctl_sched_migration_cost;
index cf87a24c0f92f1963081c93d7b0cce2356025358..535f158977b9dd4e730a62de2b9e7364a66406fc 100644 (file)
@@ -117,15 +117,15 @@ repeat:
 }
 
 /**
- * read_seqcount_begin_no_lockdep - start seq-read critical section w/o lockdep
+ * raw_read_seqcount_begin - start seq-read critical section w/o lockdep
  * @s: pointer to seqcount_t
  * Returns: count to be passed to read_seqcount_retry
  *
- * read_seqcount_begin_no_lockdep opens a read critical section of the given
+ * raw_read_seqcount_begin opens a read critical section of the given
  * seqcount, but without any lockdep checking. Validity of the critical
  * section is tested by checking read_seqcount_retry function.
  */
-static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
+static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
 {
        unsigned ret = __read_seqcount_begin(s);
        smp_rmb();
@@ -144,7 +144,7 @@ static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
 static inline unsigned read_seqcount_begin(const seqcount_t *s)
 {
        seqcount_lockdep_reader_access(s);
-       return read_seqcount_begin_no_lockdep(s);
+       return raw_read_seqcount_begin(s);
 }
 
 /**
@@ -206,14 +206,26 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
 }
 
 
+
+static inline void raw_write_seqcount_begin(seqcount_t *s)
+{
+       s->sequence++;
+       smp_wmb();
+}
+
+static inline void raw_write_seqcount_end(seqcount_t *s)
+{
+       smp_wmb();
+       s->sequence++;
+}
+
 /*
  * Sequence counter only version assumes that callers are using their
  * own mutexing.
  */
 static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
 {
-       s->sequence++;
-       smp_wmb();
+       raw_write_seqcount_begin(s);
        seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
 }
 
@@ -225,8 +237,7 @@ static inline void write_seqcount_begin(seqcount_t *s)
 static inline void write_seqcount_end(seqcount_t *s)
 {
        seqcount_release(&s->dep_map, 1, _RET_IP_);
-       smp_wmb();
-       s->sequence++;
+       raw_write_seqcount_end(s);
 }
 
 /**
index 30aa0dc60d75786287226bf3cbedffd9f1b266a3..9d55438bc4ad766bf7f02d250c61d10c61c47b6e 100644 (file)
@@ -47,6 +47,8 @@ extern int shmem_init(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
 extern struct file *shmem_file_setup(const char *name,
                                        loff_t size, unsigned long flags);
+extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
+                                           unsigned long flags);
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
 extern void shmem_unlock_mapping(struct address_space *mapping);
index bec1cc7d5e3c41efbc4939ab742eeb955b64b7f0..6f69b3f914fbf94c2d6d42beea62748a29a42d08 100644 (file)
@@ -1638,6 +1638,11 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
        skb->mac_header += offset;
 }
 
+static inline void skb_pop_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->network_header;
+}
+
 static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
 {
@@ -2263,6 +2268,24 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
 
+/**
+ *     pskb_trim_rcsum - trim received skb and update checksum
+ *     @skb: buffer to trim
+ *     @len: new length
+ *
+ *     This is exactly the same as pskb_trim except that it ensures the
+ *     checksum of received packets are still valid after the operation.
+ */
+
+static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
+{
+       if (likely(len >= skb->len))
+               return 0;
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->ip_summed = CHECKSUM_NONE;
+       return __pskb_trim(skb, len);
+}
+
 #define skb_queue_walk(queue, skb) \
                for (skb = (queue)->next;                                       \
                     skb != (struct sk_buff *)(queue);                          \
@@ -2360,27 +2383,6 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
 __wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
                    __wsum csum);
 
-/**
- *     pskb_trim_rcsum - trim received skb and update checksum
- *     @skb: buffer to trim
- *     @len: new length
- *
- *     This is exactly the same as pskb_trim except that it ensures the
- *     checksum of received packets are still valid after the operation.
- */
-
-static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
-{
-       if (likely(len >= skb->len))
-               return 0;
-       if (skb->ip_summed == CHECKSUM_COMPLETE) {
-               __wsum adj = skb_checksum(skb, len, skb->len - len, 0);
-
-               skb->csum = csum_sub(skb->csum, adj);
-       }
-       return __pskb_trim(skb, len);
-}
-
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
                                       int len, void *buffer)
 {
@@ -2529,6 +2531,10 @@ static inline void sw_tx_timestamp(struct sk_buff *skb)
  * Ethernet MAC Drivers should call this function in their hard_xmit()
  * function immediately before giving the sk_buff to the MAC hardware.
  *
+ * Specifically, one should make absolutely sure that this function is
+ * called before TX completion of this packet can trigger.  Otherwise
+ * the packet could potentially already be freed.
+ *
  * @skb: A socket buffer.
  */
 static inline void skb_tx_timestamp(struct sk_buff *skb)
index 75f34949d9ab998adf5941c0321ea45005cc7d62..3f2867ff0ced55086615610aa6807f80af042b08 100644 (file)
@@ -130,6 +130,16 @@ do {                                                               \
 #define smp_mb__before_spinlock()      smp_wmb()
 #endif
 
+/*
+ * Place this after a lock-acquisition primitive to guarantee that
+ * an UNLOCK+LOCK pair act as a full barrier.  This guarantee applies
+ * if the UNLOCK and LOCK are executed by the same CPU or if the
+ * UNLOCK and LOCK operate on the same lock variable.
+ */
+#ifndef smp_mb__after_unlock_lock
+#define smp_mb__after_unlock_lock()    do { } while (0)
+#endif
+
 /**
  * raw_spin_unlock_wait - wait until the spinlock gets unlocked
  * @lock: the spinlock in question.
index bdb9993f0fda648ee2dc58a59ff26372314a02de..42dfab89e740aeb08de1896e491607789eacda4b 100644 (file)
@@ -131,8 +131,7 @@ static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
 
 static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
 {
-       local_bh_disable();
-       preempt_disable();
+       __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
 }
@@ -174,20 +173,17 @@ static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock)
 {
        spin_release(&lock->dep_map, 1, _RET_IP_);
        do_raw_spin_unlock(lock);
-       preempt_enable_no_resched();
-       local_bh_enable_ip((unsigned long)__builtin_return_address(0));
+       __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
 }
 
 static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock)
 {
-       local_bh_disable();
-       preempt_disable();
+       __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
        if (do_raw_spin_trylock(lock)) {
                spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
                return 1;
        }
-       preempt_enable_no_resched();
-       local_bh_enable_ip((unsigned long)__builtin_return_address(0));
+       __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
        return 0;
 }
 
index af1f47229e70292ec2ec63556c4a484f41d4bc18..d0d188861ad69a1b574ea6ce96fb8dfaa6a59c3d 100644 (file)
  * flags straight, to suppress compiler warnings of unused lock
  * variables, and to add the proper checker annotations:
  */
+#define ___LOCK(lock) \
+  do { __acquire(lock); (void)(lock); } while (0)
+
 #define __LOCK(lock) \
-  do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
+  do { preempt_disable(); ___LOCK(lock); } while (0)
 
 #define __LOCK_BH(lock) \
-  do { local_bh_disable(); __LOCK(lock); } while (0)
+  do { __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_LOCK_OFFSET); ___LOCK(lock); } while (0)
 
 #define __LOCK_IRQ(lock) \
   do { local_irq_disable(); __LOCK(lock); } while (0)
 #define __LOCK_IRQSAVE(lock, flags) \
   do { local_irq_save(flags); __LOCK(lock); } while (0)
 
+#define ___UNLOCK(lock) \
+  do { __release(lock); (void)(lock); } while (0)
+
 #define __UNLOCK(lock) \
-  do { preempt_enable(); __release(lock); (void)(lock); } while (0)
+  do { preempt_enable(); ___UNLOCK(lock); } while (0)
 
 #define __UNLOCK_BH(lock) \
-  do { preempt_enable_no_resched(); local_bh_enable(); \
-         __release(lock); (void)(lock); } while (0)
+  do { __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_LOCK_OFFSET); \
+       ___UNLOCK(lock); } while (0)
 
 #define __UNLOCK_IRQ(lock) \
   do { local_irq_enable(); __UNLOCK(lock); } while (0)
index 94273bbe605007462f6e0daacf01715f2a7aca6a..40ed9e9a77e53c77448104a921c0595f2a7927eb 100644 (file)
@@ -38,6 +38,7 @@ struct rlimit;
 struct rlimit64;
 struct rusage;
 struct sched_param;
+struct sched_attr;
 struct sel_arg_struct;
 struct semaphore;
 struct sembuf;
@@ -279,9 +280,14 @@ asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
                                        struct sched_param __user *param);
 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);
 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);
 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,
index 5128d33bbb39cd5aa13a080d765c114dd40ede1b..0175d8663b6cbd9cb259b5715436fbd09e0ce213 100644 (file)
@@ -104,7 +104,7 @@ extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 extern void tick_clock_notify(void);
 extern int tick_check_oneshot_change(int allow_nohz);
 extern struct tick_sched *tick_get_tick_sched(int cpu);
-extern void tick_check_idle(int cpu);
+extern void tick_check_idle(void);
 extern int tick_oneshot_mode_active(void);
 #  ifndef arch_needs_cpu
 #   define arch_needs_cpu(cpu) (0)
@@ -112,7 +112,7 @@ extern int tick_oneshot_mode_active(void);
 # else
 static inline void tick_clock_notify(void) { }
 static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
-static inline void tick_check_idle(int cpu) { }
+static inline void tick_check_idle(void) { }
 static inline int tick_oneshot_mode_active(void) { return 0; }
 # endif
 
@@ -121,7 +121,7 @@ static inline void tick_init(void) { }
 static inline void tick_cancel_sched_timer(int cpu) { }
 static inline void tick_clock_notify(void) { }
 static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
-static inline void tick_check_idle(int cpu) { }
+static inline void tick_check_idle(void) { }
 static inline int tick_oneshot_mode_active(void) { return 0; }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
@@ -165,7 +165,7 @@ extern cpumask_var_t tick_nohz_full_mask;
 
 static inline bool tick_nohz_full_enabled(void)
 {
-       if (!static_key_false(&context_tracking_enabled))
+       if (!context_tracking_is_enabled())
                return false;
 
        return tick_nohz_full_running;
index ebeab360d851c1ece4952b3f5f4f294aa9673db0..f16dc0a4004976376c9036a244e1121ed52ed020 100644 (file)
@@ -267,6 +267,8 @@ static inline void tracepoint_synchronize_unregister(void)
 
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #endif /* DECLARE_TRACE */
 
 #ifndef TRACE_EVENT
@@ -399,4 +401,6 @@ static inline void tracepoint_synchronize_unregister(void)
 
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #endif /* ifdef TRACE_EVENT (see note above) */
index 9d8cf056e661fab2c7389a78f0c5ac1248bcfe62..ecd3319dac33140a21a7c8fd89a2c95c18ce9e42 100644 (file)
@@ -25,13 +25,16 @@ static inline void pagefault_disable(void)
 
 static inline void pagefault_enable(void)
 {
+#ifndef CONFIG_PREEMPT
        /*
         * make sure to issue those last loads/stores before enabling
         * the pagefault handler again.
         */
        barrier();
        preempt_count_dec();
-       preempt_check_resched();
+#else
+       preempt_enable();
+#endif
 }
 
 #ifndef ARCH_HAS_NOCACHE_UACCESS
index 319eae70fe8415f774e57c4861b98688fb81bb4c..e32251e00e62f0b2629c0ef7658d1445e6647586 100644 (file)
 
 #include <linux/errno.h>
 #include <linux/rbtree.h>
+#include <linux/types.h>
 
 struct vm_area_struct;
 struct mm_struct;
 struct inode;
 struct notifier_block;
 
-#ifdef CONFIG_ARCH_SUPPORTS_UPROBES
-# include <asm/uprobes.h>
-#endif
-
 #define UPROBE_HANDLER_REMOVE          1
 #define UPROBE_HANDLER_MASK            1
 
@@ -60,6 +57,8 @@ struct uprobe_consumer {
 };
 
 #ifdef CONFIG_UPROBES
+#include <asm/uprobes.h>
+
 enum uprobe_task_state {
        UTASK_RUNNING,
        UTASK_SSTEP,
@@ -72,35 +71,28 @@ enum uprobe_task_state {
  */
 struct uprobe_task {
        enum uprobe_task_state          state;
-       struct arch_uprobe_task         autask;
 
-       struct return_instance          *return_instances;
-       unsigned int                    depth;
-       struct uprobe                   *active_uprobe;
+       union {
+               struct {
+                       struct arch_uprobe_task autask;
+                       unsigned long           vaddr;
+               };
 
+               struct {
+                       struct callback_head    dup_xol_work;
+                       unsigned long           dup_xol_addr;
+               };
+       };
+
+       struct uprobe                   *active_uprobe;
        unsigned long                   xol_vaddr;
-       unsigned long                   vaddr;
-};
 
-/*
- * On a breakpoint hit, thread contests for a slot.  It frees the
- * slot after singlestep. Currently a fixed number of slots are
- * allocated.
- */
-struct xol_area {
-       wait_queue_head_t       wq;             /* if all slots are busy */
-       atomic_t                slot_count;     /* number of in-use slots */
-       unsigned long           *bitmap;        /* 0 = free slot */
-       struct page             *page;
-
-       /*
-        * We keep the vma's vm_start rather than a pointer to the vma
-        * itself.  The probed process or a naughty kernel module could make
-        * the vma go away, and we must handle that reasonably gracefully.
-        */
-       unsigned long           vaddr;          /* Page(s) of instruction slots */
+       struct return_instance          *return_instances;
+       unsigned int                    depth;
 };
 
+struct xol_area;
+
 struct uprobes_state {
        struct xol_area         *xol_area;
 };
@@ -109,6 +101,7 @@ extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsign
 extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
 extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
 extern bool __weak is_trap_insn(uprobe_opcode_t *insn);
+extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
 extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
 extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
@@ -120,7 +113,6 @@ extern void uprobe_end_dup_mmap(void);
 extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);
 extern void uprobe_free_utask(struct task_struct *t);
 extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
-extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
 extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
 extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
 extern void uprobe_notify_resume(struct pt_regs *regs);
@@ -176,10 +168,6 @@ static inline bool uprobe_deny_signal(void)
 {
        return false;
 }
-static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
-{
-       return 0;
-}
 static inline void uprobe_free_utask(struct task_struct *t)
 {
 }
index 7454865ad14834f50a05dc9baf7f6d78ea3de7b8..512ab162832ccc0bb4b30f6210d083d762573b78 100644 (file)
@@ -1264,6 +1264,8 @@ 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 0c4d4ca370ec9ba2e88c90b5d9a34b1efc9bc557..eeb28329fa3c9a17087834e2bb2f4d054757a005 100644 (file)
@@ -271,6 +271,8 @@ static inline u8 wusb_key_index(int index, int type, int originator)
 #define WUSB_KEY_INDEX_TYPE_GTK                        2
 #define WUSB_KEY_INDEX_ORIGINATOR_HOST         0
 #define WUSB_KEY_INDEX_ORIGINATOR_DEVICE       1
+/* bits 0-3 used for the key index. */
+#define WUSB_KEY_INDEX_MAX                     15
 
 /* A CCM Nonce, defined in WUSB1.0[6.4.1] */
 struct aes_ccm_nonce {
index f5b72b364bda4c6437903d4669b65b5aad0e017a..c5165fd256f9d25162d648e53e1e73d95a740caf 100644 (file)
@@ -19,8 +19,8 @@ static inline bool vtime_accounting_enabled(void) { return true; }
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
 static inline bool vtime_accounting_enabled(void)
 {
-       if (static_key_false(&context_tracking_enabled)) {
-               if (context_tracking_active())
+       if (context_tracking_is_enabled()) {
+               if (context_tracking_cpu_is_enabled())
                        return true;
        }
 
index dff42025649b32cb03f84d359c0c213ec5617569..63fbba0740c2c2bfb35b4a29f6c146b0137f695d 100644 (file)
 #ifndef _LINUX_ZORRO_H
 #define _LINUX_ZORRO_H
 
-#include <linux/device.h>
-
-
-    /*
-     *  Each Zorro board has a 32-bit ID of the form
-     *
-     *      mmmmmmmmmmmmmmmmppppppppeeeeeeee
-     *
-     *  with
-     *
-     *      mmmmmmmmmmmmmmmm   16-bit Manufacturer ID (assigned by CBM (sigh))
-     *      pppppppp           8-bit Product ID (assigned by manufacturer)
-     *      eeeeeeee           8-bit Extended Product ID (currently only used
-     *                         for some GVP boards)
-     */
-
-
-#define ZORRO_MANUF(id)                ((id) >> 16)
-#define ZORRO_PROD(id)         (((id) >> 8) & 0xff)
-#define ZORRO_EPC(id)          ((id) & 0xff)
-
-#define ZORRO_ID(manuf, prod, epc) \
-    ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc))
-
-typedef __u32 zorro_id;
-
-
-/* Include the ID list */
-#include <linux/zorro_ids.h>
-
 
-    /*
-     *  GVP identifies most of its products through the 'extended product code'
-     *  (epc). The epc has to be ANDed with the GVP_PRODMASK before the
-     *  identification.
-     */
-
-#define GVP_PRODMASK                   (0xf8)
-#define GVP_SCSICLKMASK                        (0x01)
-
-enum GVP_flags {
-    GVP_IO             = 0x01,
-    GVP_ACCEL          = 0x02,
-    GVP_SCSI           = 0x04,
-    GVP_24BITDMA       = 0x08,
-    GVP_25BITDMA       = 0x10,
-    GVP_NOBANK         = 0x20,
-    GVP_14MHZ          = 0x40,
-};
-
-
-struct Node {
-    struct  Node *ln_Succ;     /* Pointer to next (successor) */
-    struct  Node *ln_Pred;     /* Pointer to previous (predecessor) */
-    __u8    ln_Type;
-    __s8    ln_Pri;            /* Priority, for sorting */
-    __s8    *ln_Name;          /* ID string, null terminated */
-} __attribute__ ((packed));
-
-struct ExpansionRom {
-    /* -First 16 bytes of the expansion ROM */
-    __u8  er_Type;             /* Board type, size and flags */
-    __u8  er_Product;          /* Product number, assigned by manufacturer */
-    __u8  er_Flags;            /* Flags */
-    __u8  er_Reserved03;       /* Must be zero ($ff inverted) */
-    __u16 er_Manufacturer;     /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */
-    __u32 er_SerialNumber;     /* Available for use by manufacturer */
-    __u16 er_InitDiagVec;      /* Offset to optional "DiagArea" structure */
-    __u8  er_Reserved0c;
-    __u8  er_Reserved0d;
-    __u8  er_Reserved0e;
-    __u8  er_Reserved0f;
-} __attribute__ ((packed));
-
-/* er_Type board type bits */
-#define ERT_TYPEMASK   0xc0
-#define ERT_ZORROII    0xc0
-#define ERT_ZORROIII   0x80
-
-/* other bits defined in er_Type */
-#define ERTB_MEMLIST   5               /* Link RAM into free memory list */
-#define ERTF_MEMLIST   (1<<5)
-
-struct ConfigDev {
-    struct Node                cd_Node;
-    __u8               cd_Flags;       /* (read/write) */
-    __u8               cd_Pad;         /* reserved */
-    struct ExpansionRom cd_Rom;                /* copy of board's expansion ROM */
-    void               *cd_BoardAddr;  /* where in memory the board was placed */
-    __u32              cd_BoardSize;   /* size of board in bytes */
-    __u16              cd_SlotAddr;    /* which slot number (PRIVATE) */
-    __u16              cd_SlotSize;    /* number of slots (PRIVATE) */
-    void               *cd_Driver;     /* pointer to node of driver */
-    struct ConfigDev   *cd_NextCD;     /* linked list of drivers to config */
-    __u32              cd_Unused[4];   /* for whatever the driver wants */
-} __attribute__ ((packed));
-
-#define ZORRO_NUM_AUTO         16
-
-#ifdef __KERNEL__
+#include <uapi/linux/zorro.h>
 
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/mod_devicetable.h>
@@ -175,7 +78,23 @@ static inline struct zorro_driver *zorro_dev_driver(const struct zorro_dev *z)
 
 
 extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */
-extern struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
+extern struct zorro_dev *zorro_autocon;
+
+
+    /*
+     * Minimal information about a Zorro device, passed from bootinfo
+     * Only available temporarily, i.e. until initmem has been freed!
+     */
+
+struct zorro_dev_init {
+       struct ExpansionRom rom;
+       u16 slotaddr;
+       u16 slotsize;
+       u32 boardaddr;
+       u32 boardsize;
+};
+
+extern struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata;
 
 
     /*
@@ -229,6 +148,4 @@ extern DECLARE_BITMAP(zorro_unused_z2ram, 128);
 #define Z2RAM_CHUNKSHIFT       (16)
 
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_ZORRO_H */
index bd8218b15009a810af8abd5df5a4bcad31dfdb20..941055e9d125af3bfe5a6915ff551e0bb1532445 100644 (file)
@@ -83,7 +83,7 @@ struct vb2_fileio_data;
 struct vb2_mem_ops {
        void            *(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
        void            (*put)(void *buf_priv);
-       struct dma_buf *(*get_dmabuf)(void *buf_priv);
+       struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 
        void            *(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
                                        unsigned long size, int write);
index 829627d7b8460e1739da979a3937056dde92a48e..1d67fb6b23a04a88a8bcd85422f5f97df9024a05 100644 (file)
@@ -42,27 +42,10 @@ static inline bool net_busy_loop_on(void)
        return sysctl_net_busy_poll;
 }
 
-/* a wrapper to make debug_smp_processor_id() happy
- * we can use sched_clock() because we don't care much about precision
- * we only care that the average is bounded
- */
-#ifdef CONFIG_DEBUG_PREEMPT
-static inline u64 busy_loop_us_clock(void)
-{
-       u64 rc;
-
-       preempt_disable_notrace();
-       rc = sched_clock();
-       preempt_enable_no_resched_notrace();
-
-       return rc >> 10;
-}
-#else /* CONFIG_DEBUG_PREEMPT */
 static inline u64 busy_loop_us_clock(void)
 {
-       return sched_clock() >> 10;
+       return local_clock() >> 10;
 }
-#endif /* CONFIG_DEBUG_PREEMPT */
 
 static inline unsigned long sk_busy_loop_end_time(struct sock *sk)
 {
index 76d54270f2e27c175836b137f363014381e91687..65bb13035598fe141afd52a101f99ed1c9fd6838 100644 (file)
@@ -165,7 +165,6 @@ struct inet6_dev {
        struct net_device       *dev;
 
        struct list_head        addr_list;
-       int                     valid_ll_addr_cnt;
 
        struct ifmcaddr6        *mc_list;
        struct ifmcaddr6        *mc_tomb;
index 217bc5bfc6c6e99cf52117312ceda95c98f005a6..5a25f36fe3a7cb50a388e309df9b5905f013b6b4 100644 (file)
@@ -473,7 +473,7 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
 int ip_ra_control(struct sock *sk, unsigned char on,
                  void (*destructor)(struct sock *));
 
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
 void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
                   u32 info, u8 *payload);
 void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
index 2a5f668cd6836fae6ff45e551f8dacfd93dacd8e..488316e339a124fa55fdeac686a4fc6d28c0dd2c 100644 (file)
@@ -110,7 +110,8 @@ struct frag_hdr {
        __be32  identification;
 };
 
-#define        IP6_MF  0x0001
+#define        IP6_MF          0x0001
+#define        IP6_OFFSET      0xFFF8
 
 #include <net/sock.h>
 
@@ -776,8 +777,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
 
 int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
 
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                   int *addr_len);
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+                    int *addr_len);
 void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
                     u32 info, u8 *payload);
 void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
index 31e2de7d57c5d6c210e1b445b19551407fd31b6c..c0f0a13ed8183e58029aec1d12097aa1efb085f0 100644 (file)
 #define LLC_S_PF_IS_1(pdu)     ((pdu->ctrl_2 & LLC_S_PF_BIT_MASK) ? 1 : 0)
 
 #define PDU_SUPV_GET_Nr(pdu)   ((pdu->ctrl_2 & 0xFE) >> 1)
-#define PDU_GET_NEXT_Vr(sn)    (++sn & ~LLC_2_SEQ_NBR_MODULO)
+#define PDU_GET_NEXT_Vr(sn)    (((sn) + 1) & ~LLC_2_SEQ_NBR_MODULO)
 
 /* FRMR information field macros */
 
index 3f67704f3747281b3ad0852fd5d69dcd49c9b01c..90f48417b03dac91259aefe18d79c63145a23849 100644 (file)
@@ -31,7 +31,8 @@
 
 /* Compatibility glue so we can support IPv6 when it's compiled as a module */
 struct pingv6_ops {
-       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
+       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len,
+                              int *addr_len);
        int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
                                     struct sk_buff *skb);
        int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
index 2174d8da0770a5285d3d937a1174eb9e52dd2a27..0a248b323d875c08ca456d62ed46c028781e9432 100644 (file)
@@ -629,6 +629,7 @@ struct sctp_chunk {
 #define SCTP_NEED_FRTX 0x1
 #define SCTP_DONT_FRTX 0x2
        __u16   rtt_in_progress:1,      /* This chunk used for RTT calc? */
+               resent:1,               /* Has this chunk ever been resent. */
                has_tsn:1,              /* Does this chunk have a TSN yet? */
                has_ssn:1,              /* Does this chunk have a SSN yet? */
                singleton:1,            /* Only chunk in the packet? */
@@ -1045,9 +1046,6 @@ struct sctp_outq {
 
        /* Corked? */
        char cork;
-
-       /* Is this structure empty?  */
-       char empty;
 };
 
 void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
@@ -1725,12 +1723,6 @@ struct sctp_association {
        /* How many duplicated TSNs have we seen?  */
        int numduptsns;
 
-       /* Number of seconds of idle time before an association is closed.
-        * In the association context, this is really used as a boolean
-        * since the real timeout is stored in the timeouts array
-        */
-       __u32 autoclose;
-
        /* These are to support
         * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses
         *  and Enforcement of Flow and Message Limits"
index e3a18ff0c38b58aec20413489bf7237c54a14a77..2ef3c3eca47aacaa28ee25aecd236897d276845a 100644 (file)
@@ -1035,7 +1035,6 @@ enum cg_proto_flags {
 };
 
 struct cg_proto {
-       void                    (*enter_memory_pressure)(struct sock *sk);
        struct res_counter      memory_allocated;       /* Current allocated memory. */
        struct percpu_counter   sockets_allocated;      /* Current number of sockets. */
        int                     memory_pressure;
@@ -1155,8 +1154,7 @@ static inline void sk_leave_memory_pressure(struct sock *sk)
                struct proto *prot = sk->sk_prot;
 
                for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
-                       if (cg_proto->memory_pressure)
-                               cg_proto->memory_pressure = 0;
+                       cg_proto->memory_pressure = 0;
        }
 
 }
@@ -1171,7 +1169,7 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
                struct proto *prot = sk->sk_prot;
 
                for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
-                       cg_proto->enter_memory_pressure(sk);
+                       cg_proto->memory_pressure = 1;
        }
 
        sk->sk_prot->enter_memory_pressure(sk);
index 979874c627ee7f450c7aabff5c948cb2c87f84c3..61e1935c91b121d0ba6a9e5d6f05221d15060432 100644 (file)
@@ -978,7 +978,7 @@ struct ib_uobject {
 };
 
 struct ib_udata {
-       void __user *inbuf;
+       const void __user *inbuf;
        void __user *outbuf;
        size_t       inlen;
        size_t       outlen;
index 546084964d554fc8e463e9244558fce4e4eb8563..fe3b58e836c881b7598d37c46d56cbd6d1b81b6e 100644 (file)
@@ -475,6 +475,9 @@ struct scsi_host_template {
         */
        unsigned ordered_tag:1;
 
+       /* True if the controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Countdown for host blocking with no commands outstanding.
         */
@@ -677,6 +680,9 @@ struct Scsi_Host {
        /* Don't resume host in EH */
        unsigned eh_noresume:1;
 
+       /* The controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Optional work queue to be utilized by the transport
         */
index af998397041768a82ee347665e7040a9a4e44b9c..5f73785f5977e5f3c1b1a443c8f4a8f194b5f2b2 100644 (file)
@@ -108,7 +108,7 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
 {
        struct snd_sg_buf *sgbuf = dmab->private_data;
        dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
-       addr &= PAGE_MASK;
+       addr &= ~((dma_addr_t)PAGE_SIZE - 1);
        return addr + offset % PAGE_SIZE;
 }
 
index 2037c45adfe648e907fa86290f7dfea847989c20..56ebdfca627375b1a7ec7d5ce5606bc124ecdf42 100644 (file)
@@ -104,7 +104,8 @@ struct device;
        SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{      .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
+{      .id = snd_soc_dapm_mux, .name = wname, \
+       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
 {      .id = snd_soc_dapm_virt_mux, .name = wname, \
index 45412a6afa69d95ea82c820fb197d350c9d0575e..321301c0a643bfb32303b3f48cecae720f3fad87 100644 (file)
@@ -517,10 +517,6 @@ struct se_node_acl {
        u32                     acl_index;
 #define MAX_ACL_TAG_SIZE 64
        char                    acl_tag[MAX_ACL_TAG_SIZE];
-       u64                     num_cmds;
-       u64                     read_bytes;
-       u64                     write_bytes;
-       spinlock_t              stats_lock;
        /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
        atomic_t                acl_pr_ref_count;
        struct se_dev_entry     **device_list;
@@ -624,6 +620,7 @@ struct se_dev_attrib {
        u32             unmap_granularity;
        u32             unmap_granularity_alignment;
        u32             max_write_same_len;
+       u32             max_bytes_per_io;
        struct se_device *da_dev;
        struct config_group da_group;
 };
index 88b878383797d1c67607dfbe670de26e50be6168..1c875ad1ee5fe1c16e3c90af1fcb36c7802eed39 100644 (file)
@@ -5,7 +5,7 @@
 #define _TRACE_AER_H
 
 #include <linux/tracepoint.h>
-#include <linux/edac.h>
+#include <linux/aer.h>
 
 
 /*
@@ -63,10 +63,10 @@ TRACE_EVENT(aer_event,
 
        TP_printk("%s PCIe Bus Error: severity=%s, %s\n",
                __get_str(dev_name),
-               __entry->severity == HW_EVENT_ERR_CORRECTED ? "Corrected" :
-                       __entry->severity == HW_EVENT_ERR_FATAL ?
-                       "Fatal" : "Uncorrected",
-               __entry->severity == HW_EVENT_ERR_CORRECTED ?
+               __entry->severity == AER_CORRECTABLE ? "Corrected" :
+                       __entry->severity == AER_FATAL ?
+                       "Fatal" : "Uncorrected, non-fatal",
+               __entry->severity == AER_CORRECTABLE ?
                __print_flags(__entry->status, "|", aer_correctable_errors) :
                __print_flags(__entry->status, "|", aer_uncorrectable_errors))
 );
index d17a35c6537e615a384e2cd006f37b4a2828a55a..5c38606613d89a06c361a56054e97031c391c2d3 100644 (file)
 #define TRACE_EVENT_FLAGS(name, value)                                 \
        __TRACE_EVENT_FLAGS(name, value)
 
+#undef TRACE_EVENT_PERF_PERM
+#define TRACE_EVENT_PERF_PERM(name, expr...)                           \
+       __TRACE_EVENT_PERF_PERM(name, expr)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 
 #undef TRACE_EVENT_FLAGS
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#undef TRACE_EVENT_PERF_PERM
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 /*
index 2f3f7ea8c77b8a653b0972302ead53319f13e5fc..fe421e8a431bcf91dd1d5e845b5d06ce81bbe23d 100644 (file)
@@ -983,6 +983,8 @@ struct drm_radeon_cs {
 #define RADEON_INFO_SI_CP_DMA_COMPUTE  0x17
 /* CIK macrotile mode array */
 #define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY   0x18
+/* query the number of render backends */
+#define RADEON_INFO_SI_BACKEND_ENABLED_MASK    0x19
 
 
 struct drm_radeon_info {
index bcb0912afe7a4a233a171f2d1b4bb7d518c6884e..f854ca4a1372812dda6f71c20c8a84b3bdcfc19a 100644 (file)
@@ -75,6 +75,7 @@
 #define DRM_VMW_PARAM_FIFO_CAPS        4
 #define DRM_VMW_PARAM_MAX_FB_SIZE      5
 #define DRM_VMW_PARAM_FIFO_HW_VERSION  6
+#define DRM_VMW_PARAM_MAX_SURF_MEMORY  7
 
 /**
  * struct drm_vmw_getparam_arg
index 33d2b8fe166dafcd8dd39c5b7a092b8b3d5befa6..3ce25b5d75a9facfd047a526d3c3af618169e488 100644 (file)
@@ -426,3 +426,5 @@ header-y += x25.h
 header-y += xattr.h
 header-y += xfrm.h
 header-y += hw_breakpoint.h
+header-y += zorro.h
+header-y += zorro_ids.h
index 2c267bcbb85c1c4e31b676127db7686d8d027e09..bc81fb2e1f0e19d363d3c8095c85b971c521d12a 100644 (file)
@@ -61,5 +61,16 @@ struct epoll_event {
        __u64 data;
 } EPOLL_PACKED;
 
-
+#ifdef CONFIG_PM_SLEEP
+static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
+{
+       if ((epev->events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
+               epev->events &= ~EPOLLWAKEUP;
+}
+#else
+static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
+{
+       epev->events &= ~EPOLLWAKEUP;
+}
+#endif
 #endif /* _UAPI_LINUX_EVENTPOLL_H */
index 1af72d8228e04db8c1d6de05cacfa1bfd4a577b7..c3363ba1ae057f66dc5b878ee9fde7899857c450 100644 (file)
@@ -28,6 +28,7 @@ struct genlmsghdr {
 #define GENL_ID_GENERATE       0
 #define GENL_ID_CTRL           NLMSG_MIN_TYPE
 #define GENL_ID_VFS_DQUOT      (NLMSG_MIN_TYPE + 1)
+#define GENL_ID_PMCRAID                (NLMSG_MIN_TYPE + 2)
 
 /**************************************************************************
  * Controller
index b78566f59abaa54528ed86acf85eb7e7b3f305fa..6db460121f84845d4026420cdc2fd12fc4f1497e 100644 (file)
@@ -488,7 +488,9 @@ enum {
        IFLA_HSR_UNSPEC,
        IFLA_HSR_SLAVE1,
        IFLA_HSR_SLAVE2,
-       IFLA_HSR_MULTICAST_SPEC,
+       IFLA_HSR_MULTICAST_SPEC,        /* Last byte of supervision addr */
+       IFLA_HSR_SUPERVISION_ADDR,      /* Supervision frame multicast addr */
+       IFLA_HSR_SEQ_NR,
        __IFLA_HSR_MAX,
 };
 
index a3726275876dc509bfa99a01b8113385c1fb2d2f..bd24470d24a2c7a3145af21094e03f67b7ce0761 100644 (file)
@@ -464,7 +464,8 @@ struct input_keymap_entry {
 #define KEY_BRIGHTNESS_ZERO    244     /* brightness off, use ambient */
 #define KEY_DISPLAY_OFF                245     /* display device to off state */
 
-#define KEY_WIMAX              246
+#define KEY_WWAN               246     /* Wireless WAN (LTE, UMTS, GSM, etc.) */
+#define KEY_WIMAX              KEY_WWAN
 #define KEY_RFKILL             247     /* Key that controls all radios */
 
 #define KEY_MICMUTE            248     /* Mute / unmute the microphone */
@@ -719,6 +720,8 @@ struct input_keymap_entry {
 #define BTN_DPAD_LEFT          0x222
 #define BTN_DPAD_RIGHT         0x223
 
+#define KEY_ALS_TOGGLE         0x230   /* Ambient light sensor */
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
@@ -856,6 +859,7 @@ struct input_keymap_entry {
 #define SW_FRONT_PROXIMITY     0x0b  /* set = front proximity sensor active */
 #define SW_ROTATE_LOCK         0x0c  /* set = rotate locked/disabled */
 #define SW_LINEIN_INSERT       0x0d  /* set = inserted */
+#define SW_MUTE_DEVICE         0x0e  /* set = device disabled */
 #define SW_MAX                 0x0f
 #define SW_CNT                 (SW_MAX+1)
 
index 104838f65bc184cf46531e3335492668a822789e..d6629d49a2433745d205cb3685dadeaffaeab61a 100644 (file)
@@ -18,6 +18,7 @@
  */
 #define KEXEC_ARCH_DEFAULT ( 0 << 16)
 #define KEXEC_ARCH_386     ( 3 << 16)
+#define KEXEC_ARCH_68K     ( 4 << 16)
 #define KEXEC_ARCH_X86_64  (62 << 16)
 #define KEXEC_ARCH_PPC     (20 << 16)
 #define KEXEC_ARCH_PPC64   (21 << 16)
index 17e7d95e4f536b883cf98ebe363ed3734e9db958..6eb40244e0194110ce6c7e3878f738227ddfb013 100644 (file)
 
 #include <linux/virtio_ring.h>
 
-#ifndef __KERNEL__
-#define ALIGN(a, x)    (((a) + (x) - 1) & ~((x) - 1))
-#define __aligned(x)   __attribute__ ((aligned(x)))
-#endif
-
-#define mic_aligned_size(x) ALIGN(sizeof(x), 8)
+#define __mic_align(a, x) (((a) + (x) - 1) & ~((x) - 1))
 
 /**
  * struct mic_device_desc: Virtio device information shared between the
@@ -48,8 +43,8 @@ struct mic_device_desc {
        __u8 feature_len;
        __u8 config_len;
        __u8 status;
-       __u64 config[0];
-} __aligned(8);
+       __le64 config[0];
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_device_ctrl: Per virtio device information in the device page
@@ -66,7 +61,7 @@ struct mic_device_desc {
  * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
  */
 struct mic_device_ctrl {
-       __u64 vdev;
+       __le64 vdev;
        __u8 config_change;
        __u8 vdev_reset;
        __u8 guest_ack;
@@ -74,7 +69,7 @@ struct mic_device_ctrl {
        __u8 used_address_updated;
        __s8 c2h_vdev_db;
        __s8 h2c_vdev_db;
-} __aligned(8);
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_bootparam: Virtio device independent information in device page
@@ -87,13 +82,13 @@ struct mic_device_ctrl {
  * @shutdown_card: Set to 1 by the host when a card shutdown is initiated
  */
 struct mic_bootparam {
-       __u32 magic;
+       __le32 magic;
        __s8 c2h_shutdown_db;
        __s8 h2c_shutdown_db;
        __s8 h2c_config_db;
        __u8 shutdown_status;
        __u8 shutdown_card;
-} __aligned(8);
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_device_page: High level representation of the device page
@@ -116,10 +111,10 @@ struct mic_device_page {
  * @num: The number of entries in the virtio_ring
  */
 struct mic_vqconfig {
-       __u64 address;
-       __u64 used_address;
-       __u16 num;
-} __aligned(8);
+       __le64 address;
+       __le64 used_address;
+       __le16 num;
+} __attribute__ ((aligned(8)));
 
 /*
  * The alignment to use between consumer and producer parts of vring.
@@ -154,7 +149,7 @@ struct mic_vqconfig {
  */
 struct _mic_vring_info {
        __u16 avail_idx;
-       int magic;
+       __le32 magic;
 };
 
 /**
@@ -173,15 +168,13 @@ struct mic_vring {
        int len;
 };
 
-#define mic_aligned_desc_size(d) ALIGN(mic_desc_size(d), 8)
+#define mic_aligned_desc_size(d) __mic_align(mic_desc_size(d), 8)
 
 #ifndef INTEL_MIC_CARD
 static inline unsigned mic_desc_size(const struct mic_device_desc *desc)
 {
-       return mic_aligned_size(*desc)
-               + desc->num_vq * mic_aligned_size(struct mic_vqconfig)
-               + desc->feature_len * 2
-               + desc->config_len;
+       return sizeof(*desc) + desc->num_vq * sizeof(struct mic_vqconfig)
+               + desc->feature_len * 2 + desc->config_len;
 }
 
 static inline struct mic_vqconfig *
@@ -201,8 +194,7 @@ static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
 }
 static inline unsigned mic_total_desc_size(struct mic_device_desc *desc)
 {
-       return mic_aligned_desc_size(desc) +
-               mic_aligned_size(struct mic_device_ctrl);
+       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
 }
 #endif
 
index 4e31db4eea412dcfc3c56364d734b420f36afaef..f2159d30d1f5a24c76d6e939318603e72faa2637 100644 (file)
@@ -33,6 +33,7 @@ struct netlink_diag_ring {
 };
 
 enum {
+       /* NETLINK_DIAG_NONE, standard nl API requires this attribute!  */
        NETLINK_DIAG_MEMINFO,
        NETLINK_DIAG_GROUPS,
        NETLINK_DIAG_RX_RING,
index b2cc0cd9c4d9782433b4203e24480267257071ce..d08c63f3dd6ff47c7cf090927e91f27cfc0d767f 100644 (file)
@@ -29,6 +29,7 @@ struct packet_diag_msg {
 };
 
 enum {
+       /* PACKET_DIAG_NONE, standard nl API requires this attribute!  */
        PACKET_DIAG_INFO,
        PACKET_DIAG_MCLIST,
        PACKET_DIAG_RX_RING,
index e1802d6153aec4d0c5fd81300dcde057d9bf8a59..e244ed412745e544cf480c549d2439c6522cfb98 100644 (file)
@@ -679,6 +679,7 @@ enum perf_event_type {
         *
         *      { u64                   weight;   } && PERF_SAMPLE_WEIGHT
         *      { u64                   data_src; } && PERF_SAMPLE_DATA_SRC
+        *      { u64                   transaction; } && PERF_SAMPLE_TRANSACTION
         * };
         */
        PERF_RECORD_SAMPLE                      = 9,
@@ -724,6 +725,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_FD_NO_GROUP          (1U << 0)
 #define PERF_FLAG_FD_OUTPUT            (1U << 1)
 #define PERF_FLAG_PID_CGROUP           (1U << 2) /* pid=cgroup id, per-cpu mode only */
+#define PERF_FLAG_FD_CLOEXEC           (1U << 3) /* O_CLOEXEC */
 
 union perf_mem_data_src {
        __u64 val;
index 5a0f945927ace214da646d94920f485a256b7334..34f9d7387d134a12923669e3516ad2892a41f84d 100644 (file)
 #define SCHED_BATCH            3
 /* SCHED_ISO: reserved but not implemented yet */
 #define SCHED_IDLE             5
+#define SCHED_DEADLINE         6
+
 /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
 #define SCHED_RESET_ON_FORK     0x40000000
 
+/*
+ * For the sched_{set,get}attr() calls
+ */
+#define SCHED_FLAG_RESET_ON_FORK       0x01
 
 #endif /* _UAPI_LINUX_SCHED_H */
index b9e2a6a7446f077e528dd15fac8e8d97f0d9a232..1eb0b8dd18308481313b9d13b284f897a56188aa 100644 (file)
@@ -31,6 +31,7 @@ struct unix_diag_msg {
 };
 
 enum {
+       /* UNIX_DIAG_NONE, standard nl API requires this attribute!  */
        UNIX_DIAG_NAME,
        UNIX_DIAG_VFS,
        UNIX_DIAG_PEER,
diff --git a/include/uapi/linux/zorro.h b/include/uapi/linux/zorro.h
new file mode 100644 (file)
index 0000000..59d021b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  linux/zorro.h -- Amiga AutoConfig (Zorro) Bus Definitions
+ *
+ *  Copyright (C) 1995--2003 Geert Uytterhoeven
+ *
+ *  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.
+ */
+
+#ifndef _UAPI_LINUX_ZORRO_H
+#define _UAPI_LINUX_ZORRO_H
+
+#include <linux/types.h>
+
+
+    /*
+     *  Each Zorro board has a 32-bit ID of the form
+     *
+     *      mmmmmmmmmmmmmmmmppppppppeeeeeeee
+     *
+     *  with
+     *
+     *      mmmmmmmmmmmmmmmm   16-bit Manufacturer ID (assigned by CBM (sigh))
+     *      pppppppp           8-bit Product ID (assigned by manufacturer)
+     *      eeeeeeee           8-bit Extended Product ID (currently only used
+     *                         for some GVP boards)
+     */
+
+
+#define ZORRO_MANUF(id)                ((id) >> 16)
+#define ZORRO_PROD(id)         (((id) >> 8) & 0xff)
+#define ZORRO_EPC(id)          ((id) & 0xff)
+
+#define ZORRO_ID(manuf, prod, epc) \
+       ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc))
+
+typedef __u32 zorro_id;
+
+
+/* Include the ID list */
+#include <linux/zorro_ids.h>
+
+
+    /*
+     *  GVP identifies most of its products through the 'extended product code'
+     *  (epc). The epc has to be ANDed with the GVP_PRODMASK before the
+     *  identification.
+     */
+
+#define GVP_PRODMASK           (0xf8)
+#define GVP_SCSICLKMASK                (0x01)
+
+enum GVP_flags {
+       GVP_IO                  = 0x01,
+       GVP_ACCEL               = 0x02,
+       GVP_SCSI                = 0x04,
+       GVP_24BITDMA            = 0x08,
+       GVP_25BITDMA            = 0x10,
+       GVP_NOBANK              = 0x20,
+       GVP_14MHZ               = 0x40,
+};
+
+
+struct Node {
+       __be32 ln_Succ;         /* Pointer to next (successor) */
+       __be32 ln_Pred;         /* Pointer to previous (predecessor) */
+       __u8   ln_Type;
+       __s8   ln_Pri;          /* Priority, for sorting */
+       __be32 ln_Name;         /* ID string, null terminated */
+} __packed;
+
+struct ExpansionRom {
+       /* -First 16 bytes of the expansion ROM */
+       __u8   er_Type;         /* Board type, size and flags */
+       __u8   er_Product;      /* Product number, assigned by manufacturer */
+       __u8   er_Flags;                /* Flags */
+       __u8   er_Reserved03;   /* Must be zero ($ff inverted) */
+       __be16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */
+       __be32 er_SerialNumber; /* Available for use by manufacturer */
+       __be16 er_InitDiagVec;  /* Offset to optional "DiagArea" structure */
+       __u8   er_Reserved0c;
+       __u8   er_Reserved0d;
+       __u8   er_Reserved0e;
+       __u8   er_Reserved0f;
+} __packed;
+
+/* er_Type board type bits */
+#define ERT_TYPEMASK   0xc0
+#define ERT_ZORROII    0xc0
+#define ERT_ZORROIII   0x80
+
+/* other bits defined in er_Type */
+#define ERTB_MEMLIST   5               /* Link RAM into free memory list */
+#define ERTF_MEMLIST   (1<<5)
+
+struct ConfigDev {
+       struct Node     cd_Node;
+       __u8            cd_Flags;       /* (read/write) */
+       __u8            cd_Pad;         /* reserved */
+       struct ExpansionRom cd_Rom;     /* copy of board's expansion ROM */
+       __be32          cd_BoardAddr;   /* where in memory the board was placed */
+       __be32          cd_BoardSize;   /* size of board in bytes */
+       __be16          cd_SlotAddr;    /* which slot number (PRIVATE) */
+       __be16          cd_SlotSize;    /* number of slots (PRIVATE) */
+       __be32          cd_Driver;      /* pointer to node of driver */
+       __be32          cd_NextCD;      /* linked list of drivers to config */
+       __be32          cd_Unused[4];   /* for whatever the driver wants */
+} __packed;
+
+#define ZORRO_NUM_AUTO         16
+
+#endif /* _UAPI_LINUX_ZORRO_H */
index d630163b9a2e6d46f079b00357be501d3b5335fc..5759810e1c1b9768f67f8e703c625b7ce9d76e94 100644 (file)
@@ -30,7 +30,7 @@
 #include <sound/compress_params.h>
 
 
-#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 1)
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 2)
 /**
  * struct snd_compressed_buffer: compressed buffer
  * @fragment_size: size of buffer fragment in bytes
@@ -67,8 +67,8 @@ struct snd_compr_params {
 struct snd_compr_tstamp {
        __u32 byte_offset;
        __u32 copied_total;
-       snd_pcm_uframes_t pcm_frames;
-       snd_pcm_uframes_t pcm_io_frames;
+       __u32 pcm_frames;
+       __u32 pcm_io_frames;
        __u32 sampling_rate;
 };
 
index 8c5fa0e20155369cdf029c95e980271585057968..dc3193f4b5815b79eeca799ded99146f663d4ec8 100644 (file)
@@ -36,7 +36,7 @@
  * @extra_args == Operation-specific extra arguments (NULL if none).
  */
 
-/* ia64, x86: Callback for event delivery. */
+/* x86: Callback for event delivery. */
 #define CALLBACKTYPE_event                 0
 
 /* x86: Failsafe callback when guest state cannot be restored by Xen. */
index 65e12099ef89d9f3b5706858d956d8aabe427348..ae665ac59c36b6812a0470d5a7e0124c3e13a69f 100644 (file)
@@ -146,7 +146,7 @@ struct blkif_request_segment_aligned {
 struct blkif_request_rw {
        uint8_t        nr_segments;  /* number of segments                   */
        blkif_vdev_t   handle;       /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_request,u.rw.id) == 8 */
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -163,7 +163,7 @@ struct blkif_request_discard {
        uint8_t        flag;         /* BLKIF_DISCARD_SECURE or zero.        */
 #define BLKIF_DISCARD_SECURE (1<<0)  /* ignored if discard-secure=0          */
        blkif_vdev_t   _pad1;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad2;        /* offsetof(blkif_req..,u.discard.id)==8*/
 #endif
        uint64_t       id;           /* private guest value, echoed in resp  */
@@ -175,7 +175,7 @@ struct blkif_request_discard {
 struct blkif_request_other {
        uint8_t      _pad1;
        blkif_vdev_t _pad2;        /* only for read/write requests         */
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
 #endif
        uint64_t     id;           /* private guest value, echoed in resp  */
@@ -184,7 +184,7 @@ struct blkif_request_other {
 struct blkif_request_indirect {
        uint8_t        indirect_op;
        uint16_t       nr_segments;
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t       _pad1;        /* offsetof(blkif_...,u.indirect.id) == 8 */
 #endif
        uint64_t       id;
@@ -192,7 +192,7 @@ struct blkif_request_indirect {
        blkif_vdev_t   handle;
        uint16_t       _pad2;
        grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
-#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_32
        uint32_t      _pad3;         /* make it 64 byte aligned */
 #else
        uint64_t      _pad3;         /* make it 64 byte aligned */
index 056744b4b05eb7d34c10f8610a3148d3b2b4a668..545a14ba0bb3f781bb1136bc093ee278ffa3be4c 100644 (file)
@@ -3,7 +3,6 @@
 
 #define XEN_IO_PROTO_ABI_X86_32     "x86_32-abi"
 #define XEN_IO_PROTO_ABI_X86_64     "x86_64-abi"
-#define XEN_IO_PROTO_ABI_IA64       "ia64-abi"
 #define XEN_IO_PROTO_ABI_POWERPC64  "powerpc64-abi"
 #define XEN_IO_PROTO_ABI_ARM        "arm-abi"
 
@@ -11,8 +10,6 @@
 # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
 #elif defined(__x86_64__)
 # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
-#elif defined(__ia64__)
-# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
 #elif defined(__powerpc64__)
 # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
 #elif defined(__arm__) || defined(__aarch64__)
index 79383d3aa5dc5f7fe64abdcaf7d511144ca016e5..5236dc562a362b84924e9147a385787621f765cd 100644 (file)
@@ -532,7 +532,7 @@ config CONTEXT_TRACKING_FORCE
          dynticks subsystem by forcing the context tracking on all
          CPUs in the system.
 
-         Say Y only if you're working on the developpement of an
+         Say Y only if you're working on the development of an
          architecture backend for the context tracking.
 
          Say N otherwise, this option brings an overhead that you
@@ -809,6 +809,12 @@ config GENERIC_SCHED_CLOCK
 config ARCH_SUPPORTS_NUMA_BALANCING
        bool
 
+#
+# For architectures that know their GCC __int128 support is sound
+#
+config ARCH_SUPPORTS_INT128
+       bool
+
 # For architectures that (ab)use NUMA to represent different memory regions
 # all cpu-local but of different latencies, such as SuperH.
 #
index b3097bde4e9cbc999e5d09205db8014e0da27632..790d83c7d16071ffb96827fc4a372fd9b8eb4c5f 100644 (file)
@@ -5,3 +5,4 @@ config_data.h
 config_data.gz
 timeconst.h
 hz.bc
+x509_certificate_list
index bbaf7d59c1bb14f166441e6532b55585790e4b52..bc010ee272b6cfec39892e6cb04b98cc06995e1a 100644 (file)
@@ -137,9 +137,10 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
 ###############################################################################
 ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
 X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
-X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
-X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
+X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += $(objtree)/signing_key.x509
+X509_CERTIFICATES-raw := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
                                $(or $(realpath $(CERT)),$(CERT))))
+X509_CERTIFICATES := $(subst $(realpath $(objtree))/,,$(X509_CERTIFICATES-raw))
 
 ifeq ($(X509_CERTIFICATES),)
 $(warning *** No X.509 certificates found ***)
@@ -164,9 +165,9 @@ $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
 targets += $(obj)/.x509.list
 $(obj)/.x509.list:
        @echo $(X509_CERTIFICATES) >$@
+endif
 
 clean-files := x509_certificate_list .x509.list
-endif
 
 ifeq ($(CONFIG_MODULE_SIG),y)
 ###############################################################################
index 5253204afdcace55e89cda669aaf2896eba23aaa..9fd4246b04b8298ec608dbba4d9ee9997e105fbc 100644 (file)
@@ -22,6 +22,6 @@ void foo(void)
 #ifdef CONFIG_SMP
        DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS));
 #endif
-       DEFINE(BLOATED_SPINLOCKS, sizeof(spinlock_t) > sizeof(int));
+       DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
        /* End of constants */
 }
index 8b729c278b649c7c016786f6dac9886290ce794f..bc1dcabe92176636baf79c7ef52e597422aeaf75 100644 (file)
@@ -890,6 +890,16 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
                struct cgroup *cgrp = dentry->d_fsdata;
 
                BUG_ON(!(cgroup_is_dead(cgrp)));
+
+               /*
+                * XXX: cgrp->id is only used to look up css's.  As cgroup
+                * and css's lifetimes will be decoupled, it should be made
+                * per-subsystem and moved to css->id so that lookups are
+                * successful until the target css is released.
+                */
+               idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
+               cgrp->id = -1;
+
                call_rcu(&cgrp->rcu_head, cgroup_free_rcu);
        } else {
                struct cfent *cfe = __d_cfe(dentry);
@@ -4268,6 +4278,7 @@ static void css_release(struct percpu_ref *ref)
        struct cgroup_subsys_state *css =
                container_of(ref, struct cgroup_subsys_state, refcnt);
 
+       rcu_assign_pointer(css->cgroup->subsys[css->ss->subsys_id], NULL);
        call_rcu(&css->rcu_head, css_free_rcu_fn);
 }
 
@@ -4426,14 +4437,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
        root->number_of_cgroups++;
 
-       /* each css holds a ref to the cgroup's dentry and the parent css */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               dget(dentry);
-               css_get(css->parent);
-       }
-
        /* hold a ref to the parent's dentry */
        dget(parent->dentry);
 
@@ -4445,6 +4448,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                if (err)
                        goto err_destroy;
 
+               /* each css holds a ref to the cgroup's dentry and parent css */
+               dget(dentry);
+               css_get(css->parent);
+
+               /* mark it consumed for error path */
+               css_ar[ss->subsys_id] = NULL;
+
                if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
                    parent->parent) {
                        pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
@@ -4491,6 +4501,14 @@ err_free_cgrp:
        return err;
 
 err_destroy:
+       for_each_root_subsys(root, ss) {
+               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
+
+               if (css) {
+                       percpu_ref_cancel_init(&css->refcnt);
+                       ss->css_free(css);
+               }
+       }
        cgroup_destroy_locked(cgrp);
        mutex_unlock(&cgroup_mutex);
        mutex_unlock(&dentry->d_inode->i_mutex);
@@ -4652,8 +4670,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
         * will be invoked to perform the rest of destruction once the
         * percpu refs of all css's are confirmed to be killed.
         */
-       for_each_root_subsys(cgrp->root, ss)
-               kill_css(cgroup_css(cgrp, ss));
+       for_each_root_subsys(cgrp->root, ss) {
+               struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
+
+               if (css)
+                       kill_css(css);
+       }
 
        /*
         * Mark @cgrp dead.  This prevents further task migration and child
@@ -4722,14 +4744,6 @@ static void cgroup_destroy_css_killed(struct cgroup *cgrp)
        /* delete this cgroup from parent->children */
        list_del_rcu(&cgrp->sibling);
 
-       /*
-        * We should remove the cgroup object from idr before its grace
-        * period starts, so we won't be looking up a cgroup while the
-        * cgroup is being freed.
-        */
-       idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
-       cgrp->id = -1;
-
        dput(d);
 
        set_bit(CGRP_RELEASABLE, &parent->flags);
index e5f3917aa05b724f3367e4fad474534eb34138c5..6cb20d2e7ee0d28b0d6399a8cd1f3e23f9366899 100644 (file)
@@ -53,10 +53,10 @@ void context_tracking_user_enter(void)
        /*
         * Repeat the user_enter() check here because some archs may be calling
         * this from asm and if no CPU needs context tracking, they shouldn't
-        * go further. Repeat the check here until they support the static key
-        * check.
+        * go further. Repeat the check here until they support the inline static
+        * key check.
         */
-       if (!static_key_false(&context_tracking_enabled))
+       if (!context_tracking_is_enabled())
                return;
 
        /*
@@ -160,7 +160,7 @@ void context_tracking_user_exit(void)
 {
        unsigned long flags;
 
-       if (!static_key_false(&context_tracking_enabled))
+       if (!context_tracking_is_enabled())
                return;
 
        if (in_interrupt())
index 988573a9a387665dddc402af2439996aa02fd1c0..277f494c2a9ae695c9a61dd44e5a2bfe68d75b2c 100644 (file)
@@ -105,14 +105,17 @@ static void cpu_idle_loop(void)
                                __current_set_polling();
                        }
                        arch_cpu_idle_exit();
-                       /*
-                        * We need to test and propagate the TIF_NEED_RESCHED
-                        * bit here because we might not have send the
-                        * reschedule IPI to idle tasks.
-                        */
-                       if (tif_need_resched())
-                               set_preempt_need_resched();
                }
+
+               /*
+                * 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();
        }
index d724e7757cd1ec2df7a9c2ac9be1b0c23f6e4e71..56003c6edfd38c03e8dd523f1efb01d99bcf2e84 100644 (file)
@@ -119,7 +119,8 @@ static int cpu_function_call(int cpu, int (*func) (void *info), void *info)
 
 #define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\
                       PERF_FLAG_FD_OUTPUT  |\
-                      PERF_FLAG_PID_CGROUP)
+                      PERF_FLAG_PID_CGROUP |\
+                      PERF_FLAG_FD_CLOEXEC)
 
 /*
  * branch priv levels that need permission checks
@@ -1396,6 +1397,8 @@ event_sched_out(struct perf_event *event,
        if (event->state != PERF_EVENT_STATE_ACTIVE)
                return;
 
+       perf_pmu_disable(event->pmu);
+
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
@@ -1412,6 +1415,8 @@ event_sched_out(struct perf_event *event,
                ctx->nr_freq--;
        if (event->attr.exclusive || !cpuctx->active_oncpu)
                cpuctx->exclusive = 0;
+
+       perf_pmu_enable(event->pmu);
 }
 
 static void
@@ -1652,6 +1657,7 @@ event_sched_in(struct perf_event *event,
                 struct perf_event_context *ctx)
 {
        u64 tstamp = perf_event_time(event);
+       int ret = 0;
 
        if (event->state <= PERF_EVENT_STATE_OFF)
                return 0;
@@ -1674,10 +1680,13 @@ event_sched_in(struct perf_event *event,
         */
        smp_wmb();
 
+       perf_pmu_disable(event->pmu);
+
        if (event->pmu->add(event, PERF_EF_START)) {
                event->state = PERF_EVENT_STATE_INACTIVE;
                event->oncpu = -1;
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto out;
        }
 
        event->tstamp_running += tstamp - event->tstamp_stopped;
@@ -1693,7 +1702,10 @@ event_sched_in(struct perf_event *event,
        if (event->attr.exclusive)
                cpuctx->exclusive = 1;
 
-       return 0;
+out:
+       perf_pmu_enable(event->pmu);
+
+       return ret;
 }
 
 static int
@@ -2743,6 +2755,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                if (!event_filter_match(event))
                        continue;
 
+               perf_pmu_disable(event->pmu);
+
                hwc = &event->hw;
 
                if (hwc->interrupts == MAX_INTERRUPTS) {
@@ -2752,7 +2766,7 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                }
 
                if (!event->attr.freq || !event->attr.sample_freq)
-                       continue;
+                       goto next;
 
                /*
                 * stop the event and update event->count
@@ -2774,6 +2788,8 @@ static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
                        perf_adjust_period(event, period, delta, false);
 
                event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
+       next:
+               perf_pmu_enable(event->pmu);
        }
 
        perf_pmu_enable(ctx->pmu);
@@ -3527,7 +3543,7 @@ static void perf_event_for_each(struct perf_event *event,
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
        struct perf_event_context *ctx = event->ctx;
-       int ret = 0;
+       int ret = 0, active;
        u64 value;
 
        if (!is_sampling_event(event))
@@ -3551,6 +3567,20 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
                event->attr.sample_period = value;
                event->hw.sample_period = value;
        }
+
+       active = (event->state == PERF_EVENT_STATE_ACTIVE);
+       if (active) {
+               perf_pmu_disable(ctx->pmu);
+               event->pmu->stop(event, PERF_EF_UPDATE);
+       }
+
+       local64_set(&event->hw.period_left, 0);
+
+       if (active) {
+               event->pmu->start(event, PERF_EF_RELOAD);
+               perf_pmu_enable(ctx->pmu);
+       }
+
 unlock:
        raw_spin_unlock_irq(&ctx->lock);
 
@@ -5680,11 +5710,6 @@ static void swevent_hlist_put(struct perf_event *event)
 {
        int cpu;
 
-       if (event->cpu != -1) {
-               swevent_hlist_put_cpu(event, event->cpu);
-               return;
-       }
-
        for_each_possible_cpu(cpu)
                swevent_hlist_put_cpu(event, cpu);
 }
@@ -5718,9 +5743,6 @@ static int swevent_hlist_get(struct perf_event *event)
        int err;
        int cpu, failed_cpu;
 
-       if (event->cpu != -1)
-               return swevent_hlist_get_cpu(event, event->cpu);
-
        get_online_cpus();
        for_each_possible_cpu(cpu) {
                err = swevent_hlist_get_cpu(event, cpu);
@@ -6663,6 +6685,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        INIT_LIST_HEAD(&event->event_entry);
        INIT_LIST_HEAD(&event->sibling_list);
        INIT_LIST_HEAD(&event->rb_entry);
+       INIT_LIST_HEAD(&event->active_entry);
+       INIT_HLIST_NODE(&event->hlist_entry);
+
 
        init_waitqueue_head(&event->waitq);
        init_irq_work(&event->pending, perf_pending_event);
@@ -6973,6 +6998,7 @@ SYSCALL_DEFINE5(perf_event_open,
        int event_fd;
        int move_group = 0;
        int err;
+       int f_flags = O_RDWR;
 
        /* for future expandability... */
        if (flags & ~PERF_FLAG_ALL)
@@ -7001,7 +7027,10 @@ SYSCALL_DEFINE5(perf_event_open,
        if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1))
                return -EINVAL;
 
-       event_fd = get_unused_fd();
+       if (flags & PERF_FLAG_FD_CLOEXEC)
+               f_flags |= O_CLOEXEC;
+
+       event_fd = get_unused_fd_flags(f_flags);
        if (event_fd < 0)
                return event_fd;
 
@@ -7123,7 +7152,8 @@ SYSCALL_DEFINE5(perf_event_open,
                        goto err_context;
        }
 
-       event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
+       event_file = anon_inode_getfile("[perf_event]", &perf_fops, event,
+                                       f_flags);
        if (IS_ERR(event_file)) {
                err = PTR_ERR(event_file);
                goto err_context;
index e8b168af135ba3ec7d72c780746ce02f051be2e3..146a5792b1d2aaf9412eaf2610f1f4cd1f05a037 100644 (file)
@@ -61,19 +61,20 @@ again:
         *
         *   kernel                             user
         *
-        *   READ ->data_tail                   READ ->data_head
-        *   smp_mb()   (A)                     smp_rmb()       (C)
-        *   WRITE $data                        READ $data
-        *   smp_wmb()  (B)                     smp_mb()        (D)
-        *   STORE ->data_head                  WRITE ->data_tail
+        *   if (LOAD ->data_tail) {            LOAD ->data_head
+        *                      (A)             smp_rmb()       (C)
+        *      STORE $data                     LOAD $data
+        *      smp_wmb()       (B)             smp_mb()        (D)
+        *      STORE ->data_head               STORE ->data_tail
+        *   }
         *
         * Where A pairs with D, and B pairs with C.
         *
-        * I don't think A needs to be a full barrier because we won't in fact
-        * write data until we see the store from userspace. So we simply don't
-        * issue the data WRITE until we observe it. Be conservative for now.
+        * In our case (A) is a control dependency that separates the load of
+        * the ->data_tail and the stores of $data. In case ->data_tail
+        * indicates there is no room in the buffer to store $data we do not.
         *
-        * OTOH, D needs to be a full barrier since it separates the data READ
+        * D needs to be a full barrier since it separates the data READ
         * from the tail WRITE.
         *
         * For B a WMB is sufficient since it separates two WRITEs, and for C
@@ -81,7 +82,7 @@ again:
         *
         * See perf_output_begin().
         */
-       smp_wmb();
+       smp_wmb(); /* B, matches C */
        rb->user_page->data_head = head;
 
        /*
@@ -144,17 +145,26 @@ int perf_output_begin(struct perf_output_handle *handle,
                if (!rb->overwrite &&
                    unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size))
                        goto fail;
+
+               /*
+                * The above forms a control dependency barrier separating the
+                * @tail load above from the data stores below. Since the @tail
+                * load is required to compute the branch to fail below.
+                *
+                * A, matches D; the full memory barrier userspace SHOULD issue
+                * after reading the data and before storing the new tail
+                * position.
+                *
+                * See perf_output_put_handle().
+                */
+
                head += size;
        } while (local_cmpxchg(&rb->head, offset, head) != offset);
 
        /*
-        * Separate the userpage->tail read from the data stores below.
-        * Matches the MB userspace SHOULD issue after reading the data
-        * and before storing the new tail position.
-        *
-        * See perf_output_put_handle().
+        * We rely on the implied barrier() by local_cmpxchg() to ensure
+        * none of the data stores below can be lifted up by the compiler.
         */
-       smp_mb();
 
        if (unlikely(head - local_read(&rb->wakeup) > rb->watermark))
                local_add(rb->watermark, &rb->wakeup);
index 24b7d6ca871b632f2e35912e720bfc0162c939c5..b886a5e7d4ff4a5d1c7b240a63aed39538926de4 100644 (file)
@@ -73,6 +73,17 @@ struct uprobe {
        struct inode            *inode;         /* Also hold a ref to inode */
        loff_t                  offset;
        unsigned long           flags;
+
+       /*
+        * The generic code assumes that it has two members of unknown type
+        * owned by the arch-specific code:
+        *
+        *      insn -  copy_insn() saves the original instruction here for
+        *              arch_uprobe_analyze_insn().
+        *
+        *      ixol -  potentially modified instruction to execute out of
+        *              line, copied to xol_area by xol_get_insn_slot().
+        */
        struct arch_uprobe      arch;
 };
 
@@ -85,6 +96,29 @@ struct return_instance {
        struct return_instance  *next;          /* keep as stack */
 };
 
+/*
+ * Execute out of line area: anonymous executable mapping installed
+ * by the probed task to execute the copy of the original instruction
+ * mangled by set_swbp().
+ *
+ * On a breakpoint hit, thread contests for a slot.  It frees the
+ * slot after singlestep. Currently a fixed number of slots are
+ * allocated.
+ */
+struct xol_area {
+       wait_queue_head_t       wq;             /* if all slots are busy */
+       atomic_t                slot_count;     /* number of in-use slots */
+       unsigned long           *bitmap;        /* 0 = free slot */
+       struct page             *page;
+
+       /*
+        * We keep the vma's vm_start rather than a pointer to the vma
+        * itself.  The probed process or a naughty kernel module could make
+        * the vma go away, and we must handle that reasonably gracefully.
+        */
+       unsigned long           vaddr;          /* Page(s) of instruction slots */
+};
+
 /*
  * valid_vma: Verify if the specified vma is an executable vma
  * Relax restrictions while unregistering: vm_flags might have
@@ -330,7 +364,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+       return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)&auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -529,8 +563,8 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
 {
        struct address_space *mapping = uprobe->inode->i_mapping;
        loff_t offs = uprobe->offset;
-       void *insn = uprobe->arch.insn;
-       int size = MAX_UINSN_BYTES;
+       void *insn = &uprobe->arch.insn;
+       int size = sizeof(uprobe->arch.insn);
        int len, err = -EIO;
 
        /* Copy only available bytes, -EIO if nothing was read */
@@ -569,7 +603,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
                goto out;
 
        ret = -ENOTSUPP;
-       if (is_trap_insn((uprobe_opcode_t *)uprobe->arch.insn))
+       if (is_trap_insn((uprobe_opcode_t *)&uprobe->arch.insn))
                goto out;
 
        ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
@@ -1264,7 +1298,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 
        /* Initialize the slot */
        copy_to_page(area->page, xol_vaddr,
-                       uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
+                       &uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
        /*
         * We probably need flush_icache_user_range() but it needs vma.
         * This should work on supported architectures too.
@@ -1403,12 +1437,10 @@ static void uprobe_warn(struct task_struct *t, const char *msg)
 
 static void dup_xol_work(struct callback_head *work)
 {
-       kfree(work);
-
        if (current->flags & PF_EXITING)
                return;
 
-       if (!__create_xol_area(current->utask->vaddr))
+       if (!__create_xol_area(current->utask->dup_xol_addr))
                uprobe_warn(current, "dup xol area");
 }
 
@@ -1419,7 +1451,6 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags)
 {
        struct uprobe_task *utask = current->utask;
        struct mm_struct *mm = current->mm;
-       struct callback_head *work;
        struct xol_area *area;
 
        t->utask = NULL;
@@ -1441,14 +1472,9 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags)
        if (mm == t->mm)
                return;
 
-       /* TODO: move it into the union in uprobe_task */
-       work = kmalloc(sizeof(*work), GFP_KERNEL);
-       if (!work)
-               return uprobe_warn(t, "dup xol area");
-
-       t->utask->vaddr = area->vaddr;
-       init_task_work(work, dup_xol_work);
-       task_work_add(t, work, true);
+       t->utask->dup_xol_addr = area->vaddr;
+       init_task_work(&t->utask->dup_xol_work, dup_xol_work);
+       task_work_add(t, &t->utask->dup_xol_work, true);
 }
 
 /*
index 728d5be9548ce61913c85e14303248363eae0a31..294189fc7ac8991f31c97e327fb8b19841c44968 100644 (file)
@@ -537,6 +537,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
        spin_lock_init(&mm->page_table_lock);
        mm_init_aio(mm);
        mm_init_owner(mm, p);
+       clear_tlb_flush_pending(mm);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
@@ -1086,8 +1087,10 @@ static void rt_mutex_init_task(struct task_struct *p)
 {
        raw_spin_lock_init(&p->pi_lock);
 #ifdef CONFIG_RT_MUTEXES
-       plist_head_init(&p->pi_waiters);
+       p->pi_waiters = RB_ROOT;
+       p->pi_waiters_leftmost = NULL;
        p->pi_blocked_on = NULL;
+       p->pi_top_task = NULL;
 #endif
 }
 
@@ -1171,7 +1174,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         * do not allow it to share a thread group or signal handlers or
         * parent with the forking task.
         */
-       if (clone_flags & (CLONE_SIGHAND | CLONE_PARENT)) {
+       if (clone_flags & CLONE_SIGHAND) {
                if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
                    (task_active_pid_ns(current) !=
                                current->nsproxy->pid_ns_for_children))
@@ -1310,7 +1313,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 #endif
 
        /* Perform scheduler related setup. Assign this task to a CPU. */
-       sched_fork(clone_flags, p);
+       retval = sched_fork(clone_flags, p);
+       if (retval)
+               goto bad_fork_cleanup_policy;
 
        retval = perf_event_init_task(p);
        if (retval)
@@ -1402,13 +1407,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                p->tgid = p->pid;
        }
 
-       p->pdeath_signal = 0;
-       p->exit_state = 0;
-
        p->nr_dirtied = 0;
        p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10);
        p->dirty_paused_when = 0;
 
+       p->pdeath_signal = 0;
        INIT_LIST_HEAD(&p->thread_group);
        p->task_works = NULL;
 
index b462fa197517b6176701fa860cdb966bc44a69ba..aa6a8aadb911fb323b4662a4652c95ff4319f0c5 100644 (file)
@@ -19,6 +19,12 @@ EXPORT_SYMBOL(system_freezing_cnt);
 bool pm_freezing;
 bool pm_nosig_freezing;
 
+/*
+ * Temporary export for the deadlock workaround in ata_scsi_hotplug().
+ * Remove once the hack becomes unnecessary.
+ */
+EXPORT_SYMBOL_GPL(pm_freezing);
+
 /* protects freezing and frozen transitions */
 static DEFINE_SPINLOCK(freezer_lock);
 
index 80ba086f021d3022afcf3f06ecdb1d920cdc8f7c..44a1261cb9ff63a33eec42136be4794a0752a0ac 100644 (file)
 #include <linux/sched/rt.h>
 #include <linux/hugetlb.h>
 #include <linux/freezer.h>
+#include <linux/bootmem.h>
 
 #include <asm/futex.h>
 
 #include "locking/rtmutex_common.h"
 
-int __read_mostly futex_cmpxchg_enabled;
+/*
+ * Basic futex operation and ordering guarantees:
+ *
+ * The waiter reads the futex value in user space and calls
+ * futex_wait(). This function computes the hash bucket and acquires
+ * the hash bucket lock. After that it reads the futex user space value
+ * again and verifies that the data has not changed. If it has not changed
+ * it enqueues itself into the hash bucket, releases the hash bucket lock
+ * and schedules.
+ *
+ * The waker side modifies the user space value of the futex and calls
+ * futex_wake(). This function computes the hash bucket and acquires the
+ * hash bucket lock. Then it looks for waiters on that futex in the hash
+ * bucket and wakes them.
+ *
+ * In futex wake up scenarios where no tasks are blocked on a futex, taking
+ * the hb spinlock can be avoided and simply return. In order for this
+ * optimization to work, ordering guarantees must exist so that the waiter
+ * being added to the list is acknowledged when the list is concurrently being
+ * checked by the waker, avoiding scenarios like the following:
+ *
+ * CPU 0                               CPU 1
+ * val = *futex;
+ * sys_futex(WAIT, futex, val);
+ *   futex_wait(futex, val);
+ *   uval = *futex;
+ *                                     *futex = newval;
+ *                                     sys_futex(WAKE, futex);
+ *                                       futex_wake(futex);
+ *                                       if (queue_empty())
+ *                                         return;
+ *   if (uval == val)
+ *      lock(hash_bucket(futex));
+ *      queue();
+ *     unlock(hash_bucket(futex));
+ *     schedule();
+ *
+ * This would cause the waiter on CPU 0 to wait forever because it
+ * missed the transition of the user space value from val to newval
+ * and the waker did not find the waiter in the hash bucket queue.
+ *
+ * The correct serialization ensures that a waiter either observes
+ * the changed user space value before blocking or is woken by a
+ * concurrent waker:
+ *
+ * CPU 0                                 CPU 1
+ * val = *futex;
+ * sys_futex(WAIT, futex, val);
+ *   futex_wait(futex, val);
+ *
+ *   waiters++;
+ *   mb(); (A) <-- paired with -.
+ *                              |
+ *   lock(hash_bucket(futex));  |
+ *                              |
+ *   uval = *futex;             |
+ *                              |        *futex = newval;
+ *                              |        sys_futex(WAKE, futex);
+ *                              |          futex_wake(futex);
+ *                              |
+ *                              `------->  mb(); (B)
+ *   if (uval == val)
+ *     queue();
+ *     unlock(hash_bucket(futex));
+ *     schedule();                         if (waiters)
+ *                                           lock(hash_bucket(futex));
+ *                                           wake_waiters(futex);
+ *                                           unlock(hash_bucket(futex));
+ *
+ * Where (A) orders the waiters increment and the futex value read -- this
+ * is guaranteed by the head counter in the hb spinlock; and where (B)
+ * orders the write to futex and the waiters read -- this is done by the
+ * barriers in get_futex_key_refs(), through either ihold or atomic_inc,
+ * depending on the futex type.
+ *
+ * This yields the following case (where X:=waiters, Y:=futex):
+ *
+ *     X = Y = 0
+ *
+ *     w[X]=1          w[Y]=1
+ *     MB              MB
+ *     r[Y]=y          r[X]=x
+ *
+ * Which guarantees that x==0 && y==0 is impossible; which translates back into
+ * the guarantee that we cannot both miss the futex variable change and the
+ * enqueue.
+ */
 
-#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
+int __read_mostly futex_cmpxchg_enabled;
 
 /*
  * Futex flags used to encode options to functions and preserve them across
@@ -149,9 +236,41 @@ static const struct futex_q futex_q_init = {
 struct futex_hash_bucket {
        spinlock_t lock;
        struct plist_head chain;
-};
+} ____cacheline_aligned_in_smp;
+
+static unsigned long __read_mostly futex_hashsize;
+
+static struct futex_hash_bucket *futex_queues;
+
+static inline void futex_get_mm(union futex_key *key)
+{
+       atomic_inc(&key->private.mm->mm_count);
+       /*
+        * Ensure futex_get_mm() implies a full barrier such that
+        * get_futex_key() implies a full barrier. This is relied upon
+        * as full barrier (B), see the ordering comment above.
+        */
+       smp_mb__after_atomic_inc();
+}
+
+static inline bool hb_waiters_pending(struct futex_hash_bucket *hb)
+{
+#ifdef CONFIG_SMP
+       /*
+        * 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.
+        */
+       if (spin_is_locked(&hb->lock))
+               return true;
+       smp_rmb(); /* Make sure we check the lock state first */
 
-static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS];
+       return !plist_head_empty(&hb->chain);
+#else
+       return true;
+#endif
+}
 
 /*
  * We hash on the keys returned from get_futex_key (see below).
@@ -161,7 +280,7 @@ static struct futex_hash_bucket *hash_futex(union futex_key *key)
        u32 hash = jhash2((u32*)&key->both.word,
                          (sizeof(key->both.word)+sizeof(key->both.ptr))/4,
                          key->both.offset);
-       return &futex_queues[hash & ((1 << FUTEX_HASHBITS)-1)];
+       return &futex_queues[hash & (futex_hashsize - 1)];
 }
 
 /*
@@ -187,10 +306,10 @@ static void get_futex_key_refs(union futex_key *key)
 
        switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
        case FUT_OFF_INODE:
-               ihold(key->shared.inode);
+               ihold(key->shared.inode); /* implies MB (B) */
                break;
        case FUT_OFF_MMSHARED:
-               atomic_inc(&key->private.mm->mm_count);
+               futex_get_mm(key); /* implies MB (B) */
                break;
        }
 }
@@ -251,6 +370,9 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
                return -EINVAL;
        address -= key->both.offset;
 
+       if (unlikely(!access_ok(rw, uaddr, sizeof(u32))))
+               return -EFAULT;
+
        /*
         * PROCESS_PRIVATE futexes are fast.
         * As the mm cannot disappear under us and the 'key' only needs
@@ -259,11 +381,9 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
         *        but access_ok() should be faster than find_vma()
         */
        if (!fshared) {
-               if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
-                       return -EFAULT;
                key->private.mm = mm;
                key->private.address = address;
-               get_futex_key_refs(key);
+               get_futex_key_refs(key);  /* implies MB (B) */
                return 0;
        }
 
@@ -288,7 +408,7 @@ again:
                put_page(page);
                /* serialize against __split_huge_page_splitting() */
                local_irq_disable();
-               if (likely(__get_user_pages_fast(address, 1, 1, &page) == 1)) {
+               if (likely(__get_user_pages_fast(address, 1, !ro, &page) == 1)) {
                        page_head = compound_head(page);
                        /*
                         * page_head is valid pointer but we must pin
@@ -370,7 +490,7 @@ again:
                key->shared.pgoff = basepage_index(page);
        }
 
-       get_futex_key_refs(key);
+       get_futex_key_refs(key); /* implies MB (B) */
 
 out:
        unlock_page(page_head);
@@ -597,13 +717,10 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
 {
        struct futex_pi_state *pi_state = NULL;
        struct futex_q *this, *next;
-       struct plist_head *head;
        struct task_struct *p;
        pid_t pid = uval & FUTEX_TID_MASK;
 
-       head = &hb->chain;
-
-       plist_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, &hb->chain, list) {
                if (match_futex(&this->key, key)) {
                        /*
                         * Another waiter already exists - bump up
@@ -985,7 +1102,6 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
 {
        struct futex_hash_bucket *hb;
        struct futex_q *this, *next;
-       struct plist_head *head;
        union futex_key key = FUTEX_KEY_INIT;
        int ret;
 
@@ -997,10 +1113,14 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
                goto out;
 
        hb = hash_futex(&key);
+
+       /* Make sure we really have tasks to wakeup */
+       if (!hb_waiters_pending(hb))
+               goto out_put_key;
+
        spin_lock(&hb->lock);
-       head = &hb->chain;
 
-       plist_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, &hb->chain, list) {
                if (match_futex (&this->key, &key)) {
                        if (this->pi_state || this->rt_waiter) {
                                ret = -EINVAL;
@@ -1018,6 +1138,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
        }
 
        spin_unlock(&hb->lock);
+out_put_key:
        put_futex_key(&key);
 out:
        return ret;
@@ -1033,7 +1154,6 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
 {
        union futex_key key1 = FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
        struct futex_hash_bucket *hb1, *hb2;
-       struct plist_head *head;
        struct futex_q *this, *next;
        int ret, op_ret;
 
@@ -1081,9 +1201,7 @@ retry_private:
                goto retry;
        }
 
-       head = &hb1->chain;
-
-       plist_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, &hb1->chain, list) {
                if (match_futex (&this->key, &key1)) {
                        if (this->pi_state || this->rt_waiter) {
                                ret = -EINVAL;
@@ -1096,10 +1214,8 @@ retry_private:
        }
 
        if (op_ret > 0) {
-               head = &hb2->chain;
-
                op_ret = 0;
-               plist_for_each_entry_safe(this, next, head, list) {
+               plist_for_each_entry_safe(this, next, &hb2->chain, list) {
                        if (match_futex (&this->key, &key2)) {
                                if (this->pi_state || this->rt_waiter) {
                                        ret = -EINVAL;
@@ -1269,7 +1385,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
        int drop_count = 0, task_count = 0, ret;
        struct futex_pi_state *pi_state = NULL;
        struct futex_hash_bucket *hb1, *hb2;
-       struct plist_head *head1;
        struct futex_q *this, *next;
        u32 curval2;
 
@@ -1392,8 +1507,7 @@ retry_private:
                }
        }
 
-       head1 = &hb1->chain;
-       plist_for_each_entry_safe(this, next, head1, list) {
+       plist_for_each_entry_safe(this, next, &hb1->chain, list) {
                if (task_count - nr_wake >= nr_requeue)
                        break;
 
@@ -1488,12 +1602,12 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
        hb = hash_futex(&q->key);
        q->lock_ptr = &hb->lock;
 
-       spin_lock(&hb->lock);
+       spin_lock(&hb->lock); /* implies MB (A) */
        return hb;
 }
 
 static inline void
-queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
+queue_unlock(struct futex_hash_bucket *hb)
        __releases(&hb->lock)
 {
        spin_unlock(&hb->lock);
@@ -1866,7 +1980,7 @@ retry_private:
        ret = get_futex_value_locked(&uval, uaddr);
 
        if (ret) {
-               queue_unlock(q, *hb);
+               queue_unlock(*hb);
 
                ret = get_user(uval, uaddr);
                if (ret)
@@ -1880,7 +1994,7 @@ retry_private:
        }
 
        if (uval != val) {
-               queue_unlock(q, *hb);
+               queue_unlock(*hb);
                ret = -EWOULDBLOCK;
        }
 
@@ -2028,7 +2142,7 @@ retry_private:
                         * Task is exiting and we just wait for the
                         * exit to complete.
                         */
-                       queue_unlock(&q, hb);
+                       queue_unlock(hb);
                        put_futex_key(&q.key);
                        cond_resched();
                        goto retry;
@@ -2080,7 +2194,7 @@ retry_private:
        goto out_put_key;
 
 out_unlock_put_key:
-       queue_unlock(&q, hb);
+       queue_unlock(hb);
 
 out_put_key:
        put_futex_key(&q.key);
@@ -2090,7 +2204,7 @@ out:
        return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
 uaddr_faulted:
-       queue_unlock(&q, hb);
+       queue_unlock(hb);
 
        ret = fault_in_user_writeable(uaddr);
        if (ret)
@@ -2112,7 +2226,6 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
 {
        struct futex_hash_bucket *hb;
        struct futex_q *this, *next;
-       struct plist_head *head;
        union futex_key key = FUTEX_KEY_INIT;
        u32 uval, vpid = task_pid_vnr(current);
        int ret;
@@ -2152,9 +2265,7 @@ retry:
         * Ok, other tasks may need to be woken up - check waiters
         * and do the wakeup if necessary:
         */
-       head = &hb->chain;
-
-       plist_for_each_entry_safe(this, next, head, list) {
+       plist_for_each_entry_safe(this, next, &hb->chain, list) {
                if (!match_futex (&this->key, &key))
                        continue;
                ret = wake_futex_pi(uaddr, uval, this);
@@ -2315,6 +2426,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
         * code while we sleep on uaddr.
         */
        debug_rt_mutex_init_waiter(&rt_waiter);
+       RB_CLEAR_NODE(&rt_waiter.pi_tree_entry);
+       RB_CLEAR_NODE(&rt_waiter.tree_entry);
        rt_waiter.task = NULL;
 
        ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE);
@@ -2733,8 +2846,21 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
 static int __init futex_init(void)
 {
        u32 curval;
-       int i;
+       unsigned int futex_shift;
+       unsigned long i;
+
+#if CONFIG_BASE_SMALL
+       futex_hashsize = 16;
+#else
+       futex_hashsize = roundup_pow_of_two(256 * num_possible_cpus());
+#endif
 
+       futex_queues = alloc_large_system_hash("futex", sizeof(*futex_queues),
+                                              futex_hashsize, 0,
+                                              futex_hashsize < 256 ? HASH_SMALL : 0,
+                                              &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()
@@ -2748,7 +2874,7 @@ static int __init futex_init(void)
        if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
                futex_cmpxchg_enabled = 1;
 
-       for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
+       for (i = 0; i < futex_hashsize; i++) {
                plist_head_init(&futex_queues[i].chain);
                spin_lock_init(&futex_queues[i].lock);
        }
index 383319bae3f7d0d9e8154a3bb99798a477ee676f..09094361dce523fec7def28599b17c34bee16bec 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/sched.h>
 #include <linux/sched/sysctl.h>
 #include <linux/sched/rt.h>
+#include <linux/sched/deadline.h>
 #include <linux/timer.h>
 #include <linux/freezer.h>
 
@@ -1610,7 +1611,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
        unsigned long slack;
 
        slack = current->timer_slack_ns;
-       if (rt_task(current))
+       if (dl_task(current) || rt_task(current))
                slack = 0;
 
        hrtimer_init_on_stack(&t.timer, clockid, mode);
index cb228bf217603d6e841c1028dd610598ae133bff..abcd6ca86cb76b56e5979613a1964c0db743b5d0 100644 (file)
@@ -50,7 +50,7 @@ static void resume_irqs(bool want_early)
                bool is_early = desc->action &&
                        desc->action->flags & IRQF_EARLY_RESUME;
 
-               if (is_early != want_early)
+               if (!is_early && want_early)
                        continue;
 
                raw_spin_lock_irqsave(&desc->lock, flags);
index 490afc03627e52e34e51d69e0a15693b7716b17a..9c970167e4025f01be6bd696499eec2504c72ef7 100644 (file)
@@ -47,6 +47,9 @@ u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 size_t vmcoreinfo_size;
 size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
+/* Flag to indicate we are going to kexec a new kernel */
+bool kexec_in_progress = false;
+
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
        .name  = "Crash kernel",
@@ -1675,7 +1678,9 @@ int kernel_kexec(void)
        } else
 #endif
        {
+               kexec_in_progress = true;
                kernel_restart_prepare(NULL);
+               migrate_to_reboot_cpu();
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
        }
index 576ba756a32d9c80948c72e31700738bcfc5ee06..eb8a54783fa0f47bb9b51568ec9dfed3d51cc48d 100644 (file)
@@ -590,6 +590,7 @@ static int very_verbose(struct lock_class *class)
 /*
  * Is this the address of a static object:
  */
+#ifdef __KERNEL__
 static int static_obj(void *obj)
 {
        unsigned long start = (unsigned long) &_stext,
@@ -616,6 +617,7 @@ static int static_obj(void *obj)
         */
        return is_module_address(addr) || is_module_percpu_address(addr);
 }
+#endif
 
 /*
  * To make lock name printouts unique, we calculate a unique
@@ -4115,6 +4117,7 @@ void debug_check_no_locks_held(void)
 }
 EXPORT_SYMBOL_GPL(debug_check_no_locks_held);
 
+#ifdef __KERNEL__
 void debug_show_all_locks(void)
 {
        struct task_struct *g, *p;
@@ -4172,6 +4175,7 @@ retry:
                read_unlock(&tasklist_lock);
 }
 EXPORT_SYMBOL_GPL(debug_show_all_locks);
+#endif
 
 /*
  * Careful: only use this function if you are sure that
index 7e3443fe1f48a1dbea11f7287fd3a362f1adb2a7..faf6f5b53e775eefbc7ee4ea734ff0998be68d01 100644 (file)
@@ -75,7 +75,12 @@ void debug_mutex_unlock(struct mutex *lock)
                return;
 
        DEBUG_LOCKS_WARN_ON(lock->magic != lock);
-       DEBUG_LOCKS_WARN_ON(lock->owner != current);
+
+       if (!lock->owner)
+               DEBUG_LOCKS_WARN_ON(!lock->owner);
+       else
+               DEBUG_LOCKS_WARN_ON(lock->owner != current);
+
        DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
        mutex_clear_owner(lock);
 }
index 13b243a323fa0a5dfcfd965a0eb39f7d4e35fe45..49b2ed3dced848df34054ff0953ec1077b060655 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/kallsyms.h>
 #include <linux/syscalls.h>
 #include <linux/interrupt.h>
-#include <linux/plist.h>
+#include <linux/rbtree.h>
 #include <linux/fs.h>
 #include <linux/debug_locks.h>
 
@@ -57,7 +57,7 @@ static void printk_lock(struct rt_mutex *lock, int print_owner)
 
 void rt_mutex_debug_task_free(struct task_struct *task)
 {
-       DEBUG_LOCKS_WARN_ON(!plist_head_empty(&task->pi_waiters));
+       DEBUG_LOCKS_WARN_ON(!RB_EMPTY_ROOT(&task->pi_waiters));
        DEBUG_LOCKS_WARN_ON(task->pi_blocked_on);
 }
 
@@ -154,16 +154,12 @@ void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock)
 void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
 {
        memset(waiter, 0x11, sizeof(*waiter));
-       plist_node_init(&waiter->list_entry, MAX_PRIO);
-       plist_node_init(&waiter->pi_list_entry, MAX_PRIO);
        waiter->deadlock_task_pid = NULL;
 }
 
 void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
 {
        put_pid(waiter->deadlock_task_pid);
-       DEBUG_LOCKS_WARN_ON(!plist_node_empty(&waiter->list_entry));
-       DEBUG_LOCKS_WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
        memset(waiter, 0x22, sizeof(*waiter));
 }
 
index 0dd6aec1cb6ad8bb41a44ba74f770ca4439fc022..2e960a2bab81a06ae90d7c48edba6a670d16ebaf 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/sched/rt.h>
+#include <linux/sched/deadline.h>
 #include <linux/timer.h>
 
 #include "rtmutex_common.h"
@@ -91,10 +92,107 @@ static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
 }
 #endif
 
+static inline int
+rt_mutex_waiter_less(struct rt_mutex_waiter *left,
+                    struct rt_mutex_waiter *right)
+{
+       if (left->prio < right->prio)
+               return 1;
+
+       /*
+        * If both waiters have dl_prio(), we check the deadlines of the
+        * associated tasks.
+        * If left waiter has a dl_prio(), and we didn't return 1 above,
+        * then right waiter has a dl_prio() too.
+        */
+       if (dl_prio(left->prio))
+               return (left->task->dl.deadline < right->task->dl.deadline);
+
+       return 0;
+}
+
+static void
+rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
+{
+       struct rb_node **link = &lock->waiters.rb_node;
+       struct rb_node *parent = NULL;
+       struct rt_mutex_waiter *entry;
+       int leftmost = 1;
+
+       while (*link) {
+               parent = *link;
+               entry = rb_entry(parent, struct rt_mutex_waiter, tree_entry);
+               if (rt_mutex_waiter_less(waiter, entry)) {
+                       link = &parent->rb_left;
+               } else {
+                       link = &parent->rb_right;
+                       leftmost = 0;
+               }
+       }
+
+       if (leftmost)
+               lock->waiters_leftmost = &waiter->tree_entry;
+
+       rb_link_node(&waiter->tree_entry, parent, link);
+       rb_insert_color(&waiter->tree_entry, &lock->waiters);
+}
+
+static void
+rt_mutex_dequeue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
+{
+       if (RB_EMPTY_NODE(&waiter->tree_entry))
+               return;
+
+       if (lock->waiters_leftmost == &waiter->tree_entry)
+               lock->waiters_leftmost = rb_next(&waiter->tree_entry);
+
+       rb_erase(&waiter->tree_entry, &lock->waiters);
+       RB_CLEAR_NODE(&waiter->tree_entry);
+}
+
+static void
+rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
+{
+       struct rb_node **link = &task->pi_waiters.rb_node;
+       struct rb_node *parent = NULL;
+       struct rt_mutex_waiter *entry;
+       int leftmost = 1;
+
+       while (*link) {
+               parent = *link;
+               entry = rb_entry(parent, struct rt_mutex_waiter, pi_tree_entry);
+               if (rt_mutex_waiter_less(waiter, entry)) {
+                       link = &parent->rb_left;
+               } else {
+                       link = &parent->rb_right;
+                       leftmost = 0;
+               }
+       }
+
+       if (leftmost)
+               task->pi_waiters_leftmost = &waiter->pi_tree_entry;
+
+       rb_link_node(&waiter->pi_tree_entry, parent, link);
+       rb_insert_color(&waiter->pi_tree_entry, &task->pi_waiters);
+}
+
+static void
+rt_mutex_dequeue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
+{
+       if (RB_EMPTY_NODE(&waiter->pi_tree_entry))
+               return;
+
+       if (task->pi_waiters_leftmost == &waiter->pi_tree_entry)
+               task->pi_waiters_leftmost = rb_next(&waiter->pi_tree_entry);
+
+       rb_erase(&waiter->pi_tree_entry, &task->pi_waiters);
+       RB_CLEAR_NODE(&waiter->pi_tree_entry);
+}
+
 /*
- * Calculate task priority from the waiter list priority
+ * Calculate task priority from the waiter tree priority
  *
- * Return task->normal_prio when the waiter list is empty or when
+ * Return task->normal_prio when the waiter tree is empty or when
  * the waiter is not allowed to do priority boosting
  */
 int rt_mutex_getprio(struct task_struct *task)
@@ -102,10 +200,18 @@ int rt_mutex_getprio(struct task_struct *task)
        if (likely(!task_has_pi_waiters(task)))
                return task->normal_prio;
 
-       return min(task_top_pi_waiter(task)->pi_list_entry.prio,
+       return min(task_top_pi_waiter(task)->prio,
                   task->normal_prio);
 }
 
+struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
+{
+       if (likely(!task_has_pi_waiters(task)))
+               return NULL;
+
+       return task_top_pi_waiter(task)->task;
+}
+
 /*
  * Adjust the priority of a task, after its pi_waiters got modified.
  *
@@ -115,7 +221,7 @@ static void __rt_mutex_adjust_prio(struct task_struct *task)
 {
        int prio = rt_mutex_getprio(task);
 
-       if (task->prio != prio)
+       if (task->prio != prio || dl_prio(prio))
                rt_mutex_setprio(task, prio);
 }
 
@@ -233,7 +339,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
         * When deadlock detection is off then we check, if further
         * priority adjustment is necessary.
         */
-       if (!detect_deadlock && waiter->list_entry.prio == task->prio)
+       if (!detect_deadlock && waiter->prio == task->prio)
                goto out_unlock_pi;
 
        lock = waiter->lock;
@@ -254,9 +360,9 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
        top_waiter = rt_mutex_top_waiter(lock);
 
        /* Requeue the waiter */
-       plist_del(&waiter->list_entry, &lock->wait_list);
-       waiter->list_entry.prio = task->prio;
-       plist_add(&waiter->list_entry, &lock->wait_list);
+       rt_mutex_dequeue(lock, waiter);
+       waiter->prio = task->prio;
+       rt_mutex_enqueue(lock, waiter);
 
        /* Release the task */
        raw_spin_unlock_irqrestore(&task->pi_lock, flags);
@@ -280,17 +386,15 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
 
        if (waiter == rt_mutex_top_waiter(lock)) {
                /* Boost the owner */
-               plist_del(&top_waiter->pi_list_entry, &task->pi_waiters);
-               waiter->pi_list_entry.prio = waiter->list_entry.prio;
-               plist_add(&waiter->pi_list_entry, &task->pi_waiters);
+               rt_mutex_dequeue_pi(task, top_waiter);
+               rt_mutex_enqueue_pi(task, waiter);
                __rt_mutex_adjust_prio(task);
 
        } else if (top_waiter == waiter) {
                /* Deboost the owner */
-               plist_del(&waiter->pi_list_entry, &task->pi_waiters);
+               rt_mutex_dequeue_pi(task, waiter);
                waiter = rt_mutex_top_waiter(lock);
-               waiter->pi_list_entry.prio = waiter->list_entry.prio;
-               plist_add(&waiter->pi_list_entry, &task->pi_waiters);
+               rt_mutex_enqueue_pi(task, waiter);
                __rt_mutex_adjust_prio(task);
        }
 
@@ -355,7 +459,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
         * 3) it is top waiter
         */
        if (rt_mutex_has_waiters(lock)) {
-               if (task->prio >= rt_mutex_top_waiter(lock)->list_entry.prio) {
+               if (task->prio >= rt_mutex_top_waiter(lock)->prio) {
                        if (!waiter || waiter != rt_mutex_top_waiter(lock))
                                return 0;
                }
@@ -369,7 +473,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
 
                /* remove the queued waiter. */
                if (waiter) {
-                       plist_del(&waiter->list_entry, &lock->wait_list);
+                       rt_mutex_dequeue(lock, waiter);
                        task->pi_blocked_on = NULL;
                }
 
@@ -379,8 +483,7 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
                 */
                if (rt_mutex_has_waiters(lock)) {
                        top = rt_mutex_top_waiter(lock);
-                       top->pi_list_entry.prio = top->list_entry.prio;
-                       plist_add(&top->pi_list_entry, &task->pi_waiters);
+                       rt_mutex_enqueue_pi(task, top);
                }
                raw_spin_unlock_irqrestore(&task->pi_lock, flags);
        }
@@ -416,13 +519,12 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
        __rt_mutex_adjust_prio(task);
        waiter->task = task;
        waiter->lock = lock;
-       plist_node_init(&waiter->list_entry, task->prio);
-       plist_node_init(&waiter->pi_list_entry, task->prio);
+       waiter->prio = task->prio;
 
        /* Get the top priority waiter on the lock */
        if (rt_mutex_has_waiters(lock))
                top_waiter = rt_mutex_top_waiter(lock);
-       plist_add(&waiter->list_entry, &lock->wait_list);
+       rt_mutex_enqueue(lock, waiter);
 
        task->pi_blocked_on = waiter;
 
@@ -433,8 +535,8 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
 
        if (waiter == rt_mutex_top_waiter(lock)) {
                raw_spin_lock_irqsave(&owner->pi_lock, flags);
-               plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
-               plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
+               rt_mutex_dequeue_pi(owner, top_waiter);
+               rt_mutex_enqueue_pi(owner, waiter);
 
                __rt_mutex_adjust_prio(owner);
                if (owner->pi_blocked_on)
@@ -486,7 +588,7 @@ static void wakeup_next_waiter(struct rt_mutex *lock)
         * boosted mode and go back to normal after releasing
         * lock->wait_lock.
         */
-       plist_del(&waiter->pi_list_entry, &current->pi_waiters);
+       rt_mutex_dequeue_pi(current, waiter);
 
        rt_mutex_set_owner(lock, NULL);
 
@@ -510,7 +612,7 @@ static void remove_waiter(struct rt_mutex *lock,
        int chain_walk = 0;
 
        raw_spin_lock_irqsave(&current->pi_lock, flags);
-       plist_del(&waiter->list_entry, &lock->wait_list);
+       rt_mutex_dequeue(lock, waiter);
        current->pi_blocked_on = NULL;
        raw_spin_unlock_irqrestore(&current->pi_lock, flags);
 
@@ -521,13 +623,13 @@ static void remove_waiter(struct rt_mutex *lock,
 
                raw_spin_lock_irqsave(&owner->pi_lock, flags);
 
-               plist_del(&waiter->pi_list_entry, &owner->pi_waiters);
+               rt_mutex_dequeue_pi(owner, waiter);
 
                if (rt_mutex_has_waiters(lock)) {
                        struct rt_mutex_waiter *next;
 
                        next = rt_mutex_top_waiter(lock);
-                       plist_add(&next->pi_list_entry, &owner->pi_waiters);
+                       rt_mutex_enqueue_pi(owner, next);
                }
                __rt_mutex_adjust_prio(owner);
 
@@ -537,8 +639,6 @@ static void remove_waiter(struct rt_mutex *lock,
                raw_spin_unlock_irqrestore(&owner->pi_lock, flags);
        }
 
-       WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
-
        if (!chain_walk)
                return;
 
@@ -565,7 +665,8 @@ void rt_mutex_adjust_pi(struct task_struct *task)
        raw_spin_lock_irqsave(&task->pi_lock, flags);
 
        waiter = task->pi_blocked_on;
-       if (!waiter || waiter->list_entry.prio == task->prio) {
+       if (!waiter || (waiter->prio == task->prio &&
+                       !dl_prio(task->prio))) {
                raw_spin_unlock_irqrestore(&task->pi_lock, flags);
                return;
        }
@@ -638,6 +739,8 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
        int ret = 0;
 
        debug_rt_mutex_init_waiter(&waiter);
+       RB_CLEAR_NODE(&waiter.pi_tree_entry);
+       RB_CLEAR_NODE(&waiter.tree_entry);
 
        raw_spin_lock(&lock->wait_lock);
 
@@ -904,7 +1007,8 @@ void __rt_mutex_init(struct rt_mutex *lock, const char *name)
 {
        lock->owner = NULL;
        raw_spin_lock_init(&lock->wait_lock);
-       plist_head_init(&lock->wait_list);
+       lock->waiters = RB_ROOT;
+       lock->waiters_leftmost = NULL;
 
        debug_rt_mutex_init(lock, name);
 }
index 53a66c85261bffc91142709f65610154a011541e..7431a9c86f35a896ebe44b6ffad3741ea4fdda72 100644 (file)
@@ -40,13 +40,13 @@ extern void schedule_rt_mutex_test(struct rt_mutex *lock);
  * This is the control structure for tasks blocked on a rt_mutex,
  * which is allocated on the kernel stack on of the blocked task.
  *
- * @list_entry:                pi node to enqueue into the mutex waiters list
- * @pi_list_entry:     pi node to enqueue into the mutex owner waiters list
+ * @tree_entry:                pi node to enqueue into the mutex waiters tree
+ * @pi_tree_entry:     pi node to enqueue into the mutex owner waiters tree
  * @task:              task reference to the blocked task
  */
 struct rt_mutex_waiter {
-       struct plist_node       list_entry;
-       struct plist_node       pi_list_entry;
+       struct rb_node          tree_entry;
+       struct rb_node          pi_tree_entry;
        struct task_struct      *task;
        struct rt_mutex         *lock;
 #ifdef CONFIG_DEBUG_RT_MUTEXES
@@ -54,14 +54,15 @@ struct rt_mutex_waiter {
        struct pid              *deadlock_task_pid;
        struct rt_mutex         *deadlock_lock;
 #endif
+       int prio;
 };
 
 /*
- * Various helpers to access the waiters-plist:
+ * Various helpers to access the waiters-tree:
  */
 static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
 {
-       return !plist_head_empty(&lock->wait_list);
+       return !RB_EMPTY_ROOT(&lock->waiters);
 }
 
 static inline struct rt_mutex_waiter *
@@ -69,8 +70,8 @@ rt_mutex_top_waiter(struct rt_mutex *lock)
 {
        struct rt_mutex_waiter *w;
 
-       w = plist_first_entry(&lock->wait_list, struct rt_mutex_waiter,
-                              list_entry);
+       w = rb_entry(lock->waiters_leftmost, struct rt_mutex_waiter,
+                    tree_entry);
        BUG_ON(w->lock != lock);
 
        return w;
@@ -78,14 +79,14 @@ rt_mutex_top_waiter(struct rt_mutex *lock)
 
 static inline int task_has_pi_waiters(struct task_struct *p)
 {
-       return !plist_head_empty(&p->pi_waiters);
+       return !RB_EMPTY_ROOT(&p->pi_waiters);
 }
 
 static inline struct rt_mutex_waiter *
 task_top_pi_waiter(struct task_struct *p)
 {
-       return plist_first_entry(&p->pi_waiters, struct rt_mutex_waiter,
-                                 pi_list_entry);
+       return rb_entry(p->pi_waiters_leftmost, struct rt_mutex_waiter,
+                       pi_tree_entry);
 }
 
 /*
index c00b4ceb39e8b151aab790e6b498247ea53a4aa6..6d6300375090e7b2345353174d85ed09f6f35ce4 100644 (file)
@@ -33,7 +33,7 @@ static int pause_on_oops;
 static int pause_on_oops_flag;
 static DEFINE_SPINLOCK(pause_on_oops_lock);
 
-int panic_timeout;
+int panic_timeout = CONFIG_PANIC_TIMEOUT;
 EXPORT_SYMBOL_GPL(panic_timeout);
 
 ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
index c7f31aa272f74276d9d4c37d669303ba43ec1dce..3b8946416a5f836227edcf0db8dd1f8b2eb95063 100644 (file)
@@ -233,7 +233,8 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
 
 /*
  * Sample a process (thread group) clock for the given group_leader task.
- * Must be called with tasklist_lock held for reading.
+ * Must be called with task sighand lock held for safe while_each_thread()
+ * traversal.
  */
 static int cpu_clock_sample_group(const clockid_t which_clock,
                                  struct task_struct *p,
@@ -260,30 +261,53 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
        return 0;
 }
 
+static int posix_cpu_clock_get_task(struct task_struct *tsk,
+                                   const clockid_t which_clock,
+                                   struct timespec *tp)
+{
+       int err = -EINVAL;
+       unsigned long long rtn;
+
+       if (CPUCLOCK_PERTHREAD(which_clock)) {
+               if (same_thread_group(tsk, current))
+                       err = cpu_clock_sample(which_clock, tsk, &rtn);
+       } else {
+               unsigned long flags;
+               struct sighand_struct *sighand;
+
+               /*
+                * while_each_thread() is not yet entirely RCU safe,
+                * keep locking the group while sampling process
+                * clock for now.
+                */
+               sighand = lock_task_sighand(tsk, &flags);
+               if (!sighand)
+                       return err;
+
+               if (tsk == current || thread_group_leader(tsk))
+                       err = cpu_clock_sample_group(which_clock, tsk, &rtn);
+
+               unlock_task_sighand(tsk, &flags);
+       }
+
+       if (!err)
+               sample_to_timespec(which_clock, rtn, tp);
+
+       return err;
+}
+
 
 static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
 {
        const pid_t pid = CPUCLOCK_PID(which_clock);
-       int error = -EINVAL;
-       unsigned long long rtn;
+       int err = -EINVAL;
 
        if (pid == 0) {
                /*
                 * Special case constant value for our own clocks.
                 * We don't have to do any lookup to find ourselves.
                 */
-               if (CPUCLOCK_PERTHREAD(which_clock)) {
-                       /*
-                        * Sampling just ourselves we can do with no locking.
-                        */
-                       error = cpu_clock_sample(which_clock,
-                                                current, &rtn);
-               } else {
-                       read_lock(&tasklist_lock);
-                       error = cpu_clock_sample_group(which_clock,
-                                                      current, &rtn);
-                       read_unlock(&tasklist_lock);
-               }
+               err = posix_cpu_clock_get_task(current, which_clock, tp);
        } else {
                /*
                 * Find the given PID, and validate that the caller
@@ -292,29 +316,12 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
                struct task_struct *p;
                rcu_read_lock();
                p = find_task_by_vpid(pid);
-               if (p) {
-                       if (CPUCLOCK_PERTHREAD(which_clock)) {
-                               if (same_thread_group(p, current)) {
-                                       error = cpu_clock_sample(which_clock,
-                                                                p, &rtn);
-                               }
-                       } else {
-                               read_lock(&tasklist_lock);
-                               if (thread_group_leader(p) && p->sighand) {
-                                       error =
-                                           cpu_clock_sample_group(which_clock,
-                                                                  p, &rtn);
-                               }
-                               read_unlock(&tasklist_lock);
-                       }
-               }
+               if (p)
+                       err = posix_cpu_clock_get_task(p, which_clock, tp);
                rcu_read_unlock();
        }
 
-       if (error)
-               return error;
-       sample_to_timespec(which_clock, rtn, tp);
-       return 0;
+       return err;
 }
 
 
@@ -371,36 +378,40 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
  */
 static int posix_cpu_timer_del(struct k_itimer *timer)
 {
-       struct task_struct *p = timer->it.cpu.task;
        int ret = 0;
+       unsigned long flags;
+       struct sighand_struct *sighand;
+       struct task_struct *p = timer->it.cpu.task;
 
-       if (likely(p != NULL)) {
-               read_lock(&tasklist_lock);
-               if (unlikely(p->sighand == NULL)) {
-                       /*
-                        * We raced with the reaping of the task.
-                        * The deletion should have cleared us off the list.
-                        */
-                       BUG_ON(!list_empty(&timer->it.cpu.entry));
-               } else {
-                       spin_lock(&p->sighand->siglock);
-                       if (timer->it.cpu.firing)
-                               ret = TIMER_RETRY;
-                       else
-                               list_del(&timer->it.cpu.entry);
-                       spin_unlock(&p->sighand->siglock);
-               }
-               read_unlock(&tasklist_lock);
+       WARN_ON_ONCE(p == NULL);
 
-               if (!ret)
-                       put_task_struct(p);
+       /*
+        * Protect against sighand release/switch in exit/exec and process/
+        * thread timer list entry concurrent read/writes.
+        */
+       sighand = lock_task_sighand(p, &flags);
+       if (unlikely(sighand == NULL)) {
+               /*
+                * We raced with the reaping of the task.
+                * The deletion should have cleared us off the list.
+                */
+               WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry));
+       } else {
+               if (timer->it.cpu.firing)
+                       ret = TIMER_RETRY;
+               else
+                       list_del(&timer->it.cpu.entry);
+
+               unlock_task_sighand(p, &flags);
        }
 
+       if (!ret)
+               put_task_struct(p);
+
        return ret;
 }
 
-static void cleanup_timers_list(struct list_head *head,
-                               unsigned long long curr)
+static void cleanup_timers_list(struct list_head *head)
 {
        struct cpu_timer_list *timer, *next;
 
@@ -414,16 +425,11 @@ static void cleanup_timers_list(struct list_head *head,
  * time for later timer_gettime calls to return.
  * This must be called with the siglock held.
  */
-static void cleanup_timers(struct list_head *head,
-                          cputime_t utime, cputime_t stime,
-                          unsigned long long sum_exec_runtime)
+static void cleanup_timers(struct list_head *head)
 {
-
-       cputime_t ptime = utime + stime;
-
-       cleanup_timers_list(head, cputime_to_expires(ptime));
-       cleanup_timers_list(++head, cputime_to_expires(utime));
-       cleanup_timers_list(++head, sum_exec_runtime);
+       cleanup_timers_list(head);
+       cleanup_timers_list(++head);
+       cleanup_timers_list(++head);
 }
 
 /*
@@ -433,41 +439,14 @@ static void cleanup_timers(struct list_head *head,
  */
 void posix_cpu_timers_exit(struct task_struct *tsk)
 {
-       cputime_t utime, stime;
-
        add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
                                                sizeof(unsigned long long));
-       task_cputime(tsk, &utime, &stime);
-       cleanup_timers(tsk->cpu_timers,
-                      utime, stime, tsk->se.sum_exec_runtime);
+       cleanup_timers(tsk->cpu_timers);
 
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
 {
-       struct signal_struct *const sig = tsk->signal;
-       cputime_t utime, stime;
-
-       task_cputime(tsk, &utime, &stime);
-       cleanup_timers(tsk->signal->cpu_timers,
-                      utime + sig->utime, stime + sig->stime,
-                      tsk->se.sum_exec_runtime + sig->sum_sched_runtime);
-}
-
-static void clear_dead_task(struct k_itimer *itimer, unsigned long long now)
-{
-       struct cpu_timer_list *timer = &itimer->it.cpu;
-
-       /*
-        * That's all for this thread or process.
-        * We leave our residual in expires to be reported.
-        */
-       put_task_struct(timer->task);
-       timer->task = NULL;
-       if (timer->expires < now) {
-               timer->expires = 0;
-       } else {
-               timer->expires -= now;
-       }
+       cleanup_timers(tsk->signal->cpu_timers);
 }
 
 static inline int expires_gt(cputime_t expires, cputime_t new_exp)
@@ -477,8 +456,7 @@ static inline int expires_gt(cputime_t expires, cputime_t new_exp)
 
 /*
  * Insert the timer on the appropriate list before any timers that
- * expire later.  This must be called with the tasklist_lock held
- * for reading, interrupts disabled and p->sighand->siglock taken.
+ * expire later.  This must be called with the sighand lock held.
  */
 static void arm_timer(struct k_itimer *timer)
 {
@@ -569,7 +547,8 @@ static void cpu_timer_fire(struct k_itimer *timer)
 
 /*
  * Sample a process (thread group) timer for the given group_leader task.
- * Must be called with tasklist_lock held for reading.
+ * Must be called with task sighand lock held for safe while_each_thread()
+ * traversal.
  */
 static int cpu_timer_sample_group(const clockid_t which_clock,
                                  struct task_struct *p,
@@ -608,7 +587,8 @@ static DECLARE_WORK(nohz_kick_work, nohz_kick_work_fn);
  */
 static void posix_cpu_timer_kick_nohz(void)
 {
-       schedule_work(&nohz_kick_work);
+       if (context_tracking_is_enabled())
+               schedule_work(&nohz_kick_work);
 }
 
 bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk)
@@ -631,43 +611,39 @@ static inline void posix_cpu_timer_kick_nohz(void) { }
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
  * and try again.  (This happens when the timer is in the middle of firing.)
  */
-static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
+static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
                               struct itimerspec *new, struct itimerspec *old)
 {
+       unsigned long flags;
+       struct sighand_struct *sighand;
        struct task_struct *p = timer->it.cpu.task;
        unsigned long long old_expires, new_expires, old_incr, val;
        int ret;
 
-       if (unlikely(p == NULL)) {
-               /*
-                * Timer refers to a dead task's clock.
-                */
-               return -ESRCH;
-       }
+       WARN_ON_ONCE(p == NULL);
 
        new_expires = timespec_to_sample(timer->it_clock, &new->it_value);
 
-       read_lock(&tasklist_lock);
        /*
-        * We need the tasklist_lock to protect against reaping that
-        * clears p->sighand.  If p has just been reaped, we can no
+        * Protect against sighand release/switch in exit/exec and p->cpu_timers
+        * and p->signal->cpu_timers read/write in arm_timer()
+        */
+       sighand = lock_task_sighand(p, &flags);
+       /*
+        * If p has just been reaped, we can no
         * longer get any information about it at all.
         */
-       if (unlikely(p->sighand == NULL)) {
-               read_unlock(&tasklist_lock);
-               put_task_struct(p);
-               timer->it.cpu.task = NULL;
+       if (unlikely(sighand == NULL)) {
                return -ESRCH;
        }
 
        /*
         * Disarm any old timer after extracting its expiry time.
         */
-       BUG_ON(!irqs_disabled());
+       WARN_ON_ONCE(!irqs_disabled());
 
        ret = 0;
        old_incr = timer->it.cpu.incr;
-       spin_lock(&p->sighand->siglock);
        old_expires = timer->it.cpu.expires;
        if (unlikely(timer->it.cpu.firing)) {
                timer->it.cpu.firing = -1;
@@ -724,12 +700,11 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
                 * disable this firing since we are already reporting
                 * it as an overrun (thanks to bump_cpu_timer above).
                 */
-               spin_unlock(&p->sighand->siglock);
-               read_unlock(&tasklist_lock);
+               unlock_task_sighand(p, &flags);
                goto out;
        }
 
-       if (new_expires != 0 && !(flags & TIMER_ABSTIME)) {
+       if (new_expires != 0 && !(timer_flags & TIMER_ABSTIME)) {
                new_expires += val;
        }
 
@@ -743,9 +718,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int flags,
                arm_timer(timer);
        }
 
-       spin_unlock(&p->sighand->siglock);
-       read_unlock(&tasklist_lock);
-
+       unlock_task_sighand(p, &flags);
        /*
         * Install the new reload setting, and
         * set up the signal and overrun bookkeeping.
@@ -787,7 +760,8 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 {
        unsigned long long now;
        struct task_struct *p = timer->it.cpu.task;
-       int clear_dead;
+
+       WARN_ON_ONCE(p == NULL);
 
        /*
         * Easy part: convert the reload time.
@@ -800,52 +774,34 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
                return;
        }
 
-       if (unlikely(p == NULL)) {
-               /*
-                * This task already died and the timer will never fire.
-                * In this case, expires is actually the dead value.
-                */
-       dead:
-               sample_to_timespec(timer->it_clock, timer->it.cpu.expires,
-                                  &itp->it_value);
-               return;
-       }
-
        /*
         * Sample the clock to take the difference with the expiry time.
         */
        if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
                cpu_clock_sample(timer->it_clock, p, &now);
-               clear_dead = p->exit_state;
        } else {
-               read_lock(&tasklist_lock);
-               if (unlikely(p->sighand == NULL)) {
+               struct sighand_struct *sighand;
+               unsigned long flags;
+
+               /*
+                * Protect against sighand release/switch in exit/exec and
+                * also make timer sampling safe if it ends up calling
+                * thread_group_cputime().
+                */
+               sighand = lock_task_sighand(p, &flags);
+               if (unlikely(sighand == NULL)) {
                        /*
                         * The process has been reaped.
                         * We can't even collect a sample any more.
                         * Call the timer disarmed, nothing else to do.
                         */
-                       put_task_struct(p);
-                       timer->it.cpu.task = NULL;
                        timer->it.cpu.expires = 0;
-                       read_unlock(&tasklist_lock);
-                       goto dead;
+                       sample_to_timespec(timer->it_clock, timer->it.cpu.expires,
+                                          &itp->it_value);
                } else {
                        cpu_timer_sample_group(timer->it_clock, p, &now);
-                       clear_dead = (unlikely(p->exit_state) &&
-                                     thread_group_empty(p));
+                       unlock_task_sighand(p, &flags);
                }
-               read_unlock(&tasklist_lock);
-       }
-
-       if (unlikely(clear_dead)) {
-               /*
-                * We've noticed that the thread is dead, but
-                * not yet reaped.  Take this opportunity to
-                * drop our task ref.
-                */
-               clear_dead_task(timer, now);
-               goto dead;
        }
 
        if (now < timer->it.cpu.expires) {
@@ -1059,14 +1015,12 @@ static void check_process_timers(struct task_struct *tsk,
  */
 void posix_cpu_timer_schedule(struct k_itimer *timer)
 {
+       struct sighand_struct *sighand;
+       unsigned long flags;
        struct task_struct *p = timer->it.cpu.task;
        unsigned long long now;
 
-       if (unlikely(p == NULL))
-               /*
-                * The task was cleaned up already, no future firings.
-                */
-               goto out;
+       WARN_ON_ONCE(p == NULL);
 
        /*
         * Fetch the current sample and update the timer's expiry time.
@@ -1074,49 +1028,45 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
        if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
                cpu_clock_sample(timer->it_clock, p, &now);
                bump_cpu_timer(timer, now);
-               if (unlikely(p->exit_state)) {
-                       clear_dead_task(timer, now);
+               if (unlikely(p->exit_state))
+                       goto out;
+
+               /* Protect timer list r/w in arm_timer() */
+               sighand = lock_task_sighand(p, &flags);
+               if (!sighand)
                        goto out;
-               }
-               read_lock(&tasklist_lock); /* arm_timer needs it.  */
-               spin_lock(&p->sighand->siglock);
        } else {
-               read_lock(&tasklist_lock);
-               if (unlikely(p->sighand == NULL)) {
+               /*
+                * Protect arm_timer() and timer sampling in case of call to
+                * thread_group_cputime().
+                */
+               sighand = lock_task_sighand(p, &flags);
+               if (unlikely(sighand == NULL)) {
                        /*
                         * The process has been reaped.
                         * We can't even collect a sample any more.
                         */
-                       put_task_struct(p);
-                       timer->it.cpu.task = p = NULL;
                        timer->it.cpu.expires = 0;
-                       goto out_unlock;
+                       goto out;
                } else if (unlikely(p->exit_state) && thread_group_empty(p)) {
-                       /*
-                        * We've noticed that the thread is dead, but
-                        * not yet reaped.  Take this opportunity to
-                        * drop our task ref.
-                        */
-                       cpu_timer_sample_group(timer->it_clock, p, &now);
-                       clear_dead_task(timer, now);
-                       goto out_unlock;
+                       unlock_task_sighand(p, &flags);
+                       /* Optimizations: if the process is dying, no need to rearm */
+                       goto out;
                }
-               spin_lock(&p->sighand->siglock);
                cpu_timer_sample_group(timer->it_clock, p, &now);
                bump_cpu_timer(timer, now);
-               /* Leave the tasklist_lock locked for the call below.  */
+               /* Leave the sighand locked for the call below.  */
        }
 
        /*
         * Now re-arm for the new expiry time.
         */
-       BUG_ON(!irqs_disabled());
+       WARN_ON_ONCE(!irqs_disabled());
        arm_timer(timer);
-       spin_unlock(&p->sighand->siglock);
-
-out_unlock:
-       read_unlock(&tasklist_lock);
+       unlock_task_sighand(p, &flags);
 
+       /* Kick full dynticks CPUs in case they need to tick on the new timer */
+       posix_cpu_timer_kick_nohz();
 out:
        timer->it_overrun_last = timer->it_overrun;
        timer->it_overrun = -1;
@@ -1200,7 +1150,7 @@ void run_posix_cpu_timers(struct task_struct *tsk)
        struct k_itimer *timer, *next;
        unsigned long flags;
 
-       BUG_ON(!irqs_disabled());
+       WARN_ON_ONCE(!irqs_disabled());
 
        /*
         * The fast path checks that there are no expired thread or thread
@@ -1256,13 +1206,6 @@ void run_posix_cpu_timers(struct task_struct *tsk)
                        cpu_timer_fire(timer);
                spin_unlock(&timer->it_lock);
        }
-
-       /*
-        * In case some timers were rescheduled after the queue got emptied,
-        * wake up full dynticks CPUs.
-        */
-       if (tsk->signal->cputimer.running)
-               posix_cpu_timer_kick_nohz();
 }
 
 /*
@@ -1274,7 +1217,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 {
        unsigned long long now;
 
-       BUG_ON(clock_idx == CPUCLOCK_SCHED);
+       WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED);
        cpu_timer_sample_group(clock_idx, tsk, &now);
 
        if (oldval) {
index 463aa6736751a0a12d949ddeb93330b6067f053b..eacb8bd8cab4e1205230ecfdde12483be9846cf7 100644 (file)
@@ -81,6 +81,7 @@ void pm_vt_switch_unregister(struct device *dev)
        list_for_each_entry(tmp, &pm_vt_switch_list, head) {
                if (tmp->dev == dev) {
                        list_del(&tmp->head);
+                       kfree(tmp);
                        break;
                }
        }
index 7859a0a3951eae09e50a11df267213af0f6bace4..79c3877e9c5b83e089ef319a2e72a9aaddde6fa3 100644 (file)
@@ -96,19 +96,22 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
 }
 #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
-extern void kfree(const void *);
+void kfree(const void *);
 
 static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
 {
        unsigned long offset = (unsigned long)head->func;
 
+       rcu_lock_acquire(&rcu_callback_map);
        if (__is_kfree_rcu_offset(offset)) {
                RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset));
                kfree((void *)head - offset);
+               rcu_lock_release(&rcu_callback_map);
                return 1;
        } else {
                RCU_TRACE(trace_rcu_invoke_callback(rn, head));
                head->func(head);
+               rcu_lock_release(&rcu_callback_map);
                return 0;
        }
 }
index 01d5ccb8bfe3d96cf3cba70d217a8bddf0ff5f8a..3318d82843841971f4926d8a8f9eb9a375e2eab3 100644 (file)
@@ -363,6 +363,29 @@ static void srcu_flip(struct srcu_struct *sp)
 /*
  * Enqueue an SRCU callback on the specified srcu_struct structure,
  * initiating grace-period processing if it is not already running.
+ *
+ * Note that all CPUs must agree that the grace period extended beyond
+ * all pre-existing SRCU read-side critical section.  On systems with
+ * more than one CPU, this means that when "func()" is invoked, each CPU
+ * is guaranteed to have executed a full memory barrier since the end of
+ * its last corresponding SRCU read-side critical section whose beginning
+ * preceded the call to call_rcu().  It also means that each CPU executing
+ * an SRCU read-side critical section that continues beyond the start of
+ * "func()" must have executed a memory barrier after the call_rcu()
+ * but before the beginning of that SRCU read-side critical section.
+ * Note that these guarantees include CPUs that are offline, idle, or
+ * executing in user mode, as well as CPUs that are executing in the kernel.
+ *
+ * Furthermore, if CPU A invoked call_rcu() and CPU B invoked the
+ * resulting SRCU callback function "func()", then both CPU A and CPU
+ * B are guaranteed to execute a full memory barrier during the time
+ * interval between the call to call_rcu() and the invocation of "func()".
+ * This guarantee applies even if CPU A and CPU B are the same CPU (but
+ * again only if the system has more than one CPU).
+ *
+ * Of course, these guarantees apply only for invocations of call_srcu(),
+ * srcu_read_lock(), and srcu_read_unlock() that are all passed the same
+ * srcu_struct structure.
  */
 void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
                void (*func)(struct rcu_head *head))
@@ -459,7 +482,30 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
  * Note that it is illegal to call synchronize_srcu() from the corresponding
  * SRCU read-side critical section; doing so will result in deadlock.
  * However, it is perfectly legal to call synchronize_srcu() on one
- * srcu_struct from some other srcu_struct's read-side critical section.
+ * srcu_struct from some other srcu_struct's read-side critical section,
+ * as long as the resulting graph of srcu_structs is acyclic.
+ *
+ * There are memory-ordering constraints implied by synchronize_srcu().
+ * On systems with more than one CPU, when synchronize_srcu() returns,
+ * each CPU is guaranteed to have executed a full memory barrier since
+ * the end of its last corresponding SRCU-sched read-side critical section
+ * whose beginning preceded the call to synchronize_srcu().  In addition,
+ * each CPU having an SRCU read-side critical section that extends beyond
+ * the return from synchronize_srcu() is guaranteed to have executed a
+ * full memory barrier after the beginning of synchronize_srcu() and before
+ * the beginning of that SRCU read-side critical section.  Note that these
+ * guarantees include CPUs that are offline, idle, or executing in user mode,
+ * as well as CPUs that are executing in the kernel.
+ *
+ * Furthermore, if CPU A invoked synchronize_srcu(), which returned
+ * to its caller on CPU B, then both CPU A and CPU B are guaranteed
+ * to have executed a full memory barrier during the execution of
+ * synchronize_srcu().  This guarantee applies even if CPU A and CPU B
+ * are the same CPU, but again only if the system has more than one CPU.
+ *
+ * Of course, these memory-ordering guarantees apply only when
+ * synchronize_srcu(), srcu_read_lock(), and srcu_read_unlock() are
+ * passed the same srcu_struct structure.
  */
 void synchronize_srcu(struct srcu_struct *sp)
 {
@@ -476,12 +522,8 @@ EXPORT_SYMBOL_GPL(synchronize_srcu);
  * Wait for an SRCU grace period to elapse, but be more aggressive about
  * spinning rather than blocking when waiting.
  *
- * Note that it is also illegal to call synchronize_srcu_expedited()
- * from the corresponding SRCU read-side critical section;
- * doing so will result in deadlock.  However, it is perfectly legal
- * to call synchronize_srcu_expedited() on one srcu_struct from some
- * other srcu_struct's read-side critical section, as long as
- * the resulting graph of srcu_structs is acyclic.
+ * Note that synchronize_srcu_expedited() has the same deadlock and
+ * memory-ordering properties as does synchronize_srcu().
  */
 void synchronize_srcu_expedited(struct srcu_struct *sp)
 {
@@ -491,6 +533,7 @@ EXPORT_SYMBOL_GPL(synchronize_srcu_expedited);
 
 /**
  * srcu_barrier - Wait until all in-flight call_srcu() callbacks complete.
+ * @sp: srcu_struct on which to wait for in-flight callbacks.
  */
 void srcu_barrier(struct srcu_struct *sp)
 {
index 3929cd451511ef18b03c33d33a34d9b263151153..732f8ae3086a163c22329ecda6a77bf9aa018b79 100644 (file)
@@ -139,8 +139,6 @@ MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
 #define VERBOSE_PRINTK_ERRSTRING(s) \
        do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
 
-static char printk_buf[4096];
-
 static int nrealreaders;
 static struct task_struct *writer_task;
 static struct task_struct **fakewriter_tasks;
@@ -376,7 +374,7 @@ struct rcu_torture_ops {
        void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
        void (*cb_barrier)(void);
        void (*fqs)(void);
-       int (*stats)(char *page);
+       void (*stats)(char *page);
        int irq_capable;
        int can_boost;
        const char *name;
@@ -578,21 +576,19 @@ static void srcu_torture_barrier(void)
        srcu_barrier(&srcu_ctl);
 }
 
-static int srcu_torture_stats(char *page)
+static void srcu_torture_stats(char *page)
 {
-       int cnt = 0;
        int cpu;
        int idx = srcu_ctl.completed & 0x1;
 
-       cnt += sprintf(&page[cnt], "%s%s per-CPU(idx=%d):",
+       page += sprintf(page, "%s%s per-CPU(idx=%d):",
                       torture_type, TORTURE_FLAG, idx);
        for_each_possible_cpu(cpu) {
-               cnt += sprintf(&page[cnt], " %d(%lu,%lu)", 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]);
        }
-       cnt += sprintf(&page[cnt], "\n");
-       return cnt;
+       sprintf(page, "\n");
 }
 
 static void srcu_torture_synchronize_expedited(void)
@@ -1052,10 +1048,9 @@ rcu_torture_reader(void *arg)
 /*
  * Create an RCU-torture statistics message in the specified buffer.
  */
-static int
+static void
 rcu_torture_printk(char *page)
 {
-       int cnt = 0;
        int cpu;
        int i;
        long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
@@ -1071,8 +1066,8 @@ rcu_torture_printk(char *page)
                if (pipesummary[i] != 0)
                        break;
        }
-       cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
-       cnt += sprintf(&page[cnt],
+       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,
@@ -1080,53 +1075,52 @@ rcu_torture_printk(char *page)
                       atomic_read(&n_rcu_torture_alloc),
                       atomic_read(&n_rcu_torture_alloc_fail),
                       atomic_read(&n_rcu_torture_free));
-       cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ",
+       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);
-       cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ",
+       page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ",
                       n_rcu_torture_boost_failure,
                       n_rcu_torture_boosts,
                       n_rcu_torture_timers);
-       cnt += sprintf(&page[cnt],
+       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);
-       cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld",
+       page += sprintf(page, "barrier: %ld/%ld:%ld",
                       n_barrier_successes,
                       n_barrier_attempts,
                       n_rcu_torture_barrier_error);
-       cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
+       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) {
-               cnt += sprintf(&page[cnt], "!!! ");
+               page += sprintf(page, "!!! ");
                atomic_inc(&n_rcu_torture_error);
                WARN_ON_ONCE(1);
        }
-       cnt += sprintf(&page[cnt], "Reader Pipe: ");
+       page += sprintf(page, "Reader Pipe: ");
        for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
-               cnt += sprintf(&page[cnt], " %ld", pipesummary[i]);
-       cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
-       cnt += sprintf(&page[cnt], "Reader Batch: ");
+               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++)
-               cnt += sprintf(&page[cnt], " %ld", batchsummary[i]);
-       cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
-       cnt += sprintf(&page[cnt], "Free-Block Circulation: ");
+               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++) {
-               cnt += sprintf(&page[cnt], " %d",
+               page += sprintf(page, " %d",
                               atomic_read(&rcu_torture_wcount[i]));
        }
-       cnt += sprintf(&page[cnt], "\n");
+       page += sprintf(page, "\n");
        if (cur_ops->stats)
-               cnt += cur_ops->stats(&page[cnt]);
-       return cnt;
+               cur_ops->stats(page);
 }
 
 /*
@@ -1140,10 +1134,17 @@ rcu_torture_printk(char *page)
 static void
 rcu_torture_stats_print(void)
 {
-       int cnt;
+       int size = nr_cpu_ids * 200 + 8192;
+       char *buf;
 
-       cnt = rcu_torture_printk(printk_buf);
-       pr_alert("%s", printk_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);
 }
 
 /*
@@ -1578,6 +1579,7 @@ 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);
@@ -1585,10 +1587,11 @@ static int rcu_torture_barrier_cbs(void *arg)
        set_user_nice(current, 19);
        do {
                wait_event(barrier_cbs_wq[myid],
-                          barrier_phase != lastphase ||
+                          (newphase =
+                           ACCESS_ONCE(barrier_phase)) != lastphase ||
                           kthread_should_stop() ||
                           fullstop != FULLSTOP_DONTSTOP);
-               lastphase = barrier_phase;
+               lastphase = newphase;
                smp_mb(); /* ensure barrier_phase load before ->call(). */
                if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
                        break;
@@ -1625,7 +1628,7 @@ static int rcu_torture_barrier(void *arg)
                if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
                        break;
                n_barrier_attempts++;
-               cur_ops->cb_barrier();
+               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);
index dd081987a8ec62349ad7721476cb97606077f28a..b3d116cd072d7bd24803a52c8d6b478930bd6b8b 100644 (file)
@@ -369,6 +369,9 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp)
 static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
                                bool user)
 {
+       struct rcu_state *rsp;
+       struct rcu_data *rdp;
+
        trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting);
        if (!user && !is_idle_task(current)) {
                struct task_struct *idle __maybe_unused =
@@ -380,6 +383,10 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
                          current->pid, current->comm,
                          idle->pid, idle->comm); /* must be idle task! */
        }
+       for_each_rcu_flavor(rsp) {
+               rdp = this_cpu_ptr(rsp->rda);
+               do_nocb_deferred_wakeup(rdp);
+       }
        rcu_prepare_for_idle(smp_processor_id());
        /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */
        smp_mb__before_atomic_inc();  /* See above. */
@@ -411,11 +418,12 @@ static void rcu_eqs_enter(bool user)
        rdtp = this_cpu_ptr(&rcu_dynticks);
        oldval = rdtp->dynticks_nesting;
        WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0);
-       if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE)
+       if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) {
                rdtp->dynticks_nesting = 0;
-       else
+               rcu_eqs_enter_common(rdtp, oldval, user);
+       } else {
                rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE;
-       rcu_eqs_enter_common(rdtp, oldval, user);
+       }
 }
 
 /**
@@ -533,11 +541,12 @@ static void rcu_eqs_exit(bool user)
        rdtp = this_cpu_ptr(&rcu_dynticks);
        oldval = rdtp->dynticks_nesting;
        WARN_ON_ONCE(oldval < 0);
-       if (oldval & DYNTICK_TASK_NEST_MASK)
+       if (oldval & DYNTICK_TASK_NEST_MASK) {
                rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE;
-       else
+       } else {
                rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
-       rcu_eqs_exit_common(rdtp, oldval, user);
+               rcu_eqs_exit_common(rdtp, oldval, user);
+       }
 }
 
 /**
@@ -716,7 +725,7 @@ bool rcu_lockdep_current_cpu_online(void)
        bool ret;
 
        if (in_nmi())
-               return 1;
+               return true;
        preempt_disable();
        rdp = this_cpu_ptr(&rcu_sched_data);
        rnp = rdp->mynode;
@@ -754,6 +763,12 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp,
        return (rdp->dynticks_snap & 0x1) == 0;
 }
 
+/*
+ * This function really isn't for public consumption, but RCU is special in
+ * that context switches can allow the state machine to make progress.
+ */
+extern void resched_cpu(int cpu);
+
 /*
  * Return true if the specified CPU has passed through a quiescent
  * state by virtue of being in or having passed through an dynticks
@@ -812,16 +827,34 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
         */
        rcu_kick_nohz_cpu(rdp->cpu);
 
+       /*
+        * Alternatively, the CPU might be running in the kernel
+        * for an extended period of time without a quiescent state.
+        * Attempt to force the CPU through the scheduler to gain the
+        * needed quiescent state, but only if the grace period has gone
+        * on for an uncommonly long time.  If there are many stuck CPUs,
+        * we will beat on the first one until it gets unstuck, then move
+        * 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)) {
+               rdp->rsp->jiffies_resched += 5;
+               resched_cpu(rdp->cpu);
+       }
+
        return 0;
 }
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
        unsigned long j = ACCESS_ONCE(jiffies);
+       unsigned long j1;
 
        rsp->gp_start = j;
        smp_wmb(); /* Record start time before stall time. */
-       rsp->jiffies_stall = j + rcu_jiffies_till_stall_check();
+       j1 = rcu_jiffies_till_stall_check();
+       rsp->jiffies_stall = j + j1;
+       rsp->jiffies_resched = j + j1 / 2;
 }
 
 /*
@@ -1133,8 +1166,10 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp)
         * hold it, acquire the root rcu_node structure's lock in order to
         * start one (if needed).
         */
-       if (rnp != rnp_root)
+       if (rnp != rnp_root) {
                raw_spin_lock(&rnp_root->lock);
+               smp_mb__after_unlock_lock();
+       }
 
        /*
         * Get a new grace-period number.  If there really is no grace
@@ -1354,6 +1389,7 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp)
                local_irq_restore(flags);
                return;
        }
+       smp_mb__after_unlock_lock();
        __note_gp_changes(rsp, rnp, rdp);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 }
@@ -1368,6 +1404,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
 
        rcu_bind_gp_kthread();
        raw_spin_lock_irq(&rnp->lock);
+       smp_mb__after_unlock_lock();
        if (rsp->gp_flags == 0) {
                /* Spurious wakeup, tell caller to go back to sleep.  */
                raw_spin_unlock_irq(&rnp->lock);
@@ -1409,6 +1446,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
         */
        rcu_for_each_node_breadth_first(rsp, rnp) {
                raw_spin_lock_irq(&rnp->lock);
+               smp_mb__after_unlock_lock();
                rdp = this_cpu_ptr(rsp->rda);
                rcu_preempt_check_blocked_tasks(rnp);
                rnp->qsmask = rnp->qsmaskinit;
@@ -1463,6 +1501,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
        /* Clear flag to prevent immediate re-entry. */
        if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
                raw_spin_lock_irq(&rnp->lock);
+               smp_mb__after_unlock_lock();
                rsp->gp_flags &= ~RCU_GP_FLAG_FQS;
                raw_spin_unlock_irq(&rnp->lock);
        }
@@ -1480,6 +1519,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        raw_spin_lock_irq(&rnp->lock);
+       smp_mb__after_unlock_lock();
        gp_duration = jiffies - rsp->gp_start;
        if (gp_duration > rsp->gp_max)
                rsp->gp_max = gp_duration;
@@ -1505,16 +1545,19 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
         */
        rcu_for_each_node_breadth_first(rsp, rnp) {
                raw_spin_lock_irq(&rnp->lock);
+               smp_mb__after_unlock_lock();
                ACCESS_ONCE(rnp->completed) = rsp->gpnum;
                rdp = this_cpu_ptr(rsp->rda);
                if (rnp == rdp->mynode)
                        __note_gp_changes(rsp, rnp, rdp);
+               /* smp_mb() provided by prior unlock-lock pair. */
                nocb += rcu_future_gp_cleanup(rsp, rnp);
                raw_spin_unlock_irq(&rnp->lock);
                cond_resched();
        }
        rnp = rcu_get_root(rsp);
        raw_spin_lock_irq(&rnp->lock);
+       smp_mb__after_unlock_lock();
        rcu_nocb_gp_set(rnp, nocb);
 
        rsp->completed = rsp->gpnum; /* Declare grace period done. */
@@ -1553,6 +1596,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
                        wait_event_interruptible(rsp->gp_wq,
                                                 ACCESS_ONCE(rsp->gp_flags) &
                                                 RCU_GP_FLAG_INIT);
+                       /* Locking provides needed memory barrier. */
                        if (rcu_gp_init(rsp))
                                break;
                        cond_resched();
@@ -1582,6 +1626,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
                                        (!ACCESS_ONCE(rnp->qsmask) &&
                                         !rcu_preempt_blocked_readers_cgp(rnp)),
                                        j);
+                       /* Locking provides needed memory barriers. */
                        /* If grace period done, leave loop. */
                        if (!ACCESS_ONCE(rnp->qsmask) &&
                            !rcu_preempt_blocked_readers_cgp(rnp))
@@ -1749,6 +1794,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
                rnp_c = rnp;
                rnp = rnp->parent;
                raw_spin_lock_irqsave(&rnp->lock, flags);
+               smp_mb__after_unlock_lock();
                WARN_ON_ONCE(rnp_c->qsmask);
        }
 
@@ -1778,6 +1824,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
 
        rnp = rdp->mynode;
        raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
        if (rdp->passed_quiesce == 0 || rdp->gpnum != rnp->gpnum ||
            rnp->completed == rnp->gpnum) {
 
@@ -1901,13 +1948,13 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
  * Adopt the RCU callbacks from the specified rcu_state structure's
  * orphanage.  The caller must hold the ->orphan_lock.
  */
-static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
+static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
 {
        int i;
        struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
 
        /* No-CBs CPUs are handled specially. */
-       if (rcu_nocb_adopt_orphan_cbs(rsp, rdp))
+       if (rcu_nocb_adopt_orphan_cbs(rsp, rdp, flags))
                return;
 
        /* Do the accounting first. */
@@ -1986,12 +2033,13 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
 
        /* Orphan the dead CPU's callbacks, and adopt them if appropriate. */
        rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);
-       rcu_adopt_orphan_cbs(rsp);
+       rcu_adopt_orphan_cbs(rsp, flags);
 
        /* Remove the outgoing CPU from the masks in the rcu_node hierarchy. */
        mask = rdp->grpmask;    /* rnp->grplo is constant. */
        do {
                raw_spin_lock(&rnp->lock);      /* irqs already disabled. */
+               smp_mb__after_unlock_lock();
                rnp->qsmaskinit &= ~mask;
                if (rnp->qsmaskinit != 0) {
                        if (rnp != rdp->mynode)
@@ -2202,6 +2250,7 @@ static void force_qs_rnp(struct rcu_state *rsp,
                cond_resched();
                mask = 0;
                raw_spin_lock_irqsave(&rnp->lock, flags);
+               smp_mb__after_unlock_lock();
                if (!rcu_gp_in_progress(rsp)) {
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
                        return;
@@ -2231,6 +2280,7 @@ static void force_qs_rnp(struct rcu_state *rsp,
        rnp = rcu_get_root(rsp);
        if (rnp->qsmask == 0) {
                raw_spin_lock_irqsave(&rnp->lock, flags);
+               smp_mb__after_unlock_lock();
                rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
        }
 }
@@ -2263,6 +2313,7 @@ static void force_quiescent_state(struct rcu_state *rsp)
 
        /* Reached the root of the rcu_node tree, acquire lock. */
        raw_spin_lock_irqsave(&rnp_old->lock, flags);
+       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++;
@@ -2303,6 +2354,9 @@ __rcu_process_callbacks(struct rcu_state *rsp)
        /* If there are callbacks ready, invoke them. */
        if (cpu_has_callbacks_ready_to_invoke(rdp))
                invoke_rcu_callbacks(rsp, rdp);
+
+       /* Do any needed deferred wakeups of rcuo kthreads. */
+       do_nocb_deferred_wakeup(rdp);
 }
 
 /*
@@ -2378,6 +2432,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
                        struct rcu_node *rnp_root = rcu_get_root(rsp);
 
                        raw_spin_lock(&rnp_root->lock);
+                       smp_mb__after_unlock_lock();
                        rcu_start_gp(rsp);
                        raw_spin_unlock(&rnp_root->lock);
                } else {
@@ -2437,7 +2492,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
 
                if (cpu != -1)
                        rdp = per_cpu_ptr(rsp->rda, cpu);
-               offline = !__call_rcu_nocb(rdp, head, lazy);
+               offline = !__call_rcu_nocb(rdp, head, lazy, flags);
                WARN_ON_ONCE(offline);
                /* _call_rcu() is illegal on offline CPU; leak the callback. */
                local_irq_restore(flags);
@@ -2757,6 +2812,10 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
        /* Check for CPU stalls, if enabled. */
        check_cpu_stall(rsp, rdp);
 
+       /* Is this CPU a NO_HZ_FULL CPU that should ignore RCU? */
+       if (rcu_nohz_full_cpu(rsp))
+               return 0;
+
        /* Is the RCU core waiting for a quiescent state from this CPU? */
        if (rcu_scheduler_fully_active &&
            rdp->qs_pending && !rdp->passed_quiesce) {
@@ -2790,6 +2849,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
                return 1;
        }
 
+       /* Does this CPU need a deferred NOCB wakeup? */
+       if (rcu_nocb_need_deferred_wakeup(rdp)) {
+               rdp->n_rp_nocb_defer_wakeup++;
+               return 1;
+       }
+
        /* nothing to do */
        rdp->n_rp_need_nothing++;
        return 0;
@@ -3214,9 +3279,9 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
 {
        int i;
 
-       for (i = rcu_num_lvls - 1; i > 0; i--)
+       rsp->levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
+       for (i = rcu_num_lvls - 2; i >= 0; i--)
                rsp->levelspread[i] = CONFIG_RCU_FANOUT;
-       rsp->levelspread[0] = rcu_fanout_leaf;
 }
 #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
 static void __init rcu_init_levelspread(struct rcu_state *rsp)
@@ -3346,6 +3411,8 @@ static void __init rcu_init_geometry(void)
        if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF &&
            nr_cpu_ids == NR_CPUS)
                return;
+       pr_info("RCU: Adjusting geometry for rcu_fanout_leaf=%d, nr_cpu_ids=%d\n",
+               rcu_fanout_leaf, nr_cpu_ids);
 
        /*
         * Compute number of nodes that can be handled an rcu_node tree
index 52be957c9fe22360a7a307842795c09353b42789..8c19873f1ac9b7eda78d55595dae0913b4ad45e3 100644 (file)
@@ -317,6 +317,7 @@ struct rcu_data {
        unsigned long n_rp_cpu_needs_gp;
        unsigned long n_rp_gp_completed;
        unsigned long n_rp_gp_started;
+       unsigned long n_rp_nocb_defer_wakeup;
        unsigned long n_rp_need_nothing;
 
        /* 6) _rcu_barrier() and OOM callbacks. */
@@ -335,6 +336,7 @@ struct rcu_data {
        int nocb_p_count_lazy;          /*  (approximate). */
        wait_queue_head_t nocb_wq;      /* For nocb kthreads to sleep on. */
        struct task_struct *nocb_kthread;
+       bool nocb_defer_wakeup;         /* Defer wakeup of nocb_kthread. */
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
        /* 8) RCU CPU stall data. */
@@ -453,6 +455,8 @@ struct rcu_state {
                                                /*  but in jiffies. */
        unsigned long jiffies_stall;            /* Time at which to check */
                                                /*  for CPU stalls. */
+       unsigned long jiffies_resched;          /* Time at which to resched */
+                                               /*  a reluctant CPU. */
        unsigned long gp_max;                   /* Maximum GP duration in */
                                                /*  jiffies. */
        const char *name;                       /* Name of structure. */
@@ -548,9 +552,12 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq);
 static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp);
 static void rcu_init_one_nocb(struct rcu_node *rnp);
 static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
-                           bool lazy);
+                           bool lazy, unsigned long flags);
 static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
-                                     struct rcu_data *rdp);
+                                     struct rcu_data *rdp,
+                                     unsigned long flags);
+static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
+static void do_nocb_deferred_wakeup(struct rcu_data *rdp);
 static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
 static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
 static void rcu_kick_nohz_cpu(int cpu);
@@ -564,6 +571,7 @@ static void rcu_sysidle_report_gp(struct rcu_state *rsp, int isidle,
                                  unsigned long maxj);
 static void rcu_bind_gp_kthread(void);
 static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp);
+static bool rcu_nohz_full_cpu(struct rcu_state *rsp);
 
 #endif /* #ifndef RCU_TREE_NONCORE */
 
index 6abb03dff5c053f44ef5dbc28f7bf754e5669e78..6e2ef4b2b920bc3db08ececbc37d74cf83b8dc14 100644 (file)
@@ -204,6 +204,7 @@ static void rcu_preempt_note_context_switch(int cpu)
                rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
                rnp = rdp->mynode;
                raw_spin_lock_irqsave(&rnp->lock, flags);
+               smp_mb__after_unlock_lock();
                t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
                t->rcu_blocked_node = rnp;
 
@@ -312,6 +313,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)
        mask = rnp->grpmask;
        raw_spin_unlock(&rnp->lock);    /* irqs remain disabled. */
        raw_spin_lock(&rnp_p->lock);    /* irqs already disabled. */
+       smp_mb__after_unlock_lock();
        rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags);
 }
 
@@ -361,10 +363,14 @@ void rcu_read_unlock_special(struct task_struct *t)
        special = t->rcu_read_unlock_special;
        if (special & RCU_READ_UNLOCK_NEED_QS) {
                rcu_preempt_qs(smp_processor_id());
+               if (!t->rcu_read_unlock_special) {
+                       local_irq_restore(flags);
+                       return;
+               }
        }
 
-       /* Hardware IRQ handlers cannot block. */
-       if (in_irq() || in_serving_softirq()) {
+       /* Hardware IRQ handlers cannot block, complain if they get here. */
+       if (WARN_ON_ONCE(in_irq() || in_serving_softirq())) {
                local_irq_restore(flags);
                return;
        }
@@ -381,6 +387,7 @@ void rcu_read_unlock_special(struct task_struct *t)
                for (;;) {
                        rnp = t->rcu_blocked_node;
                        raw_spin_lock(&rnp->lock);  /* irqs already disabled. */
+                       smp_mb__after_unlock_lock();
                        if (rnp == t->rcu_blocked_node)
                                break;
                        raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
@@ -605,6 +612,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
        while (!list_empty(lp)) {
                t = list_entry(lp->next, typeof(*t), rcu_node_entry);
                raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
+               smp_mb__after_unlock_lock();
                list_del(&t->rcu_node_entry);
                t->rcu_blocked_node = rnp_root;
                list_add(&t->rcu_node_entry, lp_root);
@@ -629,6 +637,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
         * in this case.
         */
        raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
+       smp_mb__after_unlock_lock();
        if (rnp_root->boost_tasks != NULL &&
            rnp_root->boost_tasks != rnp_root->gp_tasks &&
            rnp_root->boost_tasks != rnp_root->exp_tasks)
@@ -772,6 +781,7 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
        unsigned long mask;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
        for (;;) {
                if (!sync_rcu_preempt_exp_done(rnp)) {
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
@@ -779,14 +789,17 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
                }
                if (rnp->parent == NULL) {
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
-                       if (wake)
+                       if (wake) {
+                               smp_mb(); /* EGP done before wake_up(). */
                                wake_up(&sync_rcu_preempt_exp_wq);
+                       }
                        break;
                }
                mask = rnp->grpmask;
                raw_spin_unlock(&rnp->lock); /* irqs remain disabled */
                rnp = rnp->parent;
                raw_spin_lock(&rnp->lock); /* irqs already disabled */
+               smp_mb__after_unlock_lock();
                rnp->expmask &= ~mask;
        }
 }
@@ -806,6 +819,7 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
        int must_wait = 0;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
        if (list_empty(&rnp->blkd_tasks)) {
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        } else {
@@ -886,6 +900,7 @@ void synchronize_rcu_expedited(void)
        /* Initialize ->expmask for all non-leaf rcu_node structures. */
        rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) {
                raw_spin_lock_irqsave(&rnp->lock, flags);
+               smp_mb__after_unlock_lock();
                rnp->expmask = rnp->qsmaskinit;
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        }
@@ -1191,6 +1206,7 @@ static int rcu_boost(struct rcu_node *rnp)
                return 0;  /* Nothing left to boost. */
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
 
        /*
         * Recheck under the lock: all tasks in need of boosting
@@ -1377,6 +1393,7 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
        if (IS_ERR(t))
                return PTR_ERR(t);
        raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
        rnp->boost_kthread_task = t;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
        sp.sched_priority = RCU_BOOST_PRIO;
@@ -1632,7 +1649,7 @@ module_param(rcu_idle_gp_delay, int, 0644);
 static int rcu_idle_lazy_gp_delay = RCU_IDLE_LAZY_GP_DELAY;
 module_param(rcu_idle_lazy_gp_delay, int, 0644);
 
-extern int tick_nohz_enabled;
+extern int tick_nohz_active;
 
 /*
  * Try to advance callbacks for all flavors of RCU on the current CPU, but
@@ -1729,7 +1746,7 @@ static void rcu_prepare_for_idle(int cpu)
        int tne;
 
        /* Handle nohz enablement switches conservatively. */
-       tne = ACCESS_ONCE(tick_nohz_enabled);
+       tne = ACCESS_ONCE(tick_nohz_active);
        if (tne != rdtp->tick_nohz_enabled_snap) {
                if (rcu_cpu_has_callbacks(cpu, NULL))
                        invoke_rcu_core(); /* force nohz to see update. */
@@ -1769,6 +1786,7 @@ static void rcu_prepare_for_idle(int cpu)
                        continue;
                rnp = rdp->mynode;
                raw_spin_lock(&rnp->lock); /* irqs already disabled. */
+               smp_mb__after_unlock_lock();
                rcu_accelerate_cbs(rsp, rnp, rdp);
                raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
        }
@@ -1852,6 +1870,7 @@ static int rcu_oom_notify(struct notifier_block *self,
 
        /* Wait for callbacks from earlier instance to complete. */
        wait_event(oom_callback_wq, atomic_read(&oom_callback_count) == 0);
+       smp_mb(); /* Ensure callback reuse happens after callback invocation. */
 
        /*
         * Prevent premature wakeup: ensure that all increments happen
@@ -2101,7 +2120,8 @@ bool rcu_is_nocb_cpu(int cpu)
 static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
                                    struct rcu_head *rhp,
                                    struct rcu_head **rhtp,
-                                   int rhcount, int rhcount_lazy)
+                                   int rhcount, int rhcount_lazy,
+                                   unsigned long flags)
 {
        int len;
        struct rcu_head **old_rhpp;
@@ -2122,9 +2142,16 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
        }
        len = atomic_long_read(&rdp->nocb_q_count);
        if (old_rhpp == &rdp->nocb_head) {
-               wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */
+               if (!irqs_disabled_flags(flags)) {
+                       wake_up(&rdp->nocb_wq); /* ... if queue was empty ... */
+                       trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+                                           TPS("WakeEmpty"));
+               } else {
+                       rdp->nocb_defer_wakeup = true;
+                       trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+                                           TPS("WakeEmptyIsDeferred"));
+               }
                rdp->qlen_last_fqs_check = 0;
-               trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty"));
        } else if (len > rdp->qlen_last_fqs_check + qhimark) {
                wake_up_process(t); /* ... or if many callbacks queued. */
                rdp->qlen_last_fqs_check = LONG_MAX / 2;
@@ -2145,12 +2172,12 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
  * "rcuo" kthread can find it.
  */
 static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
-                           bool lazy)
+                           bool lazy, unsigned long flags)
 {
 
        if (!rcu_is_nocb_cpu(rdp->cpu))
                return 0;
-       __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy);
+       __call_rcu_nocb_enqueue(rdp, rhp, &rhp->next, 1, lazy, flags);
        if (__is_kfree_rcu_offset((unsigned long)rhp->func))
                trace_rcu_kfree_callback(rdp->rsp->name, rhp,
                                         (unsigned long)rhp->func,
@@ -2168,7 +2195,8 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
  * not a no-CBs CPU.
  */
 static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
-                                                    struct rcu_data *rdp)
+                                                    struct rcu_data *rdp,
+                                                    unsigned long flags)
 {
        long ql = rsp->qlen;
        long qll = rsp->qlen_lazy;
@@ -2182,14 +2210,14 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
        /* First, enqueue the donelist, if any.  This preserves CB ordering. */
        if (rsp->orphan_donelist != NULL) {
                __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist,
-                                       rsp->orphan_donetail, ql, qll);
+                                       rsp->orphan_donetail, ql, qll, flags);
                ql = qll = 0;
                rsp->orphan_donelist = NULL;
                rsp->orphan_donetail = &rsp->orphan_donelist;
        }
        if (rsp->orphan_nxtlist != NULL) {
                __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist,
-                                       rsp->orphan_nxttail, ql, qll);
+                                       rsp->orphan_nxttail, ql, qll, flags);
                ql = qll = 0;
                rsp->orphan_nxtlist = NULL;
                rsp->orphan_nxttail = &rsp->orphan_nxtlist;
@@ -2209,6 +2237,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp)
        struct rcu_node *rnp = rdp->mynode;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
+       smp_mb__after_unlock_lock();
        c = rcu_start_future_gp(rnp, rdp);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
@@ -2250,6 +2279,7 @@ static int rcu_nocb_kthread(void *arg)
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
                                            TPS("Sleep"));
                        wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);
+                       /* Memory barrier provide by xchg() below. */
                } else if (firsttime) {
                        firsttime = 0;
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
@@ -2310,6 +2340,22 @@ static int rcu_nocb_kthread(void *arg)
        return 0;
 }
 
+/* Is a deferred wakeup of rcu_nocb_kthread() required? */
+static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp)
+{
+       return ACCESS_ONCE(rdp->nocb_defer_wakeup);
+}
+
+/* Do a deferred wakeup of rcu_nocb_kthread(). */
+static void do_nocb_deferred_wakeup(struct rcu_data *rdp)
+{
+       if (!rcu_nocb_need_deferred_wakeup(rdp))
+               return;
+       ACCESS_ONCE(rdp->nocb_defer_wakeup) = false;
+       wake_up(&rdp->nocb_wq);
+       trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("DeferredWakeEmpty"));
+}
+
 /* Initialize per-rcu_data variables for no-CBs CPUs. */
 static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
 {
@@ -2365,13 +2411,14 @@ static void rcu_init_one_nocb(struct rcu_node *rnp)
 }
 
 static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
-                           bool lazy)
+                           bool lazy, unsigned long flags)
 {
        return 0;
 }
 
 static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
-                                                    struct rcu_data *rdp)
+                                                    struct rcu_data *rdp,
+                                                    unsigned long flags)
 {
        return 0;
 }
@@ -2380,6 +2427,15 @@ static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
 {
 }
 
+static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp)
+{
+       return false;
+}
+
+static void do_nocb_deferred_wakeup(struct rcu_data *rdp)
+{
+}
+
 static void __init rcu_spawn_nocb_kthreads(struct rcu_state *rsp)
 {
 }
@@ -2829,3 +2885,23 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
 }
 
 #endif /* #else #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
+
+/*
+ * Is this CPU a NO_HZ_FULL CPU that should ignore RCU so that the
+ * grace-period kthread will do force_quiescent_state() processing?
+ * The idea is to avoid waking up RCU core processing on such a
+ * 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.
+ */
+static bool rcu_nohz_full_cpu(struct rcu_state *rsp)
+{
+#ifdef CONFIG_NO_HZ_FULL
+       if (tick_nohz_full_cpu(smp_processor_id()) &&
+           (!rcu_gp_in_progress(rsp) ||
+            ULONG_CMP_LT(jiffies, ACCESS_ONCE(rsp->gp_start) + HZ)))
+               return 1;
+#endif /* #ifdef CONFIG_NO_HZ_FULL */
+       return 0;
+}
index 3596797b7e462b2069f8ef21f1b669d777667689..4def475336d412bcbfd8aa4e34a600e0f8b62d41 100644 (file)
@@ -364,9 +364,10 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
                   rdp->n_rp_report_qs,
                   rdp->n_rp_cb_ready,
                   rdp->n_rp_cpu_needs_gp);
-       seq_printf(m, "gpc=%ld gps=%ld nn=%ld\n",
+       seq_printf(m, "gpc=%ld gps=%ld nn=%ld ndw%ld\n",
                   rdp->n_rp_gp_completed,
                   rdp->n_rp_gp_started,
+                  rdp->n_rp_nocb_defer_wakeup,
                   rdp->n_rp_need_nothing);
 }
 
index 6cb3dff89e2b73d214c9fd67d70a2abd43b64f17..802365ccd591826a60e08009a3927c9bed8c69bf 100644 (file)
@@ -128,6 +128,11 @@ struct lockdep_map rcu_sched_lock_map =
        STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key);
 EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
 
+static struct lock_class_key rcu_callback_key;
+struct lockdep_map rcu_callback_map =
+       STATIC_LOCKDEP_MAP_INIT("rcu_callback", &rcu_callback_key);
+EXPORT_SYMBOL_GPL(rcu_callback_map);
+
 int notrace debug_lockdep_rcu_enabled(void)
 {
        return rcu_scheduler_active && debug_locks &&
index f813b3474646c5b320a19d9a8997349bdd14d68e..662c83fc16b77ed79b9474c681848858666055e0 100644 (file)
@@ -104,7 +104,7 @@ int unregister_reboot_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_reboot_notifier);
 
-static void migrate_to_reboot_cpu(void)
+void migrate_to_reboot_cpu(void)
 {
        /* The boot cpu is always logical cpu 0 */
        int cpu = reboot_cpu;
index 7b621409cf15cdba77c0204b25d6bece61f6874f..9a95c8c2af2af0e9fb62c794926df3f1775a9dbe 100644 (file)
@@ -11,9 +11,10 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
 CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
 endif
 
-obj-y += core.o proc.o clock.o cputime.o idle_task.o fair.o rt.o stop_task.o
+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-$(CONFIG_SMP) += cpupri.o
+obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
 obj-$(CONFIG_SCHEDSTATS) += stats.o
 obj-$(CONFIG_SCHED_DEBUG) += debug.o
index c3ae1446461c0ffc22f41cc03a7504a84576b48b..6bd6a6731b21220cae9c9691583c59d9c992ff6f 100644 (file)
  * at 0 on boot (but people really shouldn't rely on that).
  *
  * cpu_clock(i)       -- can be used from any context, including NMI.
- * sched_clock_cpu(i) -- must be used with local IRQs disabled (implied by NMI)
  * local_clock()      -- is cpu_clock() on the current cpu.
  *
+ * sched_clock_cpu(i)
+ *
  * How:
  *
  * The implementation either uses sched_clock() when
  * Furthermore, explicit sleep and wakeup hooks allow us to account for time
  * that is otherwise invisible (TSC gets stopped).
  *
- *
- * Notes:
- *
- * The !IRQ-safetly of sched_clock() and sched_clock_cpu() comes from things
- * like cpufreq interrupts that can change the base clock (TSC) multiplier
- * and cause funny jumps in time -- although the filtering provided by
- * sched_clock_cpu() should mitigate serious artifacts we cannot rely on it
- * in general since for !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK we fully rely on
- * sched_clock().
  */
 #include <linux/spinlock.h>
 #include <linux/hardirq.h>
@@ -66,6 +58,8 @@
 #include <linux/percpu.h>
 #include <linux/ktime.h>
 #include <linux/sched.h>
+#include <linux/static_key.h>
+#include <linux/workqueue.h>
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -82,7 +76,37 @@ EXPORT_SYMBOL_GPL(sched_clock);
 __read_mostly int sched_clock_running;
 
 #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
-__read_mostly int sched_clock_stable;
+static struct static_key __sched_clock_stable = STATIC_KEY_INIT;
+
+int sched_clock_stable(void)
+{
+       if (static_key_false(&__sched_clock_stable))
+               return false;
+       return true;
+}
+
+void set_sched_clock_stable(void)
+{
+       if (!sched_clock_stable())
+               static_key_slow_dec(&__sched_clock_stable);
+}
+
+static void __clear_sched_clock_stable(struct work_struct *work)
+{
+       /* XXX worry about clock continuity */
+       if (sched_clock_stable())
+               static_key_slow_inc(&__sched_clock_stable);
+}
+
+static DECLARE_WORK(sched_clock_work, __clear_sched_clock_stable);
+
+void clear_sched_clock_stable(void)
+{
+       if (keventd_up())
+               schedule_work(&sched_clock_work);
+       else
+               __clear_sched_clock_stable(&sched_clock_work);
+}
 
 struct sched_clock_data {
        u64                     tick_raw;
@@ -242,20 +266,20 @@ u64 sched_clock_cpu(int cpu)
        struct sched_clock_data *scd;
        u64 clock;
 
-       WARN_ON_ONCE(!irqs_disabled());
-
-       if (sched_clock_stable)
+       if (sched_clock_stable())
                return sched_clock();
 
        if (unlikely(!sched_clock_running))
                return 0ull;
 
+       preempt_disable();
        scd = cpu_sdc(cpu);
 
        if (cpu != smp_processor_id())
                clock = sched_clock_remote(scd);
        else
                clock = sched_clock_local(scd);
+       preempt_enable();
 
        return clock;
 }
@@ -265,7 +289,7 @@ void sched_clock_tick(void)
        struct sched_clock_data *scd;
        u64 now, now_gtod;
 
-       if (sched_clock_stable)
+       if (sched_clock_stable())
                return;
 
        if (unlikely(!sched_clock_running))
@@ -316,14 +340,10 @@ EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
  */
 u64 cpu_clock(int cpu)
 {
-       u64 clock;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       clock = sched_clock_cpu(cpu);
-       local_irq_restore(flags);
+       if (static_key_false(&__sched_clock_stable))
+               return sched_clock_cpu(cpu);
 
-       return clock;
+       return sched_clock();
 }
 
 /*
@@ -335,14 +355,10 @@ u64 cpu_clock(int cpu)
  */
 u64 local_clock(void)
 {
-       u64 clock;
-       unsigned long flags;
+       if (static_key_false(&__sched_clock_stable))
+               return sched_clock_cpu(raw_smp_processor_id());
 
-       local_irq_save(flags);
-       clock = sched_clock_cpu(smp_processor_id());
-       local_irq_restore(flags);
-
-       return clock;
+       return sched_clock();
 }
 
 #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
@@ -362,12 +378,12 @@ u64 sched_clock_cpu(int cpu)
 
 u64 cpu_clock(int cpu)
 {
-       return sched_clock_cpu(cpu);
+       return sched_clock();
 }
 
 u64 local_clock(void)
 {
-       return sched_clock_cpu(0);
+       return sched_clock();
 }
 
 #endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
index c1808606ee5f0f4e48e2fc51380369ba248bd9fe..36c951b7eef87d88056b484814c379245d39c1fb 100644 (file)
@@ -296,8 +296,6 @@ __read_mostly int scheduler_running;
  */
 int sysctl_sched_rt_runtime = 950000;
 
-
-
 /*
  * __task_rq_lock - lock the rq @p resides on.
  */
@@ -899,7 +897,9 @@ static inline int normal_prio(struct task_struct *p)
 {
        int prio;
 
-       if (task_has_rt_policy(p))
+       if (task_has_dl_policy(p))
+               prio = MAX_DL_PRIO-1;
+       else if (task_has_rt_policy(p))
                prio = MAX_RT_PRIO-1 - p->rt_priority;
        else
                prio = __normal_prio(p);
@@ -945,7 +945,7 @@ static inline void check_class_changed(struct rq *rq, struct task_struct *p,
                if (prev_class->switched_from)
                        prev_class->switched_from(rq, p);
                p->sched_class->switched_to(rq, p);
-       } else if (oldprio != p->prio)
+       } else if (oldprio != p->prio || dl_task(p))
                p->sched_class->prio_changed(rq, p, oldprio);
 }
 
@@ -1499,8 +1499,7 @@ void scheduler_ipi(void)
         * TIF_NEED_RESCHED remotely (for the first time) will also send
         * this IPI.
         */
-       if (tif_need_resched())
-               set_preempt_need_resched();
+       preempt_fold_need_resched();
 
        if (llist_empty(&this_rq()->wake_list)
                        && !tick_nohz_full_cpu(smp_processor_id())
@@ -1717,6 +1716,13 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
        memset(&p->se.statistics, 0, sizeof(p->se.statistics));
 #endif
 
+       RB_CLEAR_NODE(&p->dl.rb_node);
+       hrtimer_init(&p->dl.dl_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       p->dl.dl_runtime = p->dl.runtime = 0;
+       p->dl.dl_deadline = p->dl.deadline = 0;
+       p->dl.dl_period = 0;
+       p->dl.flags = 0;
+
        INIT_LIST_HEAD(&p->rt.run_list);
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
@@ -1768,7 +1774,7 @@ void set_numabalancing_state(bool enabled)
 /*
  * fork()/clone()-time setup:
  */
-void sched_fork(unsigned long clone_flags, struct task_struct *p)
+int sched_fork(unsigned long clone_flags, struct task_struct *p)
 {
        unsigned long flags;
        int cpu = get_cpu();
@@ -1790,7 +1796,7 @@ void sched_fork(unsigned long clone_flags, struct task_struct *p)
         * Revert to default priority/policy on fork if requested.
         */
        if (unlikely(p->sched_reset_on_fork)) {
-               if (task_has_rt_policy(p)) {
+               if (task_has_dl_policy(p) || task_has_rt_policy(p)) {
                        p->policy = SCHED_NORMAL;
                        p->static_prio = NICE_TO_PRIO(0);
                        p->rt_priority = 0;
@@ -1807,8 +1813,14 @@ void sched_fork(unsigned long clone_flags, struct task_struct *p)
                p->sched_reset_on_fork = 0;
        }
 
-       if (!rt_prio(p->prio))
+       if (dl_prio(p->prio)) {
+               put_cpu();
+               return -EAGAIN;
+       } else if (rt_prio(p->prio)) {
+               p->sched_class = &rt_sched_class;
+       } else {
                p->sched_class = &fair_sched_class;
+       }
 
        if (p->sched_class->task_fork)
                p->sched_class->task_fork(p);
@@ -1834,11 +1846,124 @@ void sched_fork(unsigned long clone_flags, struct task_struct *p)
        init_task_preempt_count(p);
 #ifdef CONFIG_SMP
        plist_node_init(&p->pushable_tasks, MAX_PRIO);
+       RB_CLEAR_NODE(&p->pushable_dl_tasks);
 #endif
 
        put_cpu();
+       return 0;
+}
+
+unsigned long to_ratio(u64 period, u64 runtime)
+{
+       if (runtime == RUNTIME_INF)
+               return 1ULL << 20;
+
+       /*
+        * Doing this here saves a lot of checks in all
+        * the calling paths, and returning zero seems
+        * safe for them anyway.
+        */
+       if (period == 0)
+               return 0;
+
+       return div64_u64(runtime << 20, period);
+}
+
+#ifdef CONFIG_SMP
+inline struct dl_bw *dl_bw_of(int i)
+{
+       return &cpu_rq(i)->rd->dl_bw;
 }
 
+static inline int dl_bw_cpus(int i)
+{
+       struct root_domain *rd = cpu_rq(i)->rd;
+       int cpus = 0;
+
+       for_each_cpu_and(i, rd->span, cpu_active_mask)
+               cpus++;
+
+       return cpus;
+}
+#else
+inline struct dl_bw *dl_bw_of(int i)
+{
+       return &cpu_rq(i)->dl.dl_bw;
+}
+
+static inline int dl_bw_cpus(int i)
+{
+       return 1;
+}
+#endif
+
+static inline
+void __dl_clear(struct dl_bw *dl_b, u64 tsk_bw)
+{
+       dl_b->total_bw -= tsk_bw;
+}
+
+static inline
+void __dl_add(struct dl_bw *dl_b, u64 tsk_bw)
+{
+       dl_b->total_bw += tsk_bw;
+}
+
+static inline
+bool __dl_overflow(struct dl_bw *dl_b, int cpus, u64 old_bw, u64 new_bw)
+{
+       return dl_b->bw != -1 &&
+              dl_b->bw * cpus < dl_b->total_bw - old_bw + new_bw;
+}
+
+/*
+ * We must be sure that accepting a new task (or allowing changing the
+ * parameters of an existing one) is consistent with the bandwidth
+ * constraints. If yes, this function also accordingly updates the currently
+ * allocated bandwidth to reflect the new situation.
+ *
+ * This function is called while holding p's rq->lock.
+ */
+static int dl_overflow(struct task_struct *p, int policy,
+                      const struct sched_attr *attr)
+{
+
+       struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
+       u64 period = attr->sched_period;
+       u64 runtime = attr->sched_runtime;
+       u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
+       int cpus, err = -1;
+
+       if (new_bw == p->dl.dl_bw)
+               return 0;
+
+       /*
+        * Either if a task, enters, leave, or stays -deadline but changes
+        * its parameters, we may need to update accordingly the total
+        * allocated bandwidth of the container.
+        */
+       raw_spin_lock(&dl_b->lock);
+       cpus = dl_bw_cpus(task_cpu(p));
+       if (dl_policy(policy) && !task_has_dl_policy(p) &&
+           !__dl_overflow(dl_b, cpus, 0, new_bw)) {
+               __dl_add(dl_b, new_bw);
+               err = 0;
+       } else if (dl_policy(policy) && task_has_dl_policy(p) &&
+                  !__dl_overflow(dl_b, cpus, p->dl.dl_bw, new_bw)) {
+               __dl_clear(dl_b, p->dl.dl_bw);
+               __dl_add(dl_b, new_bw);
+               err = 0;
+       } else if (!dl_policy(policy) && task_has_dl_policy(p)) {
+               __dl_clear(dl_b, p->dl.dl_bw);
+               err = 0;
+       }
+       raw_spin_unlock(&dl_b->lock);
+
+       return err;
+}
+
+extern void init_dl_bw(struct dl_bw *dl_b);
+
 /*
  * wake_up_new_task - wake up a newly created task for the first time.
  *
@@ -2003,6 +2128,9 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
        if (unlikely(prev_state == TASK_DEAD)) {
                task_numa_free(prev);
 
+               if (prev->sched_class->task_dead)
+                       prev->sched_class->task_dead(prev);
+
                /*
                 * Remove function-return probe instances associated with this
                 * task and put them back on the free list.
@@ -2296,7 +2424,7 @@ void scheduler_tick(void)
 
 #ifdef CONFIG_SMP
        rq->idle_balance = idle_cpu(cpu);
-       trigger_load_balance(rq, cpu);
+       trigger_load_balance(rq);
 #endif
        rq_last_tick_reset(rq);
 }
@@ -2414,10 +2542,10 @@ static inline void schedule_debug(struct task_struct *prev)
 {
        /*
         * Test if we are atomic. Since do_exit() needs to call into
-        * schedule() atomically, we ignore that path for now.
-        * Otherwise, whine if we are scheduling when we should not be.
+        * schedule() atomically, we ignore that path. Otherwise whine
+        * if we are scheduling when we should not.
         */
-       if (unlikely(in_atomic_preempt_off() && !prev->exit_state))
+       if (unlikely(in_atomic_preempt_off() && prev->state != TASK_DEAD))
                __schedule_bug(prev);
        rcu_sleep_check();
 
@@ -2660,6 +2788,7 @@ asmlinkage void __sched notrace preempt_schedule(void)
        } while (need_resched());
 }
 EXPORT_SYMBOL(preempt_schedule);
+#endif /* CONFIG_PREEMPT */
 
 /*
  * this is the entry point to schedule() from kernel preemption
@@ -2693,8 +2822,6 @@ asmlinkage void __sched preempt_schedule_irq(void)
        exception_exit(prev_state);
 }
 
-#endif /* CONFIG_PREEMPT */
-
 int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
                          void *key)
 {
@@ -2762,11 +2889,11 @@ EXPORT_SYMBOL(sleep_on_timeout);
  */
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
-       int oldprio, on_rq, running;
+       int oldprio, on_rq, running, enqueue_flag = 0;
        struct rq *rq;
        const struct sched_class *prev_class;
 
-       BUG_ON(prio < 0 || prio > MAX_PRIO);
+       BUG_ON(prio > MAX_PRIO);
 
        rq = __task_rq_lock(p);
 
@@ -2789,6 +2916,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
        }
 
        trace_sched_pi_setprio(p, prio);
+       p->pi_top_task = rt_mutex_get_top_task(p);
        oldprio = p->prio;
        prev_class = p->sched_class;
        on_rq = p->on_rq;
@@ -2798,23 +2926,49 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
        if (running)
                p->sched_class->put_prev_task(rq, p);
 
-       if (rt_prio(prio))
+       /*
+        * Boosting condition are:
+        * 1. -rt task is running and holds mutex A
+        *      --> -dl task blocks on mutex A
+        *
+        * 2. -dl task is running and holds mutex A
+        *      --> -dl task blocks on mutex A and could preempt the
+        *          running task
+        */
+       if (dl_prio(prio)) {
+               if (!dl_prio(p->normal_prio) || (p->pi_top_task &&
+                       dl_entity_preempt(&p->pi_top_task->dl, &p->dl))) {
+                       p->dl.dl_boosted = 1;
+                       p->dl.dl_throttled = 0;
+                       enqueue_flag = ENQUEUE_REPLENISH;
+               } else
+                       p->dl.dl_boosted = 0;
+               p->sched_class = &dl_sched_class;
+       } else if (rt_prio(prio)) {
+               if (dl_prio(oldprio))
+                       p->dl.dl_boosted = 0;
+               if (oldprio < prio)
+                       enqueue_flag = ENQUEUE_HEAD;
                p->sched_class = &rt_sched_class;
-       else
+       } else {
+               if (dl_prio(oldprio))
+                       p->dl.dl_boosted = 0;
                p->sched_class = &fair_sched_class;
+       }
 
        p->prio = prio;
 
        if (running)
                p->sched_class->set_curr_task(rq);
        if (on_rq)
-               enqueue_task(rq, p, oldprio < prio ? ENQUEUE_HEAD : 0);
+               enqueue_task(rq, p, enqueue_flag);
 
        check_class_changed(rq, p, prev_class, oldprio);
 out_unlock:
        __task_rq_unlock(rq);
 }
 #endif
+
 void set_user_nice(struct task_struct *p, long nice)
 {
        int old_prio, delta, on_rq;
@@ -2832,9 +2986,9 @@ void set_user_nice(struct task_struct *p, long nice)
         * The RT priorities are set via sched_setscheduler(), but we still
         * allow the 'normal' nice value to be set - but as expected
         * it wont have any effect on scheduling until the task is
-        * SCHED_FIFO/SCHED_RR:
+        * SCHED_DEADLINE, SCHED_FIFO or SCHED_RR:
         */
-       if (task_has_rt_policy(p)) {
+       if (task_has_dl_policy(p) || task_has_rt_policy(p)) {
                p->static_prio = NICE_TO_PRIO(nice);
                goto out_unlock;
        }
@@ -2989,22 +3143,95 @@ static struct task_struct *find_process_by_pid(pid_t pid)
        return pid ? find_task_by_vpid(pid) : current;
 }
 
-/* Actually do priority change: must hold rq lock. */
+/*
+ * This function initializes the sched_dl_entity of a newly becoming
+ * SCHED_DEADLINE task.
+ *
+ * Only the static values are considered here, the actual runtime and the
+ * absolute deadline will be properly calculated when the task is enqueued
+ * for the first time with its new policy.
+ */
 static void
-__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
+__setparam_dl(struct task_struct *p, const struct sched_attr *attr)
+{
+       struct sched_dl_entity *dl_se = &p->dl;
+
+       init_dl_task_timer(dl_se);
+       dl_se->dl_runtime = attr->sched_runtime;
+       dl_se->dl_deadline = attr->sched_deadline;
+       dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline;
+       dl_se->flags = attr->sched_flags;
+       dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
+       dl_se->dl_throttled = 0;
+       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)
 {
+       int policy = attr->sched_policy;
+
+       if (policy == -1) /* setparam */
+               policy = p->policy;
+
        p->policy = policy;
-       p->rt_priority = prio;
+
+       if (dl_policy(policy))
+               __setparam_dl(p, attr);
+       else if (fair_policy(policy))
+               p->static_prio = NICE_TO_PRIO(attr->sched_nice);
+
+       /*
+        * __sched_setscheduler() ensures attr->sched_priority == 0 when
+        * !rt_policy. Always setting this ensures that things like
+        * getparam()/getattr() don't report silly values for !rt tasks.
+        */
+       p->rt_priority = attr->sched_priority;
+
        p->normal_prio = normal_prio(p);
-       /* we are holding p->pi_lock already */
        p->prio = rt_mutex_getprio(p);
-       if (rt_prio(p->prio))
+
+       if (dl_prio(p->prio))
+               p->sched_class = &dl_sched_class;
+       else if (rt_prio(p->prio))
                p->sched_class = &rt_sched_class;
        else
                p->sched_class = &fair_sched_class;
+
        set_load_weight(p);
 }
 
+static void
+__getparam_dl(struct task_struct *p, struct sched_attr *attr)
+{
+       struct sched_dl_entity *dl_se = &p->dl;
+
+       attr->sched_priority = p->rt_priority;
+       attr->sched_runtime = dl_se->dl_runtime;
+       attr->sched_deadline = dl_se->dl_deadline;
+       attr->sched_period = dl_se->dl_period;
+       attr->sched_flags = dl_se->flags;
+}
+
+/*
+ * This function validates the new parameters of a -deadline task.
+ * We ask for the deadline not being zero, and greater or equal
+ * than the runtime, as well as the period of being zero or
+ * greater than deadline. Furthermore, we have to be sure that
+ * user parameters are above the internal resolution (1us); we
+ * check sched_runtime only since it is always the smaller one.
+ */
+static bool
+__checkparam_dl(const struct sched_attr *attr)
+{
+       return attr && attr->sched_deadline != 0 &&
+               (attr->sched_period == 0 ||
+               (s64)(attr->sched_period   - attr->sched_deadline) >= 0) &&
+               (s64)(attr->sched_deadline - attr->sched_runtime ) >= 0  &&
+               attr->sched_runtime >= (2 << (DL_SCALE - 1));
+}
+
 /*
  * check the target process has a UID that matches the current process's
  */
@@ -3021,10 +3248,12 @@ static bool check_same_owner(struct task_struct *p)
        return match;
 }
 
-static int __sched_setscheduler(struct task_struct *p, int policy,
-                               const struct sched_param *param, bool user)
+static int __sched_setscheduler(struct task_struct *p,
+                               const struct sched_attr *attr,
+                               bool user)
 {
        int retval, oldprio, oldpolicy = -1, on_rq, running;
+       int policy = attr->sched_policy;
        unsigned long flags;
        const struct sched_class *prev_class;
        struct rq *rq;
@@ -3038,31 +3267,40 @@ recheck:
                reset_on_fork = p->sched_reset_on_fork;
                policy = oldpolicy = p->policy;
        } else {
-               reset_on_fork = !!(policy & SCHED_RESET_ON_FORK);
-               policy &= ~SCHED_RESET_ON_FORK;
+               reset_on_fork = !!(attr->sched_flags & SCHED_FLAG_RESET_ON_FORK);
 
-               if (policy != SCHED_FIFO && policy != SCHED_RR &&
+               if (policy != SCHED_DEADLINE &&
+                               policy != SCHED_FIFO && policy != SCHED_RR &&
                                policy != SCHED_NORMAL && policy != SCHED_BATCH &&
                                policy != SCHED_IDLE)
                        return -EINVAL;
        }
 
+       if (attr->sched_flags & ~(SCHED_FLAG_RESET_ON_FORK))
+               return -EINVAL;
+
        /*
         * Valid priorities for SCHED_FIFO and SCHED_RR are
         * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL,
         * SCHED_BATCH and SCHED_IDLE is 0.
         */
-       if (param->sched_priority < 0 ||
-           (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
-           (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
+       if ((p->mm && attr->sched_priority > MAX_USER_RT_PRIO-1) ||
+           (!p->mm && attr->sched_priority > MAX_RT_PRIO-1))
                return -EINVAL;
-       if (rt_policy(policy) != (param->sched_priority != 0))
+       if ((dl_policy(policy) && !__checkparam_dl(attr)) ||
+           (rt_policy(policy) != (attr->sched_priority != 0)))
                return -EINVAL;
 
        /*
         * Allow unprivileged RT tasks to decrease priority:
         */
        if (user && !capable(CAP_SYS_NICE)) {
+               if (fair_policy(policy)) {
+                       if (attr->sched_nice < TASK_NICE(p) &&
+                           !can_nice(p, attr->sched_nice))
+                               return -EPERM;
+               }
+
                if (rt_policy(policy)) {
                        unsigned long rlim_rtprio =
                                        task_rlimit(p, RLIMIT_RTPRIO);
@@ -3072,8 +3310,8 @@ recheck:
                                return -EPERM;
 
                        /* can't increase priority */
-                       if (param->sched_priority > p->rt_priority &&
-                           param->sched_priority > rlim_rtprio)
+                       if (attr->sched_priority > p->rt_priority &&
+                           attr->sched_priority > rlim_rtprio)
                                return -EPERM;
                }
 
@@ -3121,14 +3359,21 @@ recheck:
        /*
         * If not changing anything there's no need to proceed further:
         */
-       if (unlikely(policy == p->policy && (!rt_policy(policy) ||
-                       param->sched_priority == p->rt_priority))) {
+       if (unlikely(policy == p->policy)) {
+               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;
+
                task_rq_unlock(rq, p, &flags);
                return 0;
        }
+change:
 
-#ifdef CONFIG_RT_GROUP_SCHED
        if (user) {
+#ifdef CONFIG_RT_GROUP_SCHED
                /*
                 * Do not allow realtime tasks into groups that have no runtime
                 * assigned.
@@ -3139,8 +3384,24 @@ recheck:
                        task_rq_unlock(rq, p, &flags);
                        return -EPERM;
                }
-       }
 #endif
+#ifdef CONFIG_SMP
+               if (dl_bandwidth_enabled() && dl_policy(policy)) {
+                       cpumask_t *span = rq->rd->span;
+
+                       /*
+                        * Don't allow tasks with an affinity mask smaller than
+                        * the entire root_domain to become SCHED_DEADLINE. We
+                        * will also fail if there's no bandwidth available.
+                        */
+                       if (!cpumask_subset(span, &p->cpus_allowed) ||
+                           rq->rd->dl_bw.bw == 0) {
+                               task_rq_unlock(rq, p, &flags);
+                               return -EPERM;
+                       }
+               }
+#endif
+       }
 
        /* recheck policy now with rq lock held */
        if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
@@ -3148,6 +3409,17 @@ recheck:
                task_rq_unlock(rq, p, &flags);
                goto recheck;
        }
+
+       /*
+        * If setscheduling to SCHED_DEADLINE (or changing the parameters
+        * of a SCHED_DEADLINE task) we need to check if enough bandwidth
+        * is available.
+        */
+       if ((dl_policy(policy) || dl_task(p)) && dl_overflow(p, policy, attr)) {
+               task_rq_unlock(rq, p, &flags);
+               return -EBUSY;
+       }
+
        on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
@@ -3159,7 +3431,7 @@ recheck:
 
        oldprio = p->prio;
        prev_class = p->sched_class;
-       __setscheduler(rq, p, policy, param->sched_priority);
+       __setscheduler(rq, p, attr);
 
        if (running)
                p->sched_class->set_curr_task(rq);
@@ -3174,6 +3446,26 @@ recheck:
        return 0;
 }
 
+static int _sched_setscheduler(struct task_struct *p, int policy,
+                              const struct sched_param *param, bool check)
+{
+       struct sched_attr attr = {
+               .sched_policy   = policy,
+               .sched_priority = param->sched_priority,
+               .sched_nice     = PRIO_TO_NICE(p->static_prio),
+       };
+
+       /*
+        * Fixup the legacy SCHED_RESET_ON_FORK hack
+        */
+       if (policy & SCHED_RESET_ON_FORK) {
+               attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
+               policy &= ~SCHED_RESET_ON_FORK;
+               attr.sched_policy = policy;
+       }
+
+       return __sched_setscheduler(p, &attr, check);
+}
 /**
  * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
  * @p: the task in question.
@@ -3187,10 +3479,16 @@ recheck:
 int sched_setscheduler(struct task_struct *p, int policy,
                       const struct sched_param *param)
 {
-       return __sched_setscheduler(p, policy, param, true);
+       return _sched_setscheduler(p, policy, param, true);
 }
 EXPORT_SYMBOL_GPL(sched_setscheduler);
 
+int sched_setattr(struct task_struct *p, const struct sched_attr *attr)
+{
+       return __sched_setscheduler(p, attr, true);
+}
+EXPORT_SYMBOL_GPL(sched_setattr);
+
 /**
  * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.
  * @p: the task in question.
@@ -3207,7 +3505,7 @@ EXPORT_SYMBOL_GPL(sched_setscheduler);
 int sched_setscheduler_nocheck(struct task_struct *p, int policy,
                               const struct sched_param *param)
 {
-       return __sched_setscheduler(p, policy, param, false);
+       return _sched_setscheduler(p, policy, param, false);
 }
 
 static int
@@ -3232,6 +3530,79 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
        return retval;
 }
 
+/*
+ * Mimics kernel/events/core.c perf_copy_attr().
+ */
+static int sched_copy_attr(struct sched_attr __user *uattr,
+                          struct sched_attr *attr)
+{
+       u32 size;
+       int ret;
+
+       if (!access_ok(VERIFY_WRITE, uattr, SCHED_ATTR_SIZE_VER0))
+               return -EFAULT;
+
+       /*
+        * zero the full structure, so that a short copy will be nice.
+        */
+       memset(attr, 0, sizeof(*attr));
+
+       ret = get_user(size, &uattr->size);
+       if (ret)
+               return ret;
+
+       if (size > PAGE_SIZE)   /* silly large */
+               goto err_size;
+
+       if (!size)              /* abi compat */
+               size = SCHED_ATTR_SIZE_VER0;
+
+       if (size < SCHED_ATTR_SIZE_VER0)
+               goto err_size;
+
+       /*
+        * If we're handed a bigger struct than we know of,
+        * ensure all the unknown bits are 0 - i.e. new
+        * user-space does not rely on any kernel feature
+        * extensions we dont know about yet.
+        */
+       if (size > sizeof(*attr)) {
+               unsigned char __user *addr;
+               unsigned char __user *end;
+               unsigned char val;
+
+               addr = (void __user *)uattr + sizeof(*attr);
+               end  = (void __user *)uattr + size;
+
+               for (; addr < end; addr++) {
+                       ret = get_user(val, addr);
+                       if (ret)
+                               return ret;
+                       if (val)
+                               goto err_size;
+               }
+               size = sizeof(*attr);
+       }
+
+       ret = copy_from_user(attr, uattr, size);
+       if (ret)
+               return -EFAULT;
+
+       /*
+        * 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);
+
+out:
+       return ret;
+
+err_size:
+       put_user(sizeof(*attr), &uattr->size);
+       ret = -E2BIG;
+       goto out;
+}
+
 /**
  * sys_sched_setscheduler - set/change the scheduler policy and RT priority
  * @pid: the pid in question.
@@ -3262,6 +3633,33 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
        return do_sched_setscheduler(pid, -1, param);
 }
 
+/**
+ * sys_sched_setattr - same as above, but with extended sched_attr
+ * @pid: the pid in question.
+ * @uattr: structure containing the extended parameters.
+ */
+SYSCALL_DEFINE2(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr)
+{
+       struct sched_attr attr;
+       struct task_struct *p;
+       int retval;
+
+       if (!uattr || pid < 0)
+               return -EINVAL;
+
+       if (sched_copy_attr(uattr, &attr))
+               return -EFAULT;
+
+       rcu_read_lock();
+       retval = -ESRCH;
+       p = find_process_by_pid(pid);
+       if (p != NULL)
+               retval = sched_setattr(p, &attr);
+       rcu_read_unlock();
+
+       return retval;
+}
+
 /**
  * sys_sched_getscheduler - get the policy (scheduling class) of a thread
  * @pid: the pid in question.
@@ -3317,6 +3715,10 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
        if (retval)
                goto out_unlock;
 
+       if (task_has_dl_policy(p)) {
+               retval = -EINVAL;
+               goto out_unlock;
+       }
        lp.sched_priority = p->rt_priority;
        rcu_read_unlock();
 
@@ -3332,6 +3734,96 @@ out_unlock:
        return retval;
 }
 
+static int sched_read_attr(struct sched_attr __user *uattr,
+                          struct sched_attr *attr,
+                          unsigned int usize)
+{
+       int ret;
+
+       if (!access_ok(VERIFY_WRITE, uattr, usize))
+               return -EFAULT;
+
+       /*
+        * If we're handed a smaller struct than we know of,
+        * ensure all the unknown bits are 0 - i.e. old
+        * user-space does not get uncomplete information.
+        */
+       if (usize < sizeof(*attr)) {
+               unsigned char *addr;
+               unsigned char *end;
+
+               addr = (void *)attr + usize;
+               end  = (void *)attr + sizeof(*attr);
+
+               for (; addr < end; addr++) {
+                       if (*addr)
+                               goto err_size;
+               }
+
+               attr->size = usize;
+       }
+
+       ret = copy_to_user(uattr, attr, usize);
+       if (ret)
+               return -EFAULT;
+
+out:
+       return ret;
+
+err_size:
+       ret = -E2BIG;
+       goto out;
+}
+
+/**
+ * sys_sched_getattr - similar to sched_getparam, but with sched_attr
+ * @pid: the pid in question.
+ * @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)
+{
+       struct sched_attr attr = {
+               .size = sizeof(struct sched_attr),
+       };
+       struct task_struct *p;
+       int retval;
+
+       if (!uattr || pid < 0 || size > PAGE_SIZE ||
+           size < SCHED_ATTR_SIZE_VER0)
+               return -EINVAL;
+
+       rcu_read_lock();
+       p = find_process_by_pid(pid);
+       retval = -ESRCH;
+       if (!p)
+               goto out_unlock;
+
+       retval = security_task_getscheduler(p);
+       if (retval)
+               goto out_unlock;
+
+       attr.sched_policy = p->policy;
+       if (p->sched_reset_on_fork)
+               attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
+       if (task_has_dl_policy(p))
+               __getparam_dl(p, &attr);
+       else if (task_has_rt_policy(p))
+               attr.sched_priority = p->rt_priority;
+       else
+               attr.sched_nice = TASK_NICE(p);
+
+       rcu_read_unlock();
+
+       retval = sched_read_attr(uattr, &attr, size);
+       return retval;
+
+out_unlock:
+       rcu_read_unlock();
+       return retval;
+}
+
 long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 {
        cpumask_var_t cpus_allowed, new_mask;
@@ -3376,8 +3868,26 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
        if (retval)
                goto out_unlock;
 
+
        cpuset_cpus_allowed(p, cpus_allowed);
        cpumask_and(new_mask, in_mask, cpus_allowed);
+
+       /*
+        * Since bandwidth control happens on root_domain basis,
+        * if admission test is enabled, we only admit -deadline
+        * tasks allowed to run on all the CPUs in the task's
+        * root_domain.
+        */
+#ifdef CONFIG_SMP
+       if (task_has_dl_policy(p)) {
+               const struct cpumask *span = task_rq(p)->rd->span;
+
+               if (dl_bandwidth_enabled() && !cpumask_subset(span, new_mask)) {
+                       retval = -EBUSY;
+                       goto out_unlock;
+               }
+       }
+#endif
 again:
        retval = set_cpus_allowed_ptr(p, new_mask);
 
@@ -3654,7 +4164,7 @@ again:
        }
 
        double_rq_lock(rq, p_rq);
-       while (task_rq(p) != p_rq) {
+       if (task_rq(p) != p_rq) {
                double_rq_unlock(rq, p_rq);
                goto again;
        }
@@ -3743,6 +4253,7 @@ SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
        case SCHED_RR:
                ret = MAX_USER_RT_PRIO-1;
                break;
+       case SCHED_DEADLINE:
        case SCHED_NORMAL:
        case SCHED_BATCH:
        case SCHED_IDLE:
@@ -3769,6 +4280,7 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
        case SCHED_RR:
                ret = 1;
                break;
+       case SCHED_DEADLINE:
        case SCHED_NORMAL:
        case SCHED_BATCH:
        case SCHED_IDLE:
@@ -4515,13 +5027,31 @@ static int sched_cpu_active(struct notifier_block *nfb,
 static int sched_cpu_inactive(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
 {
+       unsigned long flags;
+       long cpu = (long)hcpu;
+
        switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_DOWN_PREPARE:
-               set_cpu_active((long)hcpu, false);
+               set_cpu_active(cpu, false);
+
+               /* explicitly allow suspend */
+               if (!(action & CPU_TASKS_FROZEN)) {
+                       struct dl_bw *dl_b = dl_bw_of(cpu);
+                       bool overflow;
+                       int cpus;
+
+                       raw_spin_lock_irqsave(&dl_b->lock, flags);
+                       cpus = dl_bw_cpus(cpu);
+                       overflow = __dl_overflow(dl_b, cpus, 0, 0);
+                       raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+
+                       if (overflow)
+                               return notifier_from_errno(-EBUSY);
+               }
                return NOTIFY_OK;
-       default:
-               return NOTIFY_DONE;
        }
+
+       return NOTIFY_DONE;
 }
 
 static int __init migration_init(void)
@@ -4740,6 +5270,8 @@ static void free_rootdomain(struct rcu_head *rcu)
        struct root_domain *rd = container_of(rcu, struct root_domain, rcu);
 
        cpupri_cleanup(&rd->cpupri);
+       cpudl_cleanup(&rd->cpudl);
+       free_cpumask_var(rd->dlo_mask);
        free_cpumask_var(rd->rto_mask);
        free_cpumask_var(rd->online);
        free_cpumask_var(rd->span);
@@ -4762,7 +5294,7 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd)
                cpumask_clear_cpu(rq->cpu, old_rd->span);
 
                /*
-                * If we dont want to free the old_rt yet then
+                * If we dont want to free the old_rd yet then
                 * set old_rd to NULL to skip the freeing later
                 * in this function:
                 */
@@ -4791,8 +5323,14 @@ static int init_rootdomain(struct root_domain *rd)
                goto out;
        if (!alloc_cpumask_var(&rd->online, GFP_KERNEL))
                goto free_span;
-       if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
+       if (!alloc_cpumask_var(&rd->dlo_mask, GFP_KERNEL))
                goto free_online;
+       if (!alloc_cpumask_var(&rd->rto_mask, GFP_KERNEL))
+               goto free_dlo_mask;
+
+       init_dl_bw(&rd->dl_bw);
+       if (cpudl_init(&rd->cpudl) != 0)
+               goto free_dlo_mask;
 
        if (cpupri_init(&rd->cpupri) != 0)
                goto free_rto_mask;
@@ -4800,6 +5338,8 @@ static int init_rootdomain(struct root_domain *rd)
 
 free_rto_mask:
        free_cpumask_var(rd->rto_mask);
+free_dlo_mask:
+       free_cpumask_var(rd->dlo_mask);
 free_online:
        free_cpumask_var(rd->online);
 free_span:
@@ -4903,6 +5443,7 @@ DEFINE_PER_CPU(struct sched_domain *, sd_asym);
 static void update_top_cache_domain(int cpu)
 {
        struct sched_domain *sd;
+       struct sched_domain *busy_sd = NULL;
        int id = cpu;
        int size = 1;
 
@@ -4910,8 +5451,9 @@ static void update_top_cache_domain(int cpu)
        if (sd) {
                id = cpumask_first(sched_domain_span(sd));
                size = cpumask_weight(sched_domain_span(sd));
-               rcu_assign_pointer(per_cpu(sd_busy, cpu), sd->parent);
+               busy_sd = sd->parent; /* sd_busy */
        }
+       rcu_assign_pointer(per_cpu(sd_busy, cpu), busy_sd);
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_size, cpu) = size;
@@ -5112,6 +5654,7 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu)
                 * die on a /0 trap.
                 */
                sg->sgp->power = SCHED_POWER_SCALE * cpumask_weight(sg_span);
+               sg->sgp->power_orig = sg->sgp->power;
 
                /*
                 * Make sure the first group of this domain contains the
@@ -6148,6 +6691,7 @@ void __init sched_init_smp(void)
        free_cpumask_var(non_isolated_cpus);
 
        init_sched_rt_class();
+       init_sched_dl_class();
 }
 #else
 void __init sched_init_smp(void)
@@ -6217,13 +6761,15 @@ void __init sched_init(void)
 #endif /* CONFIG_CPUMASK_OFFSTACK */
        }
 
+       init_rt_bandwidth(&def_rt_bandwidth,
+                       global_rt_period(), global_rt_runtime());
+       init_dl_bandwidth(&def_dl_bandwidth,
+                       global_rt_period(), global_rt_runtime());
+
 #ifdef CONFIG_SMP
        init_defrootdomain();
 #endif
 
-       init_rt_bandwidth(&def_rt_bandwidth,
-                       global_rt_period(), global_rt_runtime());
-
 #ifdef CONFIG_RT_GROUP_SCHED
        init_rt_bandwidth(&root_task_group.rt_bandwidth,
                        global_rt_period(), global_rt_runtime());
@@ -6247,6 +6793,7 @@ void __init sched_init(void)
                rq->calc_load_update = jiffies + LOAD_FREQ;
                init_cfs_rq(&rq->cfs);
                init_rt_rq(&rq->rt, rq);
+               init_dl_rq(&rq->dl, rq);
 #ifdef CONFIG_FAIR_GROUP_SCHED
                root_task_group.shares = ROOT_TASK_GROUP_LOAD;
                INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
@@ -6318,10 +6865,6 @@ void __init sched_init(void)
        INIT_HLIST_HEAD(&init_task.preempt_notifiers);
 #endif
 
-#ifdef CONFIG_RT_MUTEXES
-       plist_head_init(&init_task.pi_waiters);
-#endif
-
        /*
         * The boot idle thread does lazy MMU switching as well:
         */
@@ -6395,13 +6938,16 @@ EXPORT_SYMBOL(__might_sleep);
 static void normalize_task(struct rq *rq, struct task_struct *p)
 {
        const struct sched_class *prev_class = p->sched_class;
+       struct sched_attr attr = {
+               .sched_policy = SCHED_NORMAL,
+       };
        int old_prio = p->prio;
        int on_rq;
 
        on_rq = p->on_rq;
        if (on_rq)
                dequeue_task(rq, p, 0);
-       __setscheduler(rq, p, SCHED_NORMAL, 0);
+       __setscheduler(rq, p, &attr);
        if (on_rq) {
                enqueue_task(rq, p, 0);
                resched_task(rq->curr);
@@ -6431,7 +6977,7 @@ void normalize_rt_tasks(void)
                p->se.statistics.block_start    = 0;
 #endif
 
-               if (!rt_task(p)) {
+               if (!dl_task(p) && !rt_task(p)) {
                        /*
                         * Renice negative nice level userspace
                         * tasks back to 0:
@@ -6626,16 +7172,6 @@ void sched_move_task(struct task_struct *tsk)
 }
 #endif /* CONFIG_CGROUP_SCHED */
 
-#if defined(CONFIG_RT_GROUP_SCHED) || defined(CONFIG_CFS_BANDWIDTH)
-static unsigned long to_ratio(u64 period, u64 runtime)
-{
-       if (runtime == RUNTIME_INF)
-               return 1ULL << 20;
-
-       return div64_u64(runtime << 20, period);
-}
-#endif
-
 #ifdef CONFIG_RT_GROUP_SCHED
 /*
  * Ensure that the real time constraints are schedulable.
@@ -6809,24 +7345,13 @@ static long sched_group_rt_period(struct task_group *tg)
        do_div(rt_period_us, NSEC_PER_USEC);
        return rt_period_us;
 }
+#endif /* CONFIG_RT_GROUP_SCHED */
 
+#ifdef CONFIG_RT_GROUP_SCHED
 static int sched_rt_global_constraints(void)
 {
-       u64 runtime, period;
        int ret = 0;
 
-       if (sysctl_sched_rt_period <= 0)
-               return -EINVAL;
-
-       runtime = global_rt_runtime();
-       period = global_rt_period();
-
-       /*
-        * Sanity check on the sysctl variables.
-        */
-       if (runtime > period && runtime != RUNTIME_INF)
-               return -EINVAL;
-
        mutex_lock(&rt_constraints_mutex);
        read_lock(&tasklist_lock);
        ret = __rt_schedulable(NULL, 0, 0);
@@ -6849,17 +7374,7 @@ static int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
 static int sched_rt_global_constraints(void)
 {
        unsigned long flags;
-       int i;
-
-       if (sysctl_sched_rt_period <= 0)
-               return -EINVAL;
-
-       /*
-        * There's always some RT tasks in the root group
-        * -- migration, kstopmachine etc..
-        */
-       if (sysctl_sched_rt_runtime == 0)
-               return -EBUSY;
+       int i, ret = 0;
 
        raw_spin_lock_irqsave(&def_rt_bandwidth.rt_runtime_lock, flags);
        for_each_possible_cpu(i) {
@@ -6871,36 +7386,88 @@ static int sched_rt_global_constraints(void)
        }
        raw_spin_unlock_irqrestore(&def_rt_bandwidth.rt_runtime_lock, flags);
 
-       return 0;
+       return ret;
 }
 #endif /* CONFIG_RT_GROUP_SCHED */
 
-int sched_rr_handler(struct ctl_table *table, int write,
-               void __user *buffer, size_t *lenp,
-               loff_t *ppos)
+static int sched_dl_global_constraints(void)
 {
-       int ret;
-       static DEFINE_MUTEX(mutex);
+       u64 runtime = global_rt_runtime();
+       u64 period = global_rt_period();
+       u64 new_bw = to_ratio(period, runtime);
+       int cpu, ret = 0;
 
-       mutex_lock(&mutex);
-       ret = proc_dointvec(table, write, buffer, lenp, ppos);
-       /* make sure that internally we keep jiffies */
-       /* also, writing zero resets timeslice to default */
-       if (!ret && write) {
-               sched_rr_timeslice = sched_rr_timeslice <= 0 ?
-                       RR_TIMESLICE : msecs_to_jiffies(sched_rr_timeslice);
+       /*
+        * Here we want to check the bandwidth not being set to some
+        * value smaller than the currently allocated bandwidth in
+        * any of the root_domains.
+        *
+        * FIXME: Cycling on all the CPUs is overdoing, but simpler than
+        * cycling on root_domains... Discussion on different/better
+        * solutions is welcome!
+        */
+       for_each_possible_cpu(cpu) {
+               struct dl_bw *dl_b = dl_bw_of(cpu);
+
+               raw_spin_lock(&dl_b->lock);
+               if (new_bw < dl_b->total_bw)
+                       ret = -EBUSY;
+               raw_spin_unlock(&dl_b->lock);
+
+               if (ret)
+                       break;
        }
-       mutex_unlock(&mutex);
+
        return ret;
 }
 
+static void sched_dl_do_global(void)
+{
+       u64 new_bw = -1;
+       int cpu;
+
+       def_dl_bandwidth.dl_period = global_rt_period();
+       def_dl_bandwidth.dl_runtime = global_rt_runtime();
+
+       if (global_rt_runtime() != RUNTIME_INF)
+               new_bw = to_ratio(global_rt_period(), global_rt_runtime());
+
+       /*
+        * FIXME: As above...
+        */
+       for_each_possible_cpu(cpu) {
+               struct dl_bw *dl_b = dl_bw_of(cpu);
+
+               raw_spin_lock(&dl_b->lock);
+               dl_b->bw = new_bw;
+               raw_spin_unlock(&dl_b->lock);
+       }
+}
+
+static int sched_rt_global_validate(void)
+{
+       if (sysctl_sched_rt_period <= 0)
+               return -EINVAL;
+
+       if (sysctl_sched_rt_runtime > sysctl_sched_rt_period)
+               return -EINVAL;
+
+       return 0;
+}
+
+static void sched_rt_do_global(void)
+{
+       def_rt_bandwidth.rt_runtime = global_rt_runtime();
+       def_rt_bandwidth.rt_period = ns_to_ktime(global_rt_period());
+}
+
 int sched_rt_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos)
 {
-       int ret;
        int old_period, old_runtime;
        static DEFINE_MUTEX(mutex);
+       int ret;
 
        mutex_lock(&mutex);
        old_period = sysctl_sched_rt_period;
@@ -6909,21 +7476,50 @@ int sched_rt_handler(struct ctl_table *table, int write,
        ret = proc_dointvec(table, write, buffer, lenp, ppos);
 
        if (!ret && write) {
+               ret = sched_rt_global_validate();
+               if (ret)
+                       goto undo;
+
                ret = sched_rt_global_constraints();
-               if (ret) {
-                       sysctl_sched_rt_period = old_period;
-                       sysctl_sched_rt_runtime = old_runtime;
-               } else {
-                       def_rt_bandwidth.rt_runtime = global_rt_runtime();
-                       def_rt_bandwidth.rt_period =
-                               ns_to_ktime(global_rt_period());
-               }
+               if (ret)
+                       goto undo;
+
+               ret = sched_dl_global_constraints();
+               if (ret)
+                       goto undo;
+
+               sched_rt_do_global();
+               sched_dl_do_global();
+       }
+       if (0) {
+undo:
+               sysctl_sched_rt_period = old_period;
+               sysctl_sched_rt_runtime = old_runtime;
        }
        mutex_unlock(&mutex);
 
        return ret;
 }
 
+int sched_rr_handler(struct ctl_table *table, int write,
+               void __user *buffer, size_t *lenp,
+               loff_t *ppos)
+{
+       int ret;
+       static DEFINE_MUTEX(mutex);
+
+       mutex_lock(&mutex);
+       ret = proc_dointvec(table, write, buffer, lenp, ppos);
+       /* make sure that internally we keep jiffies */
+       /* also, writing zero resets timeslice to default */
+       if (!ret && write) {
+               sched_rr_timeslice = sched_rr_timeslice <= 0 ?
+                       RR_TIMESLICE : msecs_to_jiffies(sched_rr_timeslice);
+       }
+       mutex_unlock(&mutex);
+       return ret;
+}
+
 #ifdef CONFIG_CGROUP_SCHED
 
 static inline struct task_group *css_tg(struct cgroup_subsys_state *css)
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
new file mode 100644 (file)
index 0000000..045fc74
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ *  kernel/sched/cpudl.c
+ *
+ *  Global CPU deadline management
+ *
+ *  Author: Juri Lelli <j.lelli@sssup.it>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; version 2
+ *  of the License.
+ */
+
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include "cpudeadline.h"
+
+static inline int parent(int i)
+{
+       return (i - 1) >> 1;
+}
+
+static inline int left_child(int i)
+{
+       return (i << 1) + 1;
+}
+
+static inline int right_child(int i)
+{
+       return (i << 1) + 2;
+}
+
+static inline int dl_time_before(u64 a, u64 b)
+{
+       return (s64)(a - b) < 0;
+}
+
+static void cpudl_exchange(struct cpudl *cp, int a, int b)
+{
+       int cpu_a = cp->elements[a].cpu, cpu_b = cp->elements[b].cpu;
+
+       swap(cp->elements[a], cp->elements[b]);
+       swap(cp->cpu_to_idx[cpu_a], cp->cpu_to_idx[cpu_b]);
+}
+
+static void cpudl_heapify(struct cpudl *cp, int idx)
+{
+       int l, r, largest;
+
+       /* adapted from lib/prio_heap.c */
+       while(1) {
+               l = left_child(idx);
+               r = right_child(idx);
+               largest = idx;
+
+               if ((l < cp->size) && dl_time_before(cp->elements[idx].dl,
+                                                       cp->elements[l].dl))
+                       largest = l;
+               if ((r < cp->size) && dl_time_before(cp->elements[largest].dl,
+                                                       cp->elements[r].dl))
+                       largest = r;
+               if (largest == idx)
+                       break;
+
+               /* Push idx down the heap one level and bump one up */
+               cpudl_exchange(cp, largest, idx);
+               idx = largest;
+       }
+}
+
+static void cpudl_change_key(struct cpudl *cp, int idx, u64 new_dl)
+{
+       WARN_ON(idx > num_present_cpus() || idx == IDX_INVALID);
+
+       if (dl_time_before(new_dl, cp->elements[idx].dl)) {
+               cp->elements[idx].dl = new_dl;
+               cpudl_heapify(cp, idx);
+       } else {
+               cp->elements[idx].dl = new_dl;
+               while (idx > 0 && dl_time_before(cp->elements[parent(idx)].dl,
+                                       cp->elements[idx].dl)) {
+                       cpudl_exchange(cp, idx, parent(idx));
+                       idx = parent(idx);
+               }
+       }
+}
+
+static inline int cpudl_maximum(struct cpudl *cp)
+{
+       return cp->elements[0].cpu;
+}
+
+/*
+ * cpudl_find - find the best (later-dl) CPU in the system
+ * @cp: the cpudl max-heap context
+ * @p: the task
+ * @later_mask: a mask to fill in with the selected CPUs (or NULL)
+ *
+ * Returns: int - best CPU (heap maximum if suitable)
+ */
+int cpudl_find(struct cpudl *cp, struct task_struct *p,
+              struct cpumask *later_mask)
+{
+       int best_cpu = -1;
+       const struct sched_dl_entity *dl_se = &p->dl;
+
+       if (later_mask && cpumask_and(later_mask, cp->free_cpus,
+                       &p->cpus_allowed) && cpumask_and(later_mask,
+                       later_mask, cpu_active_mask)) {
+               best_cpu = cpumask_any(later_mask);
+               goto out;
+       } else if (cpumask_test_cpu(cpudl_maximum(cp), &p->cpus_allowed) &&
+                       dl_time_before(dl_se->deadline, cp->elements[0].dl)) {
+               best_cpu = cpudl_maximum(cp);
+               if (later_mask)
+                       cpumask_set_cpu(best_cpu, later_mask);
+       }
+
+out:
+       WARN_ON(best_cpu > num_present_cpus() && best_cpu != -1);
+
+       return best_cpu;
+}
+
+/*
+ * cpudl_set - update the cpudl max-heap
+ * @cp: the cpudl max-heap context
+ * @cpu: the target cpu
+ * @dl: the new earliest deadline for this cpu
+ *
+ * Notes: assumes cpu_rq(cpu)->lock is locked
+ *
+ * Returns: (void)
+ */
+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());
+
+       raw_spin_lock_irqsave(&cp->lock, flags);
+       old_idx = cp->cpu_to_idx[cpu];
+       if (!is_valid) {
+               /* remove item */
+               if (old_idx == IDX_INVALID) {
+                       /*
+                        * Nothing to remove if old_idx was invalid.
+                        * This could happen if a rq_offline_dl is
+                        * called for a CPU without -dl tasks running.
+                        */
+                       goto out;
+               }
+               new_cpu = cp->elements[cp->size - 1].cpu;
+               cp->elements[old_idx].dl = cp->elements[cp->size - 1].dl;
+               cp->elements[old_idx].cpu = new_cpu;
+               cp->size--;
+               cp->cpu_to_idx[new_cpu] = old_idx;
+               cp->cpu_to_idx[cpu] = IDX_INVALID;
+               while (old_idx > 0 && dl_time_before(
+                               cp->elements[parent(old_idx)].dl,
+                               cp->elements[old_idx].dl)) {
+                       cpudl_exchange(cp, old_idx, parent(old_idx));
+                       old_idx = parent(old_idx);
+               }
+               cpumask_set_cpu(cpu, cp->free_cpus);
+                cpudl_heapify(cp, old_idx);
+
+               goto out;
+       }
+
+       if (old_idx == IDX_INVALID) {
+               cp->size++;
+               cp->elements[cp->size - 1].dl = 0;
+               cp->elements[cp->size - 1].cpu = cpu;
+               cp->cpu_to_idx[cpu] = cp->size - 1;
+               cpudl_change_key(cp, cp->size - 1, dl);
+               cpumask_clear_cpu(cpu, cp->free_cpus);
+       } else {
+               cpudl_change_key(cp, old_idx, dl);
+       }
+
+out:
+       raw_spin_unlock_irqrestore(&cp->lock, flags);
+}
+
+/*
+ * cpudl_init - initialize the cpudl structure
+ * @cp: the cpudl max-heap context
+ */
+int cpudl_init(struct cpudl *cp)
+{
+       int i;
+
+       memset(cp, 0, sizeof(*cp));
+       raw_spin_lock_init(&cp->lock);
+       cp->size = 0;
+       for (i = 0; i < NR_CPUS; i++)
+               cp->cpu_to_idx[i] = IDX_INVALID;
+       if (!alloc_cpumask_var(&cp->free_cpus, GFP_KERNEL))
+               return -ENOMEM;
+       cpumask_setall(cp->free_cpus);
+
+       return 0;
+}
+
+/*
+ * cpudl_cleanup - clean up the cpudl structure
+ * @cp: the cpudl max-heap context
+ */
+void cpudl_cleanup(struct cpudl *cp)
+{
+       /*
+        * nothing to do for the moment
+        */
+}
diff --git a/kernel/sched/cpudeadline.h b/kernel/sched/cpudeadline.h
new file mode 100644 (file)
index 0000000..a202789
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _LINUX_CPUDL_H
+#define _LINUX_CPUDL_H
+
+#include <linux/sched.h>
+
+#define IDX_INVALID     -1
+
+struct array_item {
+       u64 dl;
+       int cpu;
+};
+
+struct cpudl {
+       raw_spinlock_t lock;
+       int size;
+       int cpu_to_idx[NR_CPUS];
+       struct array_item elements[NR_CPUS];
+       cpumask_var_t free_cpus;
+};
+
+
+#ifdef CONFIG_SMP
+int cpudl_find(struct cpudl *cp, struct task_struct *p,
+              struct cpumask *later_mask);
+void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid);
+int cpudl_init(struct cpudl *cp);
+void cpudl_cleanup(struct cpudl *cp);
+#else
+#define cpudl_set(cp, cpu, dl) do { } while (0)
+#define cpudl_init() do { } while (0)
+#endif /* CONFIG_SMP */
+
+#endif /* _LINUX_CPUDL_H */
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
new file mode 100644 (file)
index 0000000..0de2482
--- /dev/null
@@ -0,0 +1,1640 @@
+/*
+ * Deadline Scheduling Class (SCHED_DEADLINE)
+ *
+ * Earliest Deadline First (EDF) + Constant Bandwidth Server (CBS).
+ *
+ * Tasks that periodically executes their instances for less than their
+ * runtime won't miss any of their deadlines.
+ * Tasks that are not periodic or sporadic or that tries to execute more
+ * than their reserved bandwidth will be slowed down (and may potentially
+ * miss some of their deadlines), and won't affect any other task.
+ *
+ * Copyright (C) 2012 Dario Faggioli <raistlin@linux.it>,
+ *                    Juri Lelli <juri.lelli@gmail.com>,
+ *                    Michael Trimarchi <michael@amarulasolutions.com>,
+ *                    Fabio Checconi <fchecconi@gmail.com>
+ */
+#include "sched.h"
+
+#include <linux/slab.h>
+
+struct dl_bandwidth def_dl_bandwidth;
+
+static inline struct task_struct *dl_task_of(struct sched_dl_entity *dl_se)
+{
+       return container_of(dl_se, struct task_struct, dl);
+}
+
+static inline struct rq *rq_of_dl_rq(struct dl_rq *dl_rq)
+{
+       return container_of(dl_rq, struct rq, dl);
+}
+
+static inline struct dl_rq *dl_rq_of_se(struct sched_dl_entity *dl_se)
+{
+       struct task_struct *p = dl_task_of(dl_se);
+       struct rq *rq = task_rq(p);
+
+       return &rq->dl;
+}
+
+static inline int on_dl_rq(struct sched_dl_entity *dl_se)
+{
+       return !RB_EMPTY_NODE(&dl_se->rb_node);
+}
+
+static inline int is_leftmost(struct task_struct *p, struct dl_rq *dl_rq)
+{
+       struct sched_dl_entity *dl_se = &p->dl;
+
+       return dl_rq->rb_leftmost == &dl_se->rb_node;
+}
+
+void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime)
+{
+       raw_spin_lock_init(&dl_b->dl_runtime_lock);
+       dl_b->dl_period = period;
+       dl_b->dl_runtime = runtime;
+}
+
+extern unsigned long to_ratio(u64 period, u64 runtime);
+
+void init_dl_bw(struct dl_bw *dl_b)
+{
+       raw_spin_lock_init(&dl_b->lock);
+       raw_spin_lock(&def_dl_bandwidth.dl_runtime_lock);
+       if (global_rt_runtime() == RUNTIME_INF)
+               dl_b->bw = -1;
+       else
+               dl_b->bw = to_ratio(global_rt_period(), global_rt_runtime());
+       raw_spin_unlock(&def_dl_bandwidth.dl_runtime_lock);
+       dl_b->total_bw = 0;
+}
+
+void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq)
+{
+       dl_rq->rb_root = RB_ROOT;
+
+#ifdef CONFIG_SMP
+       /* zero means no -deadline tasks */
+       dl_rq->earliest_dl.curr = dl_rq->earliest_dl.next = 0;
+
+       dl_rq->dl_nr_migratory = 0;
+       dl_rq->overloaded = 0;
+       dl_rq->pushable_dl_tasks_root = RB_ROOT;
+#else
+       init_dl_bw(&dl_rq->dl_bw);
+#endif
+}
+
+#ifdef CONFIG_SMP
+
+static inline int dl_overloaded(struct rq *rq)
+{
+       return atomic_read(&rq->rd->dlo_count);
+}
+
+static inline void dl_set_overload(struct rq *rq)
+{
+       if (!rq->online)
+               return;
+
+       cpumask_set_cpu(rq->cpu, rq->rd->dlo_mask);
+       /*
+        * Must be visible before the overload count is
+        * set (as in sched_rt.c).
+        *
+        * Matched by the barrier in pull_dl_task().
+        */
+       smp_wmb();
+       atomic_inc(&rq->rd->dlo_count);
+}
+
+static inline void dl_clear_overload(struct rq *rq)
+{
+       if (!rq->online)
+               return;
+
+       atomic_dec(&rq->rd->dlo_count);
+       cpumask_clear_cpu(rq->cpu, rq->rd->dlo_mask);
+}
+
+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->overloaded) {
+                       dl_set_overload(rq_of_dl_rq(dl_rq));
+                       dl_rq->overloaded = 1;
+               }
+       } else if (dl_rq->overloaded) {
+               dl_clear_overload(rq_of_dl_rq(dl_rq));
+               dl_rq->overloaded = 0;
+       }
+}
+
+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++;
+
+       update_dl_migration(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--;
+
+       update_dl_migration(dl_rq);
+}
+
+/*
+ * The list of pushable -deadline task is not a plist, like in
+ * sched_rt.c, it is an rb-tree with tasks ordered by deadline.
+ */
+static void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p)
+{
+       struct dl_rq *dl_rq = &rq->dl;
+       struct rb_node **link = &dl_rq->pushable_dl_tasks_root.rb_node;
+       struct rb_node *parent = NULL;
+       struct task_struct *entry;
+       int leftmost = 1;
+
+       BUG_ON(!RB_EMPTY_NODE(&p->pushable_dl_tasks));
+
+       while (*link) {
+               parent = *link;
+               entry = rb_entry(parent, struct task_struct,
+                                pushable_dl_tasks);
+               if (dl_entity_preempt(&p->dl, &entry->dl))
+                       link = &parent->rb_left;
+               else {
+                       link = &parent->rb_right;
+                       leftmost = 0;
+               }
+       }
+
+       if (leftmost)
+               dl_rq->pushable_dl_tasks_leftmost = &p->pushable_dl_tasks;
+
+       rb_link_node(&p->pushable_dl_tasks, parent, link);
+       rb_insert_color(&p->pushable_dl_tasks, &dl_rq->pushable_dl_tasks_root);
+}
+
+static void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p)
+{
+       struct dl_rq *dl_rq = &rq->dl;
+
+       if (RB_EMPTY_NODE(&p->pushable_dl_tasks))
+               return;
+
+       if (dl_rq->pushable_dl_tasks_leftmost == &p->pushable_dl_tasks) {
+               struct rb_node *next_node;
+
+               next_node = rb_next(&p->pushable_dl_tasks);
+               dl_rq->pushable_dl_tasks_leftmost = next_node;
+       }
+
+       rb_erase(&p->pushable_dl_tasks, &dl_rq->pushable_dl_tasks_root);
+       RB_CLEAR_NODE(&p->pushable_dl_tasks);
+}
+
+static inline int has_pushable_dl_tasks(struct rq *rq)
+{
+       return !RB_EMPTY_ROOT(&rq->dl.pushable_dl_tasks_root);
+}
+
+static int push_dl_task(struct rq *rq);
+
+#else
+
+static inline
+void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p)
+{
+}
+
+static inline
+void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p)
+{
+}
+
+static inline
+void inc_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
+{
+}
+
+static inline
+void dec_dl_migration(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
+{
+}
+
+#endif /* CONFIG_SMP */
+
+static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags);
+static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags);
+static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p,
+                                 int flags);
+
+/*
+ * We are being explicitly informed that a new instance is starting,
+ * and this means that:
+ *  - the absolute deadline of the entity has to be placed at
+ *    current time + relative deadline;
+ *  - the runtime of the entity has to be set to the maximum value.
+ *
+ * The capability of specifying such event is useful whenever a -deadline
+ * entity wants to (try to!) synchronize its behaviour with the scheduler's
+ * one, and to (try to!) reconcile itself with its own scheduling
+ * parameters.
+ */
+static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se,
+                                      struct sched_dl_entity *pi_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       WARN_ON(!dl_se->dl_new || dl_se->dl_throttled);
+
+       /*
+        * We use the regular wall clock time to set deadlines in the
+        * future; in fact, we must consider execution overheads (time
+        * spent on hardirq context, etc.).
+        */
+       dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
+       dl_se->runtime = pi_se->dl_runtime;
+       dl_se->dl_new = 0;
+}
+
+/*
+ * Pure Earliest Deadline First (EDF) scheduling does not deal with the
+ * possibility of a entity lasting more than what it declared, and thus
+ * exhausting its runtime.
+ *
+ * Here we are interested in making runtime overrun possible, but we do
+ * not want a entity which is misbehaving to affect the scheduling of all
+ * other entities.
+ * Therefore, a budgeting strategy called Constant Bandwidth Server (CBS)
+ * is used, in order to confine each entity within its own bandwidth.
+ *
+ * This function deals exactly with that, and ensures that when the runtime
+ * of a entity is replenished, its deadline is also postponed. That ensures
+ * the overrunning entity can't interfere with other entity in the system and
+ * can't make them miss their deadlines. Reasons why this kind of overruns
+ * could happen are, typically, a entity voluntarily trying to overcome its
+ * runtime, or it just underestimated it during sched_setscheduler_ex().
+ */
+static void replenish_dl_entity(struct sched_dl_entity *dl_se,
+                               struct sched_dl_entity *pi_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       BUG_ON(pi_se->dl_runtime <= 0);
+
+       /*
+        * This could be the case for a !-dl task that is boosted.
+        * Just go with full inherited parameters.
+        */
+       if (dl_se->dl_deadline == 0) {
+               dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
+               dl_se->runtime = pi_se->dl_runtime;
+       }
+
+       /*
+        * We keep moving the deadline away until we get some
+        * available runtime for the entity. This ensures correct
+        * handling of situations where the runtime overrun is
+        * arbitrary large.
+        */
+       while (dl_se->runtime <= 0) {
+               dl_se->deadline += pi_se->dl_period;
+               dl_se->runtime += pi_se->dl_runtime;
+       }
+
+       /*
+        * At this point, the deadline really should be "in
+        * the future" with respect to rq->clock. If it's
+        * not, we are, for some reason, lagging too much!
+        * Anyway, after having warn userspace abut that,
+        * we still try to keep the things running by
+        * resetting the deadline and the budget of the
+        * entity.
+        */
+       if (dl_time_before(dl_se->deadline, rq_clock(rq))) {
+               static bool lag_once = false;
+
+               if (!lag_once) {
+                       lag_once = true;
+                       printk_sched("sched: DL replenish lagged to much\n");
+               }
+               dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
+               dl_se->runtime = pi_se->dl_runtime;
+       }
+}
+
+/*
+ * Here we check if --at time t-- an entity (which is probably being
+ * [re]activated or, in general, enqueued) can use its remaining runtime
+ * and its current deadline _without_ exceeding the bandwidth it is
+ * assigned (function returns true if it can't). We are in fact applying
+ * one of the CBS rules: when a task wakes up, if the residual runtime
+ * over residual deadline fits within the allocated bandwidth, then we
+ * can keep the current (absolute) deadline and residual budget without
+ * disrupting the schedulability of the system. Otherwise, we should
+ * refill the runtime and set the deadline a period in the future,
+ * because keeping the current (absolute) deadline of the task would
+ * result in breaking guarantees promised to other tasks.
+ *
+ * This function returns true if:
+ *
+ *   runtime / (deadline - t) > dl_runtime / dl_period ,
+ *
+ * IOW we can't recycle current parameters.
+ *
+ * Notice that the bandwidth check is done against the period. For
+ * task with deadline equal to period this is the same of using
+ * dl_deadline instead of dl_period in the equation above.
+ */
+static bool dl_entity_overflow(struct sched_dl_entity *dl_se,
+                              struct sched_dl_entity *pi_se, u64 t)
+{
+       u64 left, right;
+
+       /*
+        * left and right are the two sides of the equation above,
+        * after a bit of shuffling to use multiplications instead
+        * of divisions.
+        *
+        * Note that none of the time values involved in the two
+        * multiplications are absolute: dl_deadline and dl_runtime
+        * are the relative deadline and the maximum runtime of each
+        * instance, runtime is the runtime left for the last instance
+        * and (deadline - t), since t is rq->clock, is the time left
+        * to the (absolute) deadline. Even if overflowing the u64 type
+        * is very unlikely to occur in both cases, here we scale down
+        * as we want to avoid that risk at all. Scaling down by 10
+        * means that we reduce granularity to 1us. We are fine with it,
+        * since this is only a true/false check and, anyway, thinking
+        * of anything below microseconds resolution is actually fiction
+        * (but still we want to give the user that illusion >;).
+        */
+       left = (pi_se->dl_period >> DL_SCALE) * (dl_se->runtime >> DL_SCALE);
+       right = ((dl_se->deadline - t) >> DL_SCALE) *
+               (pi_se->dl_runtime >> DL_SCALE);
+
+       return dl_time_before(right, left);
+}
+
+/*
+ * When a -deadline entity is queued back on the runqueue, its runtime and
+ * deadline might need updating.
+ *
+ * The policy here is that we update the deadline of the entity only if:
+ *  - the current deadline is in the past,
+ *  - using the remaining runtime with the current deadline would make
+ *    the entity exceed its bandwidth.
+ */
+static void update_dl_entity(struct sched_dl_entity *dl_se,
+                            struct sched_dl_entity *pi_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       /*
+        * The arrival of a new instance needs special treatment, i.e.,
+        * the actual scheduling parameters have to be "renewed".
+        */
+       if (dl_se->dl_new) {
+               setup_new_dl_entity(dl_se, pi_se);
+               return;
+       }
+
+       if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
+           dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) {
+               dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
+               dl_se->runtime = pi_se->dl_runtime;
+       }
+}
+
+/*
+ * If the entity depleted all its runtime, and if we want it to sleep
+ * while waiting for some new execution time to become available, we
+ * set the bandwidth enforcement timer to the replenishment instant
+ * and try to activate it.
+ *
+ * Notice that it is important for the caller to know if the timer
+ * actually started or not (i.e., the replenishment instant is in
+ * the future or in the past).
+ */
+static int start_dl_timer(struct sched_dl_entity *dl_se, bool boosted)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+       ktime_t now, act;
+       ktime_t soft, hard;
+       unsigned long range;
+       s64 delta;
+
+       if (boosted)
+               return 0;
+       /*
+        * We want the timer to fire at the deadline, but considering
+        * that it is actually coming from rq->clock and not from
+        * hrtimer's time base reading.
+        */
+       act = ns_to_ktime(dl_se->deadline);
+       now = hrtimer_cb_get_time(&dl_se->dl_timer);
+       delta = ktime_to_ns(now) - rq_clock(rq);
+       act = ktime_add_ns(act, delta);
+
+       /*
+        * If the expiry time already passed, e.g., because the value
+        * chosen as the deadline is too small, don't even try to
+        * start the timer in the past!
+        */
+       if (ktime_us_delta(act, now) < 0)
+               return 0;
+
+       hrtimer_set_expires(&dl_se->dl_timer, act);
+
+       soft = hrtimer_get_softexpires(&dl_se->dl_timer);
+       hard = hrtimer_get_expires(&dl_se->dl_timer);
+       range = ktime_to_ns(ktime_sub(hard, soft));
+       __hrtimer_start_range_ns(&dl_se->dl_timer, soft,
+                                range, HRTIMER_MODE_ABS, 0);
+
+       return hrtimer_active(&dl_se->dl_timer);
+}
+
+/*
+ * This is the bandwidth enforcement timer callback. If here, we know
+ * a task is not on its dl_rq, since the fact that the timer was running
+ * means the task is throttled and needs a runtime replenishment.
+ *
+ * However, what we actually do depends on the fact the task is active,
+ * (it is on its rq) or has been removed from there by a call to
+ * dequeue_task_dl(). In the former case we must issue the runtime
+ * replenishment and add the task back to the dl_rq; in the latter, we just
+ * do nothing but clearing dl_throttled, so that runtime and deadline
+ * updating (and the queueing back to dl_rq) will be done by the
+ * next call to enqueue_task_dl().
+ */
+static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
+{
+       struct sched_dl_entity *dl_se = container_of(timer,
+                                                    struct sched_dl_entity,
+                                                    dl_timer);
+       struct task_struct *p = dl_task_of(dl_se);
+       struct rq *rq = task_rq(p);
+       raw_spin_lock(&rq->lock);
+
+       /*
+        * We need to take care of a possible races here. In fact, the
+        * task might have changed its scheduling policy to something
+        * different from SCHED_DEADLINE or changed its reservation
+        * parameters (through sched_setscheduler()).
+        */
+       if (!dl_task(p) || dl_se->dl_new)
+               goto unlock;
+
+       sched_clock_tick();
+       update_rq_clock(rq);
+       dl_se->dl_throttled = 0;
+       if (p->on_rq) {
+               enqueue_task_dl(rq, p, ENQUEUE_REPLENISH);
+               if (task_has_dl_policy(rq->curr))
+                       check_preempt_curr_dl(rq, p, 0);
+               else
+                       resched_task(rq->curr);
+#ifdef CONFIG_SMP
+               /*
+                * Queueing this task back might have overloaded rq,
+                * check if we need to kick someone away.
+                */
+               if (has_pushable_dl_tasks(rq))
+                       push_dl_task(rq);
+#endif
+       }
+unlock:
+       raw_spin_unlock(&rq->lock);
+
+       return HRTIMER_NORESTART;
+}
+
+void init_dl_task_timer(struct sched_dl_entity *dl_se)
+{
+       struct hrtimer *timer = &dl_se->dl_timer;
+
+       if (hrtimer_active(timer)) {
+               hrtimer_try_to_cancel(timer);
+               return;
+       }
+
+       hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       timer->function = dl_task_timer;
+}
+
+static
+int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se)
+{
+       int dmiss = dl_time_before(dl_se->deadline, rq_clock(rq));
+       int rorun = dl_se->runtime <= 0;
+
+       if (!rorun && !dmiss)
+               return 0;
+
+       /*
+        * If we are beyond our current deadline and we are still
+        * executing, then we have already used some of the runtime of
+        * the next instance. Thus, if we do not account that, we are
+        * stealing bandwidth from the system at each deadline miss!
+        */
+       if (dmiss) {
+               dl_se->runtime = rorun ? dl_se->runtime : 0;
+               dl_se->runtime -= rq_clock(rq) - dl_se->deadline;
+       }
+
+       return 1;
+}
+
+/*
+ * Update the current task's runtime statistics (provided it is still
+ * a -deadline task and has not been removed from the dl_rq).
+ */
+static void update_curr_dl(struct rq *rq)
+{
+       struct task_struct *curr = rq->curr;
+       struct sched_dl_entity *dl_se = &curr->dl;
+       u64 delta_exec;
+
+       if (!dl_task(curr) || !on_dl_rq(dl_se))
+               return;
+
+       /*
+        * Consumed budget is computed considering the time as
+        * observed by schedulable tasks (excluding time spent
+        * in hardirq context, etc.). Deadlines are instead
+        * computed using hard walltime. This seems to be the more
+        * natural solution, but the full ramifications of this
+        * approach need further study.
+        */
+       delta_exec = rq_clock_task(rq) - curr->se.exec_start;
+       if (unlikely((s64)delta_exec < 0))
+               delta_exec = 0;
+
+       schedstat_set(curr->se.statistics.exec_max,
+                     max(curr->se.statistics.exec_max, delta_exec));
+
+       curr->se.sum_exec_runtime += delta_exec;
+       account_group_exec_runtime(curr, delta_exec);
+
+       curr->se.exec_start = rq_clock_task(rq);
+       cpuacct_charge(curr, delta_exec);
+
+       sched_rt_avg_update(rq, delta_exec);
+
+       dl_se->runtime -= delta_exec;
+       if (dl_runtime_exceeded(rq, dl_se)) {
+               __dequeue_task_dl(rq, curr, 0);
+               if (likely(start_dl_timer(dl_se, curr->dl.dl_boosted)))
+                       dl_se->dl_throttled = 1;
+               else
+                       enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH);
+
+               if (!is_leftmost(curr, &rq->dl))
+                       resched_task(curr);
+       }
+
+       /*
+        * Because -- for now -- we share the rt bandwidth, we need to
+        * account our runtime there too, otherwise actual rt tasks
+        * would be able to exceed the shared quota.
+        *
+        * Account to the root rt group for now.
+        *
+        * The solution we're working towards is having the RT groups scheduled
+        * using deadline servers -- however there's a few nasties to figure
+        * out before that can happen.
+        */
+       if (rt_bandwidth_enabled()) {
+               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.
+                */
+               raw_spin_unlock(&rt_rq->rt_runtime_lock);
+       }
+}
+
+#ifdef CONFIG_SMP
+
+static struct task_struct *pick_next_earliest_dl_task(struct rq *rq, int cpu);
+
+static inline u64 next_deadline(struct rq *rq)
+{
+       struct task_struct *next = pick_next_earliest_dl_task(rq, rq->cpu);
+
+       if (next && dl_prio(next->prio))
+               return next->dl.deadline;
+       else
+               return 0;
+}
+
+static void inc_dl_deadline(struct dl_rq *dl_rq, u64 deadline)
+{
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       if (dl_rq->earliest_dl.curr == 0 ||
+           dl_time_before(deadline, dl_rq->earliest_dl.curr)) {
+               /*
+                * If the dl_rq had no -deadline tasks, or if the new task
+                * has shorter deadline than the current one on dl_rq, we
+                * know that the previous earliest becomes our next earliest,
+                * as the new task becomes the earliest itself.
+                */
+               dl_rq->earliest_dl.next = dl_rq->earliest_dl.curr;
+               dl_rq->earliest_dl.curr = deadline;
+               cpudl_set(&rq->rd->cpudl, rq->cpu, deadline, 1);
+       } else if (dl_rq->earliest_dl.next == 0 ||
+                  dl_time_before(deadline, dl_rq->earliest_dl.next)) {
+               /*
+                * On the other hand, if the new -deadline task has a
+                * a later deadline than the earliest one on dl_rq, but
+                * it is earlier than the next (if any), we must
+                * recompute the next-earliest.
+                */
+               dl_rq->earliest_dl.next = next_deadline(rq);
+       }
+}
+
+static void dec_dl_deadline(struct dl_rq *dl_rq, u64 deadline)
+{
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       /*
+        * Since we may have removed our earliest (and/or next earliest)
+        * task we must recompute them.
+        */
+       if (!dl_rq->dl_nr_running) {
+               dl_rq->earliest_dl.curr = 0;
+               dl_rq->earliest_dl.next = 0;
+               cpudl_set(&rq->rd->cpudl, rq->cpu, 0, 0);
+       } else {
+               struct rb_node *leftmost = dl_rq->rb_leftmost;
+               struct sched_dl_entity *entry;
+
+               entry = rb_entry(leftmost, struct sched_dl_entity, rb_node);
+               dl_rq->earliest_dl.curr = entry->deadline;
+               dl_rq->earliest_dl.next = next_deadline(rq);
+               cpudl_set(&rq->rd->cpudl, rq->cpu, entry->deadline, 1);
+       }
+}
+
+#else
+
+static inline void inc_dl_deadline(struct dl_rq *dl_rq, u64 deadline) {}
+static inline void dec_dl_deadline(struct dl_rq *dl_rq, u64 deadline) {}
+
+#endif /* CONFIG_SMP */
+
+static inline
+void inc_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
+{
+       int prio = dl_task_of(dl_se)->prio;
+       u64 deadline = dl_se->deadline;
+
+       WARN_ON(!dl_prio(prio));
+       dl_rq->dl_nr_running++;
+
+       inc_dl_deadline(dl_rq, deadline);
+       inc_dl_migration(dl_se, dl_rq);
+}
+
+static inline
+void dec_dl_tasks(struct sched_dl_entity *dl_se, struct dl_rq *dl_rq)
+{
+       int prio = dl_task_of(dl_se)->prio;
+
+       WARN_ON(!dl_prio(prio));
+       WARN_ON(!dl_rq->dl_nr_running);
+       dl_rq->dl_nr_running--;
+
+       dec_dl_deadline(dl_rq, dl_se->deadline);
+       dec_dl_migration(dl_se, dl_rq);
+}
+
+static void __enqueue_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rb_node **link = &dl_rq->rb_root.rb_node;
+       struct rb_node *parent = NULL;
+       struct sched_dl_entity *entry;
+       int leftmost = 1;
+
+       BUG_ON(!RB_EMPTY_NODE(&dl_se->rb_node));
+
+       while (*link) {
+               parent = *link;
+               entry = rb_entry(parent, struct sched_dl_entity, rb_node);
+               if (dl_time_before(dl_se->deadline, entry->deadline))
+                       link = &parent->rb_left;
+               else {
+                       link = &parent->rb_right;
+                       leftmost = 0;
+               }
+       }
+
+       if (leftmost)
+               dl_rq->rb_leftmost = &dl_se->rb_node;
+
+       rb_link_node(&dl_se->rb_node, parent, link);
+       rb_insert_color(&dl_se->rb_node, &dl_rq->rb_root);
+
+       inc_dl_tasks(dl_se, dl_rq);
+}
+
+static void __dequeue_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+
+       if (RB_EMPTY_NODE(&dl_se->rb_node))
+               return;
+
+       if (dl_rq->rb_leftmost == &dl_se->rb_node) {
+               struct rb_node *next_node;
+
+               next_node = rb_next(&dl_se->rb_node);
+               dl_rq->rb_leftmost = next_node;
+       }
+
+       rb_erase(&dl_se->rb_node, &dl_rq->rb_root);
+       RB_CLEAR_NODE(&dl_se->rb_node);
+
+       dec_dl_tasks(dl_se, dl_rq);
+}
+
+static void
+enqueue_dl_entity(struct sched_dl_entity *dl_se,
+                 struct sched_dl_entity *pi_se, int flags)
+{
+       BUG_ON(on_dl_rq(dl_se));
+
+       /*
+        * If this is a wakeup or a new instance, the scheduling
+        * parameters of the task might need updating. Otherwise,
+        * we want a replenishment of its runtime.
+        */
+       if (!dl_se->dl_new && flags & ENQUEUE_REPLENISH)
+               replenish_dl_entity(dl_se, pi_se);
+       else
+               update_dl_entity(dl_se, pi_se);
+
+       __enqueue_dl_entity(dl_se);
+}
+
+static void dequeue_dl_entity(struct sched_dl_entity *dl_se)
+{
+       __dequeue_dl_entity(dl_se);
+}
+
+static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
+{
+       struct task_struct *pi_task = rt_mutex_get_top_task(p);
+       struct sched_dl_entity *pi_se = &p->dl;
+
+       /*
+        * Use the scheduling parameters of the top pi-waiter
+        * task if we have one and its (relative) deadline is
+        * smaller than our one... OTW we keep our runtime and
+        * deadline.
+        */
+       if (pi_task && p->dl.dl_boosted && dl_prio(pi_task->normal_prio))
+               pi_se = &pi_task->dl;
+
+       /*
+        * If p is throttled, we do nothing. In fact, if it exhausted
+        * its budget it needs a replenishment and, since it now is on
+        * its rq, the bandwidth timer callback (which clearly has not
+        * run yet) will take care of this.
+        */
+       if (p->dl.dl_throttled)
+               return;
+
+       enqueue_dl_entity(&p->dl, pi_se, 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)
+{
+       dequeue_dl_entity(&p->dl);
+       dequeue_pushable_dl_task(rq, p);
+}
+
+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);
+}
+
+/*
+ * Yield task semantic for -deadline tasks is:
+ *
+ *   get off from the CPU until our next instance, with
+ *   a new runtime. This is of little use now, since we
+ *   don't have a bandwidth reclaiming mechanism. Anyway,
+ *   bandwidth reclaiming is planned for the future, and
+ *   yield_task_dl will indicate that some spare budget
+ *   is available for other task instances to use it.
+ */
+static void yield_task_dl(struct rq *rq)
+{
+       struct task_struct *p = rq->curr;
+
+       /*
+        * We make the task go to sleep until its current deadline by
+        * forcing its runtime to zero. This way, update_curr_dl() stops
+        * it and the bandwidth timer will wake it up and will give it
+        * new scheduling parameters (thanks to dl_new=1).
+        */
+       if (p->dl.runtime > 0) {
+               rq->curr->dl.dl_new = 1;
+               p->dl.runtime = 0;
+       }
+       update_curr_dl(rq);
+}
+
+#ifdef CONFIG_SMP
+
+static int find_later_rq(struct task_struct *task);
+
+static int
+select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags)
+{
+       struct task_struct *curr;
+       struct rq *rq;
+
+       if (sd_flag != SD_BALANCE_WAKE && sd_flag != SD_BALANCE_FORK)
+               goto out;
+
+       rq = cpu_rq(cpu);
+
+       rcu_read_lock();
+       curr = ACCESS_ONCE(rq->curr); /* unlocked access */
+
+       /*
+        * If we are dealing with a -deadline task, we must
+        * decide where to wake it up.
+        * If it has a later deadline and the current task
+        * on this rq can't move (provided the waking task
+        * can!) we prefer to send it somewhere else. On the
+        * other hand, if it has a shorter deadline, we
+        * try to make it stay here, it might be important.
+        */
+       if (unlikely(dl_task(curr)) &&
+           (curr->nr_cpus_allowed < 2 ||
+            !dl_entity_preempt(&p->dl, &curr->dl)) &&
+           (p->nr_cpus_allowed > 1)) {
+               int target = find_later_rq(p);
+
+               if (target != -1)
+                       cpu = target;
+       }
+       rcu_read_unlock();
+
+out:
+       return cpu;
+}
+
+static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p)
+{
+       /*
+        * Current can't be migrated, useless to reschedule,
+        * let's hope p can move out.
+        */
+       if (rq->curr->nr_cpus_allowed == 1 ||
+           cpudl_find(&rq->rd->cpudl, rq->curr, NULL) == -1)
+               return;
+
+       /*
+        * p is migratable, so let's not schedule it and
+        * see if it is pushed or pulled somewhere else.
+        */
+       if (p->nr_cpus_allowed != 1 &&
+           cpudl_find(&rq->rd->cpudl, p, NULL) != -1)
+               return;
+
+       resched_task(rq->curr);
+}
+
+#endif /* CONFIG_SMP */
+
+/*
+ * Only called when both the current and waking task are -deadline
+ * tasks.
+ */
+static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p,
+                                 int flags)
+{
+       if (dl_entity_preempt(&p->dl, &rq->curr->dl)) {
+               resched_task(rq->curr);
+               return;
+       }
+
+#ifdef CONFIG_SMP
+       /*
+        * In the unlikely case current and p have the same deadline
+        * let us try to decide what's the best thing to do...
+        */
+       if ((p->dl.deadline == rq->curr->dl.deadline) &&
+           !test_tsk_need_resched(rq->curr))
+               check_preempt_equal_dl(rq, p);
+#endif /* CONFIG_SMP */
+}
+
+#ifdef CONFIG_SCHED_HRTICK
+static void start_hrtick_dl(struct rq *rq, struct task_struct *p)
+{
+       s64 delta = p->dl.dl_runtime - p->dl.runtime;
+
+       if (delta > 10000)
+               hrtick_start(rq, p->dl.runtime);
+}
+#endif
+
+static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
+                                                  struct dl_rq *dl_rq)
+{
+       struct rb_node *left = dl_rq->rb_leftmost;
+
+       if (!left)
+               return NULL;
+
+       return rb_entry(left, struct sched_dl_entity, rb_node);
+}
+
+struct task_struct *pick_next_task_dl(struct rq *rq)
+{
+       struct sched_dl_entity *dl_se;
+       struct task_struct *p;
+       struct dl_rq *dl_rq;
+
+       dl_rq = &rq->dl;
+
+       if (unlikely(!dl_rq->dl_nr_running))
+               return NULL;
+
+       dl_se = pick_next_dl_entity(rq, dl_rq);
+       BUG_ON(!dl_se);
+
+       p = dl_task_of(dl_se);
+       p->se.exec_start = rq_clock_task(rq);
+
+       /* Running task will never be pushed. */
+       dequeue_pushable_dl_task(rq, p);
+
+#ifdef CONFIG_SCHED_HRTICK
+       if (hrtick_enabled(rq))
+               start_hrtick_dl(rq, p);
+#endif
+
+#ifdef CONFIG_SMP
+       rq->post_schedule = has_pushable_dl_tasks(rq);
+#endif /* CONFIG_SMP */
+
+       return p;
+}
+
+static void put_prev_task_dl(struct rq *rq, struct task_struct *p)
+{
+       update_curr_dl(rq);
+
+       if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1)
+               enqueue_pushable_dl_task(rq, p);
+}
+
+static void task_tick_dl(struct rq *rq, struct task_struct *p, int queued)
+{
+       update_curr_dl(rq);
+
+#ifdef CONFIG_SCHED_HRTICK
+       if (hrtick_enabled(rq) && queued && p->dl.runtime > 0)
+               start_hrtick_dl(rq, p);
+#endif
+}
+
+static void task_fork_dl(struct task_struct *p)
+{
+       /*
+        * SCHED_DEADLINE tasks cannot fork and this is achieved through
+        * sched_fork()
+        */
+}
+
+static void task_dead_dl(struct task_struct *p)
+{
+       struct hrtimer *timer = &p->dl.dl_timer;
+       struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
+
+       /*
+        * Since we are TASK_DEAD we won't slip out of the domain!
+        */
+       raw_spin_lock_irq(&dl_b->lock);
+       dl_b->total_bw -= p->dl.dl_bw;
+       raw_spin_unlock_irq(&dl_b->lock);
+
+       hrtimer_cancel(timer);
+}
+
+static void set_curr_task_dl(struct rq *rq)
+{
+       struct task_struct *p = rq->curr;
+
+       p->se.exec_start = rq_clock_task(rq);
+
+       /* You can't push away the running task */
+       dequeue_pushable_dl_task(rq, p);
+}
+
+#ifdef CONFIG_SMP
+
+/* Only try algorithms three times */
+#define DL_MAX_TRIES 3
+
+static int pick_dl_task(struct rq *rq, struct task_struct *p, int cpu)
+{
+       if (!task_running(rq, p) &&
+           (cpu < 0 || cpumask_test_cpu(cpu, &p->cpus_allowed)) &&
+           (p->nr_cpus_allowed > 1))
+               return 1;
+
+       return 0;
+}
+
+/* Returns the second earliest -deadline task, NULL otherwise */
+static struct task_struct *pick_next_earliest_dl_task(struct rq *rq, int cpu)
+{
+       struct rb_node *next_node = rq->dl.rb_leftmost;
+       struct sched_dl_entity *dl_se;
+       struct task_struct *p = NULL;
+
+next_node:
+       next_node = rb_next(next_node);
+       if (next_node) {
+               dl_se = rb_entry(next_node, struct sched_dl_entity, rb_node);
+               p = dl_task_of(dl_se);
+
+               if (pick_dl_task(rq, p, cpu))
+                       return p;
+
+               goto next_node;
+       }
+
+       return NULL;
+}
+
+static DEFINE_PER_CPU(cpumask_var_t, local_cpu_mask_dl);
+
+static int find_later_rq(struct task_struct *task)
+{
+       struct sched_domain *sd;
+       struct cpumask *later_mask = __get_cpu_var(local_cpu_mask_dl);
+       int this_cpu = smp_processor_id();
+       int best_cpu, cpu = task_cpu(task);
+
+       /* Make sure the mask is initialized first */
+       if (unlikely(!later_mask))
+               return -1;
+
+       if (task->nr_cpus_allowed == 1)
+               return -1;
+
+       best_cpu = cpudl_find(&task_rq(task)->rd->cpudl,
+                       task, later_mask);
+       if (best_cpu == -1)
+               return -1;
+
+       /*
+        * If we are here, some target has been found,
+        * the most suitable of which is cached in best_cpu.
+        * This is, among the runqueues where the current tasks
+        * have later deadlines than the task's one, the rq
+        * with the latest possible one.
+        *
+        * Now we check how well this matches with task's
+        * affinity and system topology.
+        *
+        * The last cpu where the task run is our first
+        * guess, since it is most likely cache-hot there.
+        */
+       if (cpumask_test_cpu(cpu, later_mask))
+               return cpu;
+       /*
+        * Check if this_cpu is to be skipped (i.e., it is
+        * not in the mask) or not.
+        */
+       if (!cpumask_test_cpu(this_cpu, later_mask))
+               this_cpu = -1;
+
+       rcu_read_lock();
+       for_each_domain(cpu, sd) {
+               if (sd->flags & SD_WAKE_AFFINE) {
+
+                       /*
+                        * If possible, preempting this_cpu is
+                        * cheaper than migrating.
+                        */
+                       if (this_cpu != -1 &&
+                           cpumask_test_cpu(this_cpu, sched_domain_span(sd))) {
+                               rcu_read_unlock();
+                               return this_cpu;
+                       }
+
+                       /*
+                        * Last chance: if best_cpu is valid and is
+                        * in the mask, that becomes our choice.
+                        */
+                       if (best_cpu < nr_cpu_ids &&
+                           cpumask_test_cpu(best_cpu, sched_domain_span(sd))) {
+                               rcu_read_unlock();
+                               return best_cpu;
+                       }
+               }
+       }
+       rcu_read_unlock();
+
+       /*
+        * At this point, all our guesses failed, we just return
+        * 'something', and let the caller sort the things out.
+        */
+       if (this_cpu != -1)
+               return this_cpu;
+
+       cpu = cpumask_any(later_mask);
+       if (cpu < nr_cpu_ids)
+               return cpu;
+
+       return -1;
+}
+
+/* Locks the rq it finds */
+static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq)
+{
+       struct rq *later_rq = NULL;
+       int tries;
+       int cpu;
+
+       for (tries = 0; tries < DL_MAX_TRIES; tries++) {
+               cpu = find_later_rq(task);
+
+               if ((cpu == -1) || (cpu == rq->cpu))
+                       break;
+
+               later_rq = cpu_rq(cpu);
+
+               /* Retry if something changed. */
+               if (double_lock_balance(rq, later_rq)) {
+                       if (unlikely(task_rq(task) != rq ||
+                                    !cpumask_test_cpu(later_rq->cpu,
+                                                      &task->cpus_allowed) ||
+                                    task_running(rq, task) || !task->on_rq)) {
+                               double_unlock_balance(rq, later_rq);
+                               later_rq = NULL;
+                               break;
+                       }
+               }
+
+               /*
+                * If the rq we found has no -deadline task, or
+                * its earliest one has a later deadline than our
+                * task, the rq is a good one.
+                */
+               if (!later_rq->dl.dl_nr_running ||
+                   dl_time_before(task->dl.deadline,
+                                  later_rq->dl.earliest_dl.curr))
+                       break;
+
+               /* Otherwise we try again. */
+               double_unlock_balance(rq, later_rq);
+               later_rq = NULL;
+       }
+
+       return later_rq;
+}
+
+static struct task_struct *pick_next_pushable_dl_task(struct rq *rq)
+{
+       struct task_struct *p;
+
+       if (!has_pushable_dl_tasks(rq))
+               return NULL;
+
+       p = rb_entry(rq->dl.pushable_dl_tasks_leftmost,
+                    struct task_struct, pushable_dl_tasks);
+
+       BUG_ON(rq->cpu != task_cpu(p));
+       BUG_ON(task_current(rq, p));
+       BUG_ON(p->nr_cpus_allowed <= 1);
+
+       BUG_ON(!p->on_rq);
+       BUG_ON(!dl_task(p));
+
+       return p;
+}
+
+/*
+ * See if the non running -deadline tasks on this rq
+ * can be sent to some other CPU where they can preempt
+ * and start executing.
+ */
+static int push_dl_task(struct rq *rq)
+{
+       struct task_struct *next_task;
+       struct rq *later_rq;
+
+       if (!rq->dl.overloaded)
+               return 0;
+
+       next_task = pick_next_pushable_dl_task(rq);
+       if (!next_task)
+               return 0;
+
+retry:
+       if (unlikely(next_task == rq->curr)) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       /*
+        * If next_task preempts rq->curr, and rq->curr
+        * can move away, it makes sense to just reschedule
+        * without going further in pushing next_task.
+        */
+       if (dl_task(rq->curr) &&
+           dl_time_before(next_task->dl.deadline, rq->curr->dl.deadline) &&
+           rq->curr->nr_cpus_allowed > 1) {
+               resched_task(rq->curr);
+               return 0;
+       }
+
+       /* We might release rq lock */
+       get_task_struct(next_task);
+
+       /* Will lock the rq it'll find */
+       later_rq = find_lock_later_rq(next_task, rq);
+       if (!later_rq) {
+               struct task_struct *task;
+
+               /*
+                * We must check all this again, since
+                * find_lock_later_rq releases rq->lock and it is
+                * then possible that next_task has migrated.
+                */
+               task = pick_next_pushable_dl_task(rq);
+               if (task_cpu(next_task) == rq->cpu && task == next_task) {
+                       /*
+                        * The task is still there. We don't try
+                        * again, some other cpu will pull it when ready.
+                        */
+                       dequeue_pushable_dl_task(rq, next_task);
+                       goto out;
+               }
+
+               if (!task)
+                       /* No more tasks */
+                       goto out;
+
+               put_task_struct(next_task);
+               next_task = task;
+               goto retry;
+       }
+
+       deactivate_task(rq, next_task, 0);
+       set_task_cpu(next_task, later_rq->cpu);
+       activate_task(later_rq, next_task, 0);
+
+       resched_task(later_rq->curr);
+
+       double_unlock_balance(rq, later_rq);
+
+out:
+       put_task_struct(next_task);
+
+       return 1;
+}
+
+static void push_dl_tasks(struct rq *rq)
+{
+       /* Terminates as it moves a -deadline task */
+       while (push_dl_task(rq))
+               ;
+}
+
+static int pull_dl_task(struct rq *this_rq)
+{
+       int this_cpu = this_rq->cpu, ret = 0, cpu;
+       struct task_struct *p;
+       struct rq *src_rq;
+       u64 dmin = LONG_MAX;
+
+       if (likely(!dl_overloaded(this_rq)))
+               return 0;
+
+       /*
+        * Match the barrier from dl_set_overloaded; this guarantees that if we
+        * see overloaded we must also see the dlo_mask bit.
+        */
+       smp_rmb();
+
+       for_each_cpu(cpu, this_rq->rd->dlo_mask) {
+               if (this_cpu == cpu)
+                       continue;
+
+               src_rq = cpu_rq(cpu);
+
+               /*
+                * It looks racy, abd it is! However, as in sched_rt.c,
+                * we are fine with this.
+                */
+               if (this_rq->dl.dl_nr_running &&
+                   dl_time_before(this_rq->dl.earliest_dl.curr,
+                                  src_rq->dl.earliest_dl.next))
+                       continue;
+
+               /* Might drop this_rq->lock */
+               double_lock_balance(this_rq, src_rq);
+
+               /*
+                * If there are no more pullable tasks on the
+                * rq, we're done with it.
+                */
+               if (src_rq->dl.dl_nr_running <= 1)
+                       goto skip;
+
+               p = pick_next_earliest_dl_task(src_rq, this_cpu);
+
+               /*
+                * We found a task to be pulled if:
+                *  - it preempts our current (if there's one),
+                *  - it will preempt the last one we pulled (if any).
+                */
+               if (p && dl_time_before(p->dl.deadline, dmin) &&
+                   (!this_rq->dl.dl_nr_running ||
+                    dl_time_before(p->dl.deadline,
+                                   this_rq->dl.earliest_dl.curr))) {
+                       WARN_ON(p == src_rq->curr);
+                       WARN_ON(!p->on_rq);
+
+                       /*
+                        * Then we pull iff p has actually an earlier
+                        * deadline than the current task of its runqueue.
+                        */
+                       if (dl_time_before(p->dl.deadline,
+                                          src_rq->curr->dl.deadline))
+                               goto skip;
+
+                       ret = 1;
+
+                       deactivate_task(src_rq, p, 0);
+                       set_task_cpu(p, this_cpu);
+                       activate_task(this_rq, p, 0);
+                       dmin = p->dl.deadline;
+
+                       /* Is there any other task even earlier? */
+               }
+skip:
+               double_unlock_balance(this_rq, src_rq);
+       }
+
+       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);
+}
+
+/*
+ * Since the task is not running and a reschedule is not going to happen
+ * anytime soon on its runqueue, we try pushing it away now.
+ */
+static void task_woken_dl(struct rq *rq, struct task_struct *p)
+{
+       if (!task_running(rq, p) &&
+           !test_tsk_need_resched(rq->curr) &&
+           has_pushable_dl_tasks(rq) &&
+           p->nr_cpus_allowed > 1 &&
+           dl_task(rq->curr) &&
+           (rq->curr->nr_cpus_allowed < 2 ||
+            dl_entity_preempt(&rq->curr->dl, &p->dl))) {
+               push_dl_tasks(rq);
+       }
+}
+
+static void set_cpus_allowed_dl(struct task_struct *p,
+                               const struct cpumask *new_mask)
+{
+       struct rq *rq;
+       int weight;
+
+       BUG_ON(!dl_task(p));
+
+       /*
+        * Update only if the task is actually running (i.e.,
+        * it is on the rq AND it is not throttled).
+        */
+       if (!on_dl_rq(&p->dl))
+               return;
+
+       weight = cpumask_weight(new_mask);
+
+       /*
+        * Only update if the process changes its state from whether it
+        * can migrate or not.
+        */
+       if ((p->nr_cpus_allowed > 1) == (weight > 1))
+               return;
+
+       rq = task_rq(p);
+
+       /*
+        * The process used to be able to migrate OR it can now migrate
+        */
+       if (weight <= 1) {
+               if (!task_current(rq, p))
+                       dequeue_pushable_dl_task(rq, p);
+               BUG_ON(!rq->dl.dl_nr_migratory);
+               rq->dl.dl_nr_migratory--;
+       } else {
+               if (!task_current(rq, p))
+                       enqueue_pushable_dl_task(rq, p);
+               rq->dl.dl_nr_migratory++;
+       }
+
+       update_dl_migration(&rq->dl);
+}
+
+/* Assumes rq->lock is held */
+static void rq_online_dl(struct rq *rq)
+{
+       if (rq->dl.overloaded)
+               dl_set_overload(rq);
+
+       if (rq->dl.dl_nr_running > 0)
+               cpudl_set(&rq->rd->cpudl, rq->cpu, rq->dl.earliest_dl.curr, 1);
+}
+
+/* Assumes rq->lock is held */
+static void rq_offline_dl(struct rq *rq)
+{
+       if (rq->dl.overloaded)
+               dl_clear_overload(rq);
+
+       cpudl_set(&rq->rd->cpudl, rq->cpu, 0, 0);
+}
+
+void init_sched_dl_class(void)
+{
+       unsigned int i;
+
+       for_each_possible_cpu(i)
+               zalloc_cpumask_var_node(&per_cpu(local_cpu_mask_dl, i),
+                                       GFP_KERNEL, cpu_to_node(i));
+}
+
+#endif /* CONFIG_SMP */
+
+static void switched_from_dl(struct rq *rq, struct task_struct *p)
+{
+       if (hrtimer_active(&p->dl.dl_timer) && !dl_policy(p->policy))
+               hrtimer_try_to_cancel(&p->dl.dl_timer);
+
+#ifdef CONFIG_SMP
+       /*
+        * Since this might be the only -deadline task on the rq,
+        * this is the right place to try to pull some other one
+        * from an overloaded cpu, if any.
+        */
+       if (!rq->dl.dl_nr_running)
+               pull_dl_task(rq);
+#endif
+}
+
+/*
+ * When switching to -deadline, we may overload the rq, then
+ * we try to push someone off, if possible.
+ */
+static void switched_to_dl(struct rq *rq, struct task_struct *p)
+{
+       int check_resched = 1;
+
+       /*
+        * If p is throttled, don't consider the possibility
+        * of preempting rq->curr, the check will be done right
+        * after its runtime will get replenished.
+        */
+       if (unlikely(p->dl.dl_throttled))
+               return;
+
+       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 */
+                       check_resched = 0;
+#endif /* CONFIG_SMP */
+               if (check_resched && task_has_dl_policy(rq->curr))
+                       check_preempt_curr_dl(rq, p, 0);
+       }
+}
+
+/*
+ * If the scheduling parameters of a -deadline task changed,
+ * a push or pull operation might be needed.
+ */
+static void prio_changed_dl(struct rq *rq, struct task_struct *p,
+                           int oldprio)
+{
+       if (p->on_rq || rq->curr == p) {
+#ifdef CONFIG_SMP
+               /*
+                * This might be too much, but unfortunately
+                * we don't have the old deadline value, and
+                * we can't argue if the task is increasing
+                * or lowering its prio, so...
+                */
+               if (!rq->dl.overloaded)
+                       pull_dl_task(rq);
+
+               /*
+                * If we now have a earlier deadline task than p,
+                * then reschedule, provided p is still on this
+                * runqueue.
+                */
+               if (dl_time_before(rq->dl.earliest_dl.curr, p->dl.deadline) &&
+                   rq->curr == p)
+                       resched_task(p);
+#else
+               /*
+                * Again, we don't know if p has a earlier
+                * or later deadline, so let's blindly set a
+                * (maybe not needed) rescheduling point.
+                */
+               resched_task(p);
+#endif /* CONFIG_SMP */
+       } else
+               switched_to_dl(rq, p);
+}
+
+const struct sched_class dl_sched_class = {
+       .next                   = &rt_sched_class,
+       .enqueue_task           = enqueue_task_dl,
+       .dequeue_task           = dequeue_task_dl,
+       .yield_task             = yield_task_dl,
+
+       .check_preempt_curr     = check_preempt_curr_dl,
+
+       .pick_next_task         = pick_next_task_dl,
+       .put_prev_task          = put_prev_task_dl,
+
+#ifdef CONFIG_SMP
+       .select_task_rq         = select_task_rq_dl,
+       .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
+
+       .set_curr_task          = set_curr_task_dl,
+       .task_tick              = task_tick_dl,
+       .task_fork              = task_fork_dl,
+       .task_dead              = task_dead_dl,
+
+       .prio_changed           = prio_changed_dl,
+       .switched_from          = switched_from_dl,
+       .switched_to            = switched_to_dl,
+};
index 5c34d1817e8f2346e853cc8f273fdabce1d52db1..dd52e7ffb10ed3e16dd36ca01a08e9438fcd7872 100644 (file)
@@ -139,7 +139,7 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
                0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L);
 #endif
 #ifdef CONFIG_NUMA_BALANCING
-       SEQ_printf(m, " %d", cpu_to_node(task_cpu(p)));
+       SEQ_printf(m, " %d", task_node(p));
 #endif
 #ifdef CONFIG_CGROUP_SCHED
        SEQ_printf(m, " %s", task_group_path(task_group(p)));
@@ -371,7 +371,7 @@ static void sched_debug_header(struct seq_file *m)
        PN(cpu_clk);
        P(jiffies);
 #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
-       P(sched_clock_stable);
+       P(sched_clock_stable());
 #endif
 #undef PN
 #undef P
index e8b652ebe027c481e87122f629a300058cf82679..b24b6cfde9aaba5ecfe038ff503e3cd5525f610e 100644 (file)
@@ -178,59 +178,61 @@ void sched_init_granularity(void)
        update_sysctl();
 }
 
-#if BITS_PER_LONG == 32
-# define WMULT_CONST   (~0UL)
-#else
-# define WMULT_CONST   (1UL << 32)
-#endif
-
+#define WMULT_CONST    (~0U)
 #define WMULT_SHIFT    32
 
-/*
- * Shift right and round:
- */
-#define SRR(x, y) (((x) + (1UL << ((y) - 1))) >> (y))
+static void __update_inv_weight(struct load_weight *lw)
+{
+       unsigned long w;
+
+       if (likely(lw->inv_weight))
+               return;
+
+       w = scale_load_down(lw->weight);
+
+       if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
+               lw->inv_weight = 1;
+       else if (unlikely(!w))
+               lw->inv_weight = WMULT_CONST;
+       else
+               lw->inv_weight = WMULT_CONST / w;
+}
 
 /*
- * delta *= weight / lw
+ * delta_exec * weight / lw.weight
+ *   OR
+ * (delta_exec * (weight * lw->inv_weight)) >> WMULT_SHIFT
+ *
+ * Either weight := NICE_0_LOAD and lw \e prio_to_wmult[], in which case
+ * we're guaranteed shift stays positive because inv_weight is guaranteed to
+ * fit 32 bits, and NICE_0_LOAD gives another 10 bits; therefore shift >= 22.
+ *
+ * Or, weight =< lw.weight (because lw.weight is the runqueue weight), thus
+ * weight/lw.weight <= 1, and therefore our shift will also be positive.
  */
-static unsigned long
-calc_delta_mine(unsigned long delta_exec, unsigned long weight,
-               struct load_weight *lw)
+static u64 __calc_delta(u64 delta_exec, unsigned long weight, struct load_weight *lw)
 {
-       u64 tmp;
+       u64 fact = scale_load_down(weight);
+       int shift = WMULT_SHIFT;
 
-       /*
-        * weight can be less than 2^SCHED_LOAD_RESOLUTION for task group sched
-        * entities since MIN_SHARES = 2. Treat weight as 1 if less than
-        * 2^SCHED_LOAD_RESOLUTION.
-        */
-       if (likely(weight > (1UL << SCHED_LOAD_RESOLUTION)))
-               tmp = (u64)delta_exec * scale_load_down(weight);
-       else
-               tmp = (u64)delta_exec;
-
-       if (!lw->inv_weight) {
-               unsigned long w = scale_load_down(lw->weight);
+       __update_inv_weight(lw);
 
-               if (BITS_PER_LONG > 32 && unlikely(w >= WMULT_CONST))
-                       lw->inv_weight = 1;
-               else if (unlikely(!w))
-                       lw->inv_weight = WMULT_CONST;
-               else
-                       lw->inv_weight = WMULT_CONST / w;
+       if (unlikely(fact >> 32)) {
+               while (fact >> 32) {
+                       fact >>= 1;
+                       shift--;
+               }
        }
 
-       /*
-        * Check whether we'd overflow the 64-bit multiplication:
-        */
-       if (unlikely(tmp > WMULT_CONST))
-               tmp = SRR(SRR(tmp, WMULT_SHIFT/2) * lw->inv_weight,
-                       WMULT_SHIFT/2);
-       else
-               tmp = SRR(tmp * lw->inv_weight, WMULT_SHIFT);
+       /* hint to use a 32x32->64 mul */
+       fact = (u64)(u32)fact * lw->inv_weight;
+
+       while (fact >> 32) {
+               fact >>= 1;
+               shift--;
+       }
 
-       return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX);
+       return mul_u64_u32_shr(delta_exec, fact, shift);
 }
 
 
@@ -443,7 +445,7 @@ find_matching_se(struct sched_entity **se, struct sched_entity **pse)
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
 static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec);
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec);
 
 /**************************************************************
  * Scheduling class tree data structure manipulation methods:
@@ -612,11 +614,10 @@ int sched_proc_update_handler(struct ctl_table *table, int write,
 /*
  * delta /= w
  */
-static inline unsigned long
-calc_delta_fair(unsigned long delta, struct sched_entity *se)
+static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)
 {
        if (unlikely(se->load.weight != NICE_0_LOAD))
-               delta = calc_delta_mine(delta, NICE_0_LOAD, &se->load);
+               delta = __calc_delta(delta, NICE_0_LOAD, &se->load);
 
        return delta;
 }
@@ -665,7 +666,7 @@ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se)
                        update_load_add(&lw, se->load.weight);
                        load = &lw;
                }
-               slice = calc_delta_mine(slice, se->load.weight, load);
+               slice = __calc_delta(slice, se->load.weight, load);
        }
        return slice;
 }
@@ -703,47 +704,32 @@ void init_task_runnable_average(struct task_struct *p)
 #endif
 
 /*
- * Update the current task's runtime statistics. Skip current tasks that
- * are not in our scheduling class.
+ * Update the current task's runtime statistics.
  */
-static inline void
-__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr,
-             unsigned long delta_exec)
-{
-       unsigned long delta_exec_weighted;
-
-       schedstat_set(curr->statistics.exec_max,
-                     max((u64)delta_exec, curr->statistics.exec_max));
-
-       curr->sum_exec_runtime += delta_exec;
-       schedstat_add(cfs_rq, exec_clock, delta_exec);
-       delta_exec_weighted = calc_delta_fair(delta_exec, curr);
-
-       curr->vruntime += delta_exec_weighted;
-       update_min_vruntime(cfs_rq);
-}
-
 static void update_curr(struct cfs_rq *cfs_rq)
 {
        struct sched_entity *curr = cfs_rq->curr;
        u64 now = rq_clock_task(rq_of(cfs_rq));
-       unsigned long delta_exec;
+       u64 delta_exec;
 
        if (unlikely(!curr))
                return;
 
-       /*
-        * Get the amount of time the current task was running
-        * since the last time we changed load (this cannot
-        * overflow on 32 bits):
-        */
-       delta_exec = (unsigned long)(now - curr->exec_start);
-       if (!delta_exec)
+       delta_exec = now - curr->exec_start;
+       if (unlikely((s64)delta_exec <= 0))
                return;
 
-       __update_curr(cfs_rq, curr, delta_exec);
        curr->exec_start = now;
 
+       schedstat_set(curr->statistics.exec_max,
+                     max(delta_exec, curr->statistics.exec_max));
+
+       curr->sum_exec_runtime += delta_exec;
+       schedstat_add(cfs_rq, exec_clock, delta_exec);
+
+       curr->vruntime += calc_delta_fair(delta_exec, curr);
+       update_min_vruntime(cfs_rq);
+
        if (entity_is_task(curr)) {
                struct task_struct *curtask = task_of(curr);
 
@@ -886,15 +872,6 @@ static unsigned int task_scan_max(struct task_struct *p)
        return max(smin, smax);
 }
 
-/*
- * Once a preferred node is selected the scheduler balancer will prefer moving
- * a task to that node for sysctl_numa_balancing_settle_count number of PTE
- * scans. This will give the process the chance to accumulate more faults on
- * the preferred node but still allow the scheduler to move the task again if
- * the nodes CPUs are overloaded.
- */
-unsigned int sysctl_numa_balancing_settle_count __read_mostly = 4;
-
 static void account_numa_enqueue(struct rq *rq, struct task_struct *p)
 {
        rq->nr_numa_running += (p->numa_preferred_nid != -1);
@@ -944,7 +921,8 @@ static inline unsigned long group_faults(struct task_struct *p, int nid)
        if (!p->numa_group)
                return 0;
 
-       return p->numa_group->faults[2*nid] + p->numa_group->faults[2*nid+1];
+       return p->numa_group->faults[task_faults_idx(nid, 0)] +
+               p->numa_group->faults[task_faults_idx(nid, 1)];
 }
 
 /*
@@ -1037,7 +1015,7 @@ struct task_numa_env {
 
        struct numa_stats src_stats, dst_stats;
 
-       int imbalance_pct, idx;
+       int imbalance_pct;
 
        struct task_struct *best_task;
        long best_imp;
@@ -1225,7 +1203,7 @@ static int task_numa_migrate(struct task_struct *p)
         * elsewhere, so there is no point in (re)trying.
         */
        if (unlikely(!sd)) {
-               p->numa_preferred_nid = cpu_to_node(task_cpu(p));
+               p->numa_preferred_nid = task_node(p);
                return -EINVAL;
        }
 
@@ -1292,7 +1270,7 @@ static void numa_migrate_preferred(struct task_struct *p)
        p->numa_migrate_retry = jiffies + HZ;
 
        /* Success if task is already running on preferred CPU */
-       if (cpu_to_node(task_cpu(p)) == p->numa_preferred_nid)
+       if (task_node(p) == p->numa_preferred_nid)
                return;
 
        /* Otherwise, try migrate to a CPU on the preferred node */
@@ -1364,7 +1342,6 @@ static void update_task_scan_period(struct task_struct *p,
                 * scanning faster if shared accesses dominate as it may
                 * simply bounce migrations uselessly
                 */
-               period_slot = DIV_ROUND_UP(diff, NUMA_PERIOD_SLOTS);
                ratio = DIV_ROUND_UP(private * NUMA_PERIOD_SLOTS, (private + shared));
                diff = (diff * ratio) / NUMA_PERIOD_SLOTS;
        }
@@ -1752,6 +1729,13 @@ void task_numa_work(struct callback_head *work)
                    (vma->vm_file && (vma->vm_flags & (VM_READ|VM_WRITE)) == (VM_READ)))
                        continue;
 
+               /*
+                * Skip inaccessible VMAs to avoid any confusion between
+                * PROT_NONE and NUMA hinting ptes
+                */
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+                       continue;
+
                do {
                        start = max(start, vma->vm_start);
                        end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
@@ -3015,8 +2999,7 @@ static void expire_cfs_rq_runtime(struct cfs_rq *cfs_rq)
        }
 }
 
-static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec)
+static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
 {
        /* dock delta_exec before expiring quota (as it could span periods) */
        cfs_rq->runtime_remaining -= delta_exec;
@@ -3034,7 +3017,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
 }
 
 static __always_inline
-void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, unsigned long delta_exec)
+void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
 {
        if (!cfs_bandwidth_used() || !cfs_rq->runtime_enabled)
                return;
@@ -3574,8 +3557,7 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq)
        return rq_clock_task(rq_of(cfs_rq));
 }
 
-static void account_cfs_rq_runtime(struct cfs_rq *cfs_rq,
-                                    unsigned long delta_exec) {}
+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 void check_enqueue_throttle(struct cfs_rq *cfs_rq) {}
 static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
@@ -3932,7 +3914,7 @@ static long effective_load(struct task_group *tg, int cpu, long wl, long wg)
 {
        struct sched_entity *se = tg->se[cpu];
 
-       if (!tg->parent || !wl) /* the trivial, non-cgroup case */
+       if (!tg->parent)        /* the trivial, non-cgroup case */
                return wl;
 
        for_each_sched_entity(se) {
@@ -4110,12 +4092,16 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
  */
 static struct sched_group *
 find_idlest_group(struct sched_domain *sd, struct task_struct *p,
-                 int this_cpu, int load_idx)
+                 int this_cpu, int sd_flag)
 {
        struct sched_group *idlest = NULL, *group = sd->groups;
        unsigned long min_load = ULONG_MAX, this_load = 0;
+       int load_idx = sd->forkexec_idx;
        int imbalance = 100 + (sd->imbalance_pct-100)/2;
 
+       if (sd_flag & SD_BALANCE_WAKE)
+               load_idx = sd->wake_idx;
+
        do {
                unsigned long load, avg_load;
                int local_group;
@@ -4283,7 +4269,6 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
        }
 
        while (sd) {
-               int load_idx = sd->forkexec_idx;
                struct sched_group *group;
                int weight;
 
@@ -4292,10 +4277,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
                        continue;
                }
 
-               if (sd_flag & SD_BALANCE_WAKE)
-                       load_idx = sd->wake_idx;
-
-               group = find_idlest_group(sd, p, cpu, load_idx);
+               group = find_idlest_group(sd, p, cpu, sd_flag);
                if (!group) {
                        sd = sd->child;
                        continue;
@@ -5379,10 +5361,31 @@ void update_group_power(struct sched_domain *sd, int cpu)
                 */
 
                for_each_cpu(cpu, sched_group_cpus(sdg)) {
-                       struct sched_group *sg = cpu_rq(cpu)->sd->groups;
+                       struct sched_group_power *sgp;
+                       struct rq *rq = cpu_rq(cpu);
+
+                       /*
+                        * build_sched_domains() -> init_sched_groups_power()
+                        * gets here before we've attached the domains to the
+                        * runqueues.
+                        *
+                        * Use power_of(), which is set irrespective of domains
+                        * in update_cpu_power().
+                        *
+                        * This avoids power/power_orig from being 0 and
+                        * causing divide-by-zero issues on boot.
+                        *
+                        * Runtime updates will correct power_orig.
+                        */
+                       if (unlikely(!rq->sd)) {
+                               power_orig += power_of(cpu);
+                               power += power_of(cpu);
+                               continue;
+                       }
 
-                       power_orig += sg->sgp->power_orig;
-                       power += sg->sgp->power;
+                       sgp = rq->sd->groups->sgp;
+                       power_orig += sgp->power_orig;
+                       power += sgp->power;
                }
        } else  {
                /*
@@ -5500,7 +5503,6 @@ static inline void update_sg_lb_stats(struct lb_env *env,
                        struct sched_group *group, int load_idx,
                        int local_group, struct sg_lb_stats *sgs)
 {
-       unsigned long nr_running;
        unsigned long load;
        int i;
 
@@ -5509,8 +5511,6 @@ static inline void update_sg_lb_stats(struct lb_env *env,
        for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {
                struct rq *rq = cpu_rq(i);
 
-               nr_running = rq->nr_running;
-
                /* Bias balancing toward cpus of our domain */
                if (local_group)
                        load = target_load(i, load_idx);
@@ -5518,7 +5518,7 @@ static inline void update_sg_lb_stats(struct lb_env *env,
                        load = source_load(i, load_idx);
 
                sgs->group_load += load;
-               sgs->sum_nr_running += nr_running;
+               sgs->sum_nr_running += rq->nr_running;
 #ifdef CONFIG_NUMA_BALANCING
                sgs->nr_numa_running += rq->nr_numa_running;
                sgs->nr_preferred_running += rq->nr_preferred_running;
@@ -6509,7 +6509,7 @@ static struct {
        unsigned long next_balance;     /* in jiffy units */
 } nohz ____cacheline_aligned;
 
-static inline int find_new_ilb(int call_cpu)
+static inline int find_new_ilb(void)
 {
        int ilb = cpumask_first(nohz.idle_cpus_mask);
 
@@ -6524,13 +6524,13 @@ static inline int find_new_ilb(int call_cpu)
  * nohz_load_balancer CPU (if there is one) otherwise fallback to any idle
  * CPU (if there is one).
  */
-static void nohz_balancer_kick(int cpu)
+static void nohz_balancer_kick(void)
 {
        int ilb_cpu;
 
        nohz.next_balance++;
 
-       ilb_cpu = find_new_ilb(cpu);
+       ilb_cpu = find_new_ilb();
 
        if (ilb_cpu >= nr_cpu_ids)
                return;
@@ -6640,10 +6640,10 @@ void update_max_interval(void)
  *
  * Balancing parameters are set up in init_sched_domains.
  */
-static void rebalance_domains(int cpu, enum cpu_idle_type idle)
+static void rebalance_domains(struct rq *rq, enum cpu_idle_type idle)
 {
        int continue_balancing = 1;
-       struct rq *rq = cpu_rq(cpu);
+       int cpu = rq->cpu;
        unsigned long interval;
        struct sched_domain *sd;
        /* Earliest time when we have to do rebalance again */
@@ -6740,9 +6740,9 @@ out:
  * In CONFIG_NO_HZ_COMMON case, the idle balance kickee will do the
  * rebalancing for all the cpus for whom scheduler ticks are stopped.
  */
-static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle)
+static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle)
 {
-       struct rq *this_rq = cpu_rq(this_cpu);
+       int this_cpu = this_rq->cpu;
        struct rq *rq;
        int balance_cpu;
 
@@ -6769,7 +6769,7 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle)
                update_idle_cpu_load(rq);
                raw_spin_unlock_irq(&rq->lock);
 
-               rebalance_domains(balance_cpu, CPU_IDLE);
+               rebalance_domains(rq, CPU_IDLE);
 
                if (time_after(this_rq->next_balance, rq->next_balance))
                        this_rq->next_balance = rq->next_balance;
@@ -6788,14 +6788,14 @@ end:
  *   - For SD_ASYM_PACKING, if the lower numbered cpu's in the scheduler
  *     domain span are idle.
  */
-static inline int nohz_kick_needed(struct rq *rq, int cpu)
+static inline int nohz_kick_needed(struct rq *rq)
 {
        unsigned long now = jiffies;
        struct sched_domain *sd;
        struct sched_group_power *sgp;
-       int nr_busy;
+       int nr_busy, cpu = rq->cpu;
 
-       if (unlikely(idle_cpu(cpu)))
+       if (unlikely(rq->idle_balance))
                return 0;
 
        /*
@@ -6844,7 +6844,7 @@ need_kick:
        return 1;
 }
 #else
-static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) { }
+static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) { }
 #endif
 
 /*
@@ -6853,38 +6853,39 @@ static void nohz_idle_balance(int this_cpu, enum cpu_idle_type idle) { }
  */
 static void run_rebalance_domains(struct softirq_action *h)
 {
-       int this_cpu = smp_processor_id();
-       struct rq *this_rq = cpu_rq(this_cpu);
+       struct rq *this_rq = this_rq();
        enum cpu_idle_type idle = this_rq->idle_balance ?
                                                CPU_IDLE : CPU_NOT_IDLE;
 
-       rebalance_domains(this_cpu, idle);
+       rebalance_domains(this_rq, idle);
 
        /*
         * If this cpu has a pending nohz_balance_kick, then do the
         * balancing on behalf of the other idle cpus whose ticks are
         * stopped.
         */
-       nohz_idle_balance(this_cpu, idle);
+       nohz_idle_balance(this_rq, idle);
 }
 
-static inline int on_null_domain(int cpu)
+static inline int on_null_domain(struct rq *rq)
 {
-       return !rcu_dereference_sched(cpu_rq(cpu)->sd);
+       return !rcu_dereference_sched(rq->sd);
 }
 
 /*
  * Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing.
  */
-void trigger_load_balance(struct rq *rq, int cpu)
+void trigger_load_balance(struct rq *rq)
 {
        /* Don't need to rebalance while attached to NULL domain */
-       if (time_after_eq(jiffies, rq->next_balance) &&
-           likely(!on_null_domain(cpu)))
+       if (unlikely(on_null_domain(rq)))
+               return;
+
+       if (time_after_eq(jiffies, rq->next_balance))
                raise_softirq(SCHED_SOFTIRQ);
 #ifdef CONFIG_NO_HZ_COMMON
-       if (nohz_kick_needed(rq, cpu) && likely(!on_null_domain(cpu)))
-               nohz_balancer_kick(cpu);
+       if (nohz_kick_needed(rq))
+               nohz_balancer_kick();
 #endif
 }
 
index 7d57275fc396d1c56475c707888f1f95fd84142b..a2740b775b456ed27c56ad088007c83e1873458b 100644 (file)
@@ -901,6 +901,13 @@ inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && prio < prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, prio);
 }
@@ -910,6 +917,13 @@ dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio)
 {
        struct rq *rq = rq_of_rt_rq(rt_rq);
 
+#ifdef CONFIG_RT_GROUP_SCHED
+       /*
+        * Change rq's cpupri only if rt_rq is the top queue.
+        */
+       if (&rq->rt != rt_rq)
+               return;
+#endif
        if (rq->online && rt_rq->highest_prio.curr != prev_prio)
                cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr);
 }
@@ -1724,7 +1738,7 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
            !test_tsk_need_resched(rq->curr) &&
            has_pushable_tasks(rq) &&
            p->nr_cpus_allowed > 1 &&
-           rt_task(rq->curr) &&
+           (dl_task(rq->curr) || rt_task(rq->curr)) &&
            (rq->curr->nr_cpus_allowed < 2 ||
             rq->curr->prio <= p->prio))
                push_rt_tasks(rq);
index 88c85b21d63346f4ba82e00962486445c9fdb410..c2119fd20f8b6dc2042a80603d44223ab9365dec 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/sched.h>
 #include <linux/sched/sysctl.h>
 #include <linux/sched/rt.h>
+#include <linux/sched/deadline.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
@@ -9,6 +10,7 @@
 #include <linux/slab.h>
 
 #include "cpupri.h"
+#include "cpudeadline.h"
 #include "cpuacct.h"
 
 struct rq;
@@ -72,6 +74,13 @@ extern void update_cpu_load_active(struct rq *this_rq);
 #define NICE_0_LOAD            SCHED_LOAD_SCALE
 #define NICE_0_SHIFT           SCHED_LOAD_SHIFT
 
+/*
+ * Single value that decides SCHED_DEADLINE internal math precision.
+ * 10 -> just above 1us
+ * 9  -> just above 0.5us
+ */
+#define DL_SCALE (10)
+
 /*
  * These are the 'tuning knobs' of the scheduler:
  */
@@ -81,11 +90,19 @@ extern void update_cpu_load_active(struct rq *this_rq);
  */
 #define RUNTIME_INF    ((u64)~0ULL)
 
+static inline int fair_policy(int policy)
+{
+       return policy == SCHED_NORMAL || policy == SCHED_BATCH;
+}
+
 static inline int rt_policy(int policy)
 {
-       if (policy == SCHED_FIFO || policy == SCHED_RR)
-               return 1;
-       return 0;
+       return policy == SCHED_FIFO || policy == SCHED_RR;
+}
+
+static inline int dl_policy(int policy)
+{
+       return policy == SCHED_DEADLINE;
 }
 
 static inline int task_has_rt_policy(struct task_struct *p)
@@ -93,6 +110,25 @@ static inline int task_has_rt_policy(struct task_struct *p)
        return rt_policy(p->policy);
 }
 
+static inline int task_has_dl_policy(struct task_struct *p)
+{
+       return dl_policy(p->policy);
+}
+
+static inline bool dl_time_before(u64 a, u64 b)
+{
+       return (s64)(a - b) < 0;
+}
+
+/*
+ * Tells if entity @a should preempt entity @b.
+ */
+static inline bool
+dl_entity_preempt(struct sched_dl_entity *a, struct sched_dl_entity *b)
+{
+       return dl_time_before(a->deadline, b->deadline);
+}
+
 /*
  * This is the priority-queue data structure of the RT scheduling class:
  */
@@ -108,6 +144,47 @@ struct rt_bandwidth {
        u64                     rt_runtime;
        struct hrtimer          rt_period_timer;
 };
+/*
+ * To keep the bandwidth of -deadline tasks and groups under control
+ * we need some place where:
+ *  - store the maximum -deadline bandwidth of the system (the group);
+ *  - cache the fraction of that bandwidth that is currently allocated.
+ *
+ * This is all done in the data structure below. It is similar to the
+ * one used for RT-throttling (rt_bandwidth), with the main difference
+ * that, since here we are only interested in admission control, we
+ * do not decrease any runtime while the group "executes", neither we
+ * need a timer to replenish it.
+ *
+ * With respect to SMP, the bandwidth is given on a per-CPU basis,
+ * meaning that:
+ *  - dl_bw (< 100%) is the bandwidth of the system (group) on each CPU;
+ *  - dl_total_bw array contains, in the i-eth element, the currently
+ *    allocated bandwidth on the i-eth CPU.
+ * Moreover, groups consume bandwidth on each CPU, while tasks only
+ * consume bandwidth on the CPU they're running on.
+ * Finally, dl_total_bw_cpu is used to cache the index of dl_total_bw
+ * that will be shown the next time the proc or cgroup controls will
+ * be red. It on its turn can be changed by writing on its own
+ * control.
+ */
+struct dl_bandwidth {
+       raw_spinlock_t dl_runtime_lock;
+       u64 dl_runtime;
+       u64 dl_period;
+};
+
+static inline int dl_bandwidth_enabled(void)
+{
+       return sysctl_sched_rt_runtime >= 0;
+}
+
+extern struct dl_bw *dl_bw_of(int i);
+
+struct dl_bw {
+       raw_spinlock_t lock;
+       u64 bw, total_bw;
+};
 
 extern struct mutex sched_domains_mutex;
 
@@ -364,6 +441,42 @@ struct rt_rq {
 #endif
 };
 
+/* Deadline class' related fields in a runqueue */
+struct dl_rq {
+       /* runqueue is an rbtree, ordered by deadline */
+       struct rb_root rb_root;
+       struct rb_node *rb_leftmost;
+
+       unsigned long dl_nr_running;
+
+#ifdef CONFIG_SMP
+       /*
+        * Deadline values of the currently executing and the
+        * earliest ready task on this rq. Caching these facilitates
+        * the decision wether or not a ready but not running task
+        * should migrate somewhere else.
+        */
+       struct {
+               u64 curr;
+               u64 next;
+       } earliest_dl;
+
+       unsigned long dl_nr_migratory;
+       unsigned long dl_nr_total;
+       int overloaded;
+
+       /*
+        * Tasks on this rq that can be pushed away. They are kept in
+        * an rb-tree, ordered by tasks' deadlines, with caching
+        * of the leftmost (earliest deadline) element.
+        */
+       struct rb_root pushable_dl_tasks_root;
+       struct rb_node *pushable_dl_tasks_leftmost;
+#else
+       struct dl_bw dl_bw;
+#endif
+};
+
 #ifdef CONFIG_SMP
 
 /*
@@ -381,6 +494,15 @@ struct root_domain {
        cpumask_var_t span;
        cpumask_var_t online;
 
+       /*
+        * The bit corresponding to a CPU gets set here if such CPU has more
+        * than one runnable -deadline task (as it is below for RT tasks).
+        */
+       cpumask_var_t dlo_mask;
+       atomic_t dlo_count;
+       struct dl_bw dl_bw;
+       struct cpudl cpudl;
+
        /*
         * The "RT overload" flag: it gets set if a CPU has more than
         * one runnable RT task.
@@ -432,6 +554,7 @@ struct rq {
 
        struct cfs_rq cfs;
        struct rt_rq rt;
+       struct dl_rq dl;
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
        /* list of leaf cfs_rq on this cpu: */
@@ -827,8 +950,6 @@ static inline u64 global_rt_runtime(void)
        return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
 }
 
-
-
 static inline int task_current(struct rq *rq, struct task_struct *p)
 {
        return rq->curr == p;
@@ -988,6 +1109,7 @@ static const u32 prio_to_wmult[40] = {
 #else
 #define ENQUEUE_WAKING         0
 #endif
+#define ENQUEUE_REPLENISH      8
 
 #define DEQUEUE_SLEEP          1
 
@@ -1023,6 +1145,7 @@ struct sched_class {
        void (*set_curr_task) (struct rq *rq);
        void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
        void (*task_fork) (struct task_struct *p);
+       void (*task_dead) (struct task_struct *p);
 
        void (*switched_from) (struct rq *this_rq, struct task_struct *task);
        void (*switched_to) (struct rq *this_rq, struct task_struct *task);
@@ -1042,6 +1165,7 @@ struct sched_class {
    for (class = sched_class_highest; class; class = class->next)
 
 extern const struct sched_class stop_sched_class;
+extern const struct sched_class dl_sched_class;
 extern const struct sched_class rt_sched_class;
 extern const struct sched_class fair_sched_class;
 extern const struct sched_class idle_sched_class;
@@ -1051,7 +1175,7 @@ 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, 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);
@@ -1068,8 +1192,11 @@ static inline void idle_balance(int cpu, struct rq *rq)
 extern void sysrq_sched_debug_show(void);
 extern void sched_init_granularity(void);
 extern void update_max_interval(void);
+
+extern void init_sched_dl_class(void);
 extern void init_sched_rt_class(void);
 extern void init_sched_fair_class(void);
+extern void init_sched_dl_class(void);
 
 extern void resched_task(struct task_struct *p);
 extern void resched_cpu(int cpu);
@@ -1077,6 +1204,12 @@ extern void resched_cpu(int cpu);
 extern struct rt_bandwidth def_rt_bandwidth;
 extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
 
+extern struct dl_bandwidth def_dl_bandwidth;
+extern void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime);
+extern void init_dl_task_timer(struct sched_dl_entity *dl_se);
+
+unsigned long to_ratio(u64 period, u64 runtime);
+
 extern void update_idle_cpu_load(struct rq *this_rq);
 
 extern void init_task_runnable_average(struct task_struct *p);
@@ -1353,6 +1486,7 @@ extern void print_rt_stats(struct seq_file *m, int cpu);
 
 extern void init_cfs_rq(struct cfs_rq *cfs_rq);
 extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
+extern void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq);
 
 extern void cfs_bandwidth_usage_inc(void);
 extern void cfs_bandwidth_usage_dec(void);
index 47197de8abd99af5dd7d734166721a5e2deb2ae8..fdb6bb0b33561af759e24d8806776dfc0823867c 100644 (file)
@@ -103,7 +103,7 @@ get_rr_interval_stop(struct rq *rq, struct task_struct *task)
  * Simple, special scheduling class for the per-CPU stop tasks:
  */
 const struct sched_class stop_sched_class = {
-       .next                   = &rt_sched_class,
+       .next                   = &dl_sched_class,
 
        .enqueue_task           = enqueue_task_stop,
        .dequeue_task           = dequeue_task_stop,
index 11025ccc06dd1e2211ca62dcbcea7ce1b05418dd..8a1e6e104892daff68dded8f7ff2af9d72f3dd1e 100644 (file)
@@ -89,7 +89,7 @@ static void wakeup_softirqd(void)
  * where hardirqs are disabled legitimately:
  */
 #ifdef CONFIG_TRACE_IRQFLAGS
-static void __local_bh_disable(unsigned long ip, unsigned int cnt)
+void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
 {
        unsigned long flags;
 
@@ -107,33 +107,21 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt)
        /*
         * Were softirqs turned off above:
         */
-       if (softirq_count() == cnt)
+       if (softirq_count() == (cnt & SOFTIRQ_MASK))
                trace_softirqs_off(ip);
        raw_local_irq_restore(flags);
 
        if (preempt_count() == cnt)
                trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
 }
-#else /* !CONFIG_TRACE_IRQFLAGS */
-static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
-{
-       preempt_count_add(cnt);
-       barrier();
-}
+EXPORT_SYMBOL(__local_bh_disable_ip);
 #endif /* CONFIG_TRACE_IRQFLAGS */
 
-void local_bh_disable(void)
-{
-       __local_bh_disable(_RET_IP_, SOFTIRQ_DISABLE_OFFSET);
-}
-
-EXPORT_SYMBOL(local_bh_disable);
-
 static void __local_bh_enable(unsigned int cnt)
 {
        WARN_ON_ONCE(!irqs_disabled());
 
-       if (softirq_count() == cnt)
+       if (softirq_count() == (cnt & SOFTIRQ_MASK))
                trace_softirqs_on(_RET_IP_);
        preempt_count_sub(cnt);
 }
@@ -151,7 +139,7 @@ void _local_bh_enable(void)
 
 EXPORT_SYMBOL(_local_bh_enable);
 
-static inline void _local_bh_enable_ip(unsigned long ip)
+void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
 {
        WARN_ON_ONCE(in_irq() || irqs_disabled());
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -166,7 +154,7 @@ static inline void _local_bh_enable_ip(unsigned long ip)
         * Keep preemption disabled until we are done with
         * softirq processing:
         */
-       preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1);
+       preempt_count_sub(cnt - 1);
 
        if (unlikely(!in_interrupt() && local_softirq_pending())) {
                /*
@@ -182,18 +170,7 @@ static inline void _local_bh_enable_ip(unsigned long ip)
 #endif
        preempt_check_resched();
 }
-
-void local_bh_enable(void)
-{
-       _local_bh_enable_ip(_RET_IP_);
-}
-EXPORT_SYMBOL(local_bh_enable);
-
-void local_bh_enable_ip(unsigned long ip)
-{
-       _local_bh_enable_ip(ip);
-}
-EXPORT_SYMBOL(local_bh_enable_ip);
+EXPORT_SYMBOL(__local_bh_enable_ip);
 
 /*
  * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times,
@@ -211,14 +188,48 @@ EXPORT_SYMBOL(local_bh_enable_ip);
 #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
 #define MAX_SOFTIRQ_RESTART 10
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+/*
+ * When we run softirqs from irq_exit() and thus on the hardirq stack we need
+ * to keep the lockdep irq context tracking as tight as possible in order to
+ * not miss-qualify lock contexts and miss possible deadlocks.
+ */
+
+static inline bool lockdep_softirq_start(void)
+{
+       bool in_hardirq = false;
+
+       if (trace_hardirq_context(current)) {
+               in_hardirq = true;
+               trace_hardirq_exit();
+       }
+
+       lockdep_softirq_enter();
+
+       return in_hardirq;
+}
+
+static inline void lockdep_softirq_end(bool in_hardirq)
+{
+       lockdep_softirq_exit();
+
+       if (in_hardirq)
+               trace_hardirq_enter();
+}
+#else
+static inline bool lockdep_softirq_start(void) { return false; }
+static inline void lockdep_softirq_end(bool in_hardirq) { }
+#endif
+
 asmlinkage void __do_softirq(void)
 {
-       struct softirq_action *h;
-       __u32 pending;
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
-       int cpu;
        unsigned long old_flags = current->flags;
        int max_restart = MAX_SOFTIRQ_RESTART;
+       struct softirq_action *h;
+       bool in_hardirq;
+       __u32 pending;
+       int cpu;
 
        /*
         * Mask out PF_MEMALLOC s current task context is borrowed for the
@@ -230,8 +241,8 @@ asmlinkage void __do_softirq(void)
        pending = local_softirq_pending();
        account_irq_enter_time(current);
 
-       __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET);
-       lockdep_softirq_enter();
+       __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
+       in_hardirq = lockdep_softirq_start();
 
        cpu = smp_processor_id();
 restart:
@@ -278,16 +289,13 @@ restart:
                wakeup_softirqd();
        }
 
-       lockdep_softirq_exit();
-
+       lockdep_softirq_end(in_hardirq);
        account_irq_exit_time(current);
        __local_bh_enable(SOFTIRQ_OFFSET);
        WARN_ON_ONCE(in_interrupt());
        tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
 
-
-
 asmlinkage void do_softirq(void)
 {
        __u32 pending;
@@ -311,8 +319,6 @@ asmlinkage void do_softirq(void)
  */
 void irq_enter(void)
 {
-       int cpu = smp_processor_id();
-
        rcu_irq_enter();
        if (is_idle_task(current) && !in_interrupt()) {
                /*
@@ -320,7 +326,7 @@ void irq_enter(void)
                 * here, as softirq will be serviced on return from interrupt.
                 */
                local_bh_disable();
-               tick_check_idle(cpu);
+               tick_check_idle();
                _local_bh_enable();
        }
 
@@ -375,13 +381,13 @@ void irq_exit(void)
 #endif
 
        account_irq_exit_time(current);
-       trace_hardirq_exit();
        preempt_count_sub(HARDIRQ_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
 
        tick_irq_exit();
        rcu_irq_exit();
+       trace_hardirq_exit(); /* must be last! */
 }
 
 /*
index 34a604726d0b7c87b4b112a3f4ab9e1a6902ffcb..c8da99f905cf522a34dd7ff059bde584e4d8c90a 100644 (file)
@@ -384,13 +384,6 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
-       {
-               .procname       = "numa_balancing_settle_count",
-               .data           = &sysctl_numa_balancing_settle_count,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
        {
                .procname       = "numa_balancing_migrate_deferred",
                .data           = &sysctl_numa_balancing_migrate_deferred,
index 4aef390671cbb9653fc5c64342f656694585f56c..3e9868d47535b44d85e8515070bf86cf5cc6fe81 100644 (file)
@@ -3,8 +3,18 @@
 
        __INITRODATA
 
+       .align 8
        .globl VMLINUX_SYMBOL(system_certificate_list)
 VMLINUX_SYMBOL(system_certificate_list):
+__cert_list_start:
        .incbin "kernel/x509_certificate_list"
-       .globl VMLINUX_SYMBOL(system_certificate_list_end)
-VMLINUX_SYMBOL(system_certificate_list_end):
+__cert_list_end:
+
+       .align 8
+       .globl VMLINUX_SYMBOL(system_certificate_list_size)
+VMLINUX_SYMBOL(system_certificate_list_size):
+#ifdef CONFIG_64BIT
+       .quad __cert_list_end - __cert_list_start
+#else
+       .long __cert_list_end - __cert_list_start
+#endif
index 564dd93430a276b0ac7db03a59cbb5648a639c93..52ebc70263f4d8e806dc436fd55e6000cf818915 100644 (file)
@@ -22,7 +22,7 @@ struct key *system_trusted_keyring;
 EXPORT_SYMBOL_GPL(system_trusted_keyring);
 
 extern __initconst const u8 system_certificate_list[];
-extern __initconst const u8 system_certificate_list_end[];
+extern __initconst const unsigned long system_certificate_list_size;
 
 /*
  * Load the compiled-in keys
@@ -60,8 +60,8 @@ static __init int load_system_certificate_list(void)
 
        pr_notice("Loading compiled-in X.509 certificates\n");
 
-       end = system_certificate_list_end;
        p = system_certificate_list;
+       end = p + system_certificate_list_size;
        while (p < end) {
                /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
                 * than 256 bytes in size.
index 68b79937598106918748832a396848f7fd22f870..0abb364642818e4ef842ab2f3631d15cb80400f2 100644 (file)
@@ -74,7 +74,7 @@ unsigned long long notrace sched_clock(void)
                return cd.epoch_ns;
 
        do {
-               seq = read_seqcount_begin(&cd.seq);
+               seq = raw_read_seqcount_begin(&cd.seq);
                epoch_cyc = cd.epoch_cyc;
                epoch_ns = cd.epoch_ns;
        } while (read_seqcount_retry(&cd.seq, seq));
@@ -99,10 +99,10 @@ static void notrace update_sched_clock(void)
                          cd.mult, cd.shift);
 
        raw_local_irq_save(flags);
-       write_seqcount_begin(&cd.seq);
+       raw_write_seqcount_begin(&cd.seq);
        cd.epoch_ns = ns;
        cd.epoch_cyc = cyc;
-       write_seqcount_end(&cd.seq);
+       raw_write_seqcount_end(&cd.seq);
        raw_local_irq_restore(flags);
 }
 
index 9532690daaa9edff1fedd01066215ee43884a8a4..43780ab5e279b1a6f6bb0e6251dfcdb29640af40 100644 (file)
@@ -538,10 +538,10 @@ int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
  * Called from irq_enter() when idle was interrupted to reenable the
  * per cpu device.
  */
-void tick_check_oneshot_broadcast(int cpu)
+void tick_check_oneshot_broadcast_this_cpu(void)
 {
-       if (cpumask_test_cpu(cpu, tick_broadcast_oneshot_mask)) {
-               struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
+       if (cpumask_test_cpu(smp_processor_id(), tick_broadcast_oneshot_mask)) {
+               struct tick_device *td = &__get_cpu_var(tick_cpu_device);
 
                /*
                 * We might be in the middle of switching over from
index 64522ecdfe0e868420acdd7b47a65de99b847748..20b2fe37d1053a21b138dbb2a7856e574c2ea9aa 100644 (file)
@@ -33,6 +33,21 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  */
 ktime_t tick_next_period;
 ktime_t tick_period;
+
+/*
+ * tick_do_timer_cpu is a timer core internal variable which holds the CPU NR
+ * which is responsible for calling do_timer(), i.e. the timekeeping stuff. This
+ * variable has two functions:
+ *
+ * 1) Prevent a thundering herd issue of a gazillion of CPUs trying to grab the
+ *    timekeeping lock all at once. Only the CPU which is assigned to do the
+ *    update is handling it.
+ *
+ * 2) Hand off the duty in the NOHZ idle case by setting the value to
+ *    TICK_DO_TIMER_NONE, i.e. a non existing CPU. So the next cpu which looks
+ *    at it will take over and keep the time keeping alive.  The handover
+ *    procedure also covers cpu hotplug.
+ */
 int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
 
 /*
@@ -70,6 +85,7 @@ static void tick_periodic(int cpu)
 
                do_timer(1);
                write_sequnlock(&jiffies_lock);
+               update_wall_time();
        }
 
        update_process_times(user_mode(get_irq_regs()));
index 18e71f7fbc2a546c7c060abe4ceb1820062dd3a8..8329669b51ec3d8a74897f979f8c6270a4db3f37 100644 (file)
@@ -51,7 +51,7 @@ extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
 extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_active(void);
-extern void tick_check_oneshot_broadcast(int cpu);
+extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
 # else /* BROADCAST */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
@@ -62,7 +62,7 @@ static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
-static inline void tick_check_oneshot_broadcast(int cpu) { }
+static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
 static inline bool tick_broadcast_oneshot_available(void) { return true; }
 # endif /* !BROADCAST */
 
@@ -155,3 +155,4 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
 #endif
 
 extern void do_timer(unsigned long ticks);
+extern void update_wall_time(void);
index 3612fc77f834372c0d5d674f3bc5ae609dd64635..08cb0c3b8ccb49a34a6eea27ea945c017a84795c 100644 (file)
@@ -86,6 +86,7 @@ static void tick_do_update_jiffies64(ktime_t now)
                tick_next_period = ktime_add(last_jiffies_update, tick_period);
        }
        write_sequnlock(&jiffies_lock);
+       update_wall_time();
 }
 
 /*
@@ -177,7 +178,7 @@ static bool can_stop_full_tick(void)
         * TODO: kick full dynticks CPUs when
         * sched_clock_stable is set.
         */
-       if (!sched_clock_stable) {
+       if (!sched_clock_stable()) {
                trace_tick_stop(0, "unstable sched clock\n");
                /*
                 * Don't allow the user to think they can get
@@ -361,8 +362,8 @@ void __init tick_nohz_init(void)
 /*
  * NO HZ enabled ?
  */
-int tick_nohz_enabled __read_mostly  = 1;
-
+static int tick_nohz_enabled __read_mostly  = 1;
+int tick_nohz_active  __read_mostly;
 /*
  * Enable / Disable tickless mode
  */
@@ -391,11 +392,9 @@ __setup("nohz=", setup_tick_nohz);
  */
 static void tick_nohz_update_jiffies(ktime_t now)
 {
-       int cpu = smp_processor_id();
-       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        unsigned long flags;
 
-       ts->idle_waketime = now;
+       __this_cpu_write(tick_cpu_sched.idle_waketime, now);
 
        local_irq_save(flags);
        tick_do_update_jiffies64(now);
@@ -426,17 +425,15 @@ update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_upda
 
 }
 
-static void tick_nohz_stop_idle(int cpu, ktime_t now)
+static void tick_nohz_stop_idle(struct tick_sched *ts, ktime_t now)
 {
-       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
-
-       update_ts_time_stats(cpu, ts, now, NULL);
+       update_ts_time_stats(smp_processor_id(), ts, now, NULL);
        ts->idle_active = 0;
 
        sched_clock_idle_wakeup_event(0);
 }
 
-static ktime_t tick_nohz_start_idle(int cpu, struct tick_sched *ts)
+static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
 {
        ktime_t now = ktime_get();
 
@@ -465,7 +462,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t now, idle;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return -1;
 
        now = ktime_get();
@@ -506,7 +503,7 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t now, iowait;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return -1;
 
        now = ktime_get();
@@ -711,8 +708,10 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
                return false;
        }
 
-       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) {
+               ts->sleep_length = (ktime_t) { .tv64 = NSEC_PER_SEC/HZ };
                return false;
+       }
 
        if (need_resched())
                return false;
@@ -752,7 +751,7 @@ static void __tick_nohz_idle_enter(struct tick_sched *ts)
        ktime_t now, expires;
        int cpu = smp_processor_id();
 
-       now = tick_nohz_start_idle(cpu, ts);
+       now = tick_nohz_start_idle(ts);
 
        if (can_stop_idle_tick(cpu, ts)) {
                int was_stopped = ts->tick_stopped;
@@ -799,11 +798,6 @@ void tick_nohz_idle_enter(void)
        local_irq_disable();
 
        ts = &__get_cpu_var(tick_cpu_sched);
-       /*
-        * set ts->inidle unconditionally. even if the system did not
-        * switch to nohz mode the cpu frequency governers rely on the
-        * update of the idle time accounting in tick_nohz_start_idle().
-        */
        ts->inidle = 1;
        __tick_nohz_idle_enter(ts);
 
@@ -914,8 +908,7 @@ static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
  */
 void tick_nohz_idle_exit(void)
 {
-       int cpu = smp_processor_id();
-       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        ktime_t now;
 
        local_irq_disable();
@@ -928,7 +921,7 @@ void tick_nohz_idle_exit(void)
                now = ktime_get();
 
        if (ts->idle_active)
-               tick_nohz_stop_idle(cpu, now);
+               tick_nohz_stop_idle(ts, now);
 
        if (ts->tick_stopped) {
                tick_nohz_restart_sched_tick(ts, now);
@@ -973,7 +966,7 @@ static void tick_nohz_switch_to_nohz(void)
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        ktime_t next;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return;
 
        local_irq_disable();
@@ -981,7 +974,7 @@ static void tick_nohz_switch_to_nohz(void)
                local_irq_enable();
                return;
        }
-
+       tick_nohz_active = 1;
        ts->nohz_mode = NOHZ_MODE_LOWRES;
 
        /*
@@ -1012,12 +1005,10 @@ static void tick_nohz_switch_to_nohz(void)
  * timer and do not touch the other magic bits which need to be done
  * when idle is left.
  */
-static void tick_nohz_kick_tick(int cpu, ktime_t now)
+static void tick_nohz_kick_tick(struct tick_sched *ts, ktime_t now)
 {
 #if 0
        /* Switch back to 2.6.27 behaviour */
-
-       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t delta;
 
        /*
@@ -1032,36 +1023,36 @@ static void tick_nohz_kick_tick(int cpu, ktime_t now)
 #endif
 }
 
-static inline void tick_check_nohz(int cpu)
+static inline void tick_check_nohz_this_cpu(void)
 {
-       struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+       struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        ktime_t now;
 
        if (!ts->idle_active && !ts->tick_stopped)
                return;
        now = ktime_get();
        if (ts->idle_active)
-               tick_nohz_stop_idle(cpu, now);
+               tick_nohz_stop_idle(ts, now);
        if (ts->tick_stopped) {
                tick_nohz_update_jiffies(now);
-               tick_nohz_kick_tick(cpu, now);
+               tick_nohz_kick_tick(ts, now);
        }
 }
 
 #else
 
 static inline void tick_nohz_switch_to_nohz(void) { }
-static inline void tick_check_nohz(int cpu) { }
+static inline void tick_check_nohz_this_cpu(void) { }
 
 #endif /* CONFIG_NO_HZ_COMMON */
 
 /*
  * Called from irq_enter to notify about the possible interruption of idle()
  */
-void tick_check_idle(int cpu)
+void tick_check_idle(void)
 {
-       tick_check_oneshot_broadcast(cpu);
-       tick_check_nohz(cpu);
+       tick_check_oneshot_broadcast_this_cpu();
+       tick_check_nohz_this_cpu();
 }
 
 /*
@@ -1139,8 +1130,10 @@ void tick_setup_sched_timer(void)
        }
 
 #ifdef CONFIG_NO_HZ_COMMON
-       if (tick_nohz_enabled)
+       if (tick_nohz_enabled) {
                ts->nohz_mode = NOHZ_MODE_HIGHRES;
+               tick_nohz_active = 1;
+       }
 #endif
 }
 #endif /* HIGH_RES_TIMERS */
index 3abf53418b67c6ee92c16522299a8821856b749d..0aa4ce81bc168e2432f8f76e1e62c0b41512d47b 100644 (file)
@@ -77,7 +77,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm)
        tk->wall_to_monotonic = wtm;
        set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec);
        tk->offs_real = timespec_to_ktime(tmp);
-       tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tk->tai_offset, 0));
+       tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tk->tai_offset, 0));
 }
 
 static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t)
@@ -90,8 +90,9 @@ static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t)
 }
 
 /**
- * timekeeper_setup_internals - Set up internals to use clocksource clock.
+ * tk_setup_internals - Set up internals to use clocksource clock.
  *
+ * @tk:                The target timekeeper to setup.
  * @clock:             Pointer to clocksource.
  *
  * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment
@@ -595,7 +596,7 @@ s32 timekeeping_get_tai_offset(void)
 static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset)
 {
        tk->tai_offset = tai_offset;
-       tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tai_offset, 0));
+       tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tai_offset, 0));
 }
 
 /**
@@ -610,6 +611,7 @@ void timekeeping_set_tai_offset(s32 tai_offset)
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
        write_seqcount_begin(&timekeeper_seq);
        __timekeeping_set_tai_offset(tk, tai_offset);
+       timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
        write_seqcount_end(&timekeeper_seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
        clock_was_set();
@@ -1023,6 +1025,8 @@ static int timekeeping_suspend(void)
                timekeeping_suspend_time =
                        timespec_add(timekeeping_suspend_time, delta_delta);
        }
+
+       timekeeping_update(tk, TK_MIRROR);
        write_seqcount_end(&timekeeper_seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
@@ -1130,16 +1134,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
                 * we can adjust by 1.
                 */
                error >>= 2;
-               /*
-                * XXX - In update_wall_time, we round up to the next
-                * nanosecond, and store the amount rounded up into
-                * the error. This causes the likely below to be unlikely.
-                *
-                * The proper fix is to avoid rounding up by using
-                * the high precision tk->xtime_nsec instead of
-                * xtime.tv_nsec everywhere. Fixing this will take some
-                * time.
-                */
                if (likely(error <= interval))
                        adj = 1;
                else
@@ -1255,7 +1249,7 @@ out_adjust:
 static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
 {
        u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
-       unsigned int action = 0;
+       unsigned int clock_set = 0;
 
        while (tk->xtime_nsec >= nsecps) {
                int leap;
@@ -1277,11 +1271,10 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
 
                        __timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
 
-                       clock_was_set_delayed();
-                       action = TK_CLOCK_WAS_SET;
+                       clock_set = TK_CLOCK_WAS_SET;
                }
        }
-       return action;
+       return clock_set;
 }
 
 /**
@@ -1294,7 +1287,8 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
  * Returns the unconsumed cycles.
  */
 static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
-                                               u32 shift)
+                                               u32 shift,
+                                               unsigned int *clock_set)
 {
        cycle_t interval = tk->cycle_interval << shift;
        u64 raw_nsecs;
@@ -1308,7 +1302,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
        tk->cycle_last += interval;
 
        tk->xtime_nsec += tk->xtime_interval << shift;
-       accumulate_nsecs_to_secs(tk);
+       *clock_set |= accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
        raw_nsecs = (u64)tk->raw_interval << shift;
@@ -1347,7 +1341,7 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk)
        tk->xtime_nsec -= remainder;
        tk->xtime_nsec += 1ULL << tk->shift;
        tk->ntp_error += remainder << tk->ntp_error_shift;
-
+       tk->ntp_error -= (1ULL << tk->shift) << tk->ntp_error_shift;
 }
 #else
 #define old_vsyscall_fixup(tk)
@@ -1359,14 +1353,14 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk)
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
  */
-static void update_wall_time(void)
+void update_wall_time(void)
 {
        struct clocksource *clock;
        struct timekeeper *real_tk = &timekeeper;
        struct timekeeper *tk = &shadow_timekeeper;
        cycle_t offset;
        int shift = 0, maxshift;
-       unsigned int action;
+       unsigned int clock_set = 0;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
@@ -1401,7 +1395,8 @@ static void update_wall_time(void)
        maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
        shift = min(shift, maxshift);
        while (offset >= tk->cycle_interval) {
-               offset = logarithmic_accumulation(tk, offset, shift);
+               offset = logarithmic_accumulation(tk, offset, shift,
+                                                       &clock_set);
                if (offset < tk->cycle_interval<<shift)
                        shift--;
        }
@@ -1419,7 +1414,7 @@ static void update_wall_time(void)
         * Finally, make sure that after the rounding
         * xtime_nsec isn't larger than NSEC_PER_SEC
         */
-       action = accumulate_nsecs_to_secs(tk);
+       clock_set |= accumulate_nsecs_to_secs(tk);
 
        write_seqcount_begin(&timekeeper_seq);
        /* Update clock->cycle_last with the new value */
@@ -1435,10 +1430,12 @@ static void update_wall_time(void)
         * updating.
         */
        memcpy(real_tk, tk, sizeof(*tk));
-       timekeeping_update(real_tk, action);
+       timekeeping_update(real_tk, clock_set);
        write_seqcount_end(&timekeeper_seq);
 out:
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
+       if (clock_set)
+               clock_was_set();
 }
 
 /**
@@ -1583,7 +1580,6 @@ struct timespec get_monotonic_coarse(void)
 void do_timer(unsigned long ticks)
 {
        jiffies_64 += ticks;
-       update_wall_time();
        calc_global_load(ticks);
 }
 
@@ -1698,12 +1694,14 @@ int do_adjtimex(struct timex *txc)
 
        if (tai != orig_tai) {
                __timekeeping_set_tai_offset(tk, tai);
-               update_pvclock_gtod(tk, true);
-               clock_was_set_delayed();
+               timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
        }
        write_seqcount_end(&timekeeper_seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
+       if (tai != orig_tai)
+               clock_was_set();
+
        ntp_notify_cmos_timer();
 
        return ret;
@@ -1739,4 +1737,5 @@ void xtime_update(unsigned long ticks)
        write_seqlock(&jiffies_lock);
        do_timer(ticks);
        write_sequnlock(&jiffies_lock);
+       update_wall_time();
 }
index 6582b82fa966d6ba503a7361f8f89f699f4de04d..accfd241b9e5d5c67040407dfa4f3d8603851de2 100644 (file)
@@ -1518,9 +1518,8 @@ static int init_timers_cpu(int cpu)
                        /*
                         * The APs use this path later in boot
                         */
-                       base = kmalloc_node(sizeof(*base),
-                                               GFP_KERNEL | __GFP_ZERO,
-                                               cpu_to_node(cpu));
+                       base = kzalloc_node(sizeof(*base), GFP_KERNEL,
+                                           cpu_to_node(cpu));
                        if (!base)
                                return -ENOMEM;
 
index 0e9f9eaade2f6a2dd0e729cd2d3bb38b4f6f8ec0..72a0f81dc5a801e62ef5bb400c068705851b32f6 100644 (file)
@@ -775,7 +775,7 @@ static int ftrace_profile_init(void)
        int cpu;
        int ret = 0;
 
-       for_each_online_cpu(cpu) {
+       for_each_possible_cpu(cpu) {
                ret = ftrace_profile_init_cpu(cpu);
                if (ret)
                        break;
index cc2f66f68dc579c7e93967e4306821df29d7adce..294b8a271a04223786827b6fffb58fd7e90fbcaf 100644 (file)
@@ -2558,7 +2558,7 @@ rb_reserve_next_event(struct ring_buffer *buffer,
                if (unlikely(test_time_stamp(delta))) {
                        int local_clock_stable = 1;
 #ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
-                       local_clock_stable = sched_clock_stable;
+                       local_clock_stable = sched_clock_stable();
 #endif
                        WARN_ONCE(delta > (1ULL << 59),
                                  KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n%s",
index 78e27e3b52ac2ee0b9e86f544b77a45e12865d95..e854f420e033eb65a2bca233bb8df2e42778faf7 100644 (file)
@@ -24,6 +24,12 @@ static int   total_ref_count;
 static int perf_trace_event_perm(struct ftrace_event_call *tp_event,
                                 struct perf_event *p_event)
 {
+       if (tp_event->perf_perm) {
+               int ret = tp_event->perf_perm(tp_event, p_event);
+               if (ret)
+                       return ret;
+       }
+
        /* The ftrace function trace is allowed only for root. */
        if (ftrace_event_is_function(tp_event) &&
            perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
@@ -173,7 +179,7 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,
 int perf_trace_init(struct perf_event *p_event)
 {
        struct ftrace_event_call *tp_event;
-       int event_id = p_event->attr.config;
+       u64 event_id = p_event->attr.config;
        int ret = -EINVAL;
 
        mutex_lock(&event_mutex);
index f919a2e21bf30e68ad6a99ee627d63f5bb6cb44c..a11800ae96de5d1f098153aaacdb715ba5098493 100644 (file)
@@ -2314,6 +2314,9 @@ int event_trace_del_tracer(struct trace_array *tr)
        /* Disable any running events */
        __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0);
 
+       /* Access to events are within rcu_read_lock_sched() */
+       synchronize_sched();
+
        down_write(&trace_event_sem);
        __trace_remove_event_dirs(tr);
        debugfs_remove_recursive(tr->event_dir);
index fee77e15d8154e5a9a7936824b14b6d805c0dc13..6e32635e5e570c7632aaebeb724c1d34e10172a1 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
 #include <linux/sched/rt.h>
+#include <linux/sched/deadline.h>
 #include <trace/events/sched.h>
 #include "trace.h"
 
@@ -27,6 +28,8 @@ static int                    wakeup_cpu;
 static int                     wakeup_current_cpu;
 static unsigned                        wakeup_prio = -1;
 static int                     wakeup_rt;
+static int                     wakeup_dl;
+static int                     tracing_dl = 0;
 
 static arch_spinlock_t wakeup_lock =
        (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
@@ -437,6 +440,7 @@ static void __wakeup_reset(struct trace_array *tr)
 {
        wakeup_cpu = -1;
        wakeup_prio = -1;
+       tracing_dl = 0;
 
        if (wakeup_task)
                put_task_struct(wakeup_task);
@@ -472,9 +476,17 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
        tracing_record_cmdline(p);
        tracing_record_cmdline(current);
 
-       if ((wakeup_rt && !rt_task(p)) ||
-                       p->prio >= wakeup_prio ||
-                       p->prio >= current->prio)
+       /*
+        * Semantic is like this:
+        *  - wakeup tracer handles all tasks in the system, independently
+        *    from their scheduling class;
+        *  - wakeup_rt tracer handles tasks belonging to sched_dl and
+        *    sched_rt class;
+        *  - wakeup_dl handles tasks belonging to sched_dl class only.
+        */
+       if (tracing_dl || (wakeup_dl && !dl_task(p)) ||
+           (wakeup_rt && !dl_task(p) && !rt_task(p)) ||
+           (!dl_task(p) && (p->prio >= wakeup_prio || p->prio >= current->prio)))
                return;
 
        pc = preempt_count();
@@ -486,7 +498,8 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
        arch_spin_lock(&wakeup_lock);
 
        /* check for races. */
-       if (!tracer_enabled || p->prio >= wakeup_prio)
+       if (!tracer_enabled || tracing_dl ||
+           (!dl_task(p) && p->prio >= wakeup_prio))
                goto out_locked;
 
        /* reset the trace */
@@ -496,6 +509,15 @@ probe_wakeup(void *ignore, struct task_struct *p, int success)
        wakeup_current_cpu = wakeup_cpu;
        wakeup_prio = p->prio;
 
+       /*
+        * Once you start tracing a -deadline task, don't bother tracing
+        * another task until the first one wakes up.
+        */
+       if (dl_task(p))
+               tracing_dl = 1;
+       else
+               tracing_dl = 0;
+
        wakeup_task = p;
        get_task_struct(wakeup_task);
 
@@ -597,16 +619,25 @@ static int __wakeup_tracer_init(struct trace_array *tr)
 
 static int wakeup_tracer_init(struct trace_array *tr)
 {
+       wakeup_dl = 0;
        wakeup_rt = 0;
        return __wakeup_tracer_init(tr);
 }
 
 static int wakeup_rt_tracer_init(struct trace_array *tr)
 {
+       wakeup_dl = 0;
        wakeup_rt = 1;
        return __wakeup_tracer_init(tr);
 }
 
+static int wakeup_dl_tracer_init(struct trace_array *tr)
+{
+       wakeup_dl = 1;
+       wakeup_rt = 0;
+       return __wakeup_tracer_init(tr);
+}
+
 static void wakeup_tracer_reset(struct trace_array *tr)
 {
        int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
@@ -674,6 +705,28 @@ static struct tracer wakeup_rt_tracer __read_mostly =
        .use_max_tr     = true,
 };
 
+static struct tracer wakeup_dl_tracer __read_mostly =
+{
+       .name           = "wakeup_dl",
+       .init           = wakeup_dl_tracer_init,
+       .reset          = wakeup_tracer_reset,
+       .start          = wakeup_tracer_start,
+       .stop           = wakeup_tracer_stop,
+       .wait_pipe      = poll_wait_pipe,
+       .print_max      = true,
+       .print_header   = wakeup_print_header,
+       .print_line     = wakeup_print_line,
+       .flags          = &tracer_flags,
+       .set_flag       = wakeup_set_flag,
+       .flag_changed   = wakeup_flag_changed,
+#ifdef CONFIG_FTRACE_SELFTEST
+       .selftest    = trace_selftest_startup_wakeup,
+#endif
+       .open           = wakeup_trace_open,
+       .close          = wakeup_trace_close,
+       .use_max_tr     = true,
+};
+
 __init static int init_wakeup_tracer(void)
 {
        int ret;
@@ -686,6 +739,10 @@ __init static int init_wakeup_tracer(void)
        if (ret)
                return ret;
 
+       ret = register_tracer(&wakeup_dl_tracer);
+       if (ret)
+               return ret;
+
        return 0;
 }
 core_initcall(init_wakeup_tracer);
index a7329b7902f81fff4c2bafa3d4ef29780b52fe3d..e98fca60974f57a36d8c2780e5164c62b10195a8 100644 (file)
@@ -1022,11 +1022,16 @@ trace_selftest_startup_nop(struct tracer *trace, struct trace_array *tr)
 #ifdef CONFIG_SCHED_TRACER
 static int trace_wakeup_test_thread(void *data)
 {
-       /* Make this a RT thread, doesn't need to be too high */
-       static const struct sched_param param = { .sched_priority = 5 };
+       /* Make this a -deadline thread */
+       static const struct sched_attr attr = {
+               .sched_policy = SCHED_DEADLINE,
+               .sched_runtime = 100000ULL,
+               .sched_deadline = 10000000ULL,
+               .sched_period = 10000000ULL
+       };
        struct completion *x = data;
 
-       sched_setscheduler(current, SCHED_FIFO, &param);
+       sched_setattr(current, &attr);
 
        /* Make it know we have a new prio */
        complete(x);
@@ -1040,8 +1045,8 @@ static int trace_wakeup_test_thread(void *data)
        /* we are awake, now wait to disappear */
        while (!kthread_should_stop()) {
                /*
-                * This is an RT task, do short sleeps to let
-                * others run.
+                * This will likely be the system top priority
+                * task, do short sleeps to let others run.
                 */
                msleep(100);
        }
@@ -1054,21 +1059,21 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
 {
        unsigned long save_max = tracing_max_latency;
        struct task_struct *p;
-       struct completion isrt;
+       struct completion is_ready;
        unsigned long count;
        int ret;
 
-       init_completion(&isrt);
+       init_completion(&is_ready);
 
-       /* create a high prio thread */
-       p = kthread_run(trace_wakeup_test_thread, &isrt, "ftrace-test");
+       /* create a -deadline thread */
+       p = kthread_run(trace_wakeup_test_thread, &is_ready, "ftrace-test");
        if (IS_ERR(p)) {
                printk(KERN_CONT "Failed to create ftrace wakeup test thread ");
                return -1;
        }
 
-       /* make sure the thread is running at an RT prio */
-       wait_for_completion(&isrt);
+       /* make sure the thread is running at -deadline policy */
+       wait_for_completion(&is_ready);
 
        /* start the tracing */
        ret = tracer_init(trace, tr);
@@ -1082,19 +1087,19 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
 
        while (p->on_rq) {
                /*
-                * Sleep to make sure the RT thread is asleep too.
+                * Sleep to make sure the -deadline thread is asleep too.
                 * On virtual machines we can't rely on timings,
                 * but we want to make sure this test still works.
                 */
                msleep(100);
        }
 
-       init_completion(&isrt);
+       init_completion(&is_ready);
 
        wake_up_process(p);
 
        /* Wait for the task to wake up */
-       wait_for_completion(&isrt);
+       wait_for_completion(&is_ready);
 
        /* stop the tracing. */
        tracing_stop();
index e4b6d11bdf78f35a2a6d8e831cd3ec21d97d9c00..ea90eb5f6f1730dce05ca992c19ebb533d7085db 100644 (file)
@@ -431,11 +431,6 @@ static void unreg_event_syscall_enter(struct ftrace_event_file *file,
        if (!tr->sys_refcount_enter)
                unregister_trace_sys_enter(ftrace_syscall_enter, tr);
        mutex_unlock(&syscall_trace_lock);
-       /*
-        * Callers expect the event to be completely disabled on
-        * return, so wait for current handlers to finish.
-        */
-       synchronize_sched();
 }
 
 static int reg_event_syscall_exit(struct ftrace_event_file *file,
@@ -474,11 +469,6 @@ static void unreg_event_syscall_exit(struct ftrace_event_file *file,
        if (!tr->sys_refcount_exit)
                unregister_trace_sys_exit(ftrace_syscall_exit, tr);
        mutex_unlock(&syscall_trace_lock);
-       /*
-        * Callers expect the event to be completely disabled on
-        * return, so wait for current handlers to finish.
-        */
-       synchronize_sched();
 }
 
 static int __init init_syscall_trace(struct ftrace_event_call *call)
index a3a0dbfda32957616f143ae2722541a5846c0a62..c006131beb77c5151f92cacb9e11e6a3b1defe1b 100644 (file)
@@ -51,9 +51,9 @@ struct user_namespace init_user_ns = {
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
-#ifdef CONFIG_KEYS_KERBEROS_CACHE
-       .krb_cache_register_sem =
-       __RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem),
+#ifdef CONFIG_PERSISTENT_KEYRINGS
+       .persistent_keyring_register_sem =
+       __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
 #endif
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
index c66912be990fbda0f61e7a58fdbc52cf304566c2..b010eac595d20eece261310cc4acb629ad70b92b 100644 (file)
@@ -2851,19 +2851,6 @@ already_gone:
        return false;
 }
 
-static bool __flush_work(struct work_struct *work)
-{
-       struct wq_barrier barr;
-
-       if (start_flush_work(work, &barr)) {
-               wait_for_completion(&barr.done);
-               destroy_work_on_stack(&barr.work);
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * flush_work - wait for a work to finish executing the last queueing instance
  * @work: the work to flush
@@ -2877,10 +2864,18 @@ static bool __flush_work(struct work_struct *work)
  */
 bool flush_work(struct work_struct *work)
 {
+       struct wq_barrier barr;
+
        lock_map_acquire(&work->lockdep_map);
        lock_map_release(&work->lockdep_map);
 
-       return __flush_work(work);
+       if (start_flush_work(work, &barr)) {
+               wait_for_completion(&barr.done);
+               destroy_work_on_stack(&barr.work);
+               return true;
+       } else {
+               return false;
+       }
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
@@ -4832,14 +4827,7 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 
        INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
        schedule_work_on(cpu, &wfc.work);
-
-       /*
-        * The work item is on-stack and can't lead to deadlock through
-        * flushing.  Use __flush_work() to avoid spurious lockdep warnings
-        * when work_on_cpu()s are nested.
-        */
-       __flush_work(&wfc.work);
-
+       flush_work(&wfc.work);
        return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);
index db25707aa41bc021b8174391091178b85258d466..6982094a7e74aa8c5daea87f90878174a8d746c1 100644 (file)
@@ -761,6 +761,15 @@ config PANIC_ON_OOPS_VALUE
        default 0 if !PANIC_ON_OOPS
        default 1 if PANIC_ON_OOPS
 
+config PANIC_TIMEOUT
+       int "panic timeout"
+       default 0
+       help
+         Set the timeout value (in seconds) until a reboot occurs when the
+         the kernel panics. If n = 0, then we wait forever. A timeout
+         value n > 0 will wait n seconds before rebooting, while a timeout
+         value n < 0 will reboot immediately.
+
 config SCHED_DEBUG
        bool "Collect scheduler debugging info"
        depends on DEBUG_KERNEL && PROC_FS
index 17edeaf1918019b43c53dffd6e620298dcb710a2..1b6a44f1ec3e3b10f3b02d19f8ab0ce59453f6d5 100644 (file)
@@ -759,8 +759,8 @@ all_leaves_cluster_together:
        pr_devel("all leaves cluster together\n");
        diff = INT_MAX;
        for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-               int x = ops->diff_objects(assoc_array_ptr_to_leaf(edit->leaf),
-                                         assoc_array_ptr_to_leaf(node->slots[i]));
+               int x = ops->diff_objects(assoc_array_ptr_to_leaf(node->slots[i]),
+                                         index_key);
                if (x < diff) {
                        BUG_ON(x < 0);
                        diff = x;
index 7473ee3b4ee712b0759e264b79f350457888be1e..8280a5dd172780371711743d297fcd0fd4e4360a 100644 (file)
@@ -82,10 +82,10 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
                unsigned long flags;
                raw_spin_lock_irqsave(&fbc->lock, flags);
                fbc->count += count;
+               __this_cpu_sub(*fbc->counters, count - amount);
                raw_spin_unlock_irqrestore(&fbc->lock, flags);
-               __this_cpu_write(*fbc->counters, 0);
        } else {
-               __this_cpu_write(*fbc->counters, count);
+               this_cpu_add(*fbc->counters, amount);
        }
        preempt_enable();
 }
index eb69f352401de910552fb7f28959b38f4746a878..723bbe04a0b0511976d3778a4df94cb2974eb9c8 100644 (file)
@@ -543,7 +543,7 @@ config ZSWAP
 
 config MEM_SOFT_DIRTY
        bool "Track memory changes"
-       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY
+       depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY && PROC_FS
        select PROC_PAGE_MONITOR
        help
          This option enables memory changes tracking by introducing a
index 805165bcd3dd0ab8f27bbff2c9105927ed803c15..f58bcd016f432dd094d6f6378aa53f9799d30811 100644 (file)
@@ -134,6 +134,10 @@ static void update_pageblock_skip(struct compact_control *cc,
                        bool migrate_scanner)
 {
        struct zone *zone = cc->zone;
+
+       if (cc->ignore_skip_hint)
+               return;
+
        if (!page)
                return;
 
index 5bff0814776870e2974e6e436ad99f99f264e05a..bbc4d660221ac4e514e24d49ce140b25ad5364d2 100644 (file)
@@ -208,9 +208,10 @@ get_write_lock:
                if (mapping_cap_account_dirty(mapping)) {
                        unsigned long addr;
                        struct file *file = get_file(vma->vm_file);
+                       /* mmap_region may free vma; grab the info now */
+                       vm_flags = vma->vm_flags;
 
-                       addr = mmap_region(file, start, size,
-                                       vma->vm_flags, pgoff);
+                       addr = mmap_region(file, start, size, vm_flags, pgoff);
                        fput(file);
                        if (IS_ERR_VALUE(addr)) {
                                err = addr;
@@ -218,7 +219,7 @@ get_write_lock:
                                BUG_ON(addr != start);
                                err = 0;
                        }
-                       goto out;
+                       goto out_freed;
                }
                mutex_lock(&mapping->i_mmap_mutex);
                flush_dcache_mmap_lock(mapping);
@@ -253,6 +254,7 @@ get_write_lock:
 out:
        if (vma)
                vm_flags = vma->vm_flags;
+out_freed:
        if (likely(!has_write_lock))
                up_read(&mm->mmap_sem);
        else
index bccd5a628ea6765478d2fa45dc01390a83ee8a5b..95d1acb0f3d237f55f5f1d6405de5774f0f9fc6a 100644 (file)
@@ -882,6 +882,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                ret = 0;
                goto out_unlock;
        }
+
        if (unlikely(pmd_trans_splitting(pmd))) {
                /* split huge page running from under us */
                spin_unlock(src_ptl);
@@ -1153,7 +1154,7 @@ alloc:
                new_page = NULL;
 
        if (unlikely(!new_page)) {
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        ret = do_huge_pmd_wp_zero_page_fallback(mm, vma,
                                        address, pmd, orig_pmd, haddr);
                } else {
@@ -1180,7 +1181,7 @@ alloc:
 
        count_vm_event(THP_FAULT_ALLOC);
 
-       if (is_huge_zero_pmd(orig_pmd))
+       if (!page)
                clear_huge_page(new_page, haddr, HPAGE_PMD_NR);
        else
                copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR);
@@ -1206,7 +1207,7 @@ alloc:
                page_add_new_anon_rmap(new_page, vma, haddr);
                set_pmd_at(mm, haddr, pmd, entry);
                update_mmu_cache_pmd(vma, address, pmd);
-               if (is_huge_zero_pmd(orig_pmd)) {
+               if (!page) {
                        add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
                        put_huge_zero_page();
                } else {
@@ -1243,6 +1244,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
                return ERR_PTR(-EFAULT);
 
+       /* Full NUMA hinting faults to serialise migration in fault paths */
+       if ((flags & FOLL_NUMA) && pmd_numa(*pmd))
+               goto out;
+
        page = pmd_page(*pmd);
        VM_BUG_ON(!PageHead(page));
        if (flags & FOLL_TOUCH) {
@@ -1295,6 +1300,17 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(!pmd_same(pmd, *pmdp)))
                goto out_unlock;
 
+       /*
+        * If there are potential migrations, wait for completion and retry
+        * without disrupting NUMA hinting information. Do not relock and
+        * check_same as the page may no longer be mapped.
+        */
+       if (unlikely(pmd_trans_migrating(*pmdp))) {
+               spin_unlock(ptl);
+               wait_migrate_huge_page(vma->anon_vma, pmdp);
+               goto out;
+       }
+
        page = pmd_page(pmd);
        BUG_ON(is_huge_zero_page(page));
        page_nid = page_to_nid(page);
@@ -1323,23 +1339,22 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                /* If the page was locked, there are no parallel migrations */
                if (page_locked)
                        goto clear_pmdnuma;
+       }
 
-               /*
-                * Otherwise wait for potential migrations and retry. We do
-                * relock and check_same as the page may no longer be mapped.
-                * As the fault is being retried, do not account for it.
-                */
+       /* Migration could have started since the pmd_trans_migrating check */
+       if (!page_locked) {
                spin_unlock(ptl);
                wait_on_page_locked(page);
                page_nid = -1;
                goto out;
        }
 
-       /* Page is misplaced, serialise migrations and parallel THP splits */
+       /*
+        * Page is misplaced. Page lock serialises migrations. Acquire anon_vma
+        * to serialises splits
+        */
        get_page(page);
        spin_unlock(ptl);
-       if (!page_locked)
-               lock_page(page);
        anon_vma = page_lock_anon_vma_read(page);
 
        /* Confirm the PMD did not change while page_table_lock was released */
@@ -1351,6 +1366,13 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out_unlock;
        }
 
+       /* Bail if we fail to protect against THP splits for any reason */
+       if (unlikely(!anon_vma)) {
+               put_page(page);
+               page_nid = -1;
+               goto clear_pmdnuma;
+       }
+
        /*
         * Migrate the THP to the requested node, returns with page unlocked
         * and pmd_numa cleared.
@@ -1481,8 +1503,18 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
                pmd = pmdp_get_and_clear(mm, old_addr, old_pmd);
                VM_BUG_ON(!pmd_none(*new_pmd));
                set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
-               if (new_ptl != old_ptl)
+               if (new_ptl != old_ptl) {
+                       pgtable_t pgtable;
+
+                       /*
+                        * Move preallocated PTE page table if new_pmd is on
+                        * different PMD page table.
+                        */
+                       pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
+                       pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
+
                        spin_unlock(new_ptl);
+               }
                spin_unlock(old_ptl);
        }
 out:
@@ -1507,6 +1539,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                ret = 1;
                if (!prot_numa) {
                        entry = pmdp_get_and_clear(mm, addr, pmd);
+                       if (pmd_numa(entry))
+                               entry = pmd_mknonnuma(entry);
                        entry = pmd_modify(entry, newprot);
                        ret = HPAGE_PMD_NR;
                        BUG_ON(pmd_write(entry));
@@ -1521,7 +1555,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
                         */
                        if (!is_huge_zero_page(page) &&
                            !pmd_numa(*pmd)) {
-                               entry = pmdp_get_and_clear(mm, addr, pmd);
+                               entry = *pmd;
                                entry = pmd_mknuma(entry);
                                ret = HPAGE_PMD_NR;
                        }
index f1a0ae6e11b86b3020c90d7241ba12d47d2bbaa8..7f1a356153c013349ce520c7763002838c02fb76 100644 (file)
@@ -338,7 +338,7 @@ struct mem_cgroup {
 static size_t memcg_size(void)
 {
        return sizeof(struct mem_cgroup) +
-               nr_node_ids * sizeof(struct mem_cgroup_per_node);
+               nr_node_ids * sizeof(struct mem_cgroup_per_node *);
 }
 
 /* internal only representation about the status of kmem accounting. */
@@ -2694,7 +2694,10 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
                goto bypass;
 
        if (unlikely(task_in_memcg_oom(current)))
-               goto bypass;
+               goto nomem;
+
+       if (gfp_mask & __GFP_NOFAIL)
+               oom = false;
 
        /*
         * We always charge the cgroup the mm_struct belongs to.
@@ -6352,6 +6355,42 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       /*
+        * XXX: css_offline() would be where we should reparent all
+        * memory to prepare the cgroup for destruction.  However,
+        * memcg does not do css_tryget() and res_counter charging
+        * under the same RCU lock region, which means that charging
+        * could race with offlining.  Offlining only happens to
+        * cgroups with no tasks in them but charges can show up
+        * without any tasks from the swapin path when the target
+        * memcg is looked up from the swapout record and not from the
+        * current task as it usually is.  A race like this can leak
+        * charges and put pages with stale cgroup pointers into
+        * circulation:
+        *
+        * #0                        #1
+        *                           lookup_swap_cgroup_id()
+        *                           rcu_read_lock()
+        *                           mem_cgroup_lookup()
+        *                           css_tryget()
+        *                           rcu_read_unlock()
+        * disable css_tryget()
+        * call_rcu()
+        *   offline_css()
+        *     reparent_charges()
+        *                           res_counter_charge()
+        *                           css_put()
+        *                             css_free()
+        *                           pc->mem_cgroup = dead memcg
+        *                           add page to lru
+        *
+        * The bulk of the charges are still moved in offline_css() to
+        * avoid pinning a lot of pages in case a long-term reference
+        * like a swapout record is deferring the css_free() to long
+        * after offlining.  But this makes sure we catch any charges
+        * made after offlining:
+        */
+       mem_cgroup_reparent_charges(memcg);
 
        memcg_destroy_kmem(memcg);
        __mem_cgroup_free(memcg);
index b7c171602ba1ebb8697f0c523f1a62f51c3a2fa4..fabe55046c1d7b9638172aa8e26ecb4f3d6ed4b9 100644 (file)
@@ -938,6 +938,16 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
                                BUG_ON(!PageHWPoison(p));
                                return SWAP_FAIL;
                        }
+                       /*
+                        * We pinned the head page for hwpoison handling,
+                        * now we split the thp and we are interested in
+                        * the hwpoisoned raw page, so move the refcount
+                        * to it.
+                        */
+                       if (hpage != p) {
+                               put_page(hpage);
+                               get_page(p);
+                       }
                        /* THP is split, so ppage should be the real poisoned page. */
                        ppage = p;
                }
@@ -1505,10 +1515,16 @@ static int soft_offline_huge_page(struct page *page, int flags)
                if (ret > 0)
                        ret = -EIO;
        } else {
-               set_page_hwpoison_huge_page(hpage);
-               dequeue_hwpoisoned_huge_page(hpage);
-               atomic_long_add(1 << compound_order(hpage),
-                               &num_poisoned_pages);
+               /* overcommit hugetlb page will be freed to buddy */
+               if (PageHuge(page)) {
+                       set_page_hwpoison_huge_page(hpage);
+                       dequeue_hwpoisoned_huge_page(hpage);
+                       atomic_long_add(1 << compound_order(hpage),
+                                       &num_poisoned_pages);
+               } else {
+                       SetPageHWPoison(page);
+                       atomic_long_inc(&num_poisoned_pages);
+               }
        }
        return ret;
 }
index 5d9025f3b3e1cd65bd97655ee95d6cd2f390ce5b..6768ce9e57d29b6d8076b11c62c2097662f334d5 100644 (file)
@@ -4271,7 +4271,7 @@ void copy_user_huge_page(struct page *dst, struct page *src,
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
 
-#if USE_SPLIT_PTE_PTLOCKS && BLOATED_SPINLOCKS
+#if USE_SPLIT_PTE_PTLOCKS && ALLOC_SPLIT_PTLOCKS
 bool ptlock_alloc(struct page *page)
 {
        spinlock_t *ptl;
index eca4a3129129751208b41cfe808e9e31e5dc7b5f..0cd2c4d4e2703f88f56b957b6f442a531fbd2e1f 100644 (file)
@@ -1197,14 +1197,16 @@ static struct page *new_vma_page(struct page *page, unsigned long private, int *
                        break;
                vma = vma->vm_next;
        }
+
+       if (PageHuge(page)) {
+               if (vma)
+                       return alloc_huge_page_noerr(vma, address, 1);
+               else
+                       return NULL;
+       }
        /*
-        * queue_pages_range() confirms that @page belongs to some vma,
-        * so vma shouldn't be NULL.
+        * if !vma, alloc_page_vma() will use task or system default policy
         */
-       BUG_ON(!vma);
-
-       if (PageHuge(page))
-               return alloc_huge_page_noerr(vma, address, 1);
        return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
 }
 #else
@@ -1318,7 +1320,7 @@ static long do_mbind(unsigned long start, unsigned long len,
                if (nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
        } else
-               putback_lru_pages(&pagelist);
+               putback_movable_pages(&pagelist);
 
        up_write(&mm->mmap_sem);
  mpol_out:
index bb940045fe8595842ed58f2e32f87b83d40485e1..9194375b230729fead356e8dd3c8f6bb951415ab 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/hugetlb_cgroup.h>
 #include <linux/gfp.h>
 #include <linux/balloon_compaction.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/tlbflush.h>
 
@@ -316,14 +317,15 @@ static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
  */
 int migrate_page_move_mapping(struct address_space *mapping,
                struct page *newpage, struct page *page,
-               struct buffer_head *head, enum migrate_mode mode)
+               struct buffer_head *head, enum migrate_mode mode,
+               int extra_count)
 {
-       int expected_count = 0;
+       int expected_count = 1 + extra_count;
        void **pslot;
 
        if (!mapping) {
                /* Anonymous page without mapping */
-               if (page_count(page) != 1)
+               if (page_count(page) != expected_count)
                        return -EAGAIN;
                return MIGRATEPAGE_SUCCESS;
        }
@@ -333,7 +335,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
        pslot = radix_tree_lookup_slot(&mapping->page_tree,
                                        page_index(page));
 
-       expected_count = 2 + page_has_private(page);
+       expected_count += 1 + page_has_private(page);
        if (page_count(page) != expected_count ||
                radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {
                spin_unlock_irq(&mapping->tree_lock);
@@ -583,7 +585,7 @@ int migrate_page(struct address_space *mapping,
 
        BUG_ON(PageWriteback(page));    /* Writeback must be complete */
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -610,7 +612,7 @@ int buffer_migrate_page(struct address_space *mapping,
 
        head = page_buffers(page);
 
-       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode);
+       rc = migrate_page_move_mapping(mapping, newpage, page, head, mode, 0);
 
        if (rc != MIGRATEPAGE_SUCCESS)
                return rc;
@@ -1654,6 +1656,18 @@ int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
        return 1;
 }
 
+bool pmd_trans_migrating(pmd_t pmd)
+{
+       struct page *page = pmd_page(pmd);
+       return PageLocked(page);
+}
+
+void wait_migrate_huge_page(struct anon_vma *anon_vma, pmd_t *pmd)
+{
+       struct page *page = pmd_page(*pmd);
+       wait_on_page_locked(page);
+}
+
 /*
  * Attempt to migrate a misplaced page to the specified destination
  * node. Caller is expected to have an elevated reference count on
@@ -1716,12 +1730,14 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                                struct page *page, int node)
 {
        spinlock_t *ptl;
-       unsigned long haddr = address & HPAGE_PMD_MASK;
        pg_data_t *pgdat = NODE_DATA(node);
        int isolated = 0;
        struct page *new_page = NULL;
        struct mem_cgroup *memcg = NULL;
        int page_lru = page_is_file_cache(page);
+       unsigned long mmun_start = address & HPAGE_PMD_MASK;
+       unsigned long mmun_end = mmun_start + HPAGE_PMD_SIZE;
+       pmd_t orig_entry;
 
        /*
         * Rate-limit the amount of data that is being migrated to a node.
@@ -1744,6 +1760,9 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                goto out_fail;
        }
 
+       if (mm_tlb_flush_pending(mm))
+               flush_tlb_range(vma, mmun_start, mmun_end);
+
        /* Prepare a page as a migration target */
        __set_page_locked(new_page);
        SetPageSwapBacked(new_page);
@@ -1755,9 +1774,12 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
        WARN_ON(PageLRU(new_page));
 
        /* Recheck the target PMD */
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
        ptl = pmd_lock(mm, pmd);
-       if (unlikely(!pmd_same(*pmd, entry))) {
+       if (unlikely(!pmd_same(*pmd, entry) || page_count(page) != 2)) {
+fail_putback:
                spin_unlock(ptl);
+               mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
                /* Reverse changes made by migrate_page_copy() */
                if (TestClearPageActive(new_page))
@@ -1774,7 +1796,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
                putback_lru_page(page);
                mod_zone_page_state(page_zone(page),
                         NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR);
-               goto out_fail;
+
+               goto out_unlock;
        }
 
        /*
@@ -1786,16 +1809,35 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_prepare_migration(page, new_page, &memcg);
 
+       orig_entry = *pmd;
        entry = mk_pmd(new_page, vma->vm_page_prot);
-       entry = pmd_mknonnuma(entry);
-       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
        entry = pmd_mkhuge(entry);
+       entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 
-       pmdp_clear_flush(vma, haddr, pmd);
-       set_pmd_at(mm, haddr, pmd, entry);
-       page_add_new_anon_rmap(new_page, vma, haddr);
+       /*
+        * Clear the old entry under pagetable lock and establish the new PTE.
+        * Any parallel GUP will either observe the old page blocking on the
+        * page lock, block on the page table lock or observe the new page.
+        * The SetPageUptodate on the new page and page_add_new_anon_rmap
+        * guarantee the copy is visible before the pagetable update.
+        */
+       flush_cache_range(vma, mmun_start, mmun_end);
+       page_add_new_anon_rmap(new_page, vma, mmun_start);
+       pmdp_clear_flush(vma, mmun_start, pmd);
+       set_pmd_at(mm, mmun_start, pmd, entry);
+       flush_tlb_range(vma, mmun_start, mmun_end);
        update_mmu_cache_pmd(vma, address, &entry);
+
+       if (page_count(page) != 2) {
+               set_pmd_at(mm, mmun_start, pmd, orig_entry);
+               flush_tlb_range(vma, mmun_start, mmun_end);
+               update_mmu_cache_pmd(vma, address, &entry);
+               page_remove_rmap(new_page);
+               goto fail_putback;
+       }
+
        page_remove_rmap(page);
+
        /*
         * Finish the charge transaction under the page table lock to
         * prevent split_huge_page() from dividing up the charge
@@ -1803,6 +1845,7 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
         */
        mem_cgroup_end_migration(memcg, page, new_page, true);
        spin_unlock(ptl);
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 
        unlock_page(new_page);
        unlock_page(page);
@@ -1820,10 +1863,15 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
 out_fail:
        count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
 out_dropref:
-       entry = pmd_mknonnuma(entry);
-       set_pmd_at(mm, haddr, pmd, entry);
-       update_mmu_cache_pmd(vma, address, &entry);
+       ptl = pmd_lock(mm, pmd);
+       if (pmd_same(*pmd, entry)) {
+               entry = pmd_mknonnuma(entry);
+               set_pmd_at(mm, mmun_start, pmd, entry);
+               update_mmu_cache_pmd(vma, address, &entry);
+       }
+       spin_unlock(ptl);
 
+out_unlock:
        unlock_page(page);
        put_page(page);
        return 0;
index d480cd6fc475854259bdd51021d5125dbdfbe479..192e6eebe4f240e4a8ece7cc0e10e902ff29f308 100644 (file)
@@ -133,7 +133,10 @@ static void __munlock_isolation_failed(struct page *page)
 
 /**
  * munlock_vma_page - munlock a vma page
- * @page - page to be unlocked
+ * @page - page to be unlocked, either a normal page or THP page head
+ *
+ * returns the size of the page as a page mask (0 for normal page,
+ *         HPAGE_PMD_NR - 1 for THP head page)
  *
  * called from munlock()/munmap() path with page supposedly on the LRU.
  * When we munlock a page, because the vma where we found the page is being
@@ -148,21 +151,30 @@ static void __munlock_isolation_failed(struct page *page)
  */
 unsigned int munlock_vma_page(struct page *page)
 {
-       unsigned int page_mask = 0;
+       unsigned int nr_pages;
 
        BUG_ON(!PageLocked(page));
 
        if (TestClearPageMlocked(page)) {
-               unsigned int nr_pages = hpage_nr_pages(page);
+               nr_pages = hpage_nr_pages(page);
                mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
-               page_mask = nr_pages - 1;
                if (!isolate_lru_page(page))
                        __munlock_isolated_page(page);
                else
                        __munlock_isolation_failed(page);
+       } else {
+               nr_pages = hpage_nr_pages(page);
        }
 
-       return page_mask;
+       /*
+        * Regardless of the original PageMlocked flag, we determine nr_pages
+        * after touching the flag. This leaves a possible race with a THP page
+        * split, such that a whole THP page was munlocked, but nr_pages == 1.
+        * Returning a smaller mask due to that is OK, the worst that can
+        * happen is subsequent useless scanning of the former tail pages.
+        * The NR_MLOCK accounting can however become broken.
+        */
+       return nr_pages - 1;
 }
 
 /**
@@ -286,10 +298,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
 {
        int i;
        int nr = pagevec_count(pvec);
-       int delta_munlocked = -nr;
+       int delta_munlocked;
        struct pagevec pvec_putback;
        int pgrescued = 0;
 
+       pagevec_init(&pvec_putback, 0);
+
        /* Phase 1: page isolation */
        spin_lock_irq(&zone->lru_lock);
        for (i = 0; i < nr; i++) {
@@ -318,18 +332,21 @@ skip_munlock:
                        /*
                         * We won't be munlocking this page in the next phase
                         * but we still need to release the follow_page_mask()
-                        * pin.
+                        * pin. We cannot do it under lru_lock however. If it's
+                        * the last pin, __page_cache_release would deadlock.
                         */
+                       pagevec_add(&pvec_putback, pvec->pages[i]);
                        pvec->pages[i] = NULL;
-                       put_page(page);
-                       delta_munlocked++;
                }
        }
+       delta_munlocked = -nr + pagevec_count(&pvec_putback);
        __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
        spin_unlock_irq(&zone->lru_lock);
 
+       /* Now we can release pins of pages that we are not munlocking */
+       pagevec_release(&pvec_putback);
+
        /* Phase 2: page munlock */
-       pagevec_init(&pvec_putback, 0);
        for (i = 0; i < nr; i++) {
                struct page *page = pvec->pages[i];
 
@@ -440,7 +457,8 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
 
        while (start < end) {
                struct page *page = NULL;
-               unsigned int page_mask, page_increm;
+               unsigned int page_mask;
+               unsigned long page_increm;
                struct pagevec pvec;
                struct zone *zone;
                int zoneid;
@@ -490,7 +508,9 @@ void munlock_vma_pages_range(struct vm_area_struct *vma,
                                goto next;
                        }
                }
-               page_increm = 1 + (~(start >> PAGE_SHIFT) & page_mask);
+               /* It's a bug to munlock in the middle of a THP page */
+               VM_BUG_ON((start >> PAGE_SHIFT) & page_mask);
+               page_increm = 1 + page_mask;
                start += page_increm * PAGE_SIZE;
 next:
                cond_resched();
index 26667971c824b08ca3dae7188a965e1e4efe0b79..bb53a6591aea1373d6bc74d5bb3e847650af8d24 100644 (file)
@@ -52,17 +52,21 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
                        pte_t ptent;
                        bool updated = false;
 
-                       ptent = ptep_modify_prot_start(mm, addr, pte);
                        if (!prot_numa) {
+                               ptent = ptep_modify_prot_start(mm, addr, pte);
+                               if (pte_numa(ptent))
+                                       ptent = pte_mknonnuma(ptent);
                                ptent = pte_modify(ptent, newprot);
                                updated = true;
                        } else {
                                struct page *page;
 
+                               ptent = *pte;
                                page = vm_normal_page(vma, addr, oldpte);
                                if (page) {
                                        if (!pte_numa(oldpte)) {
                                                ptent = pte_mknuma(ptent);
+                                               set_pte_at(mm, addr, pte, ptent);
                                                updated = true;
                                        }
                                }
@@ -79,7 +83,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
                        if (updated)
                                pages++;
-                       ptep_modify_prot_commit(mm, addr, pte, ptent);
+
+                       /* 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);
 
@@ -181,6 +188,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        BUG_ON(addr >= end);
        pgd = pgd_offset(mm, addr);
        flush_cache_range(vma, addr, end);
+       set_tlb_flush_pending(mm);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd))
@@ -192,6 +200,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
        /* Only flush the TLB if we actually modified any entries: */
        if (pages)
                flush_tlb_range(vma, start, end);
+       clear_tlb_flush_pending(mm);
 
        return pages;
 }
index 580a5f075ed0ab6e3047351a8271b1f053e35774..5248fe070aa4e9f94b4be087aa8957e16cf16c1f 100644 (file)
@@ -1816,7 +1816,7 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
 
 static bool zone_local(struct zone *local_zone, struct zone *zone)
 {
-       return node_distance(local_zone->node, zone->node) == LOCAL_DISTANCE;
+       return local_zone->node == zone->node;
 }
 
 static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
@@ -1913,18 +1913,17 @@ zonelist_scan:
                 * page was allocated in should have no effect on the
                 * time the page has in memory before being reclaimed.
                 *
-                * When zone_reclaim_mode is enabled, try to stay in
-                * local zones in the fastpath.  If that fails, the
-                * slowpath is entered, which will do another pass
-                * starting with the local zones, but ultimately fall
-                * back to remote zones that do not partake in the
-                * fairness round-robin cycle of this zonelist.
+                * Try to stay in local zones in the fastpath.  If
+                * that fails, the slowpath is entered, which will do
+                * another pass starting with the local zones, but
+                * ultimately fall back to remote zones that do not
+                * partake in the fairness round-robin cycle of this
+                * zonelist.
                 */
                if (alloc_flags & ALLOC_WMARK_LOW) {
                        if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0)
                                continue;
-                       if (zone_reclaim_mode &&
-                           !zone_local(preferred_zone, zone))
+                       if (!zone_local(preferred_zone, zone))
                                continue;
                }
                /*
@@ -2390,7 +2389,7 @@ static void prepare_slowpath(gfp_t gfp_mask, unsigned int order,
                 * thrash fairness information for zones that are not
                 * actually part of this zonelist's round-robin cycle.
                 */
-               if (zone_reclaim_mode && !zone_local(preferred_zone, zone))
+               if (!zone_local(preferred_zone, zone))
                        continue;
                mod_zone_page_state(zone, NR_ALLOC_BATCH,
                                    high_wmark_pages(zone) -
index cbb38545d9d6ab8d96ebcdb001ed9e19db772f59..a8b9199259342df9cafb84be53010eb2206ebece 100644 (file)
@@ -110,9 +110,10 @@ int pmdp_clear_flush_young(struct vm_area_struct *vma,
 pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address,
                       pte_t *ptep)
 {
+       struct mm_struct *mm = (vma)->vm_mm;
        pte_t pte;
-       pte = ptep_get_and_clear((vma)->vm_mm, address, ptep);
-       if (pte_accessible(pte))
+       pte = ptep_get_and_clear(mm, address, ptep);
+       if (pte_accessible(mm, pte))
                flush_tlb_page(vma, address);
        return pte;
 }
@@ -191,6 +192,9 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                     pmd_t *pmdp)
 {
+       pmd_t entry = *pmdp;
+       if (pmd_numa(entry))
+               entry = pmd_mknonnuma(entry);
        set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(*pmdp));
        flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
 }
index 55c8b8dc9ffb0c349eb63ad20a8d7bbcc2e9b25d..068522d8502a58e9465a963e68c37ce4ccf635d7 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -600,7 +600,11 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
        spinlock_t *ptl;
 
        if (unlikely(PageHuge(page))) {
+               /* when pud is not present, pte will be NULL */
                pte = huge_pte_offset(mm, address);
+               if (!pte)
+                       return NULL;
+
                ptl = huge_pte_lockptr(page_hstate(page), mm, pte);
                goto check;
        }
index 8297623fcaedec21b37b5080d376967e673afe92..902a14842b74a6efe5a0de23f965e8a2a9dad820 100644 (file)
@@ -2918,13 +2918,8 @@ static struct dentry_operations anon_ops = {
        .d_dname = simple_dname
 };
 
-/**
- * shmem_file_setup - get an unlinked file living in tmpfs
- * @name: name for dentry (to be seen in /proc/<pid>/maps
- * @size: size to be set for the file
- * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
- */
-struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+static struct file *__shmem_file_setup(const char *name, loff_t size,
+                                      unsigned long flags, unsigned int i_flags)
 {
        struct file *res;
        struct inode *inode;
@@ -2957,6 +2952,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
        if (!inode)
                goto put_dentry;
 
+       inode->i_flags |= i_flags;
        d_instantiate(path.dentry, inode);
        inode->i_size = size;
        clear_nlink(inode);     /* It is unlinked */
@@ -2977,6 +2973,32 @@ put_memory:
        shmem_unacct_size(flags, size);
        return res;
 }
+
+/**
+ * shmem_kernel_file_setup - get an unlinked file living in tmpfs which must be
+ *     kernel internal.  There will be NO LSM permission checks against the
+ *     underlying inode.  So users of this interface must do LSM checks at a
+ *     higher layer.  The one user is the big_key implementation.  LSM checks
+ *     are provided at the key level rather than the inode level.
+ * @name: name for dentry (to be seen in /proc/<pid>/maps
+ * @size: size to be set for the file
+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
+ */
+struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags)
+{
+       return __shmem_file_setup(name, size, flags, S_PRIVATE);
+}
+
+/**
+ * shmem_file_setup - get an unlinked file living in tmpfs
+ * @name: name for dentry (to be seen in /proc/<pid>/maps
+ * @size: size to be set for the file
+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
+ */
+struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+{
+       return __shmem_file_setup(name, size, flags, 0);
+}
 EXPORT_SYMBOL_GPL(shmem_file_setup);
 
 /**
index f7bc2096071cb925bc0e46d83d8156d38179dd0f..808f375648e77b6c1057aeee2c6d19ea26af981e 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -390,7 +390,10 @@ struct address_space *page_mapping(struct page *page)
 {
        struct address_space *mapping = page->mapping;
 
-       VM_BUG_ON(PageSlab(page));
+       /* This happens if someone calls flush_dcache_page on slab page */
+       if (unlikely(PageSlab(page)))
+               return NULL;
+
        if (unlikely(PageSwapCache(page))) {
                swp_entry_t entry;
 
index 762896ebfcf505348a659c83d8720b48e8b58c86..47c908f1f626a4d4a2de96b9f4a648ad386d4357 100644 (file)
@@ -530,6 +530,23 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
+static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev,
+                                    unsigned short type,
+                                    const void *daddr, const void *saddr,
+                                    unsigned int len)
+{
+       struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+       struct net_device *real_dev = vlan->real_dev;
+
+       return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
+}
+
+static const struct header_ops vlan_passthru_header_ops = {
+       .create  = vlan_passthru_hard_header,
+       .rebuild = dev_rebuild_header,
+       .parse   = eth_header_parse,
+};
+
 static struct device_type vlan_type = {
        .name   = "vlan",
 };
@@ -573,7 +590,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->needed_headroom = real_dev->needed_headroom;
        if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
-               dev->header_ops      = real_dev->header_ops;
+               dev->header_ops      = &vlan_passthru_header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
        } else {
                dev->header_ops      = &vlan_header_ops;
index a2b480a908723a37d47d14bd76e63628518e6561..b9c8a6eedf4537e4216f09e65f71ef72a55d4ed3 100644 (file)
@@ -307,9 +307,9 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
-       batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
-       batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
-       batadv_ogm_packet->header.ttl = 2;
+       batadv_ogm_packet->packet_type = BATADV_IV_OGM;
+       batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
+       batadv_ogm_packet->ttl = 2;
        batadv_ogm_packet->flags = BATADV_NO_FLAGS;
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
@@ -346,7 +346,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
-       batadv_ogm_packet->header.ttl = BATADV_TTL;
+       batadv_ogm_packet->ttl = BATADV_TTL;
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -435,7 +435,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
                           fwd_str, (packet_num > 0 ? "aggregated " : ""),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->tq, batadv_ogm_packet->ttl,
                           (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
                            "on" : "off"),
                           hard_iface->net_dev->name,
@@ -491,7 +491,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
        /* multihomed peer assumed
         * non-primary OGMs are only broadcasted on their interface
         */
-       if ((directlink && (batadv_ogm_packet->header.ttl == 1)) ||
+       if ((directlink && (batadv_ogm_packet->ttl == 1)) ||
            (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
                /* FIXME: what about aggregated packets ? */
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -499,7 +499,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
                           (forw_packet->own ? "Sending own" : "Forwarding"),
                           batadv_ogm_packet->orig,
                           ntohl(batadv_ogm_packet->seqno),
-                          batadv_ogm_packet->header.ttl,
+                          batadv_ogm_packet->ttl,
                           forw_packet->if_incoming->net_dev->name,
                           forw_packet->if_incoming->net_dev->dev_addr);
 
@@ -572,7 +572,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 */
                if ((!directlink) &&
                    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
-                   (batadv_ogm_packet->header.ttl != 1) &&
+                   (batadv_ogm_packet->ttl != 1) &&
 
                    /* own packets originating non-primary
                     * interfaces leave only that interface
@@ -587,7 +587,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
                 * interface only - we still can aggregate
                 */
                if ((directlink) &&
-                   (new_bat_ogm_packet->header.ttl == 1) &&
+                   (new_bat_ogm_packet->ttl == 1) &&
                    (forw_packet->if_incoming == if_incoming) &&
 
                    /* packets from direct neighbors or
@@ -778,7 +778,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
        uint16_t tvlv_len;
 
-       if (batadv_ogm_packet->header.ttl <= 1) {
+       if (batadv_ogm_packet->ttl <= 1) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
                return;
        }
@@ -798,7 +798,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
 
-       batadv_ogm_packet->header.ttl--;
+       batadv_ogm_packet->ttl--;
        memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
 
        /* apply hop penalty */
@@ -807,7 +807,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                   "Forwarding packet: tq: %i, ttl: %i\n",
-                  batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl);
+                  batadv_ogm_packet->tq, batadv_ogm_packet->ttl);
 
        /* switch of primaries first hop flag when forwarding */
        batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
@@ -972,8 +972,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);
 
        if (dup_status == BATADV_NO_DUP) {
-               orig_node->last_ttl = batadv_ogm_packet->header.ttl;
-               neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
+               orig_node->last_ttl = batadv_ogm_packet->ttl;
+               neigh_node->last_ttl = batadv_ogm_packet->ttl;
        }
 
        batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
@@ -1247,7 +1247,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * packet in an aggregation.  Here we expect that the padding
         * is always zero (or not 0x01)
         */
-       if (batadv_ogm_packet->header.packet_type != BATADV_IV_OGM)
+       if (batadv_ogm_packet->packet_type != BATADV_IV_OGM)
                return;
 
        /* could be changed by schedule_own_packet() */
@@ -1267,8 +1267,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                   if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
                   batadv_ogm_packet->prev_sender,
                   ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
-                  batadv_ogm_packet->header.ttl,
-                  batadv_ogm_packet->header.version, has_directlink_flag);
+                  batadv_ogm_packet->ttl,
+                  batadv_ogm_packet->version, has_directlink_flag);
 
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
@@ -1433,7 +1433,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
         * seqno and similar ttl as the non-duplicate
         */
        sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
-       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+       similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl;
        if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
                            (sameseq && similar_ttl)))
                batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
index 6c8c3934bd7b44bac8643683683c494e003f1ed2..b316a4cb6f147dbbafadb51cdccf687cef500373 100644 (file)
@@ -349,7 +349,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       switch (unicast_4addr_packet->u.header.packet_type) {
+       switch (unicast_4addr_packet->u.packet_type) {
        case BATADV_UNICAST:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within a UNICAST packet\n");
@@ -374,7 +374,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
                        break;
                default:
                        batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
-                                  unicast_4addr_packet->u.header.packet_type);
+                                  unicast_4addr_packet->u.packet_type);
                }
                break;
        case BATADV_BCAST:
@@ -387,7 +387,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
        default:
                batadv_dbg(BATADV_DBG_DAT, bat_priv,
                           "* encapsulated within an unknown packet type (0x%x)\n",
-                          unicast_4addr_packet->u.header.packet_type);
+                          unicast_4addr_packet->u.packet_type);
        }
 }
 
index 271d321b3a04063b4f9dfe476c7c07d9e2e50048..6ddb6145ffb564be9397728e83a4040f071c4a96 100644 (file)
@@ -355,7 +355,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
                batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
                                   skb->len + ETH_HLEN);
 
-               packet->header.ttl--;
+               packet->ttl--;
                batadv_send_skb_packet(skb, neigh_node->if_incoming,
                                       neigh_node->addr);
                ret = true;
@@ -444,9 +444,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                goto out_err;
 
        /* Create one header to be copied to all fragments */
-       frag_header.header.packet_type = BATADV_UNICAST_FRAG;
-       frag_header.header.version = BATADV_COMPAT_VERSION;
-       frag_header.header.ttl = BATADV_TTL;
+       frag_header.packet_type = BATADV_UNICAST_FRAG;
+       frag_header.version = BATADV_COMPAT_VERSION;
+       frag_header.ttl = BATADV_TTL;
        frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
        frag_header.reserved = 0;
        frag_header.no = 0;
index 29ae4efe3543e4bfc6ff013b9c97628b9e395209..130cc3217e2b0fb091dccfad6a4f41d4b0c9dbc9 100644 (file)
@@ -194,7 +194,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
                goto free_skb;
        }
 
-       if (icmp_header->header.packet_type != BATADV_ICMP) {
+       if (icmp_header->packet_type != BATADV_ICMP) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
                len = -EINVAL;
@@ -243,9 +243,9 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
 
        icmp_header->uid = socket_client->index;
 
-       if (icmp_header->header.version != BATADV_COMPAT_VERSION) {
+       if (icmp_header->version != BATADV_COMPAT_VERSION) {
                icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
-               icmp_header->header.version = BATADV_COMPAT_VERSION;
+               icmp_header->version = BATADV_COMPAT_VERSION;
                batadv_socket_add_packet(socket_client, icmp_header,
                                         packet_len);
                goto free_skb;
index c51a5e568f0a80c08beb4ded5b34b1aff8d5cfdf..faba0f61ad535da90f8cd874ce5f901f771d4fb3 100644 (file)
@@ -277,7 +277,7 @@ int batadv_max_header_len(void)
                           sizeof(struct batadv_coded_packet));
 #endif
 
-       return header_len;
+       return header_len + ETH_HLEN;
 }
 
 /**
@@ -383,17 +383,17 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 
        batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;
 
-       if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
+       if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) {
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "Drop packet: incompatible batman version (%i)\n",
-                          batadv_ogm_packet->header.version);
+                          batadv_ogm_packet->version);
                goto err_free;
        }
 
        /* all receive handlers return whether they received or reused
         * the supplied skb. if not, we have to free the skb.
         */
-       idx = batadv_ogm_packet->header.packet_type;
+       idx = batadv_ogm_packet->packet_type;
        ret = (*batadv_rx_handler[idx])(skb, hard_iface);
 
        if (ret == NET_RX_DROP)
@@ -426,8 +426,8 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
        BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
-       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
+       BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
 
        /* broadcast packet */
        batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@ -1119,9 +1119,9 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
        skb_reserve(skb, ETH_HLEN);
        tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
        unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
-       unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
-       unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_tvlv_packet->header.ttl = BATADV_TTL;
+       unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
+       unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
+       unicast_tvlv_packet->ttl = BATADV_TTL;
        unicast_tvlv_packet->reserved = 0;
        unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
        unicast_tvlv_packet->align = 0;
index 351e199bc0afff37aa9c1a4b3f40201956dfde91..511d7e1eea38b6d6e13247df0f8d4399deea8382 100644 (file)
@@ -722,7 +722,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv,
 {
        if (orig_node->last_real_seqno != ntohl(ogm_packet->seqno))
                return false;
-       if (orig_node->last_ttl != ogm_packet->header.ttl + 1)
+       if (orig_node->last_ttl != ogm_packet->ttl + 1)
                return false;
        if (!batadv_compare_eth(ogm_packet->orig, ogm_packet->prev_sender))
                return false;
@@ -1082,9 +1082,9 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        coded_packet = (struct batadv_coded_packet *)skb_dest->data;
        skb_reset_mac_header(skb_dest);
 
-       coded_packet->header.packet_type = BATADV_CODED;
-       coded_packet->header.version = BATADV_COMPAT_VERSION;
-       coded_packet->header.ttl = packet1->header.ttl;
+       coded_packet->packet_type = BATADV_CODED;
+       coded_packet->version = BATADV_COMPAT_VERSION;
+       coded_packet->ttl = packet1->ttl;
 
        /* Info about first unicast packet */
        memcpy(coded_packet->first_source, first_source, ETH_ALEN);
@@ -1097,7 +1097,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv,
        memcpy(coded_packet->second_source, second_source, ETH_ALEN);
        memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN);
        coded_packet->second_crc = packet_id2;
-       coded_packet->second_ttl = packet2->header.ttl;
+       coded_packet->second_ttl = packet2->ttl;
        coded_packet->second_ttvn = packet2->ttvn;
        coded_packet->coded_len = htons(coding_len);
 
@@ -1452,7 +1452,7 @@ bool batadv_nc_skb_forward(struct sk_buff *skb,
        /* We only handle unicast packets */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Try to find a coding opportunity and send the skb if one is found */
@@ -1505,7 +1505,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv,
        /* Check for supported packet type */
        payload = skb_network_header(skb);
        packet = (struct batadv_unicast_packet *)payload;
-       if (packet->header.packet_type != BATADV_UNICAST)
+       if (packet->packet_type != BATADV_UNICAST)
                goto out;
 
        /* Find existing nc_path or create a new */
@@ -1623,7 +1623,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
                ttvn = coded_packet_tmp.second_ttvn;
        } else {
                orig_dest = coded_packet_tmp.first_orig_dest;
-               ttl = coded_packet_tmp.header.ttl;
+               ttl = coded_packet_tmp.ttl;
                ttvn = coded_packet_tmp.first_ttvn;
        }
 
@@ -1648,9 +1648,9 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
 
        /* Create decoded unicast packet */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.packet_type = BATADV_UNICAST;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
-       unicast_packet->header.ttl = ttl;
+       unicast_packet->packet_type = BATADV_UNICAST;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
+       unicast_packet->ttl = ttl;
        memcpy(unicast_packet->dest, orig_dest, ETH_ALEN);
        unicast_packet->ttvn = ttvn;
 
index 207459b62966d0975bca70894fcf5ce266a5da29..2dd8f2422550c3157112eb4ce5a27362e6caf8fb 100644 (file)
@@ -155,6 +155,7 @@ enum batadv_tvlv_type {
        BATADV_TVLV_ROAM        = 0x05,
 };
 
+#pragma pack(2)
 /* the destination hardware field in the ARP frame is used to
  * transport the claim type and the group id
  */
@@ -163,24 +164,20 @@ struct batadv_bla_claim_dst {
        uint8_t type;           /* bla_claimframe */
        __be16 group;           /* group id */
 };
-
-struct batadv_header {
-       uint8_t  packet_type;
-       uint8_t  version;  /* batman version field */
-       uint8_t  ttl;
-       /* the parent struct has to add a byte after the header to make
-        * everything 4 bytes aligned again
-        */
-};
+#pragma pack()
 
 /**
  * struct batadv_ogm_packet - ogm (routing protocol) packet
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @flags: contains routing relevant flags - see enum batadv_iv_flags
  * @tvlv_len: length of tvlv data following the ogm header
  */
 struct batadv_ogm_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  flags;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -196,29 +193,51 @@ struct batadv_ogm_packet {
 #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
 
 /**
- * batadv_icmp_header - common ICMP header
- * @header: common batman header
+ * batadv_icmp_header - common members among all the ICMP packets
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @msg_type: ICMP packet type
  * @dst: address of the destination node
  * @orig: address of the source node
  * @uid: local ICMP socket identifier
+ * @align: not used - useful for alignment purposes only
+ *
+ * This structure is used for ICMP packets parsing only and it is never sent
+ * over the wire. The alignment field at the end is there to ensure that
+ * members are padded the same way as they are in real packets.
  */
 struct batadv_icmp_header {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  msg_type; /* see ICMP message types above */
        uint8_t  dst[ETH_ALEN];
        uint8_t  orig[ETH_ALEN];
        uint8_t  uid;
+       uint8_t  align[3];
 };
 
 /**
  * batadv_icmp_packet - ICMP packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @reserved: not used - useful for alignment
  * @seqno: ICMP sequence number
  */
 struct batadv_icmp_packet {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  reserved;
        __be16   seqno;
 };
@@ -227,13 +246,25 @@ struct batadv_icmp_packet {
 
 /**
  * batadv_icmp_packet_rr - ICMP RouteRecord packet
- * @icmph: common ICMP header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
  * @rr_cur: number of entries the rr array
  * @seqno: ICMP sequence number
  * @rr: route record array
  */
 struct batadv_icmp_packet_rr {
-       struct batadv_icmp_header icmph;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
+       uint8_t  msg_type; /* see ICMP message types above */
+       uint8_t  dst[ETH_ALEN];
+       uint8_t  orig[ETH_ALEN];
+       uint8_t  uid;
        uint8_t  rr_cur;
        __be16   seqno;
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
@@ -253,8 +284,18 @@ struct batadv_icmp_packet_rr {
  */
 #pragma pack(2)
 
+/**
+ * struct batadv_unicast_packet - unicast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @ttvn: translation table version number
+ * @dest: originator destination of the unicast packet
+ */
 struct batadv_unicast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;
+       uint8_t  ttl;
        uint8_t  ttvn; /* destination translation table version number */
        uint8_t  dest[ETH_ALEN];
        /* "4 bytes boundary + 2 bytes" long to make the payload after the
@@ -280,7 +321,9 @@ struct batadv_unicast_4addr_packet {
 
 /**
  * struct batadv_frag_packet - fragmented packet
- * @header: common batman packet header with type, compatversion, and ttl
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @dest: final destination used when routing fragments
  * @orig: originator of the fragment used when merging the packet
  * @no: fragment number within this sequence
@@ -289,7 +332,9 @@ struct batadv_unicast_4addr_packet {
  * @total_size: size of the merged packet
  */
 struct batadv_frag_packet {
-       struct  batadv_header header;
+       uint8_t packet_type;
+       uint8_t version;  /* batman version field */
+       uint8_t ttl;
 #if defined(__BIG_ENDIAN_BITFIELD)
        uint8_t no:4;
        uint8_t reserved:4;
@@ -305,8 +350,19 @@ struct batadv_frag_packet {
        __be16  total_size;
 };
 
+/**
+ * struct batadv_bcast_packet - broadcast packet for network payload
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
+ * @reserved: reserved byte for alignment
+ * @seqno: sequence identification
+ * @orig: originator of the broadcast packet
+ */
 struct batadv_bcast_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
@@ -315,11 +371,11 @@ struct batadv_bcast_packet {
         */
 };
 
-#pragma pack()
-
 /**
  * struct batadv_coded_packet - network coded packet
- * @header: common batman packet header and ttl of first included packet
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: Align following fields to 2-byte boundaries
  * @first_source: original source of first included packet
  * @first_orig_dest: original destinal of first included packet
@@ -334,7 +390,9 @@ struct batadv_bcast_packet {
  * @coded_len: length of network coded part of the payload
  */
 struct batadv_coded_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  first_ttvn;
        /* uint8_t  first_dest[ETH_ALEN]; - saved in mac header destination */
        uint8_t  first_source[ETH_ALEN];
@@ -349,9 +407,13 @@ struct batadv_coded_packet {
        __be16   coded_len;
 };
 
+#pragma pack()
+
 /**
  * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
- * @header: common batman packet header
+ * @packet_type: batman-adv packet type, part of the general header
+ * @version: batman-adv protocol version, part of the genereal header
+ * @ttl: time to live for this packet, part of the genereal header
  * @reserved: reserved field (for packet alignment)
  * @src: address of the source
  * @dst: address of the destination
@@ -359,7 +421,9 @@ struct batadv_coded_packet {
  * @align: 2 bytes to align the header to a 4 byte boundry
  */
 struct batadv_unicast_tvlv_packet {
-       struct batadv_header header;
+       uint8_t  packet_type;
+       uint8_t  version;  /* batman version field */
+       uint8_t  ttl;
        uint8_t  reserved;
        uint8_t  dst[ETH_ALEN];
        uint8_t  src[ETH_ALEN];
@@ -420,13 +484,13 @@ struct batadv_tvlv_tt_vlan_data {
  * struct batadv_tvlv_tt_change - translation table diff data
  * @flags: status indicators concerning the non-mesh client (see
  *  batadv_tt_client_flags)
- * @reserved: reserved field
+ * @reserved: reserved field - useful for alignment purposes only
  * @addr: mac address of non-mesh client that triggered this tt change
  * @vid: VLAN identifier
  */
 struct batadv_tvlv_tt_change {
        uint8_t flags;
-       uint8_t reserved;
+       uint8_t reserved[3];
        uint8_t addr[ETH_ALEN];
        __be16 vid;
 };
index d4114d775ad61f659b59437c67aa7054d9a88f92..46278bfb8fdb9469e12f8fbdc8922e49f81f8014 100644 (file)
@@ -308,7 +308,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
                memcpy(icmph->dst, icmph->orig, ETH_ALEN);
                memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
                icmph->msg_type = BATADV_ECHO_REPLY;
-               icmph->header.ttl = BATADV_TTL;
+               icmph->ttl = BATADV_TTL;
 
                res = batadv_send_skb_to_orig(skb, orig_node, NULL);
                if (res != NET_XMIT_DROP)
@@ -338,9 +338,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
        /* send TTL exceeded if packet is an echo request (traceroute) */
-       if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
+       if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
                pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
-                        icmp_packet->icmph.orig, icmp_packet->icmph.dst);
+                        icmp_packet->orig, icmp_packet->dst);
                goto out;
        }
 
@@ -349,7 +349,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
                goto out;
 
        /* get routing information */
-       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
+       orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
        if (!orig_node)
                goto out;
 
@@ -359,11 +359,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 
        icmp_packet = (struct batadv_icmp_packet *)skb->data;
 
-       memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
-       memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+       memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+       memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr,
               ETH_ALEN);
-       icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
-       icmp_packet->icmph.header.ttl = BATADV_TTL;
+       icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
+       icmp_packet->ttl = BATADV_TTL;
 
        if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
                ret = NET_RX_SUCCESS;
@@ -434,7 +434,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
                return batadv_recv_my_icmp_packet(bat_priv, skb);
 
        /* TTL exceeded */
-       if (icmph->header.ttl < 2)
+       if (icmph->ttl < 2)
                return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
 
        /* get routing information */
@@ -449,7 +449,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmph = (struct batadv_icmp_header *)skb->data;
 
        /* decrement ttl */
-       icmph->header.ttl--;
+       icmph->ttl--;
 
        /* route it */
        if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -709,7 +709,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
        /* TTL exceeded */
-       if (unicast_packet->header.ttl < 2) {
+       if (unicast_packet->ttl < 2) {
                pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
                         ethhdr->h_source, unicast_packet->dest);
                goto out;
@@ -727,9 +727,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 
        /* decrement ttl */
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.ttl--;
+       unicast_packet->ttl--;
 
-       switch (unicast_packet->header.packet_type) {
+       switch (unicast_packet->packet_type) {
        case BATADV_UNICAST_4ADDR:
                hdr_len = sizeof(struct batadv_unicast_4addr_packet);
                break;
@@ -970,7 +970,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
        unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
 
-       is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+       is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
        /* the caller function should have already pulled 2 bytes */
        if (is4addr)
                hdr_size = sizeof(*unicast_4addr_packet);
@@ -1160,7 +1160,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
                goto out;
 
-       if (bcast_packet->header.ttl < 2)
+       if (bcast_packet->ttl < 2)
                goto out;
 
        orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
index c83be5ebaa285dffe64d051850e87f2fca02624b..fba4dcfcfac21b6e9c6686c30fc6ca8a1a08f3fa 100644 (file)
@@ -161,11 +161,11 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
                return false;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
+       unicast_packet->version = BATADV_COMPAT_VERSION;
        /* batman packet type: unicast */
-       unicast_packet->header.packet_type = BATADV_UNICAST;
+       unicast_packet->packet_type = BATADV_UNICAST;
        /* set unicast ttl */
-       unicast_packet->header.ttl = BATADV_TTL;
+       unicast_packet->ttl = BATADV_TTL;
        /* copy the destination for faster routing */
        memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
        /* set the destination tt version number */
@@ -221,7 +221,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
                goto out;
 
        uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
-       uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+       uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR;
        memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
        uc_4addr_packet->subtype = packet_subtype;
        uc_4addr_packet->reserved = 0;
@@ -436,7 +436,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
 
        /* as we have a copy now, it is safe to decrease the TTL */
        bcast_packet = (struct batadv_bcast_packet *)newskb->data;
-       bcast_packet->header.ttl--;
+       bcast_packet->ttl--;
 
        skb_reset_mac_header(newskb);
 
index 36f050876f8260245a008de079cf0974fa97b76e..a8f99d1486c0441e9aa192e81d7522ad451f4bd7 100644 (file)
@@ -264,11 +264,11 @@ static int batadv_interface_tx(struct sk_buff *skb,
                        goto dropped;
 
                bcast_packet = (struct batadv_bcast_packet *)skb->data;
-               bcast_packet->header.version = BATADV_COMPAT_VERSION;
-               bcast_packet->header.ttl = BATADV_TTL;
+               bcast_packet->version = BATADV_COMPAT_VERSION;
+               bcast_packet->ttl = BATADV_TTL;
 
                /* batman packet type: broadcast */
-               bcast_packet->header.packet_type = BATADV_BCAST;
+               bcast_packet->packet_type = BATADV_BCAST;
                bcast_packet->reserved = 0;
 
                /* hw address of first interface is the orig mac because only
@@ -328,7 +328,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
                         struct sk_buff *skb, struct batadv_hard_iface *recv_if,
                         int hdr_size, struct batadv_orig_node *orig_node)
 {
-       struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
+       struct batadv_bcast_packet *batadv_bcast_packet;
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
        __be16 ethertype = htons(ETH_P_BATMAN);
        struct vlan_ethhdr *vhdr;
@@ -336,7 +336,8 @@ void batadv_interface_rx(struct net_device *soft_iface,
        unsigned short vid;
        bool is_bcast;
 
-       is_bcast = (batadv_header->packet_type == BATADV_BCAST);
+       batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
+       is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
 
        /* check if enough space is available for pulling, and pull */
        if (!pskb_may_pull(skb, hdr_size))
@@ -345,7 +346,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
-       vid = batadv_get_vid(skb, hdr_size);
+       /* clean the netfilter state now that the batman-adv header has been
+        * removed
+        */
+       nf_reset(skb);
+
+       vid = batadv_get_vid(skb, 0);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
index 4add57d4857f11e5ea9edfa13aae1f46dab3e4f9..ff625fedbc5eeb08a7569c01973f5eb1ddc71eb1 100644 (file)
@@ -333,7 +333,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
                return;
 
        tt_change_node->change.flags = flags;
-       tt_change_node->change.reserved = 0;
+       memset(tt_change_node->change.reserved, 0,
+              sizeof(tt_change_node->change.reserved));
        memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
        tt_change_node->change.vid = htons(common->vid);
 
@@ -2221,7 +2222,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
                               ETH_ALEN);
                        tt_change->flags = tt_common_entry->flags;
                        tt_change->vid = htons(tt_common_entry->vid);
-                       tt_change->reserved = 0;
+                       memset(tt_change->reserved, 0,
+                              sizeof(tt_change->reserved));
 
                        tt_num_entries++;
                        tt_change++;
index 6a6c8bb4fd72d4f2d4294b9f7fed772d81e57b93..7552f9e3089ce790040268f1ce0a067d6ef728cb 100644 (file)
@@ -940,8 +940,22 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        bt_cb(skb)->pkt_type = *((unsigned char *) skb->data);
        skb_pull(skb, 1);
 
-       if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
-           bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+       if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+               /* No permission check is needed for user channel
+                * since that gets enforced when binding the socket.
+                *
+                * However check that the packet type is valid.
+                */
+               if (bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
+                       err = -EINVAL;
+                       goto drop;
+               }
+
+               skb_queue_tail(&hdev->raw_q, skb);
+               queue_work(hdev->workqueue, &hdev->tx_work);
+       } else if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
                u16 opcode = get_unaligned_le16(skb->data);
                u16 ogf = hci_opcode_ogf(opcode);
                u16 ocf = hci_opcode_ocf(opcode);
@@ -972,14 +986,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                        goto drop;
                }
 
-               if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
-                   bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
-                   bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
-                       err = -EINVAL;
-                       goto drop;
-               }
-
                skb_queue_tail(&hdev->raw_q, skb);
                queue_work(hdev->workqueue, &hdev->tx_work);
        }
index 4c214b2b88efa01d81be93a8b8d77e57229c1fa4..ef66365b7354da9f2fe2c4d87d2056d9a781f3c8 100644 (file)
@@ -1998,7 +1998,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (!netif_running(br->dev))
                goto unlock;
 
@@ -2030,7 +2030,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
index 229d820bdf0b06453cb43058020d54e33f210297..045d56eaeca2b777973bf1450d7b410a09d2d9f1 100644 (file)
@@ -426,6 +426,16 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
 int br_handle_frame_finish(struct sk_buff *skb);
 rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
 
+static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
+{
+       return rcu_dereference(dev->rx_handler) == br_handle_frame;
+}
+
+static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev)
+{
+       return br_rx_handler_check_rcu(dev) ? br_port_get_rcu(dev) : NULL;
+}
+
 /* br_ioctl.c */
 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd,
index 8660ea3be7054571defa59bcfbfc0cd0dd7ab99e..bdb459d21ad8e2d5191023c5b096de39b6a78c90 100644 (file)
@@ -153,7 +153,7 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
        if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0)
                goto err;
 
-       p = br_port_get_rcu(dev);
+       p = br_port_get_check_rcu(dev);
        if (!p)
                goto err;
 
index 618c6a8a911b65c9a406ba5d7d0e221cb124960e..dd32e34c1e2c9481aa2db3c37437ef0d85ba5277 100644 (file)
@@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
            __get_user(kmsg->msg_flags, &umsg->msg_flags))
                return -EFAULT;
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-               return -EINVAL;
+               kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        kmsg->msg_name = compat_ptr(tmp1);
        kmsg->msg_iov = compat_ptr(tmp2);
        kmsg->msg_control = compat_ptr(tmp3);
index ba3b7ea5ebb3139cca38e82ac6f5f5e346f4a4e0..0ce469e5ec8057c674901b404db13061fe8b7392 100644 (file)
@@ -2539,7 +2539,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
 }
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv)
+                       struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
        int rc = NETDEV_TX_OK;
@@ -2605,13 +2605,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        dev_queue_xmit_nit(skb, dev);
 
                skb_len = skb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
-               else
                        rc = ops->ndo_start_xmit(skb, dev);
 
                trace_net_dev_xmit(skb, rc, dev, skb_len);
-               if (rc == NETDEV_TX_OK && txq)
+               if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
        }
@@ -2627,10 +2624,7 @@ gso:
                        dev_queue_xmit_nit(nskb, dev);
 
                skb_len = nskb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
-               else
-                       rc = ops->ndo_start_xmit(nskb, dev);
+               rc = ops->ndo_start_xmit(nskb, dev);
                trace_net_dev_xmit(nskb, rc, dev, skb_len);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
@@ -2811,7 +2805,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)
+int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 {
        struct net_device *dev = skb->dev;
        struct netdev_queue *txq;
@@ -2827,7 +2821,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
        skb_update_prio(skb);
 
-       txq = netdev_pick_tx(dev, skb);
+       txq = netdev_pick_tx(dev, skb, accel_priv);
        q = rcu_dereference_bh(txq->qdisc);
 
 #ifdef CONFIG_NET_CLS_ACT
@@ -2863,7 +2857,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                        if (!netif_xmit_stopped(txq)) {
                                __this_cpu_inc(xmit_recursion);
-                               rc = dev_hard_start_xmit(skb, dev, txq, NULL);
+                               rc = dev_hard_start_xmit(skb, dev, txq);
                                __this_cpu_dec(xmit_recursion);
                                if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
@@ -2892,8 +2886,19 @@ out:
        rcu_read_unlock_bh();
        return rc;
 }
+
+int dev_queue_xmit(struct sk_buff *skb)
+{
+       return __dev_queue_xmit(skb, NULL);
+}
 EXPORT_SYMBOL(dev_queue_xmit);
 
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
+{
+       return __dev_queue_xmit(skb, accel_priv);
+}
+EXPORT_SYMBOL(dev_queue_xmit_accel);
+
 
 /*=======================================================================
                        Receiver routines
@@ -4500,7 +4505,7 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 {
        struct netdev_adjacent *upper;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
 
        upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
 
index 95897183226e18882bdbe16d8e9ba3a111ffae71..e70301eb7a4a0472d1ade5bd3d318fe453bd2b8b 100644 (file)
@@ -64,7 +64,6 @@ static struct genl_family net_drop_monitor_family = {
        .hdrsize        = 0,
        .name           = "NET_DM",
        .version        = 2,
-       .maxattr        = NET_DM_CMD_MAX,
 };
 
 static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data);
index 01b780856db29e5a2a7ebbc36aa7062340b28bb8..ad30d626a5bd3f5cbd585d0641ab79aa29c3c446 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/filter.h>
-#include <linux/reciprocal_div.h>
 #include <linux/ratelimit.h>
 #include <linux/seccomp.h>
 #include <linux/if_vlan.h>
@@ -166,7 +165,7 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
                        A /= X;
                        continue;
                case BPF_S_ALU_DIV_K:
-                       A = reciprocal_divide(A, K);
+                       A /= K;
                        continue;
                case BPF_S_ALU_MOD_X:
                        if (X == 0)
@@ -553,11 +552,6 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
                /* Some instructions need special checks */
                switch (code) {
                case BPF_S_ALU_DIV_K:
-                       /* check for division by zero */
-                       if (ftest->k == 0)
-                               return -EINVAL;
-                       ftest->k = reciprocal_value(ftest->k);
-                       break;
                case BPF_S_ALU_MOD_K:
                        /* check for division by zero */
                        if (ftest->k == 0)
@@ -853,27 +847,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
        to->code = decodes[code];
        to->jt = filt->jt;
        to->jf = filt->jf;
-
-       if (code == BPF_S_ALU_DIV_K) {
-               /*
-                * When loaded this rule user gave us X, which was
-                * translated into R = r(X). Now we calculate the
-                * RR = r(R) and report it back. If next time this
-                * value is loaded and RRR = r(RR) is calculated
-                * then the R == RRR will be true.
-                *
-                * One exception. X == 1 translates into R == 0 and
-                * we can't calculate RR out of it with r().
-                */
-
-               if (filt->k == 0)
-                       to->k = 1;
-               else
-                       to->k = reciprocal_value(filt->k);
-
-               BUG_ON(reciprocal_value(to->k) != filt->k);
-       } else
-               to->k = filt->k;
+       to->k = filt->k;
 }
 
 int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)
index d6ef173225008ec1946ed232f781cc63754b9575..2fc5beaf578349cd543621a460bf2bb4eaa9d221 100644 (file)
@@ -395,17 +395,21 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
 EXPORT_SYMBOL(__netdev_pick_tx);
 
 struct netdev_queue *netdev_pick_tx(struct net_device *dev,
-                                   struct sk_buff *skb)
+                                   struct sk_buff *skb,
+                                   void *accel_priv)
 {
        int queue_index = 0;
 
        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);
+                       queue_index = ops->ndo_select_queue(dev, skb,
+                                                           accel_priv);
                else
                        queue_index = __netdev_pick_tx(dev, skb);
-               queue_index = dev_cap_txqueue(dev, queue_index);
+
+               if (!accel_priv)
+                       queue_index = dev_cap_txqueue(dev, queue_index);
        }
 
        skb_set_queue_mapping(skb, queue_index);
index ca15f32821fb8d536586354108488050b7cc6a0e..932c6d7cf6668e073a90432281037b51cf7dfecc 100644 (file)
@@ -1161,6 +1161,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                                                 neigh->parms->reachable_time :
                                                 0)));
                neigh->nud_state = new;
+               notify = 1;
        }
 
        if (lladdr != neigh->ha) {
@@ -1274,7 +1275,7 @@ int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
 
        if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
                            skb->len) < 0 &&
-           dev->header_ops->rebuild(skb))
+           dev_rebuild_header(skb))
                return 0;
 
        return dev_queue_xmit(skb);
index 8f971990677cd48026f651b2dba01d01190bfff6..19fe9c717cedb56051ff6cb5effca0274fd946d8 100644 (file)
@@ -375,7 +375,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
        if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {
                struct netdev_queue *txq;
 
-               txq = netdev_pick_tx(dev, skb);
+               txq = netdev_pick_tx(dev, skb, NULL);
 
                /* try until next clock tick */
                for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
@@ -386,8 +386,14 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                            !vlan_hw_offload_capable(netif_skb_features(skb),
                                                                     skb->vlan_proto)) {
                                                skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb));
-                                               if (unlikely(!skb))
-                                                       break;
+                                               if (unlikely(!skb)) {
+                                                       /* This is actually a packet drop, but we
+                                                        * don't want the code at the end of this
+                                                        * function to try and re-queue a NULL skb.
+                                                        */
+                                                       status = NETDEV_TX_OK;
+                                                       goto unlock_txq;
+                                               }
                                                skb->vlan_tci = 0;
                                        }
 
@@ -395,6 +401,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
                                        if (status == NETDEV_TX_OK)
                                                txq_trans_update(txq);
                                }
+                       unlock_txq:
                                __netif_tx_unlock(txq);
 
                                if (status == NETDEV_TX_OK)
index 261357a663001ccf98a92ba5f6d0f6ad141c7ce3..a797fff7f22213f3e5d1be6f97ab632a791079a4 100644 (file)
@@ -2527,6 +2527,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
                if (x) {
                        int ret;
                        __u8 *eth;
+                       struct iphdr *iph;
+
                        nhead = x->props.header_len - skb_headroom(skb);
                        if (nhead > 0) {
                                ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
@@ -2548,6 +2550,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
                        eth = (__u8 *) skb_push(skb, ETH_HLEN);
                        memcpy(eth, pkt_dev->hh, 12);
                        *(u16 *) &eth[12] = protocol;
+
+                       /* Update IPv4 header len as well as checksum value */
+                       iph = ip_hdr(skb);
+                       iph->tot_len = htons(skb->len - ETH_HLEN);
+                       ip_send_check(iph);
                }
        }
        return 1;
index 2718fed53d8cf5b81a06c82f8cdf8ed96632185a..06e72d3cdf60dbd96a3ad4829cfcc2baec0a80e8 100644 (file)
@@ -3584,6 +3584,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
        skb->skb_iif = 0;
+       skb->local_df = 0;
        skb_dst_drop(skb);
        skb->mark = 0;
        secpath_reset(skb);
index ab20ed9b0f31da64cb118cf645fa88f5787b5571..5393b4b719d71de2e3126664e3dcd5882c0c99d9 100644 (file)
@@ -882,7 +882,7 @@ set_rcvbuf:
 
        case SO_PEEK_OFF:
                if (sock->ops->set_peek_off)
-                       sock->ops->set_peek_off(sk, val);
+                       ret = sock->ops->set_peek_off(sk, val);
                else
                        ret = -EOPNOTSUPP;
                break;
index 4ac71ff7c2e47c4a3bcec19206845c8afd7ce9e8..2b90a786e475f78ab7084765bfeedc608632255a 100644 (file)
@@ -851,7 +851,6 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
index 4c6bdf97a6577d190332b85654769a92ce553111..595ddf0459db79c724b8eab2c8b0f6a0a7d1df97 100644 (file)
@@ -152,17 +152,6 @@ static const struct file_operations dccpprobe_fops = {
        .llseek  = noop_llseek,
 };
 
-static __init int setup_jprobe(void)
-{
-       int ret = register_jprobe(&dccp_send_probe);
-
-       if (ret) {
-               request_module("dccp");
-               ret = register_jprobe(&dccp_send_probe);
-       }
-       return ret;
-}
-
 static __init int dccpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -174,7 +163,13 @@ static __init int dccpprobe_init(void)
        if (!proc_create(procname, S_IRUSR, init_net.proc_net, &dccpprobe_fops))
                goto err0;
 
-       ret = setup_jprobe();
+       ret = register_jprobe(&dccp_send_probe);
+       if (ret) {
+               ret = request_module("dccp");
+               if (!ret)
+                       ret = register_jprobe(&dccp_send_probe);
+       }
+
        if (ret)
                goto err1;
 
index 003f5bb3acd25f4dc696255c56ac1985eae58a62..4bdab152187826f364f0acff43dca1db8d0dc938 100644 (file)
@@ -288,7 +288,8 @@ void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr,
 static bool seq_nr_after(u16 a, u16 b)
 {
        /* Remove inconsistency where
-        * seq_nr_after(a, b) == seq_nr_before(a, b) */
+        * seq_nr_after(a, b) == seq_nr_before(a, b)
+        */
        if ((int) b - a == 32768)
                return false;
 
index 5325af85eea670f5c865367fc991eaf9b907cd98..01a5261ac7a5520230fb0d2e147ffd3cf0a930ec 100644 (file)
@@ -23,6 +23,8 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
        [IFLA_HSR_SLAVE1]               = { .type = NLA_U32 },
        [IFLA_HSR_SLAVE2]               = { .type = NLA_U32 },
        [IFLA_HSR_MULTICAST_SPEC]       = { .type = NLA_U8 },
+       [IFLA_HSR_SUPERVISION_ADDR]     = { .type = NLA_BINARY, .len = ETH_ALEN },
+       [IFLA_HSR_SEQ_NR]               = { .type = NLA_U16 },
 };
 
 
@@ -59,6 +61,31 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
        return hsr_dev_finalize(dev, link, multicast_spec);
 }
 
+static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct hsr_priv *hsr_priv;
+
+       hsr_priv = netdev_priv(dev);
+
+       if (hsr_priv->slave[0])
+               if (nla_put_u32(skb, IFLA_HSR_SLAVE1, hsr_priv->slave[0]->ifindex))
+                       goto nla_put_failure;
+
+       if (hsr_priv->slave[1])
+               if (nla_put_u32(skb, IFLA_HSR_SLAVE2, hsr_priv->slave[1]->ifindex))
+                       goto nla_put_failure;
+
+       if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN,
+                   hsr_priv->sup_multicast_addr) ||
+           nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr_priv->sequence_nr))
+               goto nla_put_failure;
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
 static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .kind           = "hsr",
        .maxtype        = IFLA_HSR_MAX,
@@ -66,6 +93,7 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .priv_size      = sizeof(struct hsr_priv),
        .setup          = hsr_dev_setup,
        .newlink        = hsr_newlink,
+       .fill_info      = hsr_fill_info,
 };
 
 
index 459e200c08a40e4e737798582524cd973064b143..a2d2456a557a7621059a5b0bbe033168492f8fe7 100644 (file)
@@ -547,7 +547,7 @@ static int lowpan_header_create(struct sk_buff *skb,
                        hc06_ptr += 3;
                } else {
                        /* compress nothing */
-                       memcpy(hc06_ptr, &hdr, 4);
+                       memcpy(hc06_ptr, hdr, 4);
                        /* replace the top byte with new ECN | DSCP format */
                        *hc06_ptr = tmp;
                        hc06_ptr += 4;
index d08c7a43dcd1c72f1512b01e8a00dd2b9e6b1869..89b265aea151eaf7f301c28f391d064b7d22edfc 100644 (file)
@@ -221,8 +221,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info)
 
        if (info->attrs[IEEE802154_ATTR_DEV_TYPE]) {
                type = nla_get_u8(info->attrs[IEEE802154_ATTR_DEV_TYPE]);
-               if (type >= __IEEE802154_DEV_MAX)
-                       return -EINVAL;
+               if (type >= __IEEE802154_DEV_MAX) {
+                       rc = -EINVAL;
+                       goto nla_put_failure;
+               }
        }
 
        dev = phy->add_iface(phy, devname, type);
index 523be38e37de82736a28bc9aa229f1911d2eaa31..f2e15738534d316ed0c50b8be2e1976fa03052c5 100644 (file)
@@ -104,7 +104,10 @@ errout:
 static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 {
        struct fib_result *result = (struct fib_result *) arg->result;
-       struct net_device *dev = result->fi->fib_dev;
+       struct net_device *dev = NULL;
+
+       if (result->fi)
+               dev = result->fi->fib_dev;
 
        /* do not accept result if the route does
         * not meet the required prefix length
index e5d436188464eba55eca773f4fb88fd0f0634e97..2cd02f32f99f568c8275389aefd754700a77efa6 100644 (file)
@@ -28,6 +28,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        netdev_features_t enc_features;
        int ghl = GRE_HEADER_SECTION;
        struct gre_base_hdr *greh;
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        __be16 protocol = skb->protocol;
        int tnl_hlen;
@@ -58,13 +59,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        } else
                csum = false;
 
+       if (unlikely(!pskb_may_pull(skb, ghl)))
+               goto out;
+
        /* setup inner skb. */
        skb->protocol = greh->protocol;
        skb->encapsulation = 0;
 
-       if (unlikely(!pskb_may_pull(skb, ghl)))
-               goto out;
-
        __skb_pull(skb, ghl);
        skb_reset_mac_header(skb);
        skb_set_network_header(skb, skb_inner_network_offset(skb));
@@ -73,8 +74,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
                goto out;
+       }
 
        skb = segs;
        tnl_hlen = skb_tnl_header_len(skb);
index 56a964a553d2c739a03b880acd7158a4c9714b66..e34dccbc4d70bd26f7cec88c031dcea31124314a 100644 (file)
@@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = inet->inet_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
@@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 
        r->idiag_family       = tw->tw_family;
        r->idiag_retrans      = 0;
+
        r->id.idiag_if        = tw->tw_bound_dev_if;
        sock_diag_save_cookie(tw, r->id.idiag_cookie);
+
        r->id.idiag_sport     = tw->tw_sport;
        r->id.idiag_dport     = tw->tw_dport;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0]    = tw->tw_rcv_saddr;
        r->id.idiag_dst[0]    = tw->tw_daddr;
+
        r->idiag_state        = tw->tw_substate;
        r->idiag_timer        = 3;
        r->idiag_expires      = jiffies_to_msecs(tmo);
@@ -726,8 +737,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
 
        r->id.idiag_sport = inet->inet_sport;
        r->id.idiag_dport = ireq->ir_rmt_port;
+
+       memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
+       memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
+
        r->id.idiag_src[0] = ireq->ir_loc_addr;
        r->id.idiag_dst[0] = ireq->ir_rmt_addr;
+
        r->idiag_expires = jiffies_to_msecs(tmo);
        r->idiag_rqueue = 0;
        r->idiag_wqueue = 0;
@@ -914,12 +930,15 @@ skip_listen_ht:
                spin_lock_bh(lock);
                sk_nulls_for_each(sk, node, &head->chain) {
                        int res;
+                       int state;
 
                        if (!net_eq(sock_net(sk), net))
                                continue;
                        if (num < s_num)
                                goto next_normal;
-                       if (!(r->idiag_states & (1 << sk->sk_state)))
+                       state = (sk->sk_state == TCP_TIME_WAIT) ?
+                               inet_twsk(sk)->tw_substate : sk->sk_state;
+                       if (!(r->idiag_states & (1 << state)))
                                goto next_normal;
                        if (r->sdiag_family != AF_UNSPEC &&
                            sk->sk_family != r->sdiag_family)
index d7aea4c5b9400efec37d15db3c5a896769d0da68..e560ef34cf4bd2efe9f1f7a64424441117a4502a 100644 (file)
@@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
                                  iph->saddr, iph->daddr, tpi->key);
 
        if (tunnel) {
+               skb_pop_mac_header(skb);
                ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error);
                return PACKET_RCVD;
        }
index 912402752f2ffce701d697de1bb7a32b05c3b482..df184616493f707ea8a0ea353a33d3a5aa981fc7 100644 (file)
@@ -828,7 +828,7 @@ static int __ip_append_data(struct sock *sk,
 
        if (cork->length + length > maxnonfragsize - fragheaderlen) {
                ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
-                              mtu-exthdrlen);
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
@@ -1151,7 +1151,8 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                         mtu : 0xFFFF;
 
        if (cork->length + size > maxnonfragsize - fragheaderlen) {
-               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu);
+               ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
+                              mtu - (opt ? opt->optlen : 0));
                return -EMSGSIZE;
        }
 
index 3f858266fa7e33a0941a135ec8a36b36278fdfce..ddf32a6bc415c28f0b9639514dd86eb11b18ce85 100644 (file)
@@ -386,7 +386,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
 /*
  *     Handle MSG_ERRQUEUE
  */
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
        struct sock_exterr_skb *serr;
        struct sk_buff *skb, *skb2;
@@ -423,6 +423,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
                                                   serr->addr_offset);
                sin->sin_port = serr->port;
                memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+               *addr_len = sizeof(*sin);
        }
 
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
index 62212c772a4b95961dafe1efce3fd06f146ccbb6..1672409f5ba5a10ea05eb20d0f472a46dee3c504 100644 (file)
@@ -157,9 +157,12 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
 static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
                           struct mr_table **mrt)
 {
-       struct ipmr_result res;
-       struct fib_lookup_arg arg = { .result = &res, };
        int err;
+       struct ipmr_result res;
+       struct fib_lookup_arg arg = {
+               .result = &res,
+               .flags = FIB_LOOKUP_NOREF,
+       };
 
        err = fib_rules_lookup(net->ipv4.mr_rules_ops,
                               flowi4_to_flowi(flp4), 0, &arg);
index f13bd91d9a56774f58dcf14de892b2bedd855cc5..a313c3fbeb469e0594b2f7bccd788d687184bc61 100644 (file)
@@ -423,6 +423,7 @@ static void synproxy_tg4_destroy(const struct xt_tgdtor_param *par)
 static struct xt_target synproxy_tg4_reg __read_mostly = {
        .name           = "SYNPROXY",
        .family         = NFPROTO_IPV4,
+       .hooks          = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
        .target         = synproxy_tg4,
        .targetsize     = sizeof(struct xt_synproxy_info),
        .checkentry     = synproxy_tg4_check,
index fff5ba1a33b76321f70d1365d072f7330d524ea9..4a5e94ac314a8cfdae20d8e393724ea2d01bd588 100644 (file)
@@ -72,7 +72,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
        const struct nft_reject *priv = nft_expr_priv(expr);
 
-       if (nla_put_be32(skb, NFTA_REJECT_TYPE, priv->type))
+       if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
                goto nla_put_failure;
 
        switch (priv->type) {
index 876c6ca2d8f9e77a28f1e629aa6523df1ee8f42f..242e7f4ed6f44ff5765966388618152e2721fa87 100644 (file)
@@ -772,7 +772,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                err = PTR_ERR(rt);
                rt = NULL;
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                goto out;
        }
 
@@ -841,10 +841,11 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        if (flags & MSG_ERRQUEUE) {
                if (family == AF_INET) {
-                       return ip_recv_error(sk, msg, len);
+                       return ip_recv_error(sk, msg, len, addr_len);
 #if IS_ENABLED(CONFIG_IPV6)
                } else if (family == AF_INET6) {
-                       return pingv6_ops.ipv6_recv_error(sk, msg, len);
+                       return pingv6_ops.ipv6_recv_error(sk, msg, len,
+                                                         addr_len);
 #endif
                }
        }
index ce848461acbb07f6b758dc900225c7aff16ac690..46d6a1c923a8741776fa1de1cdd727b6cba72294 100644 (file)
 const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
 const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
 
-/*
- *     Add a protocol handler to the hash tables
- */
-
 int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        if (!prot->netns_ok) {
@@ -55,10 +51,6 @@ int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
 }
 EXPORT_SYMBOL(inet_add_offload);
 
-/*
- *     Remove a protocol from the hash tables.
- */
-
 int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        int ret;
index 5cb8ddb505ee8911461ec92a5c74feef0b441e00..23c3e5b5bb53f9e6f40ebbe8de4afd1683f9d7e5 100644 (file)
@@ -697,7 +697,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                goto out;
 
        if (flags & MSG_ERRQUEUE) {
-               err = ip_recv_error(sk, msg, len);
+               err = ip_recv_error(sk, msg, len, addr_len);
                goto out;
        }
 
index c4638e6f023843bedbceb91f1bef3c424ad3b666..82de786036860d298d63c2184de004f69901156b 100644 (file)
@@ -1623,11 +1623,11 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                    (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
                    !sysctl_tcp_low_latency &&
                    net_dma_find_channel()) {
-                       preempt_enable_no_resched();
+                       preempt_enable();
                        tp->ucopy.pinned_list =
                                        dma_pin_iovec_pages(msg->msg_iov, len);
                } else {
-                       preempt_enable_no_resched();
+                       preempt_enable();
                }
        }
 #endif
index 59a6f8b90cd9d7c9ca51bbcd2cc424153d6571df..06721392475105fec441b2d97b3c72e6927b7e54 100644 (file)
@@ -177,7 +177,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
                return err;
        }
 
index 03e9154f7e687efef63c91878e33427672bc4036..f7e522c558ba2eb43165f85d46c2ba3a91ce42eb 100644 (file)
@@ -6,13 +6,6 @@
 #include <linux/memcontrol.h>
 #include <linux/module.h>
 
-static void memcg_tcp_enter_memory_pressure(struct sock *sk)
-{
-       if (sk->sk_cgrp->memory_pressure)
-               sk->sk_cgrp->memory_pressure = 1;
-}
-EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure);
-
 int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
 {
        /*
@@ -60,7 +53,6 @@ EXPORT_SYMBOL(tcp_destroy_cgroup);
 static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 {
        struct cg_proto *cg_proto;
-       u64 old_lim;
        int i;
        int ret;
 
@@ -71,7 +63,6 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
        if (val > RES_COUNTER_MAX)
                val = RES_COUNTER_MAX;
 
-       old_lim = res_counter_read_u64(&cg_proto->memory_allocated, RES_LIMIT);
        ret = res_counter_set_limit(&cg_proto->memory_allocated, val);
        if (ret)
                return ret;
index 06493736fbc826842876180a24510d9e348cb7f3..098b3a29f6f3a082af32af35d703bf884922ec77 100644 (file)
@@ -22,6 +22,9 @@
 
 int sysctl_tcp_nometrics_save __read_mostly;
 
+static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
+                                                  struct net *net, unsigned int hash);
+
 struct tcp_fastopen_metrics {
        u16     mss;
        u16     syn_loss:10;            /* Recurring Fast Open SYN losses */
@@ -130,16 +133,41 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
        }
 }
 
+#define TCP_METRICS_TIMEOUT            (60 * 60 * HZ)
+
+static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
+{
+       if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
+               tcpm_suck_dst(tm, dst, false);
+}
+
+#define TCP_METRICS_RECLAIM_DEPTH      5
+#define TCP_METRICS_RECLAIM_PTR                (struct tcp_metrics_block *) 0x1UL
+
 static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
                                          struct inetpeer_addr *addr,
-                                         unsigned int hash,
-                                         bool reclaim)
+                                         unsigned int hash)
 {
        struct tcp_metrics_block *tm;
        struct net *net;
+       bool reclaim = false;
 
        spin_lock_bh(&tcp_metrics_lock);
        net = dev_net(dst->dev);
+
+       /* While waiting for the spin-lock the cache might have been populated
+        * with this entry and so we have to check again.
+        */
+       tm = __tcp_get_metrics(addr, net, hash);
+       if (tm == TCP_METRICS_RECLAIM_PTR) {
+               reclaim = true;
+               tm = NULL;
+       }
+       if (tm) {
+               tcpm_check_stamp(tm, dst);
+               goto out_unlock;
+       }
+
        if (unlikely(reclaim)) {
                struct tcp_metrics_block *oldest;
 
@@ -169,17 +197,6 @@ out_unlock:
        return tm;
 }
 
-#define TCP_METRICS_TIMEOUT            (60 * 60 * HZ)
-
-static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
-{
-       if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
-               tcpm_suck_dst(tm, dst, false);
-}
-
-#define TCP_METRICS_RECLAIM_DEPTH      5
-#define TCP_METRICS_RECLAIM_PTR                (struct tcp_metrics_block *) 0x1UL
-
 static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth)
 {
        if (tm)
@@ -282,7 +299,6 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
        struct inetpeer_addr addr;
        unsigned int hash;
        struct net *net;
-       bool reclaim;
 
        addr.family = sk->sk_family;
        switch (addr.family) {
@@ -304,13 +320,10 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
        hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
 
        tm = __tcp_get_metrics(&addr, net, hash);
-       reclaim = false;
-       if (tm == TCP_METRICS_RECLAIM_PTR) {
-               reclaim = true;
+       if (tm == TCP_METRICS_RECLAIM_PTR)
                tm = NULL;
-       }
        if (!tm && create)
-               tm = tcpm_new(dst, &addr, hash, reclaim);
+               tm = tcpm_new(dst, &addr, hash);
        else
                tcpm_check_stamp(tm, dst);
 
index a2b68a108eae69170c8d915be778c9aeebf0f371..05606353c7e7cb026096acaf598a8685b84b85c9 100644 (file)
@@ -274,33 +274,32 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
 {
        const struct iphdr *iph = skb_gro_network_header(skb);
        __wsum wsum;
-       __sum16 sum;
+
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
+       wsum = skb->csum;
 
        switch (skb->ip_summed) {
+       case CHECKSUM_NONE:
+               wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
+                                   0);
+
+               /* fall through */
+
        case CHECKSUM_COMPLETE:
                if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
-                                 skb->csum)) {
+                                 wsum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-flush:
+
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
-                                         skb_gro_len(skb), IPPROTO_TCP, 0);
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 5944d7d668dd91da21e945eac748bbbbbb11d67a..a7e4729e974b3206f57e3b3da4026a77432768e1 100644 (file)
@@ -560,15 +560,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
                                                 __be16 sport, __be16 dport,
                                                 struct udp_table *udptable)
 {
-       struct sock *sk;
        const struct iphdr *iph = ip_hdr(skb);
 
-       if (unlikely(sk = skb_steal_sock(skb)))
-               return sk;
-       else
-               return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
-                                        iph->daddr, dport, inet_iif(skb),
-                                        udptable);
+       return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
+                                iph->daddr, dport, inet_iif(skb),
+                                udptable);
 }
 
 struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
@@ -999,7 +995,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        err = PTR_ERR(rt);
                        rt = NULL;
                        if (err == -ENETUNREACH)
-                               IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                               IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                        goto out;
                }
 
@@ -1098,6 +1094,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
        struct udp_sock *up = udp_sk(sk);
        int ret;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        if (!up->pending) {
                struct msghdr msg = {   .msg_flags = flags|MSG_MORE };
 
@@ -1236,7 +1235,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        bool slow;
 
        if (flags & MSG_ERRQUEUE)
-               return ip_recv_error(sk, msg, len);
+               return ip_recv_error(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1600,12 +1599,16 @@ static void flush_stack(struct sock **stack, unsigned int count,
                kfree_skb(skb1);
 }
 
-static void udp_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
+/* For TCP sockets, sk_rx_dst is protected by socket lock
+ * For UDP, we use xchg() to guard against concurrent changes.
+ */
+static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
 {
-       struct dst_entry *dst = skb_dst(skb);
+       struct dst_entry *old;
 
        dst_hold(dst);
-       sk->sk_rx_dst = dst;
+       old = xchg(&sk->sk_rx_dst, dst);
+       dst_release(old);
 }
 
 /*
@@ -1736,15 +1739,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (udp4_csum_init(skb, uh, proto))
                goto csum_error;
 
-       if (skb->sk) {
+       sk = skb_steal_sock(skb);
+       if (sk) {
+               struct dst_entry *dst = skb_dst(skb);
                int ret;
-               sk = skb->sk;
 
-               if (unlikely(sk->sk_rx_dst == NULL))
-                       udp_sk_rx_dst_set(sk, skb);
+               if (unlikely(sk->sk_rx_dst != dst))
+                       udp_sk_rx_dst_set(sk, dst);
 
                ret = udp_queue_rcv_skb(sk, skb);
-
+               sock_put(sk);
                /* a return value > 0 means to resubmit the input, but
                 * it wants the return to be -protocol, or 0
                 */
@@ -1910,17 +1914,20 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
 
 void udp_v4_early_demux(struct sk_buff *skb)
 {
-       const struct iphdr *iph = ip_hdr(skb);
-       const struct udphdr *uh = udp_hdr(skb);
+       struct net *net = dev_net(skb->dev);
+       const struct iphdr *iph;
+       const struct udphdr *uh;
        struct sock *sk;
        struct dst_entry *dst;
-       struct net *net = dev_net(skb->dev);
        int dif = skb->dev->ifindex;
 
        /* validate the packet */
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
                return;
 
+       iph = ip_hdr(skb);
+       uh = udp_hdr(skb);
+
        if (skb->pkt_type == PACKET_BROADCAST ||
            skb->pkt_type == PACKET_MULTICAST)
                sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
@@ -2471,6 +2478,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
                                       netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
+       u16 mac_offset = skb->mac_header;
        int mac_len = skb->mac_len;
        int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
        __be16 protocol = skb->protocol;
@@ -2490,8 +2498,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
        /* segment inner packet. */
        enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
        segs = skb_mac_gso_segment(skb, enc_features);
-       if (!segs || IS_ERR(segs))
+       if (!segs || IS_ERR(segs)) {
+               skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
+                                    mac_len);
                goto out;
+       }
 
        outer_hlen = skb_tnl_header_len(skb);
        skb = segs;
index 83206de2bc7679dc20e4fdcf34f8b1f5cd7831ef..79c62bdcd3c549b7dc07c74449d30b77296134eb 100644 (file)
@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
+       int offset;
+       __wsum csum;
+
+       if (skb->encapsulation &&
+           skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) {
+               segs = skb_udp_tunnel_segment(skb, features);
+               goto out;
+       }
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
                goto out;
        }
 
+       /* Do software UFO. Complete and fill in the UDP checksum as
+        * HW cannot do checksum of UDP packets sent as multiple
+        * IP fragments.
+        */
+       offset = skb_checksum_start_offset(skb);
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+       offset += skb->csum_offset;
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+       skb->ip_summed = CHECKSUM_NONE;
+
        /* Fragment the skb. IP headers of the fragments are updated in
         * inet_gso_segment()
         */
-       if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
-               segs = skb_udp_tunnel_segment(skb, features);
-       else {
-               int offset;
-               __wsum csum;
-
-               /* Do software UFO. Complete and fill in the UDP checksum as
-                * HW cannot do checksum of UDP packets sent as multiple
-                * IP fragments.
-                */
-               offset = skb_checksum_start_offset(skb);
-               csum = skb_checksum(skb, offset, skb->len - offset, 0);
-               offset += skb->csum_offset;
-               *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-               skb->ip_summed = CHECKSUM_NONE;
-
-               segs = skb_segment(skb, features);
-       }
+       segs = skb_segment(skb, features);
 out:
        return segs;
 }
index 12c97d8aa6bbb31ff1519459b89b7b9fb33817f5..4b6b720971b9294910280c6ebd9d46a34ea07e35 100644 (file)
@@ -1671,7 +1671,7 @@ 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;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -1682,7 +1682,7 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
-       if (ifp->prefix_len == 127) /* RFC 6164 */
+       if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
        if (ipv6_addr_any(&addr))
@@ -2509,7 +2509,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        struct inet6_ifaddr *ifp;
 
        ifp = ipv6_add_addr(idev, addr, NULL, plen,
-                           scope, IFA_F_PERMANENT, 0, 0);
+                           scope, IFA_F_PERMANENT,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                spin_lock_bh(&ifp->lock);
                ifp->flags &= ~IFA_F_TENTATIVE;
@@ -2613,7 +2614,7 @@ static void init_loopback(struct net_device *dev)
                        if (sp_ifa->rt)
                                continue;
 
-                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
 
                        /* Failure cases are ignored */
                        if (!IS_ERR(sp_rt)) {
@@ -2637,7 +2638,8 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr
 #endif
 
 
-       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags, 0, 0);
+       ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
+                           INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        if (!IS_ERR(ifp)) {
                addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
                addrconf_dad_start(ifp);
@@ -3187,6 +3189,22 @@ out:
        in6_ifa_put(ifp);
 }
 
+/* ifp->idev must be at least read locked */
+static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
+{
+       struct inet6_ifaddr *ifpiter;
+       struct inet6_dev *idev = ifp->idev;
+
+       list_for_each_entry(ifpiter, &idev->addr_list, if_list) {
+               if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
+                   (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
+                                      IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
+                   IFA_F_PERMANENT)
+                       return false;
+       }
+       return true;
+}
+
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 {
        struct net_device *dev = ifp->idev->dev;
@@ -3206,14 +3224,11 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
         */
 
        read_lock_bh(&ifp->idev->lock);
-       spin_lock(&ifp->lock);
-       send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL &&
-                  ifp->idev->valid_ll_addr_cnt == 1;
+       send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
        send_rs = send_mld &&
                  ipv6_accept_ra(ifp->idev) &&
                  ifp->idev->cnf.rtr_solicits > 0 &&
                  (dev->flags&IFF_LOOPBACK) == 0;
-       spin_unlock(&ifp->lock);
        read_unlock_bh(&ifp->idev->lock);
 
        /* While dad is in progress mld report's source address is in6_addrany.
@@ -3456,7 +3471,12 @@ restart:
                                         &inet6_addr_lst[i], addr_lst) {
                        unsigned long age;
 
-                       if (ifp->flags & IFA_F_PERMANENT)
+                       /* When setting preferred_lft to a value not zero or
+                        * infinity, while valid_lft is infinity
+                        * IFA_F_PERMANENT has a non-infinity life time.
+                        */
+                       if ((ifp->flags & IFA_F_PERMANENT) &&
+                           (ifp->prefered_lft == INFINITY_LIFE_TIME))
                                continue;
 
                        spin_lock(&ifp->lock);
@@ -3481,7 +3501,8 @@ restart:
                                        ifp->flags |= IFA_F_DEPRECATED;
                                }
 
-                               if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
+                               if ((ifp->valid_lft != INFINITY_LIFE_TIME) &&
+                                   (time_before(ifp->tstamp + ifp->valid_lft * HZ, next)))
                                        next = ifp->tstamp + ifp->valid_lft * HZ;
 
                                spin_unlock(&ifp->lock);
@@ -3761,7 +3782,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
                      ifa->idev->dev->ifindex);
 
-       if (!(ifa->flags&IFA_F_PERMANENT)) {
+       if (!((ifa->flags&IFA_F_PERMANENT) &&
+             (ifa->prefered_lft == INFINITY_LIFE_TIME))) {
                preferred = ifa->prefered_lft;
                valid = ifa->valid_lft;
                if (preferred != INFINITY_LIFE_TIME) {
@@ -4503,19 +4525,6 @@ errout:
                rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
 }
 
-static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count)
-{
-       write_lock_bh(&ifp->idev->lock);
-       spin_lock(&ifp->lock);
-       if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|
-                           IFA_F_DADFAILED)) == IFA_F_PERMANENT) &&
-           (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL))
-               ifp->idev->valid_ll_addr_cnt += count;
-       WARN_ON(ifp->idev->valid_ll_addr_cnt < 0);
-       spin_unlock(&ifp->lock);
-       write_unlock_bh(&ifp->idev->lock);
-}
-
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 {
        struct net *net = dev_net(ifp->idev->dev);
@@ -4524,8 +4533,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
        switch (event) {
        case RTM_NEWADDR:
-               update_valid_ll_addr_cnt(ifp, 1);
-
                /*
                 * If the address was optimistic
                 * we inserted the route at the start of
@@ -4541,8 +4548,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                                              ifp->idev->dev, 0, 0);
                break;
        case RTM_DELADDR:
-               update_valid_ll_addr_cnt(ifp, -1);
-
                if (ifp->idev->cnf.forwarding)
                        addrconf_leave_anycast(ifp);
                addrconf_leave_solict(ifp->idev, &ifp->addr);
index a454b0ff57c7c67a91e2e5c887609e7a65e5a910..93b1aa34c4320304125b478bbdad73b8b691b572 100644 (file)
@@ -73,7 +73,6 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                }
        }
 
@@ -318,7 +317,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
 /*
  *     Handle MSG_ERRQUEUE
  */
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sock_exterr_skb *serr;
@@ -369,6 +368,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                                               &sin->sin6_addr);
                        sin->sin6_scope_id = 0;
                }
+               *addr_len = sizeof(*sin);
        }
 
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
@@ -377,6 +377,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
        if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
                sin->sin6_family = AF_INET6;
                sin->sin6_flowinfo = 0;
+               sin->sin6_port = 0;
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error);
 /*
  *     Handle IPV6_RECVPATHMTU
  */
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+                    int *addr_len)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sk_buff *skb;
@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
                sin->sin6_port = 0;
                sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
                sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
+               *addr_len = sizeof(*sin);
        }
 
        put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
index e27591635f92c45306a33cb9513628751e93dd16..3fd0a578329e523828fc56b40b6ffe217fd850dc 100644 (file)
@@ -122,7 +122,11 @@ out:
 static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 {
        struct rt6_info *rt = (struct rt6_info *) arg->result;
-       struct net_device *dev = rt->rt6i_idev->dev;
+       struct net_device *dev = NULL;
+
+       if (rt->rt6i_idev)
+               dev = rt->rt6i_idev->dev;
+
        /* do not accept result if the route does
         * not meet the required prefix length
         */
index 59df872e2f4d62f68b583ff40218d68c5d5189df..e6f931997996ef46efa1272b16e261bf8f6609a7 100644 (file)
@@ -116,8 +116,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
        }
        rcu_read_unlock_bh();
 
-       IP6_INC_STATS_BH(dev_net(dst->dev),
-                        ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
+       IP6_INC_STATS(dev_net(dst->dev),
+                     ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
        kfree_skb(skb);
        return -EINVAL;
 }
@@ -1193,11 +1193,35 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
        fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
                        (opt ? opt->opt_nflen : 0);
-       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
+       maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen -
+                    sizeof(struct frag_hdr);
 
        if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
-               if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
-                       ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
+               unsigned int maxnonfragsize, headersize;
+
+               headersize = sizeof(struct ipv6hdr) +
+                            (opt ? opt->tot_len : 0) +
+                            (dst_allfrag(&rt->dst) ?
+                             sizeof(struct frag_hdr) : 0) +
+                            rt->rt6i_nfheader_len;
+
+               maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ?
+                                mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN;
+
+               /* dontfrag active */
+               if ((cork->length + length > mtu - headersize) && dontfrag &&
+                   (sk->sk_protocol == IPPROTO_UDP ||
+                    sk->sk_protocol == IPPROTO_RAW)) {
+                       ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
+                                                  sizeof(struct ipv6hdr));
+                       goto emsgsize;
+               }
+
+               if (cork->length + length > maxnonfragsize - headersize) {
+emsgsize:
+                       ipv6_local_error(sk, EMSGSIZE, fl6,
+                                        mtu - headersize +
+                                        sizeof(struct ipv6hdr));
                        return -EMSGSIZE;
                }
        }
@@ -1222,12 +1246,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         * --yoshfuji
         */
 
-       if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
-                                          sk->sk_protocol == IPPROTO_RAW)) {
-               ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-               return -EMSGSIZE;
-       }
-
        skb = skb_peek_tail(&sk->sk_write_queue);
        cork->length += length;
        if (((length > mtu) ||
index d6062325db08411207fd63b435ec1e5e4e0f2001..7881965a824840a763a7e1183efcf21153f87b47 100644 (file)
@@ -103,16 +103,25 @@ struct ip6_tnl_net {
 
 static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 {
-       struct pcpu_tstats sum = { 0 };
+       struct pcpu_tstats tmp, sum = { 0 };
        int i;
 
        for_each_possible_cpu(i) {
+               unsigned int start;
                const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
 
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
+               do {
+                       start = u64_stats_fetch_begin_bh(&tstats->syncp);
+                       tmp.rx_packets = tstats->rx_packets;
+                       tmp.rx_bytes = tstats->rx_bytes;
+                       tmp.tx_packets = tstats->tx_packets;
+                       tmp.tx_bytes =  tstats->tx_bytes;
+               } while (u64_stats_fetch_retry_bh(&tstats->syncp, start));
+
+               sum.rx_packets += tmp.rx_packets;
+               sum.rx_bytes   += tmp.rx_bytes;
+               sum.tx_packets += tmp.tx_packets;
+               sum.tx_bytes   += tmp.tx_bytes;
        }
        dev->stats.rx_packets = sum.rx_packets;
        dev->stats.rx_bytes   = sum.rx_bytes;
@@ -824,8 +833,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
index ed94ba61dda0ec1c3e2b170fe74eb2334b752700..7b42d5ef868deaa193094a85a00b502aeaba0bdd 100644 (file)
@@ -75,26 +75,6 @@ struct vti6_net {
        struct ip6_tnl __rcu **tnls[2];
 };
 
-static struct net_device_stats *vti6_get_stats(struct net_device *dev)
-{
-       struct pcpu_tstats sum = { 0 };
-       int i;
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i);
-
-               sum.rx_packets += tstats->rx_packets;
-               sum.rx_bytes   += tstats->rx_bytes;
-               sum.tx_packets += tstats->tx_packets;
-               sum.tx_bytes   += tstats->tx_bytes;
-       }
-       dev->stats.rx_packets = sum.rx_packets;
-       dev->stats.rx_bytes   = sum.rx_bytes;
-       dev->stats.tx_packets = sum.tx_packets;
-       dev->stats.tx_bytes   = sum.tx_bytes;
-       return &dev->stats;
-}
-
 #define for_each_vti6_tunnel_rcu(start) \
        for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
 
@@ -331,8 +311,10 @@ static int vti6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(t->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                skb->mark = 0;
                secpath_reset(skb);
@@ -716,7 +698,7 @@ static const struct net_device_ops vti6_netdev_ops = {
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
        .ndo_change_mtu = vti6_change_mtu,
-       .ndo_get_stats  = vti6_get_stats,
+       .ndo_get_stats64 = ip_tunnel_get_stats64,
 };
 
 /**
@@ -750,12 +732,18 @@ static void vti6_dev_setup(struct net_device *dev)
 static inline int vti6_dev_init_gen(struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
+       int i;
 
        t->dev = dev;
        t->net = dev_net(dev);
        dev->tstats = alloc_percpu(struct pcpu_tstats);
        if (!dev->tstats)
                return -ENOMEM;
+       for_each_possible_cpu(i) {
+               struct pcpu_tstats *stats;
+               stats = per_cpu_ptr(dev->tstats, i);
+               u64_stats_init(&stats->syncp);
+       }
        return 0;
 }
 
index f365310bfcca30420a9cce321c1875d7f4319c21..0eb4038a4d63434738e938113b37bfe6611e07c3 100644 (file)
@@ -141,9 +141,12 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
 static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
                            struct mr6_table **mrt)
 {
-       struct ip6mr_result res;
-       struct fib_lookup_arg arg = { .result = &res, };
        int err;
+       struct ip6mr_result res;
+       struct fib_lookup_arg arg = {
+               .result = &res,
+               .flags = FIB_LOOKUP_NOREF,
+       };
 
        err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
                               flowi6_to_flowi(flp6), 0, &arg);
index 3512177deb4d0e7d12c6d145781802074f490615..3008651713947c76dac697d466f1301d05bba025 100644 (file)
@@ -1277,6 +1277,9 @@ skip_linkparms:
                            ri->prefix_len == 0)
                                continue;
 #endif
+                       if (ri->prefix_len == 0 &&
+                           !in6_dev->cnf.accept_ra_defrtr)
+                               continue;
                        if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
                                continue;
                        rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
index f78f41aca8e90967a026a145f938746ce317cf10..a0d17270117c37793be3cb61c4d767cd57f70611 100644 (file)
@@ -446,6 +446,7 @@ static void synproxy_tg6_destroy(const struct xt_tgdtor_param *par)
 static struct xt_target synproxy_tg6_reg __read_mostly = {
        .name           = "SYNPROXY",
        .family         = NFPROTO_IPV6,
+       .hooks          = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
        .target         = synproxy_tg6,
        .targetsize     = sizeof(struct xt_synproxy_info),
        .checkentry     = synproxy_tg6_check,
index 8815e31a87fed4ba51ebd78a6724df8a3a436b85..a83243c3d656f553b6ccec94451e26e28cd1e743 100644 (file)
@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = {
 
 
 /* Compatibility glue so we can support IPv6 when it's compiled as a module */
-static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                                int *addr_len)
 {
        return -EAFNOSUPPORT;
 }
index 22d1bd4670dab741b2417051b45370b4a75b42a3..e048cf1bb6a234bb1c0eac0987d8e093a733f2f1 100644 (file)
@@ -36,10 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol
 }
 EXPORT_SYMBOL(inet6_add_protocol);
 
-/*
- *     Remove a protocol from the hash tables.
- */
-
 int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
        int ret;
index e24ff1df0401288e4e810cf79ec3ea20d86a06c0..b6bb87e55805873ec3244db9586f58b14700835d 100644 (file)
@@ -466,10 +466,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
                return -EOPNOTSUPP;
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
@@ -792,7 +792,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
index 7faa9d5e15033ae45715d63a33c21150e74f8665..4b4944c3e4c4473c8b1ca4fbce8700a8af988604 100644 (file)
@@ -84,6 +84,8 @@ static int             ip6_dst_gc(struct dst_ops *ops);
 
 static int             ip6_pkt_discard(struct sk_buff *skb);
 static int             ip6_pkt_discard_out(struct sk_buff *skb);
+static int             ip6_pkt_prohibit(struct sk_buff *skb);
+static int             ip6_pkt_prohibit_out(struct sk_buff *skb);
 static void            ip6_link_failure(struct sk_buff *skb);
 static void            ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
                                           struct sk_buff *skb, u32 mtu);
@@ -234,9 +236,6 @@ static const struct rt6_info ip6_null_entry_template = {
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
-static int ip6_pkt_prohibit(struct sk_buff *skb);
-static int ip6_pkt_prohibit_out(struct sk_buff *skb);
-
 static const struct rt6_info ip6_prohibit_entry_template = {
        .dst = {
                .__refcnt       = ATOMIC_INIT(1),
@@ -1565,21 +1564,24 @@ int ip6_route_add(struct fib6_config *cfg)
                                goto out;
                        }
                }
-               rt->dst.output = ip6_pkt_discard_out;
-               rt->dst.input = ip6_pkt_discard;
                rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
                switch (cfg->fc_type) {
                case RTN_BLACKHOLE:
                        rt->dst.error = -EINVAL;
+                       rt->dst.output = dst_discard;
+                       rt->dst.input = dst_discard;
                        break;
                case RTN_PROHIBIT:
                        rt->dst.error = -EACCES;
+                       rt->dst.output = ip6_pkt_prohibit_out;
+                       rt->dst.input = ip6_pkt_prohibit;
                        break;
                case RTN_THROW:
-                       rt->dst.error = -EAGAIN;
-                       break;
                default:
-                       rt->dst.error = -ENETUNREACH;
+                       rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
+                                       : -ENETUNREACH;
+                       rt->dst.output = ip6_pkt_discard_out;
+                       rt->dst.input = ip6_pkt_discard;
                        break;
                }
                goto install_route;
@@ -1903,9 +1905,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                else
                        rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
-               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
-                   (RTF_DEFAULT | RTF_ADDRCONF))
-                       rt6_set_from(rt, ort);
+               rt6_set_from(rt, ort);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -2144,8 +2144,6 @@ static int ip6_pkt_discard_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
 }
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-
 static int ip6_pkt_prohibit(struct sk_buff *skb)
 {
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
@@ -2157,8 +2155,6 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
 }
 
-#endif
-
 /*
  *     Allocate a dst for local (unicast / anycast) address.
  */
@@ -2168,12 +2164,10 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
                                    bool anycast)
 {
        struct net *net = dev_net(idev->dev);
-       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL);
-
-       if (!rt) {
-               net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n");
+       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
+                                           DST_NOCOUNT, NULL);
+       if (!rt)
                return ERR_PTR(-ENOMEM);
-       }
 
        in6_dev_hold(idev);
 
index 1b4a4a95367552c8cc22d19850b0779eee87cdc6..d3005b34476a82f8172cfe8807507d561d307938 100644 (file)
@@ -478,14 +478,44 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
        dev_put(dev);
 }
 
+/* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
+ * if sufficient data bytes are available
+ */
+static int ipip6_err_gen_icmpv6_unreach(struct sk_buff *skb)
+{
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       struct rt6_info *rt;
+       struct sk_buff *skb2;
+
+       if (!pskb_may_pull(skb, iph->ihl * 4 + sizeof(struct ipv6hdr) + 8))
+               return 1;
+
+       skb2 = skb_clone(skb, GFP_ATOMIC);
+
+       if (!skb2)
+               return 1;
+
+       skb_dst_drop(skb2);
+       skb_pull(skb2, iph->ihl * 4);
+       skb_reset_network_header(skb2);
+
+       rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0);
+
+       if (rt && rt->dst.dev)
+               skb2->dev = rt->dst.dev;
+
+       icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
+
+       if (rt)
+               ip6_rt_put(rt);
+
+       kfree_skb(skb2);
+
+       return 0;
+}
 
 static int ipip6_err(struct sk_buff *skb, u32 info)
 {
-
-/* All the routers (except for Linux) return only
-   8 bytes of packet payload. It means, that precise relaying of
-   ICMP in the real Internet is absolutely infeasible.
- */
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
@@ -500,7 +530,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        case ICMP_DEST_UNREACH:
                switch (code) {
                case ICMP_SR_FAILED:
-               case ICMP_PORT_UNREACH:
                        /* Impossible event. */
                        return 0;
                default:
@@ -545,6 +574,9 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                goto out;
 
        err = 0;
+       if (!ipip6_err_gen_icmpv6_unreach(skb))
+               goto out;
+
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
                goto out;
 
@@ -670,8 +702,10 @@ static int ipip6_rcv(struct sk_buff *skb)
                }
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
 
                netif_rx(skb);
 
@@ -892,7 +926,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (tunnel->parms.iph.daddr && skb_dst(skb))
                        skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
 
-               if (skb->len > mtu) {
+               if (skb->len > mtu && !skb_is_gso(skb)) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                        ip_rt_put(rt);
                        goto tx_error;
@@ -919,7 +953,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (!new_skb) {
                        ip_rt_put(rt);
                        dev->stats.tx_dropped++;
-                       dev_kfree_skb(skb);
+                       kfree_skb(skb);
                        return NETDEV_TX_OK;
                }
                if (skb->sk)
@@ -934,8 +968,10 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 
        skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT);
-       if (IS_ERR(skb))
+       if (IS_ERR(skb)) {
+               ip_rt_put(rt);
                goto out;
+       }
 
        err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos,
                            ttl, df, !net_eq(tunnel->net, dev_net(dev)));
@@ -945,7 +981,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 tx_error_icmp:
        dst_link_failure(skb);
 tx_error:
-       dev_kfree_skb(skb);
+       kfree_skb(skb);
 out:
        dev->stats.tx_errors++;
        return NETDEV_TX_OK;
@@ -985,7 +1021,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
 
 tx_err:
        dev->stats.tx_errors++;
-       dev_kfree_skb(skb);
+       kfree_skb(skb);
        return NETDEV_TX_OK;
 
 }
index 0740f93a114a26ac09150638576f523bcd53694c..f67033b4bb6687621b7df4f9d3b691519c65f629 100644 (file)
@@ -156,7 +156,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
index c1097c79890070e3d04517cecb7f0b263c0a4fc7..6d18157dc32c5e6fadf7798d26cdd665e18cb541 100644 (file)
@@ -37,34 +37,32 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
        __wsum wsum;
-       __sum16 sum;
+
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
+       wsum = skb->csum;
 
        switch (skb->ip_summed) {
+       case CHECKSUM_NONE:
+               wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
+                                   wsum);
+
+               /* fall through */
+
        case CHECKSUM_COMPLETE:
                if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
-                                 skb->csum)) {
+                                 wsum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-flush:
+
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
-                                                   skb_gro_len(skb),
-                                                   IPPROTO_TCP, 0));
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 81eb8cf8389b6a5af55f7b2994d7dbefe3d732bf..089c741a399217b2c7dd90f7783df4aa89eb5424 100644 (file)
@@ -393,10 +393,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        bool slow;
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1140,7 +1140,6 @@ do_udp_sendmsg:
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
index cfd65304be60ae8937449a8c1e4cf77406c11305..bb6e206ea70b84ed180eb73a302fb6349b0f3fe8 100644 (file)
@@ -528,7 +528,6 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
@@ -665,7 +664,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                *addr_len = sizeof(*lsa);
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
index 7b01b9f5846c845bcf4f04b21cfbcb5786c19421..c71b699eb555165e124ec21109e37212587c7741 100644 (file)
@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
        unsigned long cpu_flags;
        size_t copied = 0;
        u32 peek_seq = 0;
-       u32 *seq;
+       u32 *seq, skb_len;
        unsigned long used;
        int target;     /* Read at least this many bytes */
        long timeo;
@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
                continue;
        found_ok_skb:
+               skb_len = skb->len;
                /* Ok so how much can we use? */
                used = skb->len - offset;
                if (len < used)
@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                /* Partial read */
-               if (used + offset < skb->len)
+               if (used + offset < skb_len)
                        continue;
        } while (len > 0);
 
index 95667b088c5b73cd0e95e8c1753ed76acec9dca0..364ce0c5962fd48c85ea23b71b2d1dd463082575 100644 (file)
@@ -1368,7 +1368,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                        changed |=
                              ieee80211_mps_set_sta_local_pm(sta,
                                                             params->local_pm);
-               ieee80211_bss_info_change_notify(sdata, changed);
+               ieee80211_mbss_info_change_notify(sdata, changed);
 #endif
        }
 
@@ -2488,8 +2488,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
-       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-           sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return -EOPNOTSUPP;
 
        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
@@ -3120,9 +3119,17 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                    params->chandef.chan->band)
                        return -EINVAL;
 
+               ifmsh->chsw_init = true;
+               if (!ifmsh->pre_value)
+                       ifmsh->pre_value = 1;
+               else
+                       ifmsh->pre_value++;
+
                err = ieee80211_mesh_csa_beacon(sdata, params, true);
-               if (err < 0)
+               if (err < 0) {
+                       ifmsh->chsw_init = false;
                        return err;
+               }
                break;
 #endif
        default:
index 531be040b9ae85972d61bf7df248ae28308d811b..27a39de89679b7d3710fea18a65b6d5df6d003d0 100644 (file)
@@ -823,6 +823,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        if (err)
                return false;
 
+       /* channel switch is not supported, disconnect */
+       if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
+               goto disconnect;
+
        params.count = csa_ie.count;
        params.chandef = csa_ie.chandef;
 
index 29dc505be125c3c19737f8f6cee911492c52727c..4aea4e7911135133818e66a1439b111d14e6147e 100644 (file)
@@ -1228,6 +1228,7 @@ struct ieee80211_csa_ie {
        u8 mode;
        u8 count;
        u8 ttl;
+       u16 pre_value;
 };
 
 /* Parsed Information Elements */
index ff101ea1d9ae1e208deb5d6fe1d67c1677b398c2..a0757913046eab8eee0c99104d8900db4e338c3e 100644 (file)
@@ -1061,7 +1061,8 @@ static void ieee80211_uninit(struct net_device *dev)
 }
 
 static u16 ieee80211_netdev_select_queue(struct net_device *dev,
-                                        struct sk_buff *skb)
+                                        struct sk_buff *skb,
+                                        void *accel_priv)
 {
        return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
 }
@@ -1078,7 +1079,8 @@ static const struct net_device_ops ieee80211_dataif_ops = {
 };
 
 static u16 ieee80211_monitor_select_queue(struct net_device *dev,
-                                         struct sk_buff *skb)
+                                         struct sk_buff *skb,
+                                         void *accel_priv)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
@@ -1325,7 +1327,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.bssid = NULL;
                break;
        case NL80211_IFTYPE_AP_VLAN:
-               break;
        case NL80211_IFTYPE_P2P_DEVICE:
                sdata->vif.bss_conf.bssid = sdata->vif.addr;
                break;
index 21d5d44444d04c82fc73c9fd6dee3f58ab56e512..7d1c3ac48ed941866170afdf387def183690d612 100644 (file)
@@ -940,6 +940,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
                            result);
 
+       local->hw.conf.flags = IEEE80211_CONF_IDLE;
+
        ieee80211_led_init(local);
 
        rtnl_lock();
@@ -1047,6 +1049,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        cancel_work_sync(&local->restart_work);
        cancel_work_sync(&local->reconfig_filter);
+       flush_work(&local->sched_scan_stopped_work);
 
        ieee80211_clear_tx_pending(local);
        rate_control_deinitialize(local);
index 896fe3bd599e9bedd5db13dbc8ed04ab76e5bd88..ba105257d03f1cffc4398f42c52e67b1e8d3eaaa 100644 (file)
@@ -943,14 +943,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
                 params.chandef.chan->center_freq);
 
        params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
-       if (beacon)
+       if (beacon) {
                ifmsh->chsw_ttl = csa_ie.ttl - 1;
-       else
-               ifmsh->chsw_ttl = 0;
+               if (ifmsh->pre_value >= csa_ie.pre_value)
+                       return false;
+               ifmsh->pre_value = csa_ie.pre_value;
+       }
 
-       if (ifmsh->chsw_ttl > 0)
+       if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
                if (ieee80211_mesh_csa_beacon(sdata, &params, false) < 0)
                        return false;
+       } else {
+               return false;
+       }
 
        sdata->csa_radar_required = params.radar_required;
 
@@ -1163,7 +1168,6 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
        offset_ttl = (len < 42) ? 7 : 10;
        *(pos + offset_ttl) -= 1;
        *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
-       sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
 
        memcpy(mgmt_fwd, mgmt, len);
        eth_broadcast_addr(mgmt_fwd->da);
@@ -1182,7 +1186,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
        u16 pre_value;
        bool fwd_csa = true;
        size_t baselen;
-       u8 *pos, ttl;
+       u8 *pos;
 
        if (mgmt->u.action.u.measurement.action_code !=
            WLAN_ACTION_SPCT_CHL_SWITCH)
@@ -1193,8 +1197,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
                           u.action.u.chan_switch.variable);
        ieee802_11_parse_elems(pos, len - baselen, false, &elems);
 
-       ttl = elems.mesh_chansw_params_ie->mesh_ttl;
-       if (!--ttl)
+       ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
+       if (!--ifmsh->chsw_ttl)
                fwd_csa = false;
 
        pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
index d7504ab61a34c7ef6a51f8adce10e58c021408d0..b3a3ce316656ce8406859a3cdc325fa262e024a5 100644 (file)
@@ -1910,6 +1910,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
                already = true;
 
+       ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
+
        mutex_unlock(&sdata->local->mtx);
 
        if (already)
index 5d60779a0c1be89e987b2cd478af865ec806d4bb..4096ff6cc24fe8a5c3505411c5b232e0d800e050 100644 (file)
@@ -226,7 +226,7 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
                nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
 
        nsecs += minstrel_mcs_groups[group].duration[rate];
-       tp = 1000000 * ((mr->probability * 1000) / nsecs);
+       tp = 1000000 * ((prob * 1000) / nsecs);
 
        mr->cur_tp = MINSTREL_TRUNC(tp);
 }
@@ -277,13 +277,15 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
                        if (!(mg->supported & BIT(i)))
                                continue;
 
+                       index = MCS_GROUP_RATES * group + i;
+
                        /* initialize rates selections starting indexes */
                        if (!mg_rates_valid) {
                                mg->max_tp_rate = mg->max_tp_rate2 =
                                        mg->max_prob_rate = i;
                                if (!mi_rates_valid) {
                                        mi->max_tp_rate = mi->max_tp_rate2 =
-                                               mi->max_prob_rate = i;
+                                               mi->max_prob_rate = index;
                                        mi_rates_valid = true;
                                }
                                mg_rates_valid = true;
@@ -291,7 +293,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 
                        mr = &mg->rates[i];
                        mr->retry_updated = false;
-                       index = MCS_GROUP_RATES * group + i;
                        minstrel_calc_rate_ewma(mr);
                        minstrel_ht_calc_tp(mi, group, i);
 
index caecef870c0e44e3562cdc0a874bcfd233fc77a1..2b0debb0422b91d89a0a7982b94726f3b9ceae11 100644 (file)
@@ -911,7 +911,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        u16 sc;
        u8 tid, ack_policy;
 
-       if (!ieee80211_is_data_qos(hdr->frame_control))
+       if (!ieee80211_is_data_qos(hdr->frame_control) ||
+           is_multicast_ether_addr(hdr->addr1))
                goto dont_reorder;
 
        /*
index 5ad66a83ef7f4d4525de163c2c2f1fe9d6931a04..bcc4833d7542b91e1b754ed490d1dedcaee559c1 100644 (file)
@@ -1088,6 +1088,6 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
 
        trace_api_sched_scan_stopped(local);
 
-       ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work);
+       schedule_work(&local->sched_scan_stopped_work);
 }
 EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
index a40da20b32e074a3923f844edf104eca33a6134c..6ab00907008461fb14d551b2633a8dbcd4fef623 100644 (file)
@@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
        if (elems->mesh_chansw_params_ie) {
                csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
                csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
+               csa_ie->pre_value = le16_to_cpu(
+                               elems->mesh_chansw_params_ie->mesh_pre_value);
        }
 
        new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
index c558b246ef0036c38e6c8a00b338b43c46913f78..ca7fa7f0613dba22cdc0e82d8a96e1de9ff011dc 100644 (file)
@@ -463,7 +463,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 {
        struct sta_info *sta = tx->sta;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
 
        if (unlikely(!sta))
@@ -474,15 +473,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
                     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
-               /* only deauth, disassoc and action are bufferable MMPDUs */
-               if (ieee80211_is_mgmt(hdr->frame_control) &&
-                   !ieee80211_is_deauth(hdr->frame_control) &&
-                   !ieee80211_is_disassoc(hdr->frame_control) &&
-                   !ieee80211_is_action(hdr->frame_control)) {
-                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
-                       return TX_CONTINUE;
-               }
-
                ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n",
                       sta->sta.addr, sta->sta.aid, ac);
                if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -525,9 +515,22 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 {
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
        if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
                return TX_CONTINUE;
 
+       /* only deauth, disassoc and action are bufferable MMPDUs */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_deauth(hdr->frame_control) &&
+           !ieee80211_is_disassoc(hdr->frame_control) &&
+           !ieee80211_is_action(hdr->frame_control)) {
+               if (tx->flags & IEEE80211_TX_UNICAST)
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+               return TX_CONTINUE;
+       }
+
        if (tx->flags & IEEE80211_TX_UNICAST)
                return ieee80211_tx_h_unicast_ps_buf(tx);
        else
index 592a18171f95e9ec5273b03307235dff2bd1c946..9f9b9bd3fd44798e7030fb3a44c46da962cfd7ba 100644 (file)
@@ -2278,17 +2278,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
 {
        struct ieee80211_local *local =
                container_of(work, struct ieee80211_local, radar_detected_work);
-       struct cfg80211_chan_def chandef;
+       struct cfg80211_chan_def chandef = local->hw.conf.chandef;
 
        ieee80211_dfs_cac_cancel(local);
 
        if (local->use_chanctx)
                /* currently not handled */
                WARN_ON(1);
-       else {
-               chandef = local->hw.conf.chandef;
+       else
                cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
-       }
 }
 
 void ieee80211_radar_detected(struct ieee80211_hw *hw)
@@ -2459,14 +2457,9 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
                          WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
                put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
                pos += 2;
-               if (!ifmsh->pre_value)
-                       ifmsh->pre_value = 1;
-               else
-                       ifmsh->pre_value++;
                pre_value = cpu_to_le16(ifmsh->pre_value);
                memcpy(pos, &pre_value, 2);             /* Precedence Value */
                pos += 2;
-               ifmsh->chsw_init = true;
        }
 
        ieee80211_tx_skb(sdata, skb);
index 2bc2dec20b007026e78aba74451e70039c6e5988..6226803fc490ce33c53994c344a1c034b9b0cce9 100644 (file)
@@ -59,7 +59,7 @@ hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1,
                     u32 *multi)
 {
        return ip1->ipcmp == ip2->ipcmp &&
-              ip2->ccmp == ip2->ccmp;
+              ip1->ccmp == ip2->ccmp;
 }
 
 static inline int
index c8beafd401aa283f0befa0494e02649359bab83f..5a355a46d1dc4a70e82fadcd509ddd4fae34c3e1 100644 (file)
@@ -63,6 +63,7 @@
 #include <net/ip_vs.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_expect.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_zones.h>
 
@@ -97,6 +98,11 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
                return;
 
+       /* Applications may adjust TCP seqs */
+       if (cp->app && nf_ct_protonum(ct) == IPPROTO_TCP &&
+           !nfct_seqadj(ct) && !nfct_seqadj_ext_add(ct))
+               return;
+
        /*
         * The connection is not yet in the hashtable, so we update it.
         * CIP->VIP will remain the same, so leave the tuple in
index 17c1bcb182c6b58a782744e23bfe671de160bf92..f6e2ae91a80badd697a1f77e299dc332bc34a8d1 100644 (file)
@@ -36,6 +36,11 @@ int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        if (off == 0)
                return 0;
 
+       if (unlikely(!seqadj)) {
+               WARN_ONCE(1, "Missing nfct_seqadj_ext_add() setup call\n");
+               return 0;
+       }
+
        set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 
        spin_lock_bh(&ct->lock);
index 902fb0a6b38ad9baac15c3fc3f17a3e695510db8..7a394df0deb7686fa7fe4da162ff77d3c03435c5 100644 (file)
@@ -97,7 +97,6 @@ int nf_conntrack_tstamp_pernet_init(struct net *net)
 void nf_conntrack_tstamp_pernet_fini(struct net *net)
 {
        nf_conntrack_tstamp_fini_sysctl(net);
-       nf_ct_extend_unregister(&tstamp_extend);
 }
 
 int nf_conntrack_tstamp_init(void)
index f02b3605823e5616bc70f128a896e76d8f984ff2..1fb2258c35357c8c6f5072ae6593de2d53ab9f03 100644 (file)
@@ -34,10 +34,14 @@ static unsigned int help(struct sk_buff *skb,
                         struct nf_conntrack_expect *exp)
 {
        char buffer[sizeof("4294967296 65635")];
+       struct nf_conn *ct = exp->master;
+       union nf_inet_addr newaddr;
        u_int16_t port;
        unsigned int ret;
 
        /* Reply comes from server. */
+       newaddr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3;
+
        exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
@@ -57,17 +61,35 @@ static unsigned int help(struct sk_buff *skb,
        }
 
        if (port == 0) {
-               nf_ct_helper_log(skb, exp->master, "all ports in use");
+               nf_ct_helper_log(skb, ct, "all ports in use");
                return NF_DROP;
        }
 
-       ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo,
-                                      protoff, matchoff, matchlen, buffer,
-                                      strlen(buffer));
+       /* strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
+        * strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
+        * strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
+        * strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
+        *
+        * AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
+        *                        255.255.255.255==4294967296, 10 digits)
+        * P:         bound port (min 1 d, max 5d (65635))
+        * F:         filename   (min 1 d )
+        * S:         size       (min 1 d )
+        * 0x01, \n:  terminators
+        */
+       /* AAA = "us", ie. where server normally talks to. */
+       snprintf(buffer, sizeof(buffer), "%u %u", ntohl(newaddr.ip), port);
+       pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n",
+                buffer, &newaddr.ip, port);
+
+       ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff,
+                                      matchlen, buffer, strlen(buffer));
        if (ret != NF_ACCEPT) {
-               nf_ct_helper_log(skb, exp->master, "cannot mangle packet");
+               nf_ct_helper_log(skb, ct, "cannot mangle packet");
                nf_ct_unexpect_related(exp);
        }
+
        return ret;
 }
 
index dcddc49c0e08363044195695138543e4277f83f0..71a9f49a768b887dec1b361b78147016cb2b9307 100644 (file)
@@ -312,6 +312,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        int err, i = 0;
 
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                err = nf_register_hook(&nft_base_chain(chain)->ops);
                if (err < 0)
                        goto err;
@@ -321,6 +324,9 @@ static int nf_tables_table_enable(struct nft_table *table)
        return 0;
 err:
        list_for_each_entry(chain, &table->chains, list) {
+               if (!(chain->flags & NFT_BASE_CHAIN))
+                       continue;
+
                if (i-- <= 0)
                        break;
 
@@ -333,8 +339,10 @@ static int nf_tables_table_disable(struct nft_table *table)
 {
        struct nft_chain *chain;
 
-       list_for_each_entry(chain, &table->chains, list)
-               nf_unregister_hook(&nft_base_chain(chain)->ops);
+       list_for_each_entry(chain, &table->chains, list) {
+               if (chain->flags & NFT_BASE_CHAIN)
+                       nf_unregister_hook(&nft_base_chain(chain)->ops);
+       }
 
        return 0;
 }
@@ -1717,6 +1725,19 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
        return -ENOENT;
 }
 
+static int nf_table_delrule_by_chain(struct nft_ctx *ctx)
+{
+       struct nft_rule *rule;
+       int err;
+
+       list_for_each_entry(rule, &ctx->chain->rules, list) {
+               err = nf_tables_delrule_one(ctx, rule);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
 static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
                             const struct nlmsghdr *nlh,
                             const struct nlattr * const nla[])
@@ -1725,8 +1746,8 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
        const struct nft_af_info *afi;
        struct net *net = sock_net(skb->sk);
        const struct nft_table *table;
-       struct nft_chain *chain;
-       struct nft_rule *rule, *tmp;
+       struct nft_chain *chain = NULL;
+       struct nft_rule *rule;
        int family = nfmsg->nfgen_family, err = 0;
        struct nft_ctx ctx;
 
@@ -1738,22 +1759,29 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(table))
                return PTR_ERR(table);
 
-       chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
-       if (IS_ERR(chain))
-               return PTR_ERR(chain);
+       if (nla[NFTA_RULE_CHAIN]) {
+               chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
+               if (IS_ERR(chain))
+                       return PTR_ERR(chain);
+       }
 
        nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
 
-       if (nla[NFTA_RULE_HANDLE]) {
-               rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
-               if (IS_ERR(rule))
-                       return PTR_ERR(rule);
+       if (chain) {
+               if (nla[NFTA_RULE_HANDLE]) {
+                       rule = nf_tables_rule_lookup(chain,
+                                                    nla[NFTA_RULE_HANDLE]);
+                       if (IS_ERR(rule))
+                               return PTR_ERR(rule);
 
-               err = nf_tables_delrule_one(&ctx, rule);
-       } else {
-               /* Remove all rules in this chain */
-               list_for_each_entry_safe(rule, tmp, &chain->rules, list) {
                        err = nf_tables_delrule_one(&ctx, rule);
+               } else {
+                       err = nf_table_delrule_by_chain(&ctx);
+               }
+       } else {
+               list_for_each_entry(chain, &table->chains, list) {
+                       ctx.chain = chain;
+                       err = nf_table_delrule_by_chain(&ctx);
                        if (err < 0)
                                break;
                }
@@ -2078,17 +2106,21 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
                                   struct netlink_callback *cb)
 {
        const struct nft_set *set;
-       unsigned int idx = 0, s_idx = cb->args[0];
+       unsigned int idx, s_idx = cb->args[0];
        struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
 
        if (cb->args[1])
                return skb->len;
 
        list_for_each_entry(table, &ctx->afi->tables, list) {
-               if (cur_table && cur_table != table)
-                       continue;
+               if (cur_table) {
+                       if (cur_table != table)
+                               continue;
 
+                       cur_table = NULL;
+               }
                ctx->table = table;
+               idx = 0;
                list_for_each_entry(set, &ctx->table->sets, list) {
                        if (idx < s_idx)
                                goto cont;
@@ -2350,7 +2382,9 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
        enum nft_registers dreg;
 
        dreg = nft_type_to_reg(set->dtype);
-       return nft_validate_data_load(ctx, dreg, &elem->data, set->dtype);
+       return nft_validate_data_load(ctx, dreg, &elem->data,
+                                     set->dtype == NFT_DATA_VERDICT ?
+                                     NFT_DATA_VERDICT : NFT_DATA_VALUE);
 }
 
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
index 3c4b69e5fe17348b422f390bf79ab4269043fe5d..a155d19a225edcfb4b1a550ebc898f40d51c564d 100644 (file)
@@ -1053,6 +1053,7 @@ static void __net_exit nfnl_log_net_exit(struct net *net)
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter);
 #endif
+       nf_log_unset(net, &nfulnl_logger);
 }
 
 static struct pernet_operations nfnl_log_net_ops = {
index 8e0bb75e7c51e61092fb904dc1d93befe1e7320d..55c939f5371fabf35ad996efb51ea52a29630703 100644 (file)
@@ -31,7 +31,7 @@ static void nft_exthdr_eval(const struct nft_expr *expr,
 {
        struct nft_exthdr *priv = nft_expr_priv(expr);
        struct nft_data *dest = &data[priv->dreg];
-       unsigned int offset;
+       unsigned int offset = 0;
        int err;
 
        err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL);
index 9ff035c7140324632965fbf82764d532d4d0a284..a3910fc2122bc1aa560815394b525098cb02e85c 100644 (file)
@@ -325,21 +325,24 @@ static void htable_gc(unsigned long htlong)
        add_timer(&ht->timer);
 }
 
-static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo)
 {
        struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net);
        struct proc_dir_entry *parent;
 
-       del_timer_sync(&hinfo->timer);
-
        if (hinfo->family == NFPROTO_IPV4)
                parent = hashlimit_net->ipt_hashlimit;
        else
                parent = hashlimit_net->ip6t_hashlimit;
 
-       if(parent != NULL)
+       if (parent != NULL)
                remove_proc_entry(hinfo->name, parent);
+}
 
+static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+{
+       del_timer_sync(&hinfo->timer);
+       htable_remove_proc_entry(hinfo);
        htable_selective_cleanup(hinfo, select_all);
        kfree(hinfo->name);
        vfree(hinfo);
@@ -883,21 +886,15 @@ static int __net_init hashlimit_proc_net_init(struct net *net)
 static void __net_exit hashlimit_proc_net_exit(struct net *net)
 {
        struct xt_hashlimit_htable *hinfo;
-       struct proc_dir_entry *pde;
        struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
 
-       /* recent_net_exit() is called before recent_mt_destroy(). Make sure
-        * that the parent xt_recent proc entry is is empty before trying to
-        * remove it.
+       /* hashlimit_net_exit() is called before hashlimit_mt_destroy().
+        * Make sure that the parent ipt_hashlimit and ip6t_hashlimit proc
+        * entries is empty before trying to remove it.
         */
        mutex_lock(&hashlimit_mutex);
-       pde = hashlimit_net->ipt_hashlimit;
-       if (pde == NULL)
-               pde = hashlimit_net->ip6t_hashlimit;
-
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node)
-               remove_proc_entry(hinfo->name, pde);
-
+               htable_remove_proc_entry(hinfo);
        hashlimit_net->ipt_hashlimit = NULL;
        hashlimit_net->ip6t_hashlimit = NULL;
        mutex_unlock(&hashlimit_mutex);
index 4518a57aa5febb14db1c1d750f217102dd8fd2a9..713671ae45aff688e693d6087ae4d8ce9e986f48 100644 (file)
@@ -74,9 +74,12 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
  * Bit 17 is marked as already used since the VFS quota code
  * also abused this API and relied on family == group ID, we
  * cater to that by giving it a static family and group ID.
+ * Bit 18 is marked as already used since the PMCRAID driver
+ * did the same thing as the VFS quota code (maybe copied?)
  */
 static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
-                                     BIT(GENL_ID_VFS_DQUOT);
+                                     BIT(GENL_ID_VFS_DQUOT) |
+                                     BIT(GENL_ID_PMCRAID);
 static unsigned long *mc_groups = &mc_group_start;
 static unsigned long mc_groups_longs = 1;
 
@@ -139,6 +142,7 @@ static u16 genl_generate_id(void)
 
        for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
                if (id_gen_idx != GENL_ID_VFS_DQUOT &&
+                   id_gen_idx != GENL_ID_PMCRAID &&
                    !genl_family_find_byid(id_gen_idx))
                        return id_gen_idx;
                if (++id_gen_idx > GENL_MAX_ID)
@@ -214,7 +218,7 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
 {
        int first_id;
        int n_groups = family->n_mcgrps;
-       int err, i;
+       int err = 0, i;
        bool groups_allocated = false;
 
        if (!n_groups)
@@ -236,9 +240,12 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
        } else if (strcmp(family->name, "NET_DM") == 0) {
                first_id = 1;
                BUG_ON(n_groups != 1);
-       } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
+       } else if (family->id == GENL_ID_VFS_DQUOT) {
                first_id = GENL_ID_VFS_DQUOT;
                BUG_ON(n_groups != 1);
+       } else if (family->id == GENL_ID_PMCRAID) {
+               first_id = GENL_ID_PMCRAID;
+               BUG_ON(n_groups != 1);
        } else {
                groups_allocated = true;
                err = genl_allocate_reserve_groups(n_groups, &first_id);
index 872529105abc7c3a2e41b9d579e934e019e8e5ff..83b9927e7d19f3b14c8db4b199385122843d6764 100644 (file)
@@ -384,7 +384,7 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 {
        dev->dep_link_up = true;
 
-       if (!dev->active_target) {
+       if (!dev->active_target && rf_mode == NFC_RF_INITIATOR) {
                struct nfc_target *target;
 
                target = nfc_find_target(dev, target_idx);
index ac27c86ef6d11e00c2ecb1512b09bbda73c3eefc..88cfbc189558f75b4b508b849827eea18c3be7c0 100644 (file)
@@ -237,6 +237,30 @@ struct packet_skb_cb {
 static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
 static void __fanout_link(struct sock *sk, struct packet_sock *po);
 
+static struct net_device *packet_cached_dev_get(struct packet_sock *po)
+{
+       struct net_device *dev;
+
+       rcu_read_lock();
+       dev = rcu_dereference(po->cached_dev);
+       if (likely(dev))
+               dev_hold(dev);
+       rcu_read_unlock();
+
+       return dev;
+}
+
+static void packet_cached_dev_assign(struct packet_sock *po,
+                                    struct net_device *dev)
+{
+       rcu_assign_pointer(po->cached_dev, dev);
+}
+
+static void packet_cached_dev_reset(struct packet_sock *po)
+{
+       RCU_INIT_POINTER(po->cached_dev, NULL);
+}
+
 /* 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()).
@@ -246,12 +270,10 @@ static void register_prot_hook(struct sock *sk)
        struct packet_sock *po = pkt_sk(sk);
 
        if (!po->running) {
-               if (po->fanout) {
+               if (po->fanout)
                        __fanout_link(sk, po);
-               } else {
+               else
                        dev_add_pack(&po->prot_hook);
-                       rcu_assign_pointer(po->cached_dev, po->prot_hook.dev);
-               }
 
                sock_hold(sk);
                po->running = 1;
@@ -270,12 +292,11 @@ static void __unregister_prot_hook(struct sock *sk, bool sync)
        struct packet_sock *po = pkt_sk(sk);
 
        po->running = 0;
-       if (po->fanout) {
+
+       if (po->fanout)
                __fanout_unlink(sk, po);
-       } else {
+       else
                __dev_remove_pack(&po->prot_hook);
-               RCU_INIT_POINTER(po->cached_dev, NULL);
-       }
 
        __sock_put(sk);
 
@@ -439,9 +460,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po,
 
        pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
 
-       spin_lock(&rb_queue->lock);
+       spin_lock_bh(&rb_queue->lock);
        pkc->delete_blk_timer = 1;
-       spin_unlock(&rb_queue->lock);
+       spin_unlock_bh(&rb_queue->lock);
 
        prb_del_retire_blk_timer(pkc);
 }
@@ -2059,19 +2080,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
        return tp_len;
 }
 
-static struct net_device *packet_cached_dev_get(struct packet_sock *po)
-{
-       struct net_device *dev;
-
-       rcu_read_lock();
-       dev = rcu_dereference(po->cached_dev);
-       if (dev)
-               dev_hold(dev);
-       rcu_read_unlock();
-
-       return dev;
-}
-
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 {
        struct sk_buff *skb;
@@ -2088,7 +2096,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
-       if (saddr == NULL) {
+       if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
                addr    = NULL;
@@ -2242,7 +2250,7 @@ static int packet_snd(struct socket *sock,
         *      Get and verify the address.
         */
 
-       if (saddr == NULL) {
+       if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
                addr    = NULL;
@@ -2451,6 +2459,8 @@ static int packet_release(struct socket *sock)
 
        spin_lock(&po->bind_lock);
        unregister_prot_hook(sk, false);
+       packet_cached_dev_reset(po);
+
        if (po->prot_hook.dev) {
                dev_put(po->prot_hook.dev);
                po->prot_hook.dev = NULL;
@@ -2506,14 +2516,17 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
 
        spin_lock(&po->bind_lock);
        unregister_prot_hook(sk, true);
+
        po->num = protocol;
        po->prot_hook.type = protocol;
        if (po->prot_hook.dev)
                dev_put(po->prot_hook.dev);
-       po->prot_hook.dev = dev;
 
+       po->prot_hook.dev = dev;
        po->ifindex = dev ? dev->ifindex : 0;
 
+       packet_cached_dev_assign(po, dev);
+
        if (protocol == 0)
                goto out_unlock;
 
@@ -2626,7 +2639,8 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
        po = pkt_sk(sk);
        sk->sk_family = PF_PACKET;
        po->num = proto;
-       RCU_INIT_POINTER(po->cached_dev, NULL);
+
+       packet_cached_dev_reset(po);
 
        sk->sk_destruct = packet_sock_destruct;
        sk_refcnt_debug_inc(sk);
@@ -3337,6 +3351,7 @@ static int packet_notifier(struct notifier_block *this,
                                                sk->sk_error_report(sk);
                                }
                                if (msg == NETDEV_UNREGISTER) {
+                                       packet_cached_dev_reset(po);
                                        po->ifindex = -1;
                                        if (po->prot_hook.dev)
                                                dev_put(po->prot_hook.dev);
index b4c8b0022feeebea1aec424542e37a8391d87297..ba2dffeff60876ca669993d1863dcbb6cb76a740 100644 (file)
@@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 addr)
        ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
        /* due to this, we will claim to support iWARP devices unless we
           check node_type. */
-       if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA)
+       if (ret || !cm_id->device ||
+           cm_id->device->node_type != RDMA_NODE_IB_CA)
                ret = -EADDRNOTAVAIL;
 
        rdsdebug("addr %pI4 ret %d node type %d\n",
index 8eb9501e3d60d41d30c3af511551f039a6264958..b7ebe23cdedfb5f31cfafab415b54b3db3f0c30b 100644 (file)
@@ -421,8 +421,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
                                 struct rds_ib_refill_cache *cache)
 {
        unsigned long flags;
-       struct list_head *old;
-       struct list_head __percpu *chpfirst;
+       struct list_head *old, *chpfirst;
 
        local_irq_save(flags);
 
@@ -432,7 +431,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
        else /* put on front */
                list_add_tail(new_item, chpfirst);
 
-       __this_cpu_write(chpfirst, new_item);
+       __this_cpu_write(cache->percpu->first, new_item);
        __this_cpu_inc(cache->percpu->count);
 
        if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT)
@@ -452,7 +451,7 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
        } while (old);
 
 
-       __this_cpu_write(chpfirst, NULL);
+       __this_cpu_write(cache->percpu->first, NULL);
        __this_cpu_write(cache->percpu->count, 0);
 end:
        local_irq_restore(flags);
index e59094981175cd6c390b5ed83a2dec15d8e2407e..37be6e226d1b46fefe8e0cf554580b1faf19cfb8 100644 (file)
@@ -552,9 +552,8 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
            && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
                rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
                scat = &rm->data.op_sg[sg];
-               ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
-               ret = min_t(int, ret, scat->length - conn->c_xmit_data_off);
-               return ret;
+               ret = max_t(int, RDS_CONG_MAP_BYTES, scat->length);
+               return sizeof(struct rds_header) + ret;
        }
 
        /* FIXME we may overallocate here */
index 33af77246bfeb90c6b31bfe6163dc2c9cfbda787..62ced6516c586f5c7b5cb779e079ad57b72b7518 100644 (file)
@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (msg->msg_name) {
                struct sockaddr_rose *srose;
+               struct full_sockaddr_rose *full_srose = msg->msg_name;
 
                memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
                srose = msg->msg_name;
@@ -1260,18 +1261,9 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
                srose->srose_addr   = rose->dest_addr;
                srose->srose_call   = rose->dest_call;
                srose->srose_ndigis = rose->dest_ndigis;
-               if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) {
-                       struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name;
-                       for (n = 0 ; n < rose->dest_ndigis ; n++)
-                               full_srose->srose_digis[n] = rose->dest_digis[n];
-                       msg->msg_namelen = sizeof(struct full_sockaddr_rose);
-               } else {
-                       if (rose->dest_ndigis >= 1) {
-                               srose->srose_ndigis = 1;
-                               srose->srose_digi = rose->dest_digis[0];
-                       }
-                       msg->msg_namelen = sizeof(struct sockaddr_rose);
-               }
+               for (n = 0 ; n < rose->dest_ndigis ; n++)
+                       full_srose->srose_digis[n] = rose->dest_digis[n];
+               msg->msg_namelen = sizeof(struct full_sockaddr_rose);
        }
 
        skb_free_datagram(sk, skb);
index fd7072827a40139c4ffba595aaa261282641e37f..69cb848e83455035a3e9ad85b2d7922434069d7e 100644 (file)
@@ -270,6 +270,16 @@ int tcf_register_action(struct tc_action_ops *act)
 {
        struct tc_action_ops *a, **ap;
 
+       /* Must supply act, dump, cleanup and init */
+       if (!act->act || !act->dump || !act->cleanup || !act->init)
+               return -EINVAL;
+
+       /* Supply defaults */
+       if (!act->lookup)
+               act->lookup = tcf_hash_search;
+       if (!act->walk)
+               act->walk = tcf_generic_walker;
+
        write_lock(&act_mod_lock);
        for (ap = &act_base; (a = *ap) != NULL; ap = &a->next) {
                if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
@@ -381,7 +391,7 @@ int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
        }
        while ((a = act) != NULL) {
 repeat:
-               if (a->ops && a->ops->act) {
+               if (a->ops) {
                        ret = a->ops->act(skb, a, res);
                        if (TC_MUNGED & skb->tc_verd) {
                                /* copied already, allow trampling */
@@ -405,7 +415,7 @@ void tcf_action_destroy(struct tc_action *act, int bind)
        struct tc_action *a;
 
        for (a = act; a; a = act) {
-               if (a->ops && a->ops->cleanup) {
+               if (a->ops) {
                        if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
                                module_put(a->ops->owner);
                        act = act->next;
@@ -424,7 +434,7 @@ tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        int err = -EINVAL;
 
-       if (a->ops == NULL || a->ops->dump == NULL)
+       if (a->ops == NULL)
                return err;
        return a->ops->dump(skb, a, bind, ref);
 }
@@ -436,7 +446,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
 
-       if (a->ops == NULL || a->ops->dump == NULL)
+       if (a->ops == NULL)
                return err;
 
        if (nla_put_string(skb, TCA_KIND, a->ops->kind))
@@ -723,8 +733,6 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
        a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
        if (a->ops == NULL)
                goto err_free;
-       if (a->ops->lookup == NULL)
-               goto err_mod;
        err = -ENOENT;
        if (a->ops->lookup(a, index) == 0)
                goto err_mod;
@@ -1084,12 +1092,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
        memset(&a, 0, sizeof(struct tc_action));
        a.ops = a_o;
 
-       if (a_o->walk == NULL) {
-               WARN(1, "tc_dump_action: %s !capable of dumping table\n",
-                    a_o->kind);
-               goto out_module_put;
-       }
-
        nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
                        cb->nlh->nlmsg_type, sizeof(*t), 0);
        if (!nlh)
index 3a4c0caa1f7de0fdfdb618bac9308aa32330c7f7..11fe1a416433f1fe2ea46c86ee753826e523b716 100644 (file)
@@ -77,16 +77,16 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
                                     &csum_idx_gen, &csum_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_csum(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_csum(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &csum_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &csum_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
+       p = to_tcf_csum(pc);
        spin_lock_bh(&p->tcf_lock);
        p->tcf_action = parm->action;
        p->update_flags = parm->update_flags;
@@ -585,9 +585,7 @@ static struct tc_action_ops act_csum_ops = {
        .act            = tcf_csum,
        .dump           = tcf_csum_dump,
        .cleanup        = tcf_csum_cleanup,
-       .lookup         = tcf_hash_search,
        .init           = tcf_csum_init,
-       .walk           = tcf_generic_walker
 };
 
 MODULE_DESCRIPTION("Checksum updating actions");
index fd2b3cff5fa28cf4da25690da9e7bad410c60a78..eb9ba60ebab4394527d10f25511b36b5aff84a32 100644 (file)
@@ -102,10 +102,11 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &gact_hash_info);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_hash_release(pc, bind, &gact_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        gact = to_gact(pc);
@@ -206,9 +207,7 @@ static struct tc_action_ops act_gact_ops = {
        .act            =       tcf_gact,
        .dump           =       tcf_gact_dump,
        .cleanup        =       tcf_gact_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_gact_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
index 60d88b6b9560bc0a7836fa0cba845ddd6a57cb3c..dcbfe8ce04a6a30ee9ce273f8e82196a5ba4a319 100644 (file)
@@ -141,10 +141,12 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                        return PTR_ERR(pc);
                ret = ACT_P_CREATED;
        } else {
-               if (!ovr) {
-                       tcf_ipt_release(to_ipt(pc), bind);
+               if (bind)/* dont override defaults */
+                       return 0;
+               tcf_ipt_release(to_ipt(pc), bind);
+
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        ipt = to_ipt(pc);
 
@@ -298,9 +300,7 @@ static struct tc_action_ops act_ipt_ops = {
        .act            =       tcf_ipt,
        .dump           =       tcf_ipt_dump,
        .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
 };
 
 static struct tc_action_ops act_xt_ops = {
@@ -312,9 +312,7 @@ static struct tc_action_ops act_xt_ops = {
        .act            =       tcf_ipt,
        .dump           =       tcf_ipt_dump,
        .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");
index 977c10e0631b6dfe4ead45af617c0ad93c4a0759..252378121ce7cd1848beab20aa666389937bf610 100644 (file)
@@ -271,9 +271,7 @@ static struct tc_action_ops act_mirred_ops = {
        .act            =       tcf_mirred,
        .dump           =       tcf_mirred_dump,
        .cleanup        =       tcf_mirred_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_mirred_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002)");
index 876f0ef29694a3f28260a221d0862d4fe3756f8d..76869538d0287148e48bf43660d3e243912a6e30 100644 (file)
@@ -70,15 +70,15 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                                     &nat_idx_gen, &nat_hash_info);
                if (IS_ERR(pc))
                        return PTR_ERR(pc);
-               p = to_tcf_nat(pc);
                ret = ACT_P_CREATED;
        } else {
-               p = to_tcf_nat(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &nat_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &nat_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
+       p = to_tcf_nat(pc);
 
        spin_lock_bh(&p->tcf_lock);
        p->old_addr = parm->old_addr;
@@ -308,9 +308,7 @@ static struct tc_action_ops act_nat_ops = {
        .act            =       tcf_nat,
        .dump           =       tcf_nat_dump,
        .cleanup        =       tcf_nat_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_nat_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_DESCRIPTION("Stateless NAT actions");
index 7ed78c9e505cf7e18bc5a0b066837d19d33d4b10..7aa2dcd989f842976c57d449452d2e0458a7b32c 100644 (file)
@@ -84,10 +84,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                p = to_pedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &pedit_hash_info);
+               tcf_hash_release(pc, bind, &pedit_hash_info);
+               if (bind)
+                       return 0;
+               if (!ovr)
                        return -EEXIST;
-               }
+
                if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
                        keys = kmalloc(ksize, GFP_KERNEL);
                        if (keys == NULL)
@@ -243,9 +245,7 @@ static struct tc_action_ops act_pedit_ops = {
        .act            =       tcf_pedit,
        .dump           =       tcf_pedit_dump,
        .cleanup        =       tcf_pedit_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_pedit_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
index 272d8e924cf6b2467e2772898aca2d7895131545..ef246d87e68bbdf628bc00eebb05e9cb88a3cb87 100644 (file)
@@ -177,10 +177,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
+                               return 0;
                        }
                        if (ovr)
                                goto override;
-                       return ret;
+                       /* not replacing */
+                       return -EEXIST;
                }
        }
 
@@ -407,7 +409,6 @@ static struct tc_action_ops act_police_ops = {
        .act            =       tcf_act_police,
        .dump           =       tcf_act_police_dump,
        .cleanup        =       tcf_act_police_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_act_police_locate,
        .walk           =       tcf_act_police_walker
 };
index 7725eb4ab756caa841eca2e0f4778880c310e5c4..f7b45ab85388748e9f730939b7f214952f8df84e 100644 (file)
@@ -142,10 +142,13 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
-               if (!ovr) {
-                       tcf_simp_release(d, bind);
+
+               if (bind)
+                       return 0;
+               tcf_simp_release(d, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
+
                reset_policy(d, defdata, parm);
        }
 
@@ -201,7 +204,6 @@ static struct tc_action_ops act_simp_ops = {
        .dump           =       tcf_simp_dump,
        .cleanup        =       tcf_simp_cleanup,
        .init           =       tcf_simp_init,
-       .walk           =       tcf_generic_walker,
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2005)");
index cb4221171f93f0c5b8fbb98f41b11241aa17d02a..8fe9d25c3008ece001d4da815cdf4f50c893fdab 100644 (file)
@@ -120,10 +120,11 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                ret = ACT_P_CREATED;
        } else {
                d = to_skbedit(pc);
-               if (!ovr) {
-                       tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (bind)
+                       return 0;
+               tcf_hash_release(pc, bind, &skbedit_hash_info);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
 
        spin_lock_bh(&d->tcf_lock);
@@ -203,7 +204,6 @@ static struct tc_action_ops act_skbedit_ops = {
        .dump           =       tcf_skbedit_dump,
        .cleanup        =       tcf_skbedit_cleanup,
        .init           =       tcf_skbedit_init,
-       .walk           =       tcf_generic_walker,
 };
 
 MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
index 922a09406ba70573499877ac3e561c9ee7b61a5c..7fc899a943a8fa8368415bc0c6c8a939bd042963 100644 (file)
@@ -126,7 +126,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
 
        HARD_TX_LOCK(dev, txq, smp_processor_id());
        if (!netif_xmit_frozen_or_stopped(txq))
-               ret = dev_hard_start_xmit(skb, dev, txq, NULL);
+               ret = dev_hard_start_xmit(skb, dev, txq);
 
        HARD_TX_UNLOCK(dev, txq);
 
index 0e1e38b40025fd111f50bfce339a6d2e7cae1252..717b2108f852b52399270a5be516441d9c79ed83 100644 (file)
@@ -1477,11 +1477,22 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                sch_tree_lock(sch);
        }
 
+       rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
+
+       ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
+
+       psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
+       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
+
        /* it used to be a nasty bug here, we have to check that node
         * is really leaf before changing cl->un.leaf !
         */
        if (!cl->level) {
-               cl->quantum = hopt->rate.rate / q->rate2quantum;
+               u64 quantum = cl->rate.rate_bytes_ps;
+
+               do_div(quantum, q->rate2quantum);
+               cl->quantum = min_t(u64, quantum, INT_MAX);
+
                if (!hopt->quantum && cl->quantum < 1000) {
                        pr_warning(
                               "HTB: quantum of class %X is small. Consider r2q change.\n",
@@ -1500,13 +1511,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                        cl->prio = TC_HTB_NUMPRIO - 1;
        }
 
-       rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
-
-       ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
-
-       psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
-       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
-
        cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
        cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer);
 
index 75c94e59a3bd3889cd87460afe87ac611eeb024e..bccd52b36e97be79d446e233dedc960fe65d5f16 100644 (file)
@@ -215,10 +215,10 @@ static bool loss_4state(struct netem_sched_data *q)
                if (rnd < clg->a4) {
                        clg->state = 4;
                        return true;
-               } else if (clg->a4 < rnd && rnd < clg->a1) {
+               } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
                        clg->state = 3;
                        return true;
-               } else if (clg->a1 < rnd)
+               } else if (clg->a1 + clg->a4 < rnd)
                        clg->state = 1;
 
                break;
@@ -268,10 +268,11 @@ static bool loss_gilb_ell(struct netem_sched_data *q)
                        clg->state = 2;
                if (net_random() < clg->a4)
                        return true;
+               break;
        case 2:
                if (net_random() < clg->a2)
                        clg->state = 1;
-               if (clg->a3 > net_random())
+               if (net_random() > clg->a3)
                        return true;
        }
 
index 68f98595819c1224f7e64ad368ad51155ff07fea..887e672f9d7d4b185542957bcb7e10b7d8a70cec 100644 (file)
@@ -21,6 +21,7 @@
 #include <net/netlink.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
+#include <net/tcp.h>
 
 
 /*     Simple Token Bucket Filter.
@@ -117,6 +118,48 @@ struct tbf_sched_data {
 };
 
 
+/* Time to Length, convert time in ns to length in bytes
+ * to determinate how many bytes can be sent in given time.
+ */
+static u64 psched_ns_t2l(const struct psched_ratecfg *r,
+                        u64 time_in_ns)
+{
+       /* The formula is :
+        * len = (time_in_ns * r->rate_bytes_ps) / NSEC_PER_SEC
+        */
+       u64 len = time_in_ns * r->rate_bytes_ps;
+
+       do_div(len, NSEC_PER_SEC);
+
+       if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) {
+               do_div(len, 53);
+               len = len * 48;
+       }
+
+       if (len > r->overhead)
+               len -= r->overhead;
+       else
+               len = 0;
+
+       return len;
+}
+
+/*
+ * Return length of individual segments of a gso packet,
+ * including all headers (MAC, IP, TCP/UDP)
+ */
+static unsigned int skb_gso_seglen(const struct sk_buff *skb)
+{
+       unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
+       const struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+       if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
+               hdr_len += tcp_hdrlen(skb);
+       else
+               hdr_len += sizeof(struct udphdr);
+       return hdr_len + shinfo->gso_size;
+}
+
 /* GSO packet is too big, segment it so that tbf can transmit
  * each segment in time
  */
@@ -136,12 +179,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
        while (segs) {
                nskb = segs->next;
                segs->next = NULL;
-               if (likely(segs->len <= q->max_size)) {
-                       qdisc_skb_cb(segs)->pkt_len = segs->len;
-                       ret = qdisc_enqueue(segs, q->qdisc);
-               } else {
-                       ret = qdisc_reshape_fail(skb, sch);
-               }
+               qdisc_skb_cb(segs)->pkt_len = segs->len;
+               ret = qdisc_enqueue(segs, q->qdisc);
                if (ret != NET_XMIT_SUCCESS) {
                        if (net_xmit_drop_count(ret))
                                sch->qstats.drops++;
@@ -163,7 +202,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
-               if (skb_is_gso(skb))
+               if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size)
                        return tbf_segment(skb, sch);
                return qdisc_reshape_fail(skb, sch);
        }
@@ -276,10 +315,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        struct tbf_sched_data *q = qdisc_priv(sch);
        struct nlattr *tb[TCA_TBF_MAX + 1];
        struct tc_tbf_qopt *qopt;
-       struct qdisc_rate_table *rtab = NULL;
-       struct qdisc_rate_table *ptab = NULL;
        struct Qdisc *child = NULL;
-       int max_size, n;
+       struct psched_ratecfg rate;
+       struct psched_ratecfg peak;
+       u64 max_size;
+       s64 buffer, mtu;
        u64 rate64 = 0, prate64 = 0;
 
        err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy);
@@ -291,33 +331,13 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                goto done;
 
        qopt = nla_data(tb[TCA_TBF_PARMS]);
-       rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]);
-       if (rtab == NULL)
-               goto done;
+       if (qopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
+               qdisc_put_rtab(qdisc_get_rtab(&qopt->rate,
+                                             tb[TCA_TBF_RTAB]));
 
-       if (qopt->peakrate.rate) {
-               if (qopt->peakrate.rate > qopt->rate.rate)
-                       ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]);
-               if (ptab == NULL)
-                       goto done;
-       }
-
-       for (n = 0; n < 256; n++)
-               if (rtab->data[n] > qopt->buffer)
-                       break;
-       max_size = (n << qopt->rate.cell_log) - 1;
-       if (ptab) {
-               int size;
-
-               for (n = 0; n < 256; n++)
-                       if (ptab->data[n] > qopt->mtu)
-                               break;
-               size = (n << qopt->peakrate.cell_log) - 1;
-               if (size < max_size)
-                       max_size = size;
-       }
-       if (max_size < 0)
-               goto done;
+       if (qopt->peakrate.linklayer == TC_LINKLAYER_UNAWARE)
+                       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);
@@ -331,6 +351,39 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                }
        }
 
+       buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
+       mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
+
+       if (tb[TCA_TBF_RATE64])
+               rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
+       psched_ratecfg_precompute(&rate, &qopt->rate, rate64);
+
+       max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+
+       if (qopt->peakrate.rate) {
+               if (tb[TCA_TBF_PRATE64])
+                       prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
+               psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64);
+               if (peak.rate_bytes_ps <= rate.rate_bytes_ps) {
+                       pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n",
+                                           peak.rate_bytes_ps, rate.rate_bytes_ps);
+                       err = -EINVAL;
+                       goto done;
+               }
+
+               max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+       }
+
+       if (max_size < psched_mtu(qdisc_dev(sch)))
+               pr_warn_ratelimited("sch_tbf: burst %llu is lower than device %s mtu (%u) !\n",
+                                   max_size, qdisc_dev(sch)->name,
+                                   psched_mtu(qdisc_dev(sch)));
+
+       if (!max_size) {
+               err = -EINVAL;
+               goto done;
+       }
+
        sch_tree_lock(sch);
        if (child) {
                qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
@@ -344,13 +397,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
 
-       if (tb[TCA_TBF_RATE64])
-               rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
-       psched_ratecfg_precompute(&q->rate, &rtab->rate, rate64);
-       if (ptab) {
-               if (tb[TCA_TBF_PRATE64])
-                       prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
-               psched_ratecfg_precompute(&q->peak, &ptab->rate, prate64);
+       memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg));
+       if (qopt->peakrate.rate) {
+               memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg));
                q->peak_present = true;
        } else {
                q->peak_present = false;
@@ -359,10 +408,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        sch_tree_unlock(sch);
        err = 0;
 done:
-       if (rtab)
-               qdisc_put_rtab(rtab);
-       if (ptab)
-               qdisc_put_rtab(ptab);
        return err;
 }
 
index 68a27f9796d2ece54bcb53b98a47e8f98645077b..31ed008c8e13e88b88935c5d83a503bdc089076e 100644 (file)
@@ -154,8 +154,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
-               min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ;
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
 
        /* Initializes the timers */
        for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -291,8 +290,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
                asoc->peer.ipv6_address = 1;
        INIT_LIST_HEAD(&asoc->asocs);
 
-       asoc->autoclose = sp->autoclose;
-
        asoc->default_stream = sp->default_stream;
        asoc->default_ppid = sp->default_ppid;
        asoc->default_flags = sp->default_flags;
index e650978daf279abe9b1277dabb22f2e865c64a7a..0fb140f8f088abe9421c401680731fb1c916a154 100644 (file)
@@ -474,10 +474,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                         * for a given destination transport address.
                         */
 
-                       if (!tp->rto_pending) {
+                       if (!chunk->resent && !tp->rto_pending) {
                                chunk->rtt_in_progress = 1;
                                tp->rto_pending = 1;
                        }
+
                        has_data = 1;
                }
 
@@ -580,7 +581,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                unsigned long timeout;
 
                /* Restart the AUTOCLOSE timer when sending data. */
-               if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
+               if (sctp_state(asoc, ESTABLISHED) &&
+                   asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                        timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
                        timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
 
index 94df7587786992fa0a6341caaed284beb1df42e0..59268f6e2c36a0b32ac6b768dea15b7b6be0021d 100644 (file)
@@ -208,8 +208,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
        INIT_LIST_HEAD(&q->retransmit);
        INIT_LIST_HEAD(&q->sacked);
        INIT_LIST_HEAD(&q->abandoned);
-
-       q->empty = 1;
 }
 
 /* Free the outqueue structure and any related pending chunks.
@@ -332,7 +330,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                                SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
                        else
                                SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS);
-                       q->empty = 0;
                        break;
                }
        } else {
@@ -446,6 +443,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                                transport->rto_pending = 0;
                        }
 
+                       chunk->resent = 1;
+
                        /* Move the chunk to the retransmit queue. The chunks
                         * on the retransmit queue are always kept in order.
                         */
@@ -652,7 +651,6 @@ redo:
                        if (chunk->fast_retransmit == SCTP_NEED_FRTX)
                                chunk->fast_retransmit = SCTP_DONT_FRTX;
 
-                       q->empty = 0;
                        q->asoc->stats.rtxchunks++;
                        break;
                }
@@ -1063,8 +1061,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                        sctp_transport_reset_timers(transport);
 
-                       q->empty = 0;
-
                        /* Only let one DATA chunk get bundled with a
                         * COOKIE-ECHO chunk.
                         */
@@ -1273,29 +1269,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
                 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,
                 asoc->adv_peer_ack_point);
 
-       /* See if all chunks are acked.
-        * Make sure the empty queue handler will get run later.
-        */
-       q->empty = (list_empty(&q->out_chunk_list) &&
-                   list_empty(&q->retransmit));
-       if (!q->empty)
-               goto finish;
-
-       list_for_each_entry(transport, transport_list, transports) {
-               q->empty = q->empty && list_empty(&transport->transmitted);
-               if (!q->empty)
-                       goto finish;
-       }
-
-       pr_debug("%s: sack queue is empty\n", __func__);
-finish:
-       return q->empty;
+       return sctp_outq_is_empty(q);
 }
 
-/* Is the outqueue empty?  */
+/* Is the outqueue empty?
+ * The queue is empty when we have not pending data, no in-flight data
+ * and nothing pending retransmissions.
+ */
 int sctp_outq_is_empty(const struct sctp_outq *q)
 {
-       return q->empty;
+       return q->out_qlen == 0 && q->outstanding_bytes == 0 &&
+              list_empty(&q->retransmit);
 }
 
 /********************************************************************
@@ -1375,6 +1359,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                 * instance).
                                 */
                                if (!tchunk->tsn_gap_acked &&
+                                   !tchunk->resent &&
                                    tchunk->rtt_in_progress) {
                                        tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
@@ -1391,7 +1376,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                         */
                        if (!tchunk->tsn_gap_acked) {
                                tchunk->tsn_gap_acked = 1;
-                               *highest_new_tsn_in_sack = tsn;
+                               if (TSN_lt(*highest_new_tsn_in_sack, tsn))
+                                       *highest_new_tsn_in_sack = tsn;
                                bytes_acked += sctp_data_size(tchunk);
                                if (!tchunk->transport)
                                        migrate_bytes += sctp_data_size(tchunk);
index 53c452efb40b4ab761a54acc37f8c1333fc73fd7..5e68b94ee64012571bc4d5f277a9cc594467cc3b 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
+MODULE_SOFTDEP("pre: sctp");
 MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>");
 MODULE_DESCRIPTION("SCTP snooper");
 MODULE_LICENSE("GPL");
@@ -182,6 +183,20 @@ static struct jprobe sctp_recv_probe = {
        .entry  = jsctp_sf_eat_sack,
 };
 
+static __init int sctp_setup_jprobe(void)
+{
+       int ret = register_jprobe(&sctp_recv_probe);
+
+       if (ret) {
+               if (request_module("sctp"))
+                       goto out;
+               ret = register_jprobe(&sctp_recv_probe);
+       }
+
+out:
+       return ret;
+}
+
 static __init int sctpprobe_init(void)
 {
        int ret = -ENOMEM;
@@ -202,7 +217,7 @@ static __init int sctpprobe_init(void)
                         &sctpprobe_fops))
                goto free_kfifo;
 
-       ret = register_jprobe(&sctp_recv_probe);
+       ret = sctp_setup_jprobe();
        if (ret)
                goto remove_proc;
 
index dfe3f36ff2aa27165b35a39d382583759cd3ebae..a26065be728901ed3c7e35690bafc51deabab115 100644 (file)
@@ -820,7 +820,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
 
-       if (new_asoc->autoclose)
+       if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -908,7 +908,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
        SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -2970,7 +2970,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net,
        if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
                force = SCTP_FORCE();
 
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@ -3878,7 +3878,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net,
                                SCTP_CHUNK(chunk));
 
        /* Count this as receiving DATA. */
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@ -5267,7 +5267,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
 
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -5346,7 +5346,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
index 72046b9729a8a6a669fb9c75446de8ef2fe345c6..42b709c95cf3d0f97b1de88d727a4258e8835396 100644 (file)
@@ -2196,6 +2196,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
                                     unsigned int optlen)
 {
        struct sctp_sock *sp = sctp_sk(sk);
+       struct net *net = sock_net(sk);
 
        /* Applicable to UDP-style socket only */
        if (sctp_style(sk, TCP))
@@ -2205,6 +2206,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
        if (copy_from_user(&sp->autoclose, optval, optlen))
                return -EFAULT;
 
+       if (sp->autoclose > net->sctp.max_autoclose)
+               sp->autoclose = net->sctp.max_autoclose;
+
        return 0;
 }
 
@@ -2811,6 +2815,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne
 {
        struct sctp_rtoinfo rtoinfo;
        struct sctp_association *asoc;
+       unsigned long rto_min, rto_max;
+       struct sctp_sock *sp = sctp_sk(sk);
 
        if (optlen != sizeof (struct sctp_rtoinfo))
                return -EINVAL;
@@ -2824,26 +2830,36 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne
        if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
                return -EINVAL;
 
+       rto_max = rtoinfo.srto_max;
+       rto_min = rtoinfo.srto_min;
+
+       if (rto_max)
+               rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max;
+       else
+               rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max;
+
+       if (rto_min)
+               rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min;
+       else
+               rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min;
+
+       if (rto_min > rto_max)
+               return -EINVAL;
+
        if (asoc) {
                if (rtoinfo.srto_initial != 0)
                        asoc->rto_initial =
                                msecs_to_jiffies(rtoinfo.srto_initial);
-               if (rtoinfo.srto_max != 0)
-                       asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
-               if (rtoinfo.srto_min != 0)
-                       asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);
+               asoc->rto_max = rto_max;
+               asoc->rto_min = rto_min;
        } else {
                /* If there is no association or the association-id = 0
                 * set the values to the endpoint.
                 */
-               struct sctp_sock *sp = sctp_sk(sk);
-
                if (rtoinfo.srto_initial != 0)
                        sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
-               if (rtoinfo.srto_max != 0)
-                       sp->rtoinfo.srto_max = rtoinfo.srto_max;
-               if (rtoinfo.srto_min != 0)
-                       sp->rtoinfo.srto_min = rtoinfo.srto_min;
+               sp->rtoinfo.srto_max = rto_max;
+               sp->rtoinfo.srto_min = rto_min;
        }
 
        return 0;
index 6b36561a1b3b7cceab5f5a4a9dce7aa2bc362266..b0565afb61c740bcd0ed9863049dc74cd62072f0 100644 (file)
@@ -56,11 +56,16 @@ extern long sysctl_sctp_mem[3];
 extern int sysctl_sctp_rmem[3];
 extern int sysctl_sctp_wmem[3];
 
-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
-
                                loff_t *ppos);
+
 static struct ctl_table sctp_table[] = {
        {
                .procname       = "sctp_mem",
@@ -102,17 +107,17 @@ static struct ctl_table sctp_net_table[] = {
                .data           = &init_net.sctp.rto_min,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_sctp_do_rto_min,
                .extra1         = &one,
-               .extra2         = &timer_max
+               .extra2         = &init_net.sctp.rto_max
        },
        {
                .procname       = "rto_max",
                .data           = &init_net.sctp.rto_max,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .proc_handler   = proc_sctp_do_rto_max,
+               .extra1         = &init_net.sctp.rto_min,
                .extra2         = &timer_max
        },
        {
@@ -294,8 +299,7 @@ static struct ctl_table sctp_net_table[] = {
        { /* sentinel */ }
 };
 
-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
                                loff_t *ppos)
 {
@@ -342,6 +346,60 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
        return ret;
 }
 
+static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_min;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_min = new_value;
+       }
+       return ret;
+}
+
+static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_max;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_max = new_value;
+       }
+       return ret;
+}
+
 int sctp_sysctl_net_register(struct net *net)
 {
        struct ctl_table *table;
index e332efb124cc0c34f93786232353c37dd2e10ea1..efc46ffed1fd63a5fb510046bc6fd013dd99c252 100644 (file)
@@ -573,7 +573,7 @@ void sctp_transport_burst_limited(struct sctp_transport *t)
        u32 old_cwnd = t->cwnd;
        u32 max_burst_bytes;
 
-       if (t->burst_limited)
+       if (t->burst_limited || asoc->max_burst == 0)
                return;
 
        max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
index 0b18693f2be6deb2f6f6b6bbf99aa131c767e830..e83c416708af5554f89c98723bba150b8750b3f0 100644 (file)
@@ -1973,7 +1973,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
        if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
                return -EFAULT;
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-               return -EINVAL;
+               kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        return 0;
 }
 
index 97912b40c254d8a270e18f71e9e5b714e0dbcba8..42fdfc634e568a58bda35d2dbb1effbf44dd1bd4 100644 (file)
@@ -1517,7 +1517,7 @@ out:
 static int
 gss_refresh_null(struct rpc_task *task)
 {
-       return -EACCES;
+       return 0;
 }
 
 static __be32 *
index fd4eeeaa972a6f4226f1dce420d7fb0b17670c78..c6d3f75a9e1bba6f99cff5aed75d8e5a96f94484 100644 (file)
@@ -113,7 +113,6 @@ err:
 static void tipc_core_stop(void)
 {
        tipc_netlink_stop();
-       tipc_handler_stop();
        tipc_cfg_stop();
        tipc_subscr_stop();
        tipc_nametbl_stop();
@@ -146,9 +145,10 @@ static int tipc_core_start(void)
                res = tipc_subscr_start();
        if (!res)
                res = tipc_cfg_init();
-       if (res)
+       if (res) {
+               tipc_handler_stop();
                tipc_core_stop();
-
+       }
        return res;
 }
 
@@ -178,6 +178,7 @@ 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 b36f0fcd9bdfe76d04adf287687190ada3e9ccca..e4bc8a2967447fbde1f39d0d19146f2c7848ac99 100644 (file)
@@ -56,12 +56,13 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument)
 {
        struct queue_item *item;
 
+       spin_lock_bh(&qitem_lock);
        if (!handler_enabled) {
                pr_err("Signal request ignored by handler\n");
+               spin_unlock_bh(&qitem_lock);
                return -ENOPROTOOPT;
        }
 
-       spin_lock_bh(&qitem_lock);
        item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
        if (!item) {
                pr_err("Signal queue out of memory\n");
@@ -112,10 +113,14 @@ void tipc_handler_stop(void)
        struct list_head *l, *n;
        struct queue_item *item;
 
-       if (!handler_enabled)
+       spin_lock_bh(&qitem_lock);
+       if (!handler_enabled) {
+               spin_unlock_bh(&qitem_lock);
                return;
-
+       }
        handler_enabled = 0;
+       spin_unlock_bh(&qitem_lock);
+
        tasklet_kill(&tipc_tasklet);
 
        spin_lock_bh(&qitem_lock);
index 69cd9bf3f561d64d377ddb65091b98e1017e15cf..13b9877458201fa4d5bb14a36892825272229050 100644 (file)
@@ -1498,6 +1498,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
                int type;
 
                head = head->next;
+               buf->next = NULL;
 
                /* Ensure bearer is still enabled */
                if (unlikely(!b_ptr->active))
index c081a7632302ca0798c193b039214466c3180184..d43f3182b1d4cc1628817d882c9d006006e27e1e 100644 (file)
@@ -251,18 +251,15 @@ struct tipc_port *tipc_createport(struct sock *sk,
        return p_ptr;
 }
 
-int tipc_deleteport(u32 ref)
+int tipc_deleteport(struct tipc_port *p_ptr)
 {
-       struct tipc_port *p_ptr;
        struct sk_buff *buf = NULL;
 
-       tipc_withdraw(ref, 0, NULL);
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
+       tipc_withdraw(p_ptr, 0, NULL);
 
-       tipc_ref_discard(ref);
-       tipc_port_unlock(p_ptr);
+       spin_lock_bh(p_ptr->lock);
+       tipc_ref_discard(p_ptr->ref);
+       spin_unlock_bh(p_ptr->lock);
 
        k_cancel_timer(&p_ptr->timer);
        if (p_ptr->connected) {
@@ -704,47 +701,36 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 }
 
 
-int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
+                struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        u32 key;
-       int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
+       if (p_ptr->connected)
                return -EINVAL;
+       key = p_ptr->ref + p_ptr->pub_count + 1;
+       if (key == p_ptr->ref)
+               return -EADDRINUSE;
 
-       if (p_ptr->connected)
-               goto exit;
-       key = ref + p_ptr->pub_count + 1;
-       if (key == ref) {
-               res = -EADDRINUSE;
-               goto exit;
-       }
        publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
                                    scope, p_ptr->ref, key);
        if (publ) {
                list_add(&publ->pport_list, &p_ptr->publications);
                p_ptr->pub_count++;
                p_ptr->published = 1;
-               res = 0;
+               return 0;
        }
-exit:
-       tipc_port_unlock(p_ptr);
-       return res;
+       return -EINVAL;
 }
 
-int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
+                 struct tipc_name_seq const *seq)
 {
-       struct tipc_port *p_ptr;
        struct publication *publ;
        struct publication *tpubl;
        int res = -EINVAL;
 
-       p_ptr = tipc_port_lock(ref);
-       if (!p_ptr)
-               return -EINVAL;
        if (!seq) {
                list_for_each_entry_safe(publ, tpubl,
                                         &p_ptr->publications, pport_list) {
@@ -771,7 +757,6 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
        }
        if (list_empty(&p_ptr->publications))
                p_ptr->published = 0;
-       tipc_port_unlock(p_ptr);
        return res;
 }
 
index 9122535973430edff99e8ee6070a091975dea457..34f12bd4074e49ff8b4c7809bfe0bc706941ec7c 100644 (file)
@@ -116,7 +116,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err);
 
 void tipc_acknowledge(u32 port_ref, u32 ack);
 
-int tipc_deleteport(u32 portref);
+int tipc_deleteport(struct tipc_port *p_ptr);
 
 int tipc_portimportance(u32 portref, unsigned int *importance);
 int tipc_set_portimportance(u32 portref, unsigned int importance);
@@ -127,9 +127,9 @@ int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
 int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
 int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
 
-int tipc_publish(u32 portref, unsigned int scope,
+int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
                 struct tipc_name_seq const *name_seq);
-int tipc_withdraw(u32 portref, unsigned int scope,
+int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
                  struct tipc_name_seq const *name_seq);
 
 int tipc_connect(u32 portref, struct tipc_portid const *port);
index 3b61851bb9276ec733f7ab8c9d2179a5dd7fef4d..e741416d1d24d4655cd4096b07f84cd978c90cc7 100644 (file)
@@ -354,7 +354,7 @@ static int release(struct socket *sock)
         * Delete TIPC port; this ensures no more messages are queued
         * (also disconnects an active connection & sends a 'FIN-' to peer)
         */
-       res = tipc_deleteport(tport->ref);
+       res = tipc_deleteport(tport);
 
        /* Discard any remaining (connection-based) messages in receive queue */
        __skb_queue_purge(&sk->sk_receive_queue);
@@ -386,30 +386,46 @@ static int release(struct socket *sock)
  */
 static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
 {
+       struct sock *sk = sock->sk;
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
-       u32 portref = tipc_sk_port(sock->sk)->ref;
+       struct tipc_port *tport = tipc_sk_port(sock->sk);
+       int res = -EINVAL;
 
-       if (unlikely(!uaddr_len))
-               return tipc_withdraw(portref, 0, NULL);
+       lock_sock(sk);
+       if (unlikely(!uaddr_len)) {
+               res = tipc_withdraw(tport, 0, NULL);
+               goto exit;
+       }
 
-       if (uaddr_len < sizeof(struct sockaddr_tipc))
-               return -EINVAL;
-       if (addr->family != AF_TIPC)
-               return -EAFNOSUPPORT;
+       if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+               res = -EINVAL;
+               goto exit;
+       }
+       if (addr->family != AF_TIPC) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if (addr->addrtype == TIPC_ADDR_NAME)
                addr->addr.nameseq.upper = addr->addr.nameseq.lower;
-       else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
-               return -EAFNOSUPPORT;
+       else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+               res = -EAFNOSUPPORT;
+               goto exit;
+       }
 
        if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
            (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
-           (addr->addr.nameseq.type != TIPC_CFG_SRV))
-               return -EACCES;
+           (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
+               res = -EACCES;
+               goto exit;
+       }
 
-       return (addr->scope > 0) ?
-               tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
-               tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
+       res = (addr->scope > 0) ?
+               tipc_publish(tport, addr->scope, &addr->addr.nameseq) :
+               tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq);
+exit:
+       release_sock(sk);
+       return res;
 }
 
 /**
index 01625ccc3ae64ac3b5b1c664feec7f0136973e04..a427623ee574e88d9926c7972a0650c5c6f9a3eb 100644 (file)
@@ -530,13 +530,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
 static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t, int);
 
-static void unix_set_peek_off(struct sock *sk, int val)
+static int unix_set_peek_off(struct sock *sk, int val)
 {
        struct unix_sock *u = unix_sk(sk);
 
-       mutex_lock(&u->readlock);
+       if (mutex_lock_interruptible(&u->readlock))
+               return -EINTR;
+
        sk->sk_peek_off = val;
        mutex_unlock(&u->readlock);
+
+       return 0;
 }
 
 
@@ -714,7 +718,9 @@ static int unix_autobind(struct socket *sock)
        int err;
        unsigned int retries = 0;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               return err;
 
        err = 0;
        if (u->addr)
@@ -873,7 +879,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        addr_len = err;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               goto out;
 
        err = -EINVAL;
        if (u->addr)
index aff959e5a1b360e7cb467cade7f7d617544b3909..52b865fb7351ac3c221c120bc0cc236687a12513 100644 (file)
@@ -451,6 +451,15 @@ 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.
+        */
+       wiphy->flags &= ~WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
 #ifdef CONFIG_PM
        if (WARN_ON(wiphy->wowlan &&
                    (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
index 9d797df56649c5a47fdf1f61e665ee31e4b77e7c..89737ee2669a8de9bc8f02aa1c392052369d210b 100644 (file)
@@ -262,7 +262,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 
        /* try to find an IBSS channel if none requested ... */
        if (!wdev->wext.ibss.chandef.chan) {
-               wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+               struct ieee80211_channel *new_chan = NULL;
 
                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                        struct ieee80211_supported_band *sband;
@@ -278,18 +278,19 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
                                        continue;
                                if (chan->flags & IEEE80211_CHAN_DISABLED)
                                        continue;
-                               wdev->wext.ibss.chandef.chan = chan;
-                               wdev->wext.ibss.chandef.center_freq1 =
-                                       chan->center_freq;
+                               new_chan = chan;
                                break;
                        }
 
-                       if (wdev->wext.ibss.chandef.chan)
+                       if (new_chan)
                                break;
                }
 
-               if (!wdev->wext.ibss.chandef.chan)
+               if (!new_chan)
                        return -EINVAL;
+
+               cfg80211_chandef_create(&wdev->wext.ibss.chandef, new_chan,
+                                       NL80211_CHAN_NO_HT);
        }
 
        /* don't join -- SSID is not there */
@@ -363,9 +364,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
                return err;
 
        if (chan) {
-               wdev->wext.ibss.chandef.chan = chan;
-               wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
-               wdev->wext.ibss.chandef.center_freq1 = freq;
+               cfg80211_chandef_create(&wdev->wext.ibss.chandef, chan,
+                                       NL80211_CHAN_NO_HT);
                wdev->wext.ibss.channel_fixed = true;
        } else {
                /* cfg80211_ibss_wext_join will pick one if needed */
index a1eb21073176115a587f9eb1edf5d36dba582484..138dc3bb8b67d8c345531a95ce0c8342271ce79e 100644 (file)
@@ -2687,7 +2687,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_NEW_KEY);
        if (!hdr)
-               return -ENOBUFS;
+               goto nla_put_failure;
 
        cookie.msg = msg;
        cookie.idx = key_idx;
@@ -5349,6 +5349,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                                err = -EINVAL;
                                goto out_free;
                        }
+
+                       if (!wiphy->bands[band])
+                               continue;
+
                        err = ieee80211_get_ratemask(wiphy->bands[band],
                                                     nla_data(attr),
                                                     nla_len(attr),
@@ -9633,8 +9637,9 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
            nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
                goto nla_put_failure;
 
-       if (req->flags)
-               nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+       if (req->flags &&
+           nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
+               goto nla_put_failure;
 
        return 0;
  nla_put_failure:
@@ -11093,6 +11098,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                struct nlattr *reasons;
 
                reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+               if (!reasons)
+                       goto free_msg;
 
                if (wakeup->disconnect &&
                    nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
@@ -11118,16 +11125,18 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                                wakeup->pattern_idx))
                        goto free_msg;
 
-               if (wakeup->tcp_match)
-                       nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH);
+               if (wakeup->tcp_match &&
+                   nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
+                       goto free_msg;
 
-               if (wakeup->tcp_connlost)
-                       nla_put_flag(msg,
-                                    NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST);
+               if (wakeup->tcp_connlost &&
+                   nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
+                       goto free_msg;
 
-               if (wakeup->tcp_nomoretokens)
-                       nla_put_flag(msg,
-                               NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS);
+               if (wakeup->tcp_nomoretokens &&
+                   nla_put_flag(msg,
+                                NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
+                       goto free_msg;
 
                if (wakeup->packet) {
                        u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
@@ -11263,24 +11272,29 @@ void cfg80211_ft_event(struct net_device *netdev,
                return;
 
        hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
-       if (!hdr) {
-               nlmsg_free(msg);
-               return;
-       }
+       if (!hdr)
+               goto out;
 
-       nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
-       nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
-       nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap);
-       if (ft_event->ies)
-               nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
-       if (ft_event->ric_ies)
-               nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
-                       ft_event->ric_ies);
+       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
+               goto out;
+
+       if (ft_event->ies &&
+           nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
+               goto out;
+       if (ft_event->ric_ies &&
+           nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+                   ft_event->ric_ies))
+               goto out;
 
        genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
                                NL80211_MCGRP_MLME, GFP_KERNEL);
+       return;
+ out:
+       nlmsg_free(msg);
 }
 EXPORT_SYMBOL(cfg80211_ft_event);
 
index a271c27fac774ce987c0db6f1330ffbfca6dc7f7..722da616438cd1e933fb4d5e60a2c4846f44d186 100644 (file)
@@ -124,6 +124,10 @@ int ieee80211_radiotap_iterator_init(
        /* find payload start allowing for extended bitmap(s) */
 
        if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+               if ((unsigned long)iterator->_arg -
+                   (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+                   (unsigned long)iterator->_max_length)
+                       return -EINVAL;
                while (get_unaligned_le32(iterator->_arg) &
                                        (1 << IEEE80211_RADIOTAP_EXT)) {
                        iterator->_arg += sizeof(uint32_t);
index 65f800890d70d857c9b42d379caad887f5a98c74..d3c5bd7c6b513cd376a2e37857cb8f19919b5a43 100644 (file)
@@ -632,6 +632,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
        }
 #endif
 
+       if (!bss && (status == WLAN_STATUS_SUCCESS)) {
+               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
+               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+                                      wdev->ssid, wdev->ssid_len,
+                                      WLAN_CAPABILITY_ESS,
+                                      WLAN_CAPABILITY_ESS);
+               if (bss)
+                       cfg80211_hold_bss(bss_from_pub(bss));
+       }
+
        if (wdev->current_bss) {
                cfg80211_unhold_bss(wdev->current_bss);
                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
@@ -649,16 +659,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                return;
        }
 
-       if (!bss) {
-               WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect);
-               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-                                      wdev->ssid, wdev->ssid_len,
-                                      WLAN_CAPABILITY_ESS,
-                                      WLAN_CAPABILITY_ESS);
-               if (WARN_ON(!bss))
-                       return;
-               cfg80211_hold_bss(bss_from_pub(bss));
-       }
+       if (WARN_ON(!bss))
+               return;
 
        wdev->current_bss = bss_from_pub(bss);
 
index 4606cdfb859d59ac71a8e6d353a33d6f2a7110a0..31331723e810746d08f46c01928c20b2555018a8 100644 (file)
@@ -219,6 +219,13 @@ sub read_kconfig {
            $depends{$config} = $1;
        } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
            $depends{$config} .= " " . $1;
+       } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
+           my $dep = $3;
+           if ($dep !~ /^\s*(y|m|n)\s*$/) {
+               $dep =~ s/.*\sif\s+//;
+               $depends{$config} .= " " . $dep;
+               dprint "Added default depends $dep to $config\n";
+           }
 
        # Get the configs that select this config
        } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
index 32b10f53d0b4cbad76b13ef86d547ad864ae19c2..2dcb37736d8469a0e18e4c1ba262281e3fd8cf37 100644 (file)
@@ -82,7 +82,9 @@ kallsyms()
                kallsymopt="${kallsymopt} --all-symbols"
        fi
 
-       kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
+               kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+       fi
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
index d0da66396f6201b5dbce7e8b9aa2ae421aefd40a..91280b82da0874787e6947a18ed8381d1567b483 100755 (executable)
@@ -364,7 +364,8 @@ if ($arch eq "x86_64") {
 } elsif ($arch eq "blackfin") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $mcount_adjust = -4;
-} elsif ($arch eq "tilegx") {
+} elsif ($arch eq "tilegx" || $arch eq "tile") {
+    # Default to the newer TILE-Gx architecture if only "tile" is given.
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $type = ".quad";
     $alignment = 8;
index 5f7a8b663cb9c9eb59b32f4ce63076a6a86914cc..7941fbdfb050e573120f36b770ae8321130d8d01 100644 (file)
 #include <tools/be_byteshift.h>
 #include <tools/le_byteshift.h>
 
+#ifndef EM_ARCOMPACT
+#define EM_ARCOMPACT   93
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64     183
 #endif
@@ -268,6 +272,7 @@ do_file(char const *const fname)
        case EM_S390:
                custom_sort = sort_relative_table;
                break;
+       case EM_ARCOMPACT:
        case EM_ARM:
        case EM_AARCH64:
        case EM_MIPS:
index 9636e17c9f5d709ae735d60bccddd3d2bc481470..0356e1d437ca31cde30910567128168dbfd0a5ca 100644 (file)
@@ -148,6 +148,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                            int xattr_len, struct ima_template_entry **entry);
 int ima_store_template(struct ima_template_entry *entry, int violation,
                       struct inode *inode, const unsigned char *filename);
+void ima_free_template_entry(struct ima_template_entry *entry);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* rbtree tree calls to lookup, insert, delete
index 80374842fe0bb4cfef8a7dec8144eeff5278d408..c38bbce8c6a629e246d8f6bef7557e224707d88b 100644 (file)
 #include <crypto/hash_info.h>
 #include "ima.h"
 
+/*
+ * ima_free_template_entry - free an existing template entry
+ */
+void ima_free_template_entry(struct ima_template_entry *entry)
+{
+       int i;
+
+       for (i = 0; i < entry->template_desc->num_fields; i++)
+               kfree(entry->template_data[i].data);
+
+       kfree(entry);
+}
+
 /*
  * ima_alloc_init_template - create and initialize a new template entry
  */
@@ -37,6 +50,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
        if (!*entry)
                return -ENOMEM;
 
+       (*entry)->template_desc = template_desc;
        for (i = 0; i < template_desc->num_fields; i++) {
                struct ima_template_field *field = template_desc->fields[i];
                u32 len;
@@ -51,10 +65,9 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                (*entry)->template_data_len += sizeof(len);
                (*entry)->template_data_len += len;
        }
-       (*entry)->template_desc = template_desc;
        return 0;
 out:
-       kfree(*entry);
+       ima_free_template_entry(*entry);
        *entry = NULL;
        return result;
 }
@@ -134,7 +147,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
        }
        result = ima_store_template(entry, violation, inode, filename);
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
 err_out:
        integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
                            op, cause, result, 0);
@@ -269,7 +282,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        if (!result || result == -EEXIST)
                iint->flags |= IMA_MEASURED;
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
 }
 
 void ima_audit_measurement(struct integrity_iint_cache *iint,
index 15f34bd40abed1530216be53c59658b6245d280b..37122768554a9e69d4866f9c9a72864f157afef3 100644 (file)
@@ -63,7 +63,6 @@ static void __init ima_add_boot_aggregate(void)
                result = ima_calc_boot_aggregate(&hash.hdr);
                if (result < 0) {
                        audit_cause = "hashing_error";
-                       kfree(entry);
                        goto err_out;
                }
        }
@@ -76,7 +75,7 @@ static void __init ima_add_boot_aggregate(void)
        result = ima_store_template(entry, violation, NULL,
                                    boot_aggregate_name);
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
        return;
 err_out:
        integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
index 913e1927f916fccdfc7b0991d0f5795888291bbf..635695f6a185a1d24ee3d1bfb05d4f7ebe8cedb0 100644 (file)
@@ -110,7 +110,7 @@ static int template_desc_init_fields(const char *template_fmt,
                                     struct ima_template_field ***fields,
                                     int *num_fields)
 {
-       char *c, *template_fmt_copy;
+       char *c, *template_fmt_copy, *template_fmt_ptr;
        int template_num_fields = template_fmt_size(template_fmt);
        int i, result = 0;
 
@@ -127,7 +127,9 @@ static int template_desc_init_fields(const char *template_fmt,
                result = -ENOMEM;
                goto out;
        }
-       for (i = 0; (c = strsep(&template_fmt_copy, "|")) != NULL &&
+
+       template_fmt_ptr = template_fmt_copy;
+       for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL &&
             i < template_num_fields; i++) {
                struct ima_template_field *f = lookup_template_field(c);
 
index 7f44c3207a9bb95982d3bb41990568c41f64c54e..8137b27d641dad9080df66c829f8109472dbccc6 100644 (file)
@@ -70,7 +70,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
                 *
                 * TODO: Encrypt the stored data with a temporary key.
                 */
-               file = shmem_file_setup("", datalen, 0);
+               file = shmem_kernel_file_setup("", datalen, 0);
                if (IS_ERR(file)) {
                        ret = PTR_ERR(file);
                        goto err_quota;
index 55d110f0acedc96d17bcc5f5903aaa743ed6cb32..6e21c11e48bc1cd434664d28f83084b54db50bd6 100644 (file)
@@ -272,7 +272,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        }
 
        /* allocate and initialise the key and its description */
-       key = kmem_cache_alloc(key_jar, GFP_KERNEL);
+       key = kmem_cache_zalloc(key_jar, GFP_KERNEL);
        if (!key)
                goto no_memory_2;
 
@@ -293,18 +293,12 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        key->uid = uid;
        key->gid = gid;
        key->perm = perm;
-       key->flags = 0;
-       key->expiry = 0;
-       key->payload.data = NULL;
-       key->security = NULL;
 
        if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
                key->flags |= 1 << KEY_FLAG_IN_QUOTA;
        if (flags & KEY_ALLOC_TRUSTED)
                key->flags |= 1 << KEY_FLAG_TRUSTED;
 
-       memset(&key->type_data, 0, sizeof(key->type_data));
-
 #ifdef KEY_DEBUGGING
        key->magic = KEY_DEBUG_MAGIC;
 #endif
index 69f0cb7bab7e873f8d8997d71db7c42430f72ce6..d46cbc5e335e9c330ccd74a08fcbf78aeafe8c96 100644 (file)
@@ -160,7 +160,7 @@ static u64 mult_64x32_and_fold(u64 x, u32 y)
 static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key)
 {
        const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;
-       const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK;
+       const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK;
        const char *description = index_key->description;
        unsigned long hash, type;
        u32 piece;
@@ -194,10 +194,10 @@ static unsigned long hash_key_type_and_desc(const struct keyring_index_key *inde
         * ordinary keys by making sure the lowest level segment in the hash is
         * zero for keyrings and non-zero otherwise.
         */
-       if (index_key->type != &key_type_keyring && (hash & level_mask) == 0)
+       if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0)
                return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1;
-       if (index_key->type == &key_type_keyring && (hash & level_mask) != 0)
-               return (hash + (hash << level_shift)) & ~level_mask;
+       if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0)
+               return (hash + (hash << level_shift)) & ~fan_mask;
        return hash;
 }
 
@@ -279,12 +279,11 @@ static bool keyring_compare_object(const void *object, const void *data)
  * Compare the index keys of a pair of objects and determine the bit position
  * at which they differ - if they differ.
  */
-static int keyring_diff_objects(const void *_a, const void *_b)
+static int keyring_diff_objects(const void *object, const void *data)
 {
-       const struct key *key_a = keyring_ptr_to_key(_a);
-       const struct key *key_b = keyring_ptr_to_key(_b);
+       const struct key *key_a = keyring_ptr_to_key(object);
        const struct keyring_index_key *a = &key_a->index_key;
-       const struct keyring_index_key *b = &key_b->index_key;
+       const struct keyring_index_key *b = data;
        unsigned long seg_a, seg_b;
        int level, i;
 
@@ -691,8 +690,8 @@ descend_to_node:
                smp_read_barrier_depends();
                ptr = ACCESS_ONCE(shortcut->next_node);
                BUG_ON(!assoc_array_ptr_is_node(ptr));
-               node = assoc_array_ptr_to_node(ptr);
        }
+       node = assoc_array_ptr_to_node(ptr);
 
 begin_node:
        kdebug("begin_node");
index 794c3ca49eac92998caa17be71a4bdc472c2e9c8..57b0b49f4e6e23a9c6dd974e3f9dd78664f1f59a 100644 (file)
@@ -53,6 +53,7 @@
 #include <net/ip.h>            /* for local_port_range[] */
 #include <net/sock.h>
 #include <net/tcp.h>           /* struct or_callable used in sock_rcv_skb */
+#include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
 #include <linux/uaccess.h>
 #include "audit.h"
 #include "avc_ss.h"
 
-#define SB_TYPE_FMT "%s%s%s"
-#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
-#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
-
 extern struct security_operations *security_ops;
 
 /* SECMARK reference count */
@@ -237,6 +234,14 @@ static int inode_alloc_security(struct inode *inode)
        return 0;
 }
 
+static void inode_free_rcu(struct rcu_head *head)
+{
+       struct inode_security_struct *isec;
+
+       isec = container_of(head, struct inode_security_struct, rcu);
+       kmem_cache_free(sel_inode_cache, isec);
+}
+
 static void inode_free_security(struct inode *inode)
 {
        struct inode_security_struct *isec = inode->i_security;
@@ -247,8 +252,16 @@ static void inode_free_security(struct inode *inode)
                list_del_init(&isec->list);
        spin_unlock(&sbsec->isec_lock);
 
-       inode->i_security = NULL;
-       kmem_cache_free(sel_inode_cache, isec);
+       /*
+        * The inode may still be referenced in a path walk and
+        * a call to selinux_inode_permission() can be made
+        * after inode_free_security() is called. Ideally, the VFS
+        * wouldn't do this, but fixing that is a much harder
+        * job. For now, simply free the i_security via RCU, and
+        * leave the current inode->i_security pointer intact.
+        * The inode will be freed after the RCU grace period too.
+        */
+       call_rcu(&isec->rcu, inode_free_rcu);
 }
 
 static int file_alloc_security(struct file *file)
@@ -413,8 +426,8 @@ static int sb_finish_set_opts(struct super_block *sb)
                   the first boot of the SELinux kernel before we have
                   assigned xattr values to the filesystem. */
                if (!root_inode->i_op->getxattr) {
-                       printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
-                              "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
+                       printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
+                              "xattr support\n", sb->s_id, sb->s_type->name);
                        rc = -EOPNOTSUPP;
                        goto out;
                }
@@ -422,22 +435,22 @@ static int sb_finish_set_opts(struct super_block *sb)
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
-                                      SB_TYPE_FMT") has no security xattr handler\n",
-                                      sb->s_id, SB_TYPE_ARGS(sb));
+                                      "%s) has no security xattr handler\n",
+                                      sb->s_id, sb->s_type->name);
                        else
                                printk(KERN_WARNING "SELinux: (dev %s, type "
-                                      SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
-                                      SB_TYPE_ARGS(sb), -rc);
+                                      "%s) getxattr errno %d\n", sb->s_id,
+                                      sb->s_type->name, -rc);
                        goto out;
                }
        }
 
        if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
-               printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
-                      sb->s_id, SB_TYPE_ARGS(sb));
+               printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
+                      sb->s_id, sb->s_type->name);
        else
-               printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
-                      sb->s_id, SB_TYPE_ARGS(sb),
+               printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
+                      sb->s_id, sb->s_type->name,
                       labeling_behaviors[sbsec->behavior-1]);
 
        sbsec->flags |= SE_SBINITIALIZED;
@@ -600,6 +613,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
        const struct cred *cred = current_cred();
        int rc = 0, i;
        struct superblock_security_struct *sbsec = sb->s_security;
+       const char *name = sb->s_type->name;
        struct inode *inode = sbsec->sb->s_root->d_inode;
        struct inode_security_struct *root_isec = inode->i_security;
        u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -658,8 +672,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                                             strlen(mount_options[i]), &sid);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
-                              "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
-                              mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
+                              "(%s) failed for (dev %s, type %s) errno=%d\n",
+                              mount_options[i], sb->s_id, name, rc);
                        goto out;
                }
                switch (flags[i]) {
@@ -806,8 +820,7 @@ out:
 out_double_mount:
        rc = -EINVAL;
        printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, different "
-              "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
-              SB_TYPE_ARGS(sb));
+              "security settings for (dev %s, type %s)\n", sb->s_id, name);
        goto out;
 }
 
@@ -2480,8 +2493,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
                rc = security_context_to_sid(mount_options[i], len, &sid);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
-                              "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
-                              mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
+                              "(%s) failed for (dev %s, type %s) errno=%d\n",
+                              mount_options[i], sb->s_id, sb->s_type->name, rc);
                        goto out_free_opts;
                }
                rc = -EINVAL;
@@ -2519,8 +2532,8 @@ out_free_secdata:
        return rc;
 out_bad_option:
        printk(KERN_WARNING "SELinux: unable to change security options "
-              "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
-              SB_TYPE_ARGS(sb));
+              "during remount (dev %s, type=%s)\n", sb->s_id,
+              sb->s_type->name);
        goto out_free_opts;
 }
 
@@ -3828,7 +3841,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        u32 nlbl_sid;
        u32 nlbl_type;
 
-       err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+       err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
        if (unlikely(err))
                return -EACCES;
        err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
@@ -3846,6 +3859,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        return 0;
 }
 
+/**
+ * selinux_conn_sid - Determine the child socket label for a connection
+ * @sk_sid: the parent socket's SID
+ * @skb_sid: the packet's SID
+ * @conn_sid: the resulting connection SID
+ *
+ * If @skb_sid is valid then the user:role:type information from @sk_sid is
+ * combined with the MLS information from @skb_sid in order to create
+ * @conn_sid.  If @skb_sid is not valid then then @conn_sid is simply a copy
+ * of @sk_sid.  Returns zero on success, negative values on failure.
+ *
+ */
+static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
+{
+       int err = 0;
+
+       if (skb_sid != SECSID_NULL)
+               err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
+       else
+               *conn_sid = sk_sid;
+
+       return err;
+}
+
 /* socket security operations */
 
 static int socket_sockcreate_sid(const struct task_security_struct *tsec,
@@ -4313,8 +4350,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
-               if (err)
+               if (err) {
                        selinux_netlbl_err(skb, err, 0);
+                       return err;
+               }
        }
 
        if (secmark_active) {
@@ -4452,7 +4491,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
        struct sk_security_struct *sksec = sk->sk_security;
        int err;
        u16 family = sk->sk_family;
-       u32 newsid;
+       u32 connsid;
        u32 peersid;
 
        /* handle mapped IPv4 packets arriving via IPv6 sockets */
@@ -4462,16 +4501,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
        err = selinux_skb_peerlbl_sid(skb, family, &peersid);
        if (err)
                return err;
-       if (peersid == SECSID_NULL) {
-               req->secid = sksec->sid;
-               req->peer_secid = SECSID_NULL;
-       } else {
-               err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
-               if (err)
-                       return err;
-               req->secid = newsid;
-               req->peer_secid = peersid;
-       }
+       err = selinux_conn_sid(sksec->sid, peersid, &connsid);
+       if (err)
+               return err;
+       req->secid = connsid;
+       req->peer_secid = peersid;
 
        return selinux_netlbl_inet_conn_request(req, family);
 }
@@ -4731,6 +4765,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
 static unsigned int selinux_ip_output(struct sk_buff *skb,
                                      u16 family)
 {
+       struct sock *sk;
        u32 sid;
 
        if (!netlbl_enabled())
@@ -4739,8 +4774,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
        /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
         * because we want to make sure we apply the necessary labeling
         * before IPsec is applied so we can leverage AH protection */
-       if (skb->sk) {
-               struct sk_security_struct *sksec = skb->sk->sk_security;
+       sk = skb->sk;
+       if (sk) {
+               struct sk_security_struct *sksec;
+
+               if (sk->sk_state == TCP_LISTEN)
+                       /* if the socket is the listening state then this
+                        * packet is a SYN-ACK packet which means it needs to
+                        * be labeled based on the connection/request_sock and
+                        * not the parent socket.  unfortunately, we can't
+                        * lookup the request_sock yet as it isn't queued on
+                        * the parent socket until after the SYN-ACK is sent.
+                        * the "solution" is to simply pass the packet as-is
+                        * as any IP option based labeling should be copied
+                        * from the initial connection request (in the IP
+                        * layer).  it is far from ideal, but until we get a
+                        * security label in the packet itself this is the
+                        * best we can do. */
+                       return NF_ACCEPT;
+
+               /* standard practice, label using the parent socket */
+               sksec = sk->sk_security;
                sid = sksec->sid;
        } else
                sid = SECINITSID_KERNEL;
@@ -4810,27 +4864,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
         * as fast and as clean as possible. */
        if (!selinux_policycap_netpeer)
                return selinux_ip_postroute_compat(skb, ifindex, family);
+
+       secmark_active = selinux_secmark_enabled();
+       peerlbl_active = selinux_peerlbl_enabled();
+       if (!secmark_active && !peerlbl_active)
+               return NF_ACCEPT;
+
+       sk = skb->sk;
+
 #ifdef CONFIG_XFRM
        /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
         * packet transformation so allow the packet to pass without any checks
         * since we'll have another chance to perform access control checks
         * when the packet is on it's final way out.
         * NOTE: there appear to be some IPv6 multicast cases where skb->dst
-        *       is NULL, in this case go ahead and apply access control. */
-       if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
+        *       is NULL, in this case go ahead and apply access control.
+        * NOTE: if this is a local socket (skb->sk != NULL) that is in the
+        *       TCP listening state we cannot wait until the XFRM processing
+        *       is done as we will miss out on the SA label if we do;
+        *       unfortunately, this means more work, but it is only once per
+        *       connection. */
+       if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
+           !(sk != NULL && sk->sk_state == TCP_LISTEN))
                return NF_ACCEPT;
 #endif
-       secmark_active = selinux_secmark_enabled();
-       peerlbl_active = selinux_peerlbl_enabled();
-       if (!secmark_active && !peerlbl_active)
-               return NF_ACCEPT;
 
-       /* if the packet is being forwarded then get the peer label from the
-        * packet itself; otherwise check to see if it is from a local
-        * application or the kernel, if from an application get the peer label
-        * from the sending socket, otherwise use the kernel's sid */
-       sk = skb->sk;
        if (sk == NULL) {
+               /* Without an associated socket the packet is either coming
+                * from the kernel or it is being forwarded; check the packet
+                * to determine which and if the packet is being forwarded
+                * query the packet directly to determine the security label. */
                if (skb->skb_iif) {
                        secmark_perm = PACKET__FORWARD_OUT;
                        if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
@@ -4839,7 +4902,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
                        secmark_perm = PACKET__SEND;
                        peer_sid = SECINITSID_KERNEL;
                }
+       } else if (sk->sk_state == TCP_LISTEN) {
+               /* Locally generated packet but the associated socket is in the
+                * listening state which means this is a SYN-ACK packet.  In
+                * this particular case the correct security label is assigned
+                * to the connection/request_sock but unfortunately we can't
+                * query the request_sock as it isn't queued on the parent
+                * socket until after the SYN-ACK packet is sent; the only
+                * viable choice is to regenerate the label like we do in
+                * selinux_inet_conn_request().  See also selinux_ip_output()
+                * for similar problems. */
+               u32 skb_sid;
+               struct sk_security_struct *sksec = sk->sk_security;
+               if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
+                       return NF_DROP;
+               /* At this point, if the returned skb peerlbl is SECSID_NULL
+                * and the packet has been through at least one XFRM
+                * transformation then we must be dealing with the "final"
+                * form of labeled IPsec packet; since we've already applied
+                * all of our access controls on this packet we can safely
+                * pass the packet. */
+               if (skb_sid == SECSID_NULL) {
+                       switch (family) {
+                       case PF_INET:
+                               if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
+                                       return NF_ACCEPT;
+                               break;
+                       case PF_INET6:
+                               if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
+                                       return NF_ACCEPT;
+                       default:
+                               return NF_DROP_ERR(-ECONNREFUSED);
+                       }
+               }
+               if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
+                       return NF_DROP;
+               secmark_perm = PACKET__SEND;
        } else {
+               /* Locally generated packet, fetch the security label from the
+                * associated socket. */
                struct sk_security_struct *sksec = sk->sk_security;
                peer_sid = sksec->sid;
                secmark_perm = PACKET__SEND;
@@ -5503,11 +5604,11 @@ static int selinux_setprocattr(struct task_struct *p,
                /* Check for ptracing, and update the task SID if ok.
                   Otherwise, leave SID unchanged and fail. */
                ptsid = 0;
-               task_lock(p);
+               rcu_read_lock();
                tracer = ptrace_parent(p);
                if (tracer)
                        ptsid = task_sid(tracer);
-               task_unlock(p);
+               rcu_read_unlock();
 
                if (tracer) {
                        error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
index b1dfe104945078ead53647c247c46aa6134fac2e..078e553f52f27a03ab83490f20bb2353782d2ef2 100644 (file)
@@ -38,7 +38,10 @@ struct task_security_struct {
 
 struct inode_security_struct {
        struct inode *inode;    /* back pointer to inode object */
-       struct list_head list;  /* list of inode_security_struct */
+       union {
+               struct list_head list;  /* list of inode_security_struct */
+               struct rcu_head rcu;    /* for freeing the inode_security_struct */
+       };
        u32 task_sid;           /* SID of creating task */
        u32 sid;                /* SID of this object */
        u16 sclass;             /* security class of this object */
index 0dec76c64cf53853d0eea6aac983db307c8636b8..48c3cc94c1681718a78e6793c7e961e2d404f3fb 100644 (file)
@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
 int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
                                struct common_audit_data *ad, u8 proto);
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid);
 
 static inline void selinux_xfrm_notify_policyload(void)
 {
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
 static inline void selinux_xfrm_notify_policyload(void)
 {
 }
-#endif
 
-static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
 {
-       return selinux_xfrm_decode_session(skb, sid, 0);
+       *sid = SECSID_NULL;
+       return 0;
 }
+#endif
 
 #endif /* _SELINUX_XFRM_H_ */
index ee470a0b5c27fdad95a59b258792b6182435b999..d106733ad9878d6ee7543ff31c05a51f2c74b523 100644 (file)
@@ -2334,50 +2334,16 @@ int security_fs_use(struct super_block *sb)
        struct ocontext *c;
        struct superblock_security_struct *sbsec = sb->s_security;
        const char *fstype = sb->s_type->name;
-       const char *subtype = (sb->s_subtype && sb->s_subtype[0]) ? sb->s_subtype : NULL;
-       struct ocontext *base = NULL;
 
        read_lock(&policy_rwlock);
 
-       for (c = policydb.ocontexts[OCON_FSUSE]; c; c = c->next) {
-               char *sub;
-               int baselen;
-
-               baselen = strlen(fstype);
-
-               /* if base does not match, this is not the one */
-               if (strncmp(fstype, c->u.name, baselen))
-                       continue;
-
-               /* if there is no subtype, this is the one! */
-               if (!subtype)
-                       break;
-
-               /* skip past the base in this entry */
-               sub = c->u.name + baselen;
-
-               /* entry is only a base. save it. keep looking for subtype */
-               if (sub[0] == '\0') {
-                       base = c;
-                       continue;
-               }
-
-               /* entry is not followed by a subtype, so it is not a match */
-               if (sub[0] != '.')
-                       continue;
-
-               /* whew, we found a subtype of this fstype */
-               sub++; /* move past '.' */
-
-               /* exact match of fstype AND subtype */
-               if (!strcmp(subtype, sub))
+       c = policydb.ocontexts[OCON_FSUSE];
+       while (c) {
+               if (strcmp(fstype, c->u.name) == 0)
                        break;
+               c = c->next;
        }
 
-       /* in case we had found an fstype match but no subtype match */
-       if (!c)
-               c = base;
-
        if (c) {
                sbsec->behavior = c->v.behavior;
                if (!c->sid[0]) {
index a91d205ec0c6094cc9a0fecb5d427d4d24b1ed9a..0462cb3ff0a741a36b279dcef37ee784e8520c5c 100644 (file)
@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
                            NULL) ? 0 : 1);
 }
 
-/*
- * LSM hook implementation that checks and/or returns the xfrm sid for the
- * incoming packet.
- */
-int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
 {
-       u32 sid_session = SECSID_NULL;
-       struct sec_path *sp;
+       struct dst_entry *dst = skb_dst(skb);
+       struct xfrm_state *x;
 
-       if (skb == NULL)
-               goto out;
+       if (dst == NULL)
+               return SECSID_NULL;
+       x = dst->xfrm;
+       if (x == NULL || !selinux_authorizable_xfrm(x))
+               return SECSID_NULL;
+
+       return x->security->ctx_sid;
+}
+
+static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
+                                       u32 *sid, int ckall)
+{
+       u32 sid_session = SECSID_NULL;
+       struct sec_path *sp = skb->sp;
 
-       sp = skb->sp;
        if (sp) {
                int i;
 
@@ -247,6 +254,30 @@ out:
        return 0;
 }
 
+/*
+ * LSM hook implementation that checks and/or returns the xfrm sid for the
+ * incoming packet.
+ */
+int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+{
+       if (skb == NULL) {
+               *sid = SECSID_NULL;
+               return 0;
+       }
+       return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
+}
+
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
+{
+       int rc;
+
+       rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
+       if (rc == 0 && *sid == SECSID_NULL)
+               *sid = selinux_xfrm_skb_sid_egress(skb);
+
+       return rc;
+}
+
 /*
  * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
  */
@@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
                return rc;
 
        ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
-       if (!ctx)
-               return -ENOMEM;
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto out;
+       }
 
        ctx->ctx_doi = XFRM_SC_DOI_LSM;
        ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
        ctx->ctx_sid = secid;
        ctx->ctx_len = str_len;
        memcpy(ctx->ctx_str, ctx_str, str_len);
-       kfree(ctx_str);
 
        x->security = ctx;
        atomic_inc(&selinux_xfrm_refcount);
-       return 0;
+out:
+       kfree(ctx_str);
+       return rc;
 }
 
 /*
index 872d59e35ee23583cc60a2be24afa5ba1bf3c88d..721d8fd45685f769cbc616a6ba0552b85cd5c841 100644 (file)
@@ -357,7 +357,8 @@ static int set_sample_rates(struct atmel_abdac *dac)
                if (new_rate < 0)
                        break;
                /* make sure we are below the ABDAC clock */
-               if (new_rate <= clk_get_rate(dac->pclk)) {
+               if (index < MAX_NUM_RATES &&
+                   new_rate <= clk_get_rate(dac->pclk)) {
                        dac->rates[index] = new_rate / 256;
                        index++;
                }
index 6e03b465e44e3a05f82e93a2d25a61f030cc3cf6..a2104671f51d38df6eec99b3e0aa8ac570ea8988 100644 (file)
@@ -1937,6 +1937,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
                case SNDRV_PCM_STATE_DISCONNECTED:
                        err = -EBADFD;
                        goto _endloop;
+               case SNDRV_PCM_STATE_PAUSED:
+                       continue;
                }
                if (!tout) {
                        snd_printd("%s write error (DMA or IRQ trouble?)\n",
index 57bcd31fcc123c38cd293cab40b52310734698a2..c0aa64941cee0bd927450a6b69314d14f2f02bce 100644 (file)
@@ -1019,7 +1019,7 @@ static void dice_proc_read(struct snd_info_entry *entry,
 
        if (dice_proc_read_mem(dice, &tx_rx_header, sections[2], 2) < 0)
                return;
-       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx));
+       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx) / 4);
        for (stream = 0; stream < tx_rx_header.number; ++stream) {
                if (dice_proc_read_mem(dice, &buf.tx, sections[2] + 2 +
                                       stream * tx_rx_header.size,
@@ -1045,7 +1045,7 @@ static void dice_proc_read(struct snd_info_entry *entry,
 
        if (dice_proc_read_mem(dice, &tx_rx_header, sections[4], 2) < 0)
                return;
-       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx));
+       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx) / 4);
        for (stream = 0; stream < tx_rx_header.number; ++stream) {
                if (dice_proc_read_mem(dice, &buf.rx, sections[4] + 2 +
                                       stream * tx_rx_header.size,
index c4671d00babd6772193f955237c48412a3239a5a..c7f6d1cab6063a6483802ee6c80391c18c2de884 100644 (file)
@@ -474,6 +474,20 @@ static void invalidate_nid_path(struct hda_codec *codec, int idx)
        memset(path, 0, sizeof(*path));
 }
 
+/* return a DAC if paired to the given pin by codec driver */
+static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
+{
+       struct hda_gen_spec *spec = codec->spec;
+       const hda_nid_t *list = spec->preferred_dacs;
+
+       if (!list)
+               return 0;
+       for (; *list; list += 2)
+               if (*list == pin)
+                       return list[1];
+       return 0;
+}
+
 /* look for an empty DAC slot */
 static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
                              bool is_digital)
@@ -1192,7 +1206,14 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
                        continue;
                }
 
-               dacs[i] = look_for_dac(codec, pin, false);
+               dacs[i] = get_preferred_dac(codec, pin);
+               if (dacs[i]) {
+                       if (is_dac_already_used(codec, dacs[i]))
+                               badness += bad->shared_primary;
+               }
+
+               if (!dacs[i])
+                       dacs[i] = look_for_dac(codec, pin, false);
                if (!dacs[i] && !i) {
                        /* try to steal the DAC of surrounds for the front */
                        for (j = 1; j < num_outs; j++) {
@@ -4297,6 +4318,26 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
        return AC_PWRST_D3;
 }
 
+/* mute all aamix inputs initially; parse up to the first leaves */
+static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
+{
+       int i, nums;
+       const hda_nid_t *conn;
+       bool has_amp;
+
+       nums = snd_hda_get_conn_list(codec, mix, &conn);
+       has_amp = nid_has_mute(codec, mix, HDA_INPUT);
+       for (i = 0; i < nums; i++) {
+               if (has_amp)
+                       snd_hda_codec_amp_stereo(codec, mix,
+                                                HDA_INPUT, i,
+                                                0xff, HDA_AMP_MUTE);
+               else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
+                       snd_hda_codec_amp_stereo(codec, conn[i],
+                                                HDA_OUTPUT, 0,
+                                                0xff, HDA_AMP_MUTE);
+       }
+}
 
 /*
  * Parse the given BIOS configuration and set up the hda_gen_spec
@@ -4435,6 +4476,10 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                }
        }
 
+       /* mute all aamix input initially */
+       if (spec->mixer_nid)
+               mute_all_mixer_nid(codec, spec->mixer_nid);
+
  dig_only:
        parse_digital(codec);
 
index 7e45cb44d1514497385f2f6bc2b63251391cdaba..0929a06df8128495f5e717768fcfa28eaed7360d 100644 (file)
@@ -249,6 +249,9 @@ struct hda_gen_spec {
        const struct badness_table *main_out_badness;
        const struct badness_table *extra_out_badness;
 
+       /* preferred pin/DAC pairs; an array of paired NIDs */
+       const hda_nid_t *preferred_dacs;
+
        /* loopback mixing mode */
        bool aamix_mode;
 
index c6d230193da6214700e23369df0d2355c301012a..956871d8b3d26a9255723eb4bdfdf963c50f031b 100644 (file)
@@ -3433,6 +3433,10 @@ static void check_probe_mask(struct azx *chip, int dev)
  * white/black-list for enable_msi
  */
 static struct snd_pci_quirk msi_black_list[] = {
+       SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
+       SND_PCI_QUIRK(0x103c, 0x21fa, "HP", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
@@ -3876,7 +3880,8 @@ static int azx_probe(struct pci_dev *pci,
        }
 
        dev++;
-       complete_all(&chip->probe_wait);
+       if (chip->disabled)
+               complete_all(&chip->probe_wait);
        return 0;
 
 out_free:
@@ -3953,10 +3958,10 @@ static int azx_probe_continue(struct azx *chip)
        if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo)
                pm_runtime_put_noidle(&pci->dev);
 
-       return 0;
-
 out_free:
-       chip->init_failed = 1;
+       if (err < 0)
+               chip->init_failed = 1;
+       complete_all(&chip->probe_wait);
        return err;
 }
 
index 1a83559f4cbd27e455a941adaddc6d0513d9dd81..699262a3e07abcd9558bb538de0916d96bc63bcd 100644 (file)
@@ -147,6 +147,8 @@ static void ad_vmaster_eapd_hook(void *private_data, int enabled)
 
        if (!spec->eapd_nid)
                return;
+       if (codec->inv_eapd)
+               enabled = !enabled;
        snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
                                   AC_VERB_SET_EAPD_BTLENABLE,
                                   enabled ? 0x02 : 0x00);
@@ -338,6 +340,14 @@ static int patch_ad1986a(struct hda_codec *codec)
 {
        int err;
        struct ad198x_spec *spec;
+       static hda_nid_t preferred_pairs[] = {
+               0x1a, 0x03,
+               0x1b, 0x03,
+               0x1c, 0x04,
+               0x1d, 0x05,
+               0x1e, 0x03,
+               0
+       };
 
        err = alloc_ad_spec(codec);
        if (err < 0)
@@ -358,6 +368,11 @@ static int patch_ad1986a(struct hda_codec *codec)
         * So, let's disable the shared stream.
         */
        spec->gen.multiout.no_share_stream = 1;
+       /* give fixed DAC/pin pairs */
+       spec->gen.preferred_dacs = preferred_pairs;
+
+       /* AD1986A can't manage the dynamic pin on/off smoothly */
+       spec->gen.auto_mute_via_amp = 1;
 
        snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
                           ad1986a_fixups);
@@ -962,6 +977,7 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
                spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
+               spec->gen.own_eapd_ctl = 1;
                snd_hda_sequence_write_cache(codec, gpio_init_verbs);
                break;
        case HDA_FIXUP_ACT_PROBE:
index 1f2717f817a0142f4ef17910ffd50dafe42e4c09..3fbf2883e06e855e7a79213b0414e3049b539f28 100644 (file)
@@ -2936,7 +2936,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
-       SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
        SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
        SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
index 08407bed093e5a64d4b659f90bf236dead9ec002..f281c8068557e63b72370e25a9973372dbaf0bae 100644 (file)
@@ -1142,32 +1142,34 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
 
 static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
 
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+static void jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack)
 {
        struct hdmi_spec *spec = codec->spec;
+       int pin_idx = pin_nid_to_pin_index(spec, jack->nid);
+       if (pin_idx < 0)
+               return;
+
+       if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
+               snd_hda_jack_report_sync(codec);
+}
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
        int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int pin_nid;
-       int pin_idx;
        struct hda_jack_tbl *jack;
        int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
 
        jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
        if (!jack)
                return;
-       pin_nid = jack->nid;
        jack->jack_dirty = 1;
 
        _snd_printd(SND_PR_VERBOSE,
                "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n",
-               codec->addr, pin_nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
+               codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
                !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
 
-       pin_idx = pin_nid_to_pin_index(spec, pin_nid);
-       if (pin_idx < 0)
-               return;
-
-       if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
-               snd_hda_jack_report_sync(codec);
+       jack_callback(codec, jack);
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -2095,7 +2097,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
                hda_nid_t pin_nid = per_pin->pin_nid;
 
                hdmi_init_pin(codec, pin_nid);
-               snd_hda_jack_detect_enable(codec, pin_nid, pin_nid);
+               snd_hda_jack_detect_enable_callback(codec, pin_nid, pin_nid,
+                       codec->jackpoll_interval > 0 ? jack_callback : NULL);
        }
        return 0;
 }
@@ -2334,8 +2337,9 @@ static int simple_playback_build_controls(struct hda_codec *codec)
        int err;
 
        per_cvt = get_cvt(spec, 0);
-       err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
-                                           per_cvt->cvt_nid);
+       err = snd_hda_create_dig_out_ctls(codec, per_cvt->cvt_nid,
+                                         per_cvt->cvt_nid,
+                                         HDA_PCM_TYPE_HDMI);
        if (err < 0)
                return err;
        return simple_hdmi_build_jack(codec, 0);
index c770bdba6531c8a0d3eaf2f64e2c38d6d8ad758c..c5646941539a87df9505eece6241dd5e9230c4ff 100644 (file)
@@ -1780,6 +1780,7 @@ enum {
        ALC889_FIXUP_DAC_ROUTE,
        ALC889_FIXUP_MBP_VREF,
        ALC889_FIXUP_IMAC91_VREF,
+       ALC889_FIXUP_MBA21_VREF,
        ALC882_FIXUP_INV_DMIC,
        ALC882_FIXUP_NO_PRIMARY_HP,
        ALC887_FIXUP_ASUS_BASS,
@@ -1884,17 +1885,13 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec,
        }
 }
 
-/* Set VREF on speaker pins on imac91 */
-static void alc889_fixup_imac91_vref(struct hda_codec *codec,
-                                    const struct hda_fixup *fix, int action)
+static void alc889_fixup_mac_pins(struct hda_codec *codec,
+                                 const hda_nid_t *nids, int num_nids)
 {
        struct alc_spec *spec = codec->spec;
-       static hda_nid_t nids[2] = { 0x18, 0x1a };
        int i;
 
-       if (action != HDA_FIXUP_ACT_INIT)
-               return;
-       for (i = 0; i < ARRAY_SIZE(nids); i++) {
+       for (i = 0; i < num_nids; i++) {
                unsigned int val;
                val = snd_hda_codec_get_pin_target(codec, nids[i]);
                val |= AC_PINCTL_VREF_50;
@@ -1903,6 +1900,26 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
        spec->gen.keep_vref_in_automute = 1;
 }
 
+/* Set VREF on speaker pins on imac91 */
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[2] = { 0x18, 0x1a };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
+/* Set VREF on speaker pins on mba21 */
+static void alc889_fixup_mba21_vref(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[2] = { 0x18, 0x19 };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
 /* Don't take HP output as primary
  * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
  * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
@@ -2102,6 +2119,12 @@ static const struct hda_fixup alc882_fixups[] = {
                .chained = true,
                .chain_id = ALC882_FIXUP_GPIO1,
        },
+       [ALC889_FIXUP_MBA21_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc889_fixup_mba21_vref,
+               .chained = true,
+               .chain_id = ALC889_FIXUP_MBP_VREF,
+       },
        [ALC882_FIXUP_INV_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
@@ -2172,7 +2195,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
-       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
+       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
        SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
@@ -3287,6 +3310,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
                alc_write_coef_idx(codec, 0x18, 0x7388);
                break;
        case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
                alc_write_coef_idx(codec, 0x15, 0x0d60);
                alc_write_coef_idx(codec, 0xc3, 0x0000);
                break;
@@ -3315,6 +3339,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
                alc_write_coef_idx(codec, 0x18, 0x7388);
                break;
        case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
                alc_write_coef_idx(codec, 0x15, 0x0d50);
                alc_write_coef_idx(codec, 0xc3, 0x0000);
                break;
@@ -3600,11 +3625,6 @@ static void alc283_hp_automute_hook(struct hda_codec *codec,
                            vref);
 }
 
-static void alc283_chromebook_caps(struct hda_codec *codec)
-{
-       snd_hda_override_wcaps(codec, 0x03, 0);
-}
-
 static void alc283_fixup_chromebook(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
@@ -3613,9 +3633,26 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
 
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
-               alc283_chromebook_caps(codec);
+               snd_hda_override_wcaps(codec, 0x03, 0);
                /* Disable AA-loopback as it causes white noise */
                spec->gen.mixer_nid = 0;
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               /* Enable Line1 input control by verb */
+               val = alc_read_coef_idx(codec, 0x1a);
+               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
+               break;
+       }
+}
+
+static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       int val;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
                spec->gen.hp_automute_hook = alc283_hp_automute_hook;
                break;
        case HDA_FIXUP_ACT_INIT:
@@ -3623,9 +3660,6 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
                /* Set to manual mode */
                val = alc_read_coef_idx(codec, 0x06);
                alc_write_coef_idx(codec, 0x06, val & ~0x000c);
-               /* Enable Line1 input control by verb */
-               val = alc_read_coef_idx(codec, 0x1a);
-               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
                break;
        }
 }
@@ -3815,12 +3849,14 @@ enum {
        ALC269_FIXUP_ASUS_X101,
        ALC271_FIXUP_AMIC_MIC2,
        ALC271_FIXUP_HP_GATE_MIC_JACK,
+       ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
        ALC269_FIXUP_ACER_AC700,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
        ALC269VB_FIXUP_ASUS_ZENBOOK,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
        ALC269VB_FIXUP_ORDISSIMO_EVE2,
        ALC283_FIXUP_CHROME_BOOK,
+       ALC283_FIXUP_SENSE_COMBO_JACK,
        ALC282_FIXUP_ASUS_TX300,
        ALC283_FIXUP_INT_MIC,
        ALC290_FIXUP_MONO_SPEAKERS,
@@ -4076,6 +4112,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC271_FIXUP_AMIC_MIC2,
        },
+       [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
+       },
        [ALC269_FIXUP_ACER_AC700] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -4120,6 +4162,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc283_fixup_chromebook,
        },
+       [ALC283_FIXUP_SENSE_COMBO_JACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc283_fixup_sense_combo_jack,
+               .chained = true,
+               .chain_id = ALC283_FIXUP_CHROME_BOOK,
+       },
        [ALC282_FIXUP_ASUS_TX300] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc282_fixup_asus_tx300,
@@ -4167,6 +4215,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4198,11 +4247,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
        SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
+       SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0640, "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),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -4210,7 +4264,6 @@ 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),
-       SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco Chromebook", ALC283_FIXUP_CHROME_BOOK),
        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),
@@ -4318,6 +4371,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
        {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
        {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
+       {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-chrome"},
+       {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
        {}
 };
 
@@ -4493,6 +4548,7 @@ enum {
        ALC861_FIXUP_AMP_VREF_0F,
        ALC861_FIXUP_NO_JACK_DETECT,
        ALC861_FIXUP_ASUS_A6RP,
+       ALC660_FIXUP_ASUS_W7J,
 };
 
 /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
@@ -4542,10 +4598,22 @@ static const struct hda_fixup alc861_fixups[] = {
                .v.func = alc861_fixup_asus_amp_vref_0f,
                .chained = true,
                .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
+       },
+       [ALC660_FIXUP_ASUS_W7J] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* ASUS W7J needs a magic pin setup on unused NID 0x10
+                        * for enabling outputs
+                        */
+                       {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+                       { }
+               },
        }
 };
 
 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
+       SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
        SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
        SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
        SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
@@ -4978,8 +5046,11 @@ 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, 0x0623, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        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_DELL_MIC_NO_PRESENCE),
        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 8697cedccd21240f76b4b5076ba6d0968a394d75..1ead3c977a51743619b0bb2084ec174b7cf867a8 100644 (file)
@@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 
        dma_params = ssc_p->dma_params[dir];
 
-       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
        ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
        pr_debug("%s enabled SSC_SR=0x%08x\n",
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
+                            int cmd, struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct atmel_pcm_dma_params *dma_params;
+       int dir;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dir = 0;
+       else
+               dir = 1;
+
+       dma_params = ssc_p->dma_params[dir];
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+               break;
+       default:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+               break;
+       }
+
+       return 0;
+}
 
 #ifdef CONFIG_PM
 static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
@@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .startup        = atmel_ssc_startup,
        .shutdown       = atmel_ssc_shutdown,
        .prepare        = atmel_ssc_prepare,
+       .trigger        = atmel_ssc_trigger,
        .hw_params      = atmel_ssc_hw_params,
        .set_fmt        = atmel_ssc_set_dai_fmt,
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
index 992ae38d5a15afda177080da1032300bcffd18ac..7d6a9055874b822bb440eab72a66dc5c034127ed 100644 (file)
@@ -97,6 +97,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
                goto out;
        }
 
+       snd_soc_card_set_drvdata(card, priv);
+
        card->dev = &pdev->dev;
        card->owner = THIS_MODULE;
        card->dai_link = dai;
@@ -107,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
        dai->stream_name = "WM8731 PCM";
        dai->codec_dai_name = "wm8731-hifi";
        dai->init = sam9x5_wm8731_init;
-       dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+       dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
                | SND_SOC_DAIFMT_CBM_CFM;
 
        ret = snd_soc_of_parse_card_name(card, "atmel,model");
index c3c7396a618115d06171bb87314b363cc8ac9f6d..0ab2dc296474373e1e407abf0762afeeffead4c6 100644 (file)
@@ -248,19 +248,6 @@ ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE),
 
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-          ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("HPOUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-          ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("HPOUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-          ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
-          ARIZONA_OUT4_OSR_SHIFT, 1, 0),
-SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
-          ARIZONA_OUT5_OSR_SHIFT, 1, 0),
-SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
-          ARIZONA_OUT6_OSR_SHIFT, 1, 0),
-
 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
             ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -293,18 +280,6 @@ SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L,
                 ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_1R,
-                      ARIZONA_OUT1L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_2R,
-                      ARIZONA_OUT2L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_3R,
-                      ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
-
 SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
           ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
@@ -1037,7 +1012,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "AEC Loopback", "HPOUT3L", "OUT3L" },
        { "AEC Loopback", "HPOUT3R", "OUT3R" },
        { "HPOUT3L", NULL, "OUT3L" },
-       { "HPOUT3R", NULL, "OUT3L" },
+       { "HPOUT3R", NULL, "OUT3R" },
 
        { "AEC Loopback", "SPKOUTL", "OUT4L" },
        { "SPKOUTLN", NULL, "OUT4L" },
index 456bb8c6d759176a3bf31c5f7003a6e8cfc2d799..bc7472c968e37300edfdd38f9108bee0af77bb4f 100644 (file)
@@ -447,10 +447,10 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
                iface |= 0x0001;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               iface |= 0x0003;
+               iface |= 0x0013;
                break;
        case SND_SOC_DAIFMT_DSP_B:
-               iface |= 0x0013;
+               iface |= 0x0003;
                break;
        default:
                return -EINVAL;
index 3938fb1c203ed86b5452ff130071d349a6821a87..53bbfac6a83ad14ed43d2aafca2514ea3a319468 100644 (file)
@@ -1444,7 +1444,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
-               aif1 |= WM8904_AIF_LRCLK_INV;
+               aif1 |= 0x3 | WM8904_AIF_LRCLK_INV;
        case SND_SOC_DAIFMT_DSP_A:
                aif1 |= 0x3;
                break;
index 543c5c2631b61827bcebca8af1926ea02b5655e9..0f17ed3e29f41dc9d7ddebb505b7fad8fc545b02 100644 (file)
@@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8962_CLOCKING_4,
                            WM8962_SYSCLK_RATE_MASK, clocking4);
 
+       /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK.
+        * So we here provisionally enable it and then disable it afterward
+        * if current bias_level hasn't reached SND_SOC_BIAS_ON.
+        */
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
+
        dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, 0);
+
        if (dspclk < 0) {
                dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
                return;
index 253c88bb7a4cbdb06d3d1df2862f10e80095aaa8..4f05fb88bddf1394509b9eb14c7b746909074873 100644 (file)
@@ -1259,6 +1259,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
                snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
+
+               codec->cache_sync = 1;
                break;
        }
 
index 46ec0e9744d4b88b50cc922cfdc65a0b4247e567..4fbcab63e61f1c5d8b4843fdec5c6d3dbfa498ed 100644 (file)
@@ -1474,13 +1474,17 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
                return ret;
 
        /* Wait for the RAM to start, should be near instantaneous */
-       count = 0;
-       do {
+       for (count = 0; count < 10; ++count) {
                ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
                                  &val);
                if (ret != 0)
                        return ret;
-       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+               if (val & ADSP2_RAM_RDY)
+                       break;
+
+               msleep(1);
+       }
 
        if (!(val & ADSP2_RAM_RDY)) {
                adsp_err(dsp, "Failed to start DSP RAM\n");
index 61e48852b9e8bd21b26eec98cca4fc9ba0eea145..3fd76bc391de19a2431dd320d0abfbdcd9616cf5 100644 (file)
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
                break;
        }
 
-       dapm->bias_level = level;
-
        return 0;
 }
 
index eb4373840bb6e1ab2cbbb1e5e9220e1c8474cb29..3665f612819d4bd2d443b0e7072cf9753ee1905b 100644 (file)
@@ -69,7 +69,6 @@ static int pcm030_fabric_probe(struct platform_device *op)
                return -ENOMEM;
 
        card->dev = &op->dev;
-       platform_set_drvdata(op, pdata);
 
        pdata->card = card;
 
@@ -98,6 +97,8 @@ static int pcm030_fabric_probe(struct platform_device *op)
        if (ret)
                dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
 
+       platform_set_drvdata(op, pdata);
+
        return ret;
 }
 
index d34d91743e3ffe95f9e4823bafdd33d78875b6c3..3920a5e8125f886e15caa6607fed9e84a32950cd 100644 (file)
         SNDRV_PCM_FMTBIT_S24_LE | \
         SNDRV_PCM_FMTBIT_S32_LE)
 
+#define KIRKWOOD_SPDIF_FORMATS \
+       (SNDRV_PCM_FMTBIT_S16_LE | \
+        SNDRV_PCM_FMTBIT_S24_LE)
+
 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
@@ -244,15 +248,15 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                   ctl);
        }
 
-       if (dai->id == 0)
-               ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
-       else
-               ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
-
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                /* configure */
                ctl = priv->ctl_play;
+               if (dai->id == 0)
+                       ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
+               else
+                       ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
+
                value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
                writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
@@ -449,14 +453,14 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
                                SNDRV_PCM_RATE_96000,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
                                SNDRV_PCM_RATE_96000,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
     },
@@ -469,17 +473,17 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
                .formats = KIRKWOOD_I2S_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
@@ -490,18 +494,18 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_192000 |
-                        SNDRV_PCM_RATE_CONTINUOUS |
-                        SNDRV_PCM_RATE_KNOT,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 5512,
+               .rate_max = 192000,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
     },
index 6d216cb6c19bd2ba92c4d326d2ee6761dc2e5ef3..3fde9e402710f2bb16baf80b605da42772df69a0 100644 (file)
@@ -100,12 +100,12 @@ static int n810_startup(struct snd_pcm_substream *substream)
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
 
        n810_ext_control(&codec->dapm);
-       return clk_enable(sys_clkout2);
+       return clk_prepare_enable(sys_clkout2);
 }
 
 static void n810_shutdown(struct snd_pcm_substream *substream)
 {
-       clk_disable(sys_clkout2);
+       clk_disable_unprepare(sys_clkout2);
 }
 
 static int n810_hw_params(struct snd_pcm_substream *substream,
index 14011d90d70af3180f4eeedee2fa254a6d5fde25..ff60e11ecb564674bdffbe8814392fe1b2b01065 100644 (file)
@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
 config SND_SOC_RCAR
        tristate "R-Car series SRU/SCU/SSIU/SSI support"
        select SND_SIMPLE_CARD
+       select REGMAP
        help
          This option enables R-Car SUR/SCU/SSIU/SSI sound support
 
index 4e53d87e881d0891a3d8437881d12d41225303cc..a66783e13a9cca182e3077b3e998c804aa40ff1d 100644 (file)
@@ -3212,11 +3212,11 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
                        break;
                case 2:
                        ((u16 *)(&ucontrol->value.bytes.data))[0]
-                               &= ~params->mask;
+                               &= cpu_to_be16(~params->mask);
                        break;
                case 4:
                        ((u32 *)(&ucontrol->value.bytes.data))[0]
-                               &= ~params->mask;
+                               &= cpu_to_be32(~params->mask);
                        break;
                default:
                        return -EINVAL;
index b1d732255c0275fd06039efe36988b1a8ba3e8d2..3449c1e909ae10c71a695f6dc2eedecba9e8c163 100644 (file)
@@ -66,7 +66,7 @@ static void devm_card_release(struct device *dev, void *res)
  */
 int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
 {
-       struct device **ptr;
+       struct snd_soc_card **ptr;
        int ret;
 
        ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
@@ -75,7 +75,7 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
 
        ret = snd_soc_register_card(card);
        if (ret == 0) {
-               *ptr = dev;
+               *ptr = card;
                devres_add(dev, ptr);
        } else {
                devres_free(ptr);
index cbc9c96ce1f412123a1704b171220a2990ad503d..41949af3baaed2580dae2df585222339ade75208 100644 (file)
@@ -305,6 +305,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
        }
 }
 
+static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
+{
+       unsigned int i;
+
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (!pcm->chan[i])
+                       continue;
+               dma_release_channel(pcm->chan[i]);
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
+       }
+}
+
 /**
  * snd_dmaengine_pcm_register - Register a dmaengine based PCM device
  * @dev: The parent device for the PCM device
@@ -315,6 +329,7 @@ int snd_dmaengine_pcm_register(struct device *dev,
        const struct snd_dmaengine_pcm_config *config, unsigned int flags)
 {
        struct dmaengine_pcm *pcm;
+       int ret;
 
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
        if (!pcm)
@@ -326,11 +341,20 @@ int snd_dmaengine_pcm_register(struct device *dev,
        dmaengine_pcm_request_chan_of(pcm, dev);
 
        if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_no_residue_pcm_platform);
        else
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_pcm_platform);
+       if (ret)
+               goto err_free_dma;
+
+       return 0;
+
+err_free_dma:
+       dmaengine_pcm_release_chan(pcm);
+       kfree(pcm);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
 
@@ -345,7 +369,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 {
        struct snd_soc_platform *platform;
        struct dmaengine_pcm *pcm;
-       unsigned int i;
 
        platform = snd_soc_lookup_platform(dev);
        if (!platform)
@@ -353,15 +376,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 
        pcm = soc_platform_to_pcm(platform);
 
-       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-               if (pcm->chan[i]) {
-                       dma_release_channel(pcm->chan[i]);
-                       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
-                               break;
-               }
-       }
-
        snd_soc_remove_platform(platform);
+       dmaengine_pcm_release_chan(pcm);
        kfree(pcm);
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
index 42782c01e41320e924efb4b93c839802f0df5722..891b9a9bcbf885df92bad9007b3f23054ce68c18 100644 (file)
@@ -148,12 +148,12 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
        }
 }
 
-static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
+static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
        struct snd_soc_pcm_stream *codec_stream,
        struct snd_soc_pcm_stream *cpu_stream)
 {
-       hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
-       hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max);
+       struct snd_pcm_hardware *hw = &runtime->hw;
+
        hw->channels_min = max(codec_stream->channels_min,
                cpu_stream->channels_min);
        hw->channels_max = min(codec_stream->channels_max,
@@ -166,6 +166,13 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
        if (cpu_stream->rates
                & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
                hw->rates |= codec_stream->rates;
+
+       snd_pcm_limit_hw_rates(runtime);
+
+       hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
+       hw->rate_min = max(hw->rate_min, codec_stream->rate_min);
+       hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
+       hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max);
 }
 
 /*
@@ -235,15 +242,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 
        /* Check that the codec and cpu DAIs are compatible */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback,
+               soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback,
                        &cpu_dai_drv->playback);
        } else {
-               soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture,
+               soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture,
                        &cpu_dai_drv->capture);
        }
 
        ret = -EINVAL;
-       snd_pcm_limit_hw_rates(runtime);
        if (!runtime->hw.rates) {
                printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
                        codec_dai->name, cpu_dai->name);
@@ -594,12 +600,13 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_codec *codec = rtd->codec;
+       bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
        /* apply codec digital mute */
-       if (!codec->active)
+       if ((playback && codec_dai->playback_active == 1) ||
+           (!playback && codec_dai->capture_active == 1))
                snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
 
        /* free any machine hw params */
index 364bf6a907e1c39a36df89ded1d6b2681172940f..8c819f8114708f7a94e33929a04ebecbdf3e2ffc 100644 (file)
@@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index 08bc6931c7c7fc0477703037098a8e7185d7c69d..8c7c1028e5797dbc9b23ec88b58a4cd840db1c5c 100644 (file)
@@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
        int ret, spdifclock;
 
-       mask = TEGRA20_SPDIF_CTRL_PACK |
-              TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+       mask |= TEGRA20_SPDIF_CTRL_PACK |
+               TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
-               val = TEGRA20_SPDIF_CTRL_PACK |
-                     TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+               val |= TEGRA20_SPDIF_CTRL_PACK |
+                      TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
                break;
        default:
                return -EINVAL;
index 231a785b3921a5bd95d87914a92e7f5f2d266a63..02247fee1cf7e1450fb4bbcdf2e58cf5ee76c7e8 100644 (file)
@@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index 3454262358b398913779954846ab12c11e7c5973..f4b12c216f1cd55c2db4396746a5abc9f20ed302 100644 (file)
@@ -1603,7 +1603,7 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
                        return err;
        }
 
-       return err;
+       return 0;
 }
 
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
index a9b02008443ce9a3356d46828bd075a63514b36a..927cd46d36dcbd98fb29676b0da0cb4da8eb4793 100644 (file)
@@ -39,10 +39,10 @@ cpupower: FORCE
 cgroup firewire guest usb virtio vm net: FORCE
        $(call descend,$@)
 
-liblk: FORCE
-       $(call descend,lib/lk)
+libapikfs: FORCE
+       $(call descend,lib/api)
 
-perf: liblk FORCE
+perf: libapikfs FORCE
        $(call descend,$@)
 
 selftests: FORCE
@@ -80,10 +80,10 @@ cpupower_clean:
 cgroup_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean:
        $(call descend,$(@:_clean=),clean)
 
-liblk_clean:
-       $(call descend,lib/lk,clean)
+libapikfs_clean:
+       $(call descend,lib/api,clean)
 
-perf_clean: liblk_clean
+perf_clean: libapikfs_clean
        $(call descend,$(@:_clean=),clean)
 
 selftests_clean:
similarity index 81%
rename from tools/perf/util/include/asm/bug.h
rename to tools/include/asm/bug.h
index 7fcc6810adc2165ff486902d7c84c1eb40166bbb..9e5f4846967fcf6e098c039c61b455f1a9326b64 100644 (file)
@@ -1,5 +1,7 @@
-#ifndef _PERF_ASM_GENERIC_BUG_H
-#define _PERF_ASM_GENERIC_BUG_H
+#ifndef _TOOLS_ASM_BUG_H
+#define _TOOLS_ASM_BUG_H
+
+#include <linux/compiler.h>
 
 #define __WARN_printf(arg...)  do { fprintf(stderr, arg); } while (0)
 
@@ -19,4 +21,5 @@
                        __warned = 1;           \
        unlikely(__ret_warn_once);              \
 })
-#endif
+
+#endif /* _TOOLS_ASM_BUG_H */
similarity index 64%
rename from tools/perf/util/include/linux/compiler.h
rename to tools/include/linux/compiler.h
index b003ad7200b230702b133071ab3d402395ab57e6..fbc6665c6d53e8f8c9f9caf91e32d48a35277573 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _PERF_LINUX_COMPILER_H_
-#define _PERF_LINUX_COMPILER_H_
+#ifndef _TOOLS_LINUX_COMPILER_H_
+#define _TOOLS_LINUX_COMPILER_H_
 
 #ifndef __always_inline
 # define __always_inline       inline __attribute__((always_inline))
 # define __weak                        __attribute__((weak))
 #endif
 
+#ifndef likely
+# define likely(x)             __builtin_expect(!!(x), 1)
 #endif
+
+#ifndef unlikely
+# define unlikely(x)           __builtin_expect(!!(x), 0)
+#endif
+
+#endif /* _TOOLS_LINUX_COMPILER_H */
similarity index 66%
rename from tools/lib/lk/Makefile
rename to tools/lib/api/Makefile
index 3dba0a4aebbf5b36ac0f24638eaf557d28b15170..ed2f51e11b80f36d63601c7abb1ea32db13566ff 100644 (file)
@@ -1,4 +1,5 @@
 include ../../scripts/Makefile.include
+include ../../perf/config/utilities.mak                # QUIET_CLEAN
 
 CC = $(CROSS_COMPILE)gcc
 AR = $(CROSS_COMPILE)ar
@@ -7,11 +8,11 @@ AR = $(CROSS_COMPILE)ar
 LIB_H=
 LIB_OBJS=
 
-LIB_H += debugfs.h
+LIB_H += fs/debugfs.h
 
-LIB_OBJS += $(OUTPUT)debugfs.o
+LIB_OBJS += $(OUTPUT)fs/debugfs.o
 
-LIBFILE = liblk.a
+LIBFILE = libapikfs.a
 
 CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC
 EXTLIBS = -lelf -lpthread -lrt -lm
@@ -25,14 +26,17 @@ $(LIBFILE): $(LIB_OBJS)
 
 $(LIB_OBJS): $(LIB_H)
 
-$(OUTPUT)%.o: %.c
+libapi_dirs:
+       $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/
+
+$(OUTPUT)%.o: %.c libapi_dirs
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
-$(OUTPUT)%.s: %.c
+$(OUTPUT)%.s: %.c libapi_dirs
        $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
-$(OUTPUT)%.o: %.S
+$(OUTPUT)%.o: %.S libapi_dirs
        $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
 
 clean:
-       $(RM) $(LIB_OBJS) $(LIBFILE)
+       $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE)
 
 .PHONY: clean
similarity index 86%
rename from tools/lib/lk/debugfs.h
rename to tools/lib/api/fs/debugfs.h
index 935c59bdb4428a975ef28b04c977c2dca28a85b6..f19d3df9609dd2c94e96a949b9a232183be98532 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __LK_DEBUGFS_H__
-#define __LK_DEBUGFS_H__
+#ifndef __API_DEBUGFS_H__
+#define __API_DEBUGFS_H__
 
 #define _STR(x) #x
 #define STR(x) _STR(x)
@@ -26,4 +26,4 @@ char *debugfs_mount(const char *mountpoint);
 
 extern char debugfs_mountpoint[];
 
-#endif /* __LK_DEBUGFS_H__ */
+#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
new file mode 100644 (file)
index 0000000..da8b7aa
--- /dev/null
@@ -0,0 +1,251 @@
+# liblockdep version
+LL_VERSION = 0
+LL_PATCHLEVEL = 0
+LL_EXTRAVERSION = 1
+
+# file format version
+FILE_VERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+prefix ?= /usr/local
+libdir_relative = lib
+libdir = $(prefix)/$(libdir_relative)
+bindir_relative = bin
+bindir = $(prefix)/$(bindir_relative)
+
+export DESTDIR DESTDIR_SQ INSTALL
+
+# copy a bit from Linux kbuild
+
+ifeq ("$(origin V)", "command line")
+  VERBOSE = $(V)
+endif
+ifndef VERBOSE
+  VERBOSE = 0
+endif
+
+ifeq ("$(origin O)", "command line")
+  BUILD_OUTPUT := $(O)
+endif
+
+ifeq ($(BUILD_SRC),)
+ifneq ($(BUILD_OUTPUT),)
+
+define build_output
+       $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
+       BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
+endef
+
+saved-output := $(BUILD_OUTPUT)
+BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
+$(if $(BUILD_OUTPUT),, \
+     $(error output directory "$(saved-output)" does not exist))
+
+all: sub-make
+
+gui: force
+       $(call build_output, all_cmd)
+
+$(filter-out gui,$(MAKECMDGOALS)): sub-make
+
+sub-make: force
+       $(call build_output, $(MAKECMDGOALS))
+
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+
+endif # BUILD_OUTPUT
+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)
+src            := $(srctree)
+obj            := $(objtree)
+
+export prefix libdir bindir src obj
+
+# Shell quotes
+libdir_SQ = $(subst ','\'',$(libdir))
+bindir_SQ = $(subst ','\'',$(bindir))
+
+LIB_FILE = liblockdep.a liblockdep.so
+BIN_FILE = lockdep
+
+CONFIG_INCLUDES =
+CONFIG_LIBS    =
+CONFIG_FLAGS   =
+
+OBJ            = $@
+N              =
+
+export Q VERBOSE
+
+LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
+
+INCLUDES = -I. -I/usr/local/include -I./uinclude $(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
+
+override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
+
+ifeq ($(VERBOSE),1)
+  Q =
+  print_compile =
+  print_app_build =
+  print_fpic_compile =
+  print_shared_lib_compile =
+  print_install =
+else
+  Q = @
+  print_compile =              echo '  CC                 '$(OBJ);
+  print_app_build =            echo '  BUILD              '$(OBJ);
+  print_fpic_compile =         echo '  CC FPIC            '$(OBJ);
+  print_shared_lib_compile =   echo '  BUILD SHARED LIB   '$(OBJ);
+  print_static_lib_build =     echo '  BUILD STATIC LIB   '$(OBJ);
+  print_install =              echo '  INSTALL     '$1'        to      $(DESTDIR_SQ)$2';
+endif
+
+do_fpic_compile =                                      \
+       ($(print_fpic_compile)                          \
+       $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
+
+do_app_build =                                         \
+       ($(print_app_build)                             \
+       $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
+
+do_compile_shared_library =                    \
+       ($(print_shared_lib_compile)            \
+       $(CC) --shared $^ -o $@ -lpthread -ldl)
+
+do_build_static_lib =                          \
+       ($(print_static_lib_build)              \
+       $(RM) $@;  $(AR) rcs $@ $^)
+
+
+define do_compile
+       $(print_compile)                                                \
+       $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
+endef
+
+$(obj)/%.o: $(src)/%.c
+       $(Q)$(call do_compile)
+
+%.o: $(src)/%.c
+       $(Q)$(call do_compile)
+
+PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
+
+ALL_OBJS = $(PEVENT_LIB_OBJS)
+
+CMD_TARGETS = $(LIB_FILE)
+
+TARGETS = $(CMD_TARGETS)
+
+
+all: all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+liblockdep.so: $(PEVENT_LIB_OBJS)
+       $(Q)$(do_compile_shared_library)
+
+liblockdep.a: $(PEVENT_LIB_OBJS)
+       $(Q)$(do_build_static_lib)
+
+$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
+       $(Q)$(do_fpic_compile)
+
+## make deps
+
+all_objs := $(sort $(ALL_OBJS))
+all_deps := $(all_objs:%.o=.%.d)
+
+# let .d file also depends on the source and header files
+define check_deps
+               @set -e; $(RM) $@; \
+               $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+               sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+               $(RM) $@.$$$$
+endef
+
+$(all_deps): .%.d: $(src)/%.c
+       $(Q)$(call check_deps)
+
+$(all_objs) : %.o : .%.d
+
+dep_includes := $(wildcard $(all_deps))
+
+ifneq ($(dep_includes),)
+ include $(dep_includes)
+endif
+
+### Detect environment changes
+TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
+
+tags:  force
+       $(RM) tags
+       find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
+       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+
+TAGS:  force
+       $(RM) TAGS
+       find . -name '*.[ch]' | xargs etags \
+       --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+
+define do_install
+       $(print_install)                                \
+       if [ ! -d '$(DESTDIR_SQ)$2' ]; then             \
+               $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
+       fi;                                             \
+       $(INSTALL) $1 '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: all_cmd
+       $(Q)$(call do_install,$(LIB_FILE),$(libdir_SQ))
+       $(Q)$(call do_install,$(BIN_FILE),$(bindir_SQ))
+
+install: install_lib
+
+clean:
+       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
+       $(RM) tags TAGS
+
+endif # skip-makefile
+
+PHONY += force
+force:
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
new file mode 100644 (file)
index 0000000..8ef602f
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <linux/compiler.h>
+#include <linux/lockdep.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+static __thread struct task_struct current_obj;
+
+/* lockdep wants these */
+bool debug_locks = true;
+bool debug_locks_silent;
+
+__attribute__((constructor)) static void liblockdep_init(void)
+{
+       lockdep_init();
+}
+
+__attribute__((destructor)) static void liblockdep_exit(void)
+{
+       debug_check_no_locks_held(&current_obj);
+}
+
+struct task_struct *__curr(void)
+{
+       if (current_obj.pid == 0) {
+               /* Makes lockdep output pretty */
+               prctl(PR_GET_NAME, current_obj.comm);
+               current_obj.pid = syscall(__NR_gettid);
+       }
+
+       return &current_obj;
+}
diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h
new file mode 100644 (file)
index 0000000..0bda630
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _LIBLOCKDEP_COMMON_H
+#define _LIBLOCKDEP_COMMON_H
+
+#include <pthread.h>
+
+#define NR_LOCKDEP_CACHING_CLASSES 2
+#define MAX_LOCKDEP_SUBCLASSES 8UL
+
+#ifndef CALLER_ADDR0
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#endif
+
+#ifndef _RET_IP_
+#define _RET_IP_ CALLER_ADDR0
+#endif
+
+#ifndef _THIS_IP_
+#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
+#endif
+
+struct lockdep_subclass_key {
+       char __one_byte;
+};
+
+struct lock_class_key {
+       struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
+};
+
+struct lockdep_map {
+       struct lock_class_key   *key;
+       struct lock_class       *class_cache[NR_LOCKDEP_CACHING_CLASSES];
+       const char              *name;
+#ifdef CONFIG_LOCK_STAT
+       int                     cpu;
+       unsigned long           ip;
+#endif
+};
+
+void lockdep_init_map(struct lockdep_map *lock, const char *name,
+                       struct lock_class_key *key, int subclass);
+void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+                       int trylock, int read, int check,
+                       struct lockdep_map *nest_lock, unsigned long ip);
+void lock_release(struct lockdep_map *lock, int nested,
+                       unsigned long ip);
+
+#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
+       { .name = (_name), .key = (void *)(_key), }
+
+#endif
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h
new file mode 100644 (file)
index 0000000..c342f70
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _LIBLOCKDEP_MUTEX_H
+#define _LIBLOCKDEP_MUTEX_H
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_mutex {
+       pthread_mutex_t mutex;
+       struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_mutex liblockdep_pthread_mutex_t;
+
+#define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx)                      \
+               (const struct liblockdep_pthread_mutex) {               \
+       .mutex = PTHREAD_MUTEX_INITIALIZER,                             \
+       .dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)), \
+}
+
+static inline int __mutex_init(liblockdep_pthread_mutex_t *lock,
+                               const char *name,
+                               struct lock_class_key *key,
+                               const pthread_mutexattr_t *__mutexattr)
+{
+       lockdep_init_map(&lock->dep_map, name, key, 0);
+       return pthread_mutex_init(&lock->mutex, __mutexattr);
+}
+
+#define liblockdep_pthread_mutex_init(mutex, mutexattr)                \
+({                                                             \
+       static struct lock_class_key __key;                     \
+                                                               \
+       __mutex_init((mutex), #mutex, &__key, (mutexattr));     \
+})
+
+static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_mutex_lock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock)
+{
+       lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_);
+       return pthread_mutex_unlock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock)
+{
+       return pthread_mutex_destroy(&lock->mutex);
+}
+
+#ifdef __USE_LIBLOCKDEP
+
+#define pthread_mutex_t         liblockdep_pthread_mutex_t
+#define pthread_mutex_init      liblockdep_pthread_mutex_init
+#define pthread_mutex_lock      liblockdep_pthread_mutex_lock
+#define pthread_mutex_unlock    liblockdep_pthread_mutex_unlock
+#define pthread_mutex_trylock   liblockdep_pthread_mutex_trylock
+#define pthread_mutex_destroy   liblockdep_pthread_mutex_destroy
+
+#endif
+
+#endif
diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h
new file mode 100644 (file)
index 0000000..a680ab8
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef _LIBLOCKDEP_RWLOCK_H
+#define _LIBLOCKDEP_RWLOCK_H
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_rwlock {
+       pthread_rwlock_t rwlock;
+       struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_rwlock liblockdep_pthread_rwlock_t;
+
+#define LIBLOCKDEP_PTHREAD_RWLOCK_INITIALIZER(rwl)                     \
+               (struct liblockdep_pthread_rwlock) {                    \
+       .rwlock = PTHREAD_RWLOCK_INITIALIZER,                           \
+       .dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)), \
+}
+
+static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock,
+                               const char *name,
+                               struct lock_class_key *key,
+                               const pthread_rwlockattr_t *attr)
+{
+       lockdep_init_map(&lock->dep_map, name, key, 0);
+
+       return pthread_rwlock_init(&lock->rwlock, attr);
+}
+
+#define liblockdep_pthread_rwlock_init(lock, attr)             \
+({                                                     \
+       static struct lock_class_key __key;             \
+                                                       \
+       __rwlock_init((lock), #lock, &__key, (attr));   \
+})
+
+static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_rdlock(&lock->rwlock);
+
+}
+
+static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_);
+       return pthread_rwlock_unlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_wrlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
+{
+       return pthread_rwlock_destroy(&lock->rwlock);
+}
+
+#ifdef __USE_LIBLOCKDEP
+
+#define pthread_rwlock_t               liblockdep_pthread_rwlock_t
+#define pthread_rwlock_init            liblockdep_pthread_rwlock_init
+#define pthread_rwlock_rdlock          liblockdep_pthread_rwlock_rdlock
+#define pthread_rwlock_unlock          liblockdep_pthread_rwlock_unlock
+#define pthread_rwlock_wrlock          liblockdep_pthread_rwlock_wrlock
+#define pthread_rwlock_tryrdlock       liblockdep_pthread_rwlock_tryrdlock
+#define pthread_rwlock_trywlock                liblockdep_pthread_rwlock_trywlock
+#define pthread_rwlock_destroy         liblockdep_rwlock_destroy
+
+#endif
+
+#endif
diff --git a/tools/lib/lockdep/lockdep b/tools/lib/lockdep/lockdep
new file mode 100755 (executable)
index 0000000..49af9fe
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+LD_PRELOAD="./liblockdep.so $LD_PRELOAD" "$@"
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c
new file mode 100644 (file)
index 0000000..f42b7e9
--- /dev/null
@@ -0,0 +1,2 @@
+#include <linux/lockdep.h>
+#include "../../../kernel/locking/lockdep.c"
diff --git a/tools/lib/lockdep/lockdep_internals.h b/tools/lib/lockdep/lockdep_internals.h
new file mode 100644 (file)
index 0000000..29d0c95
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../kernel/locking/lockdep_internals.h"
diff --git a/tools/lib/lockdep/lockdep_states.h b/tools/lib/lockdep/lockdep_states.h
new file mode 100644 (file)
index 0000000..248d235
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../kernel/locking/lockdep_states.h"
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c
new file mode 100644 (file)
index 0000000..f8465a8
--- /dev/null
@@ -0,0 +1,447 @@
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include "include/liblockdep/mutex.h"
+#include "../../../include/linux/rbtree.h"
+
+/**
+ * struct lock_lookup - liblockdep's view of a single unique lock
+ * @orig: pointer to the original pthread lock, used for lookups
+ * @dep_map: lockdep's dep_map structure
+ * @key: lockdep's key structure
+ * @node: rb-tree node used to store the lock in a global tree
+ * @name: a unique name for the lock
+ */
+struct lock_lookup {
+       void *orig; /* Original pthread lock, used for lookups */
+       struct lockdep_map dep_map; /* Since all locks are dynamic, we need
+                                    * a dep_map and a key for each lock */
+       /*
+        * Wait, there's no support for key classes? Yup :(
+        * Most big projects wrap the pthread api with their own calls to
+        * be compatible with different locking methods. This means that
+        * "classes" will be brokes since the function that creates all
+        * locks will point to a generic locking function instead of the
+        * actual code that wants to do the locking.
+        */
+       struct lock_class_key key;
+       struct rb_node node;
+#define LIBLOCKDEP_MAX_LOCK_NAME 22
+       char name[LIBLOCKDEP_MAX_LOCK_NAME];
+};
+
+/* This is where we store our locks */
+static struct rb_root locks = RB_ROOT;
+static pthread_rwlock_t locks_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* pthread mutex API */
+
+#ifdef __GLIBC__
+extern int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
+extern int __pthread_mutex_lock(pthread_mutex_t *mutex);
+extern int __pthread_mutex_trylock(pthread_mutex_t *mutex);
+extern int __pthread_mutex_unlock(pthread_mutex_t *mutex);
+extern int __pthread_mutex_destroy(pthread_mutex_t *mutex);
+#else
+#define __pthread_mutex_init   NULL
+#define __pthread_mutex_lock   NULL
+#define __pthread_mutex_trylock        NULL
+#define __pthread_mutex_unlock NULL
+#define __pthread_mutex_destroy        NULL
+#endif
+static int (*ll_pthread_mutex_init)(pthread_mutex_t *mutex,
+                       const pthread_mutexattr_t *attr)        = __pthread_mutex_init;
+static int (*ll_pthread_mutex_lock)(pthread_mutex_t *mutex)    = __pthread_mutex_lock;
+static int (*ll_pthread_mutex_trylock)(pthread_mutex_t *mutex) = __pthread_mutex_trylock;
+static int (*ll_pthread_mutex_unlock)(pthread_mutex_t *mutex)  = __pthread_mutex_unlock;
+static int (*ll_pthread_mutex_destroy)(pthread_mutex_t *mutex) = __pthread_mutex_destroy;
+
+/* pthread rwlock API */
+
+#ifdef __GLIBC__
+extern int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
+extern int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
+#else
+#define __pthread_rwlock_init          NULL
+#define __pthread_rwlock_destroy       NULL
+#define __pthread_rwlock_wrlock                NULL
+#define __pthread_rwlock_trywrlock     NULL
+#define __pthread_rwlock_rdlock                NULL
+#define __pthread_rwlock_tryrdlock     NULL
+#define __pthread_rwlock_unlock                NULL
+#endif
+
+static int (*ll_pthread_rwlock_init)(pthread_rwlock_t *rwlock,
+                       const pthread_rwlockattr_t *attr)               = __pthread_rwlock_init;
+static int (*ll_pthread_rwlock_destroy)(pthread_rwlock_t *rwlock)      = __pthread_rwlock_destroy;
+static int (*ll_pthread_rwlock_rdlock)(pthread_rwlock_t *rwlock)       = __pthread_rwlock_rdlock;
+static int (*ll_pthread_rwlock_tryrdlock)(pthread_rwlock_t *rwlock)    = __pthread_rwlock_tryrdlock;
+static int (*ll_pthread_rwlock_trywrlock)(pthread_rwlock_t *rwlock)    = __pthread_rwlock_trywrlock;
+static int (*ll_pthread_rwlock_wrlock)(pthread_rwlock_t *rwlock)       = __pthread_rwlock_wrlock;
+static int (*ll_pthread_rwlock_unlock)(pthread_rwlock_t *rwlock)       = __pthread_rwlock_unlock;
+
+enum { none, prepare, done, } __init_state;
+static void init_preload(void);
+static void try_init_preload(void)
+{
+       if (!__init_state != done)
+               init_preload();
+}
+
+static struct rb_node **__get_lock_node(void *lock, struct rb_node **parent)
+{
+       struct rb_node **node = &locks.rb_node;
+       struct lock_lookup *l;
+
+       *parent = NULL;
+
+       while (*node) {
+               l = rb_entry(*node, struct lock_lookup, node);
+
+               *parent = *node;
+               if (lock < l->orig)
+                       node = &l->node.rb_left;
+               else if (lock > l->orig)
+                       node = &l->node.rb_right;
+               else
+                       return node;
+       }
+
+       return node;
+}
+
+#ifndef LIBLOCKDEP_STATIC_ENTRIES
+#define LIBLOCKDEP_STATIC_ENTRIES      1024
+#endif
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static struct lock_lookup __locks[LIBLOCKDEP_STATIC_ENTRIES];
+static int __locks_nr;
+
+static inline bool is_static_lock(struct lock_lookup *lock)
+{
+       return lock >= __locks && lock < __locks + ARRAY_SIZE(__locks);
+}
+
+static struct lock_lookup *alloc_lock(void)
+{
+       if (__init_state != done) {
+               /*
+                * Some programs attempt to initialize and use locks in their
+                * allocation path. This means that a call to malloc() would
+                * result in locks being initialized and locked.
+                *
+                * Why is it an issue for us? dlsym() below will try allocating
+                * to give us the original function. Since this allocation will
+                * result in a locking operations, we have to let pthread deal
+                * with it, but we can't! we don't have the pointer to the
+                * original API since we're inside dlsym() trying to get it
+                */
+
+               int idx = __locks_nr++;
+               if (idx >= ARRAY_SIZE(__locks)) {
+                       fprintf(stderr,
+               "LOCKDEP error: insufficient LIBLOCKDEP_STATIC_ENTRIES\n");
+                       exit(EX_UNAVAILABLE);
+               }
+               return __locks + idx;
+       }
+
+       return malloc(sizeof(struct lock_lookup));
+}
+
+static inline void free_lock(struct lock_lookup *lock)
+{
+       if (likely(!is_static_lock(lock)))
+               free(lock);
+}
+
+/**
+ * __get_lock - find or create a lock instance
+ * @lock: pointer to a pthread lock function
+ *
+ * Try to find an existing lock in the rbtree using the provided pointer. If
+ * one wasn't found - create it.
+ */
+static struct lock_lookup *__get_lock(void *lock)
+{
+       struct rb_node **node, *parent;
+       struct lock_lookup *l;
+
+       ll_pthread_rwlock_rdlock(&locks_rwlock);
+       node = __get_lock_node(lock, &parent);
+       ll_pthread_rwlock_unlock(&locks_rwlock);
+       if (*node) {
+               return rb_entry(*node, struct lock_lookup, node);
+       }
+
+       /* We didn't find the lock, let's create it */
+       l = alloc_lock();
+       if (l == NULL)
+               return NULL;
+
+       l->orig = lock;
+       /*
+        * Currently the name of the lock is the ptr value of the pthread lock,
+        * while not optimal, it makes debugging a bit easier.
+        *
+        * TODO: Get the real name of the lock using libdwarf
+        */
+       sprintf(l->name, "%p", lock);
+       lockdep_init_map(&l->dep_map, l->name, &l->key, 0);
+
+       ll_pthread_rwlock_wrlock(&locks_rwlock);
+       /* This might have changed since the last time we fetched it */
+       node = __get_lock_node(lock, &parent);
+       rb_link_node(&l->node, parent, node);
+       rb_insert_color(&l->node, &locks);
+       ll_pthread_rwlock_unlock(&locks_rwlock);
+
+       return l;
+}
+
+static void __del_lock(struct lock_lookup *lock)
+{
+       ll_pthread_rwlock_wrlock(&locks_rwlock);
+       rb_erase(&lock->node, &locks);
+       ll_pthread_rwlock_unlock(&locks_rwlock);
+       free_lock(lock);
+}
+
+int pthread_mutex_init(pthread_mutex_t *mutex,
+                       const pthread_mutexattr_t *attr)
+{
+       int r;
+
+       /*
+        * We keep trying to init our preload module because there might be
+        * code in init sections that tries to touch locks before we are
+        * initialized, in that case we'll need to manually call preload
+        * to get us going.
+        *
+        * Funny enough, kernel's lockdep had the same issue, and used
+        * (almost) the same solution. See look_up_lock_class() in
+        * kernel/locking/lockdep.c for details.
+        */
+       try_init_preload();
+
+       r = ll_pthread_mutex_init(mutex, attr);
+       if (r == 0)
+               /*
+                * We do a dummy initialization here so that lockdep could
+                * warn us if something fishy is going on - such as
+                * initializing a held lock.
+                */
+               __get_lock(mutex);
+
+       return r;
+}
+
+int pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+       int r;
+
+       try_init_preload();
+
+       lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL,
+                       (unsigned long)_RET_IP_);
+       /*
+        * Here's the thing with pthread mutexes: unlike the kernel variant,
+        * they can fail.
+        *
+        * This means that the behaviour here is a bit different from what's
+        * going on in the kernel: there we just tell lockdep that we took the
+        * lock before actually taking it, but here we must deal with the case
+        * that locking failed.
+        *
+        * To do that we'll "release" the lock if locking failed - this way
+        * we'll get lockdep doing the correct checks when we try to take
+        * the lock, and if that fails - we'll be back to the correct
+        * state by releasing it.
+        */
+       r = ll_pthread_mutex_lock(mutex);
+       if (r)
+               lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+       int r;
+
+       try_init_preload();
+
+       lock_acquire(&__get_lock(mutex)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_mutex_trylock(mutex);
+       if (r)
+               lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+       int r;
+
+       try_init_preload();
+
+       lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_);
+       /*
+        * Just like taking a lock, only in reverse!
+        *
+        * If we fail releasing the lock, tell lockdep we're holding it again.
+        */
+       r = ll_pthread_mutex_unlock(mutex);
+       if (r)
+               lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+       try_init_preload();
+
+       /*
+        * Let's see if we're releasing a lock that's held.
+        *
+        * TODO: Hook into free() and add that check there as well.
+        */
+       debug_check_no_locks_freed(mutex, mutex + sizeof(*mutex));
+       __del_lock(__get_lock(mutex));
+       return ll_pthread_mutex_destroy(mutex);
+}
+
+/* This is the rwlock part, very similar to what happened with mutex above */
+int pthread_rwlock_init(pthread_rwlock_t *rwlock,
+                       const pthread_rwlockattr_t *attr)
+{
+       int r;
+
+       try_init_preload();
+
+       r = ll_pthread_rwlock_init(rwlock, attr);
+       if (r == 0)
+               __get_lock(rwlock);
+
+       return r;
+}
+
+int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
+{
+       try_init_preload();
+
+       debug_check_no_locks_freed(rwlock, rwlock + sizeof(*rwlock));
+       __del_lock(__get_lock(rwlock));
+       return ll_pthread_rwlock_destroy(rwlock);
+}
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_rdlock(rwlock);
+       if (r)
+               lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_tryrdlock(rwlock);
+       if (r)
+               lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_trywrlock(rwlock);
+       if (r)
+                lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_wrlock(rwlock);
+       if (r)
+               lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_unlock(rwlock);
+       if (r)
+               lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+__attribute__((constructor)) static void init_preload(void)
+{
+       if (__init_state != done)
+               return;
+
+#ifndef __GLIBC__
+       __init_state = prepare;
+
+       ll_pthread_mutex_init = dlsym(RTLD_NEXT, "pthread_mutex_init");
+       ll_pthread_mutex_lock = dlsym(RTLD_NEXT, "pthread_mutex_lock");
+       ll_pthread_mutex_trylock = dlsym(RTLD_NEXT, "pthread_mutex_trylock");
+       ll_pthread_mutex_unlock = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
+       ll_pthread_mutex_destroy = dlsym(RTLD_NEXT, "pthread_mutex_destroy");
+
+       ll_pthread_rwlock_init = dlsym(RTLD_NEXT, "pthread_rwlock_init");
+       ll_pthread_rwlock_destroy = dlsym(RTLD_NEXT, "pthread_rwlock_destroy");
+       ll_pthread_rwlock_rdlock = dlsym(RTLD_NEXT, "pthread_rwlock_rdlock");
+       ll_pthread_rwlock_tryrdlock = dlsym(RTLD_NEXT, "pthread_rwlock_tryrdlock");
+       ll_pthread_rwlock_wrlock = dlsym(RTLD_NEXT, "pthread_rwlock_wrlock");
+       ll_pthread_rwlock_trywrlock = dlsym(RTLD_NEXT, "pthread_rwlock_trywrlock");
+       ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock");
+#endif
+
+       printf("%p\n", ll_pthread_mutex_trylock);fflush(stdout);
+
+       lockdep_init();
+
+       __init_state = done;
+}
diff --git a/tools/lib/lockdep/rbtree.c b/tools/lib/lockdep/rbtree.c
new file mode 100644 (file)
index 0000000..f7f4303
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../lib/rbtree.c"
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
new file mode 100644 (file)
index 0000000..5334ad9
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/bash
+
+make &> /dev/null
+
+for i in `ls tests/*.c`; do
+       testname=$(basename -s .c "$i")
+       gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
+       echo -ne "$testname... "
+       if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then
+               echo "PASSED!"
+       else
+               echo "FAILED!"
+       fi
+       rm tests/$testname
+done
+
+for i in `ls tests/*.c`; do
+       testname=$(basename -s .c "$i")
+       gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null
+       echo -ne "(PRELOAD) $testname... "
+       if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then
+               echo "PASSED!"
+       else
+               echo "FAILED!"
+       fi
+       rm tests/$testname
+done
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c
new file mode 100644 (file)
index 0000000..0f782ff
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+       pthread_mutex_t a, b;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+
+       pthread_mutex_lock(&a);
+       pthread_mutex_lock(&b);
+       pthread_mutex_lock(&a);
+}
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c
new file mode 100644 (file)
index 0000000..07f0e29
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(b, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c
new file mode 100644 (file)
index 0000000..843db09
--- /dev/null
@@ -0,0 +1,15 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(b, c);
+       LOCK_UNLOCK_2(c, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c
new file mode 100644 (file)
index 0000000..33620e2
--- /dev/null
@@ -0,0 +1,17 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c, d;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+       pthread_mutex_init(&d, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(b, c);
+       LOCK_UNLOCK_2(c, d);
+       LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c
new file mode 100644 (file)
index 0000000..3fee51e
--- /dev/null
@@ -0,0 +1,15 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(c, a);
+       LOCK_UNLOCK_2(b, c);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c
new file mode 100644 (file)
index 0000000..427ba56
--- /dev/null
@@ -0,0 +1,17 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c, d;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+       pthread_mutex_init(&d, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(c, d);
+       LOCK_UNLOCK_2(b, c);
+       LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c
new file mode 100644 (file)
index 0000000..680c6cf
--- /dev/null
@@ -0,0 +1,17 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c, d;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+       pthread_mutex_init(&d, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(c, d);
+       LOCK_UNLOCK_2(b, d);
+       LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c
new file mode 100644 (file)
index 0000000..d44f77d
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/rwlock.h>
+
+void main(void)
+{
+       pthread_rwlock_t a, b;
+
+       pthread_rwlock_init(&a, NULL);
+       pthread_rwlock_init(&b, NULL);
+
+       pthread_rwlock_wrlock(&a);
+       pthread_rwlock_rdlock(&b);
+       pthread_rwlock_wrlock(&a);
+}
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h
new file mode 100644 (file)
index 0000000..d89e94d
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_TEST_COMMON_H
+#define _LIBLOCKDEP_TEST_COMMON_H
+
+#define LOCK_UNLOCK_2(a, b)                    \
+       do {                                    \
+               pthread_mutex_lock(&(a));       \
+               pthread_mutex_lock(&(b));       \
+               pthread_mutex_unlock(&(b));     \
+               pthread_mutex_unlock(&(a));     \
+       } while(0)
+
+#endif
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c
new file mode 100644 (file)
index 0000000..0bc62de
--- /dev/null
@@ -0,0 +1,12 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+       pthread_mutex_t a;
+
+       pthread_mutex_init(&a, NULL);
+
+       pthread_mutex_lock(&a);
+       pthread_mutex_unlock(&a);
+       pthread_mutex_unlock(&a);
+}
diff --git a/tools/lib/lockdep/uinclude/asm/hweight.h b/tools/lib/lockdep/uinclude/asm/hweight.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/asm/sections.h b/tools/lib/lockdep/uinclude/asm/sections.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/bitops.h b/tools/lib/lockdep/uinclude/linux/bitops.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h
new file mode 100644 (file)
index 0000000..7ac838a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_COMPILER_H_
+#define _LIBLOCKDEP_LINUX_COMPILER_H_
+
+#define __used         __attribute__((__unused__))
+#define unlikely
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/debug_locks.h b/tools/lib/lockdep/uinclude/linux/debug_locks.h
new file mode 100644 (file)
index 0000000..f38eb64
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_
+#define _LIBLOCKDEP_DEBUG_LOCKS_H_
+
+#include <stddef.h>
+#include <linux/compiler.h>
+
+#define DEBUG_LOCKS_WARN_ON(x) (x)
+
+extern bool debug_locks;
+extern bool debug_locks_silent;
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/delay.h b/tools/lib/lockdep/uinclude/linux/delay.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/export.h b/tools/lib/lockdep/uinclude/linux/export.h
new file mode 100644 (file)
index 0000000..6bdf349
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_EXPORT_H_
+#define _LIBLOCKDEP_LINUX_EXPORT_H_
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/ftrace.h b/tools/lib/lockdep/uinclude/linux/ftrace.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/gfp.h b/tools/lib/lockdep/uinclude/linux/gfp.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/lib/lockdep/uinclude/linux/hardirq.h
new file mode 100644 (file)
index 0000000..c8f3f8f
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_
+#define _LIBLOCKDEP_LINUX_HARDIRQ_H_
+
+#define SOFTIRQ_BITS   0UL
+#define HARDIRQ_BITS   0UL
+#define SOFTIRQ_SHIFT  0UL
+#define HARDIRQ_SHIFT  0UL
+#define hardirq_count()        0UL
+#define softirq_count()        0UL
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h
new file mode 100644 (file)
index 0000000..0f84798
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/hash.h"
diff --git a/tools/lib/lockdep/uinclude/linux/interrupt.h b/tools/lib/lockdep/uinclude/linux/interrupt.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/lib/lockdep/uinclude/linux/irqflags.h
new file mode 100644 (file)
index 0000000..6cc296f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+
+# define trace_hardirq_context(p)      0
+# define trace_softirq_context(p)      0
+# define trace_hardirqs_enabled(p)     0
+# define trace_softirqs_enabled(p)     0
+# define trace_hardirq_enter()         do { } while (0)
+# define trace_hardirq_exit()          do { } while (0)
+# define lockdep_softirq_enter()       do { } while (0)
+# define lockdep_softirq_exit()                do { } while (0)
+# define INIT_TRACE_IRQFLAGS
+
+# define stop_critical_timings() do { } while (0)
+# define start_critical_timings() do { } while (0)
+
+#define raw_local_irq_disable() do { } while (0)
+#define raw_local_irq_enable() do { } while (0)
+#define raw_local_irq_save(flags) ((flags) = 0)
+#define raw_local_irq_restore(flags) do { } while (0)
+#define raw_local_save_flags(flags) ((flags) = 0)
+#define raw_irqs_disabled_flags(flags) do { } while (0)
+#define raw_irqs_disabled() 0
+#define raw_safe_halt()
+
+#define local_irq_enable() do { } while (0)
+#define local_irq_disable() do { } while (0)
+#define local_irq_save(flags) ((flags) = 0)
+#define local_irq_restore(flags) do { } while (0)
+#define local_save_flags(flags)        ((flags) = 0)
+#define irqs_disabled() (1)
+#define irqs_disabled_flags(flags) (0)
+#define safe_halt() do { } while (0)
+
+#define trace_lock_release(x, y)
+#define trace_lock_acquire(a, b, c, d, e, f, g)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/lib/lockdep/uinclude/linux/kallsyms.h
new file mode 100644 (file)
index 0000000..b0f2dbd
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_
+#define _LIBLOCKDEP_LINUX_KALLSYMS_H_
+
+#include <linux/kernel.h>
+#include <stdio.h>
+
+#define KSYM_NAME_LEN 128
+
+struct module;
+
+static inline const char *kallsyms_lookup(unsigned long addr,
+                                         unsigned long *symbolsize,
+                                         unsigned long *offset,
+                                         char **modname, char *namebuf)
+{
+       return NULL;
+}
+
+#include <execinfo.h>
+#include <stdlib.h>
+static inline void print_ip_sym(unsigned long ip)
+{
+       char **name;
+
+       name = backtrace_symbols((void **)&ip, 1);
+
+       printf("%s\n", *name);
+
+       free(name);
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kern_levels.h b/tools/lib/lockdep/uinclude/linux/kern_levels.h
new file mode 100644 (file)
index 0000000..3b9bade
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __KERN_LEVELS_H__
+#define __KERN_LEVELS_H__
+
+#define KERN_SOH       ""              /* ASCII Start Of Header */
+#define KERN_SOH_ASCII ''
+
+#define KERN_EMERG     KERN_SOH ""     /* system is unusable */
+#define KERN_ALERT     KERN_SOH ""     /* action must be taken immediately */
+#define KERN_CRIT      KERN_SOH ""     /* critical conditions */
+#define KERN_ERR       KERN_SOH ""     /* error conditions */
+#define KERN_WARNING   KERN_SOH ""     /* warning conditions */
+#define KERN_NOTICE    KERN_SOH ""     /* normal but significant condition */
+#define KERN_INFO      KERN_SOH ""     /* informational */
+#define KERN_DEBUG     KERN_SOH ""     /* debug-level messages */
+
+#define KERN_DEFAULT   KERN_SOH ""     /* the default kernel loglevel */
+
+/*
+ * Annotation for a "continued" line of log printout (only done after a
+ * line that had no enclosing \n). Only to be used by core/arch code
+ * during early bootup (a continued line is not SMP-safe otherwise).
+ */
+#define KERN_CONT      ""
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h
new file mode 100644 (file)
index 0000000..a11e3c3
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _LIBLOCKDEP_LINUX_KERNEL_H_
+#define _LIBLOCKDEP_LINUX_KERNEL_H_
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/rcu.h>
+#include <linux/hardirq.h>
+#include <linux/kern_levels.h>
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({                     \
+       const typeof(((type *)0)->member) * __mptr = (ptr);     \
+       (type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define max(x, y) ({                           \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#define WARN_ON(x) (x)
+#define WARN_ON_ONCE(x) (x)
+#define likely(x) (x)
+#define WARN(x, y, z) (x)
+#define uninitialized_var(x) x
+#define __init
+#define noinline
+#define list_add_tail_rcu list_add_tail
+
+#ifndef CALLER_ADDR0
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#endif
+
+#ifndef _RET_IP_
+#define _RET_IP_ CALLER_ADDR0
+#endif
+
+#ifndef _THIS_IP_
+#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
+#endif
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/lib/lockdep/uinclude/linux/kmemcheck.h
new file mode 100644 (file)
index 0000000..94d598b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+#define _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+
+static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
+{
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/linkage.h b/tools/lib/lockdep/uinclude/linux/linkage.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h
new file mode 100644 (file)
index 0000000..6e9ef31
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/list.h"
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
new file mode 100644 (file)
index 0000000..d0f5d6e
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _LIBLOCKDEP_LOCKDEP_H_
+#define _LIBLOCKDEP_LOCKDEP_H_
+
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <limits.h>
+#include <linux/utsname.h>
+
+
+#define MAX_LOCK_DEPTH 2000UL
+
+#include "../../../include/linux/lockdep.h"
+
+struct task_struct {
+       u64 curr_chain_key;
+       int lockdep_depth;
+       unsigned int lockdep_recursion;
+       struct held_lock held_locks[MAX_LOCK_DEPTH];
+       gfp_t lockdep_reclaim_gfp;
+       int pid;
+       char comm[17];
+};
+
+extern struct task_struct *__curr(void);
+
+#define current (__curr())
+
+#define debug_locks_off() 1
+#define task_pid_nr(tsk) ((tsk)->pid)
+
+#define KSYM_NAME_LEN 128
+#define printk printf
+
+#define list_del_rcu list_del
+
+#define atomic_t unsigned long
+#define atomic_inc(x) ((*(x))++)
+
+static struct new_utsname *init_utsname(void)
+{
+       static struct new_utsname n = (struct new_utsname) {
+               .release = "liblockdep",
+               .version = LIBLOCKDEP_VERSION,
+       };
+
+       return &n;
+}
+
+#define print_tainted() ""
+#define static_obj(x) 1
+
+#define debug_show_all_locks()
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/lib/lockdep/uinclude/linux/module.h
new file mode 100644 (file)
index 0000000..09c7a7b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_MODULE_H_
+#define _LIBLOCKDEP_LINUX_MODULE_H_
+
+#define module_param(name, type, perm)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/mutex.h b/tools/lib/lockdep/uinclude/linux/mutex.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h
new file mode 100644 (file)
index 0000000..0c27bdf
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/poison.h"
diff --git a/tools/lib/lockdep/uinclude/linux/prefetch.h b/tools/lib/lockdep/uinclude/linux/prefetch.h
new file mode 100644 (file)
index 0000000..d73fe6f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_
+#define _LIBLOCKDEP_LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/proc_fs.h b/tools/lib/lockdep/uinclude/linux/proc_fs.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree.h b/tools/lib/lockdep/uinclude/linux/rbtree.h
new file mode 100644 (file)
index 0000000..965901d
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/rbtree.h"
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h
new file mode 100644 (file)
index 0000000..c375947
--- /dev/null
@@ -0,0 +1,2 @@
+#define __always_inline
+#include "../../../include/linux/rbtree_augmented.h"
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h
new file mode 100644 (file)
index 0000000..4c99fcb
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _LIBLOCKDEP_RCU_H_
+#define _LIBLOCKDEP_RCU_H_
+
+int rcu_scheduler_active;
+
+static inline int rcu_lockdep_current_cpu_online(void)
+{
+       return 1;
+}
+
+static inline int rcu_is_cpu_idle(void)
+{
+       return 1;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/seq_file.h b/tools/lib/lockdep/uinclude/linux/seq_file.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h
new file mode 100644 (file)
index 0000000..68c1aa2
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _LIBLOCKDEP_SPINLOCK_H_
+#define _LIBLOCKDEP_SPINLOCK_H_
+
+#include <pthread.h>
+#include <stdbool.h>
+
+#define arch_spinlock_t pthread_mutex_t
+#define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
+
+static inline void arch_spin_lock(arch_spinlock_t *mutex)
+{
+       pthread_mutex_lock(mutex);
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *mutex)
+{
+       pthread_mutex_unlock(mutex);
+}
+
+static inline bool arch_spin_is_locked(arch_spinlock_t *mutex)
+{
+       return true;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/lib/lockdep/uinclude/linux/stacktrace.h
new file mode 100644 (file)
index 0000000..39aecc6
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_
+#define _LIBLOCKDEP_LINUX_STACKTRACE_H_
+
+#include <execinfo.h>
+
+struct stack_trace {
+       unsigned int nr_entries, max_entries;
+       unsigned long *entries;
+       int skip;
+};
+
+static inline void print_stack_trace(struct stack_trace *trace, int spaces)
+{
+       backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1);
+}
+
+#define save_stack_trace(trace)        \
+       ((trace)->nr_entries =  \
+               backtrace((void **)(trace)->entries, (trace)->max_entries))
+
+static inline int dump_stack(void)
+{
+       void *array[64];
+       size_t size;
+
+       size = backtrace(array, 64);
+       backtrace_symbols_fd(array, size, 1);
+
+       return 0;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h
new file mode 100644 (file)
index 0000000..05dfcd1
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_
+#define _LIBLOCKDEP_LINUX_STRINGIFY_H_
+
+#define __stringify_1(x...)    #x
+#define __stringify(x...)      __stringify_1(x)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/types.h b/tools/lib/lockdep/uinclude/linux/types.h
new file mode 100644 (file)
index 0000000..929938f
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCKDEP_LINUX_TYPES_H_
+#define _LIBLOCKDEP_LINUX_TYPES_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#define __SANE_USERSPACE_TYPES__       /* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+struct page;
+struct kmem_cache;
+
+typedef unsigned gfp_t;
+
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8  u8;
+typedef __s8  s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+struct hlist_head {
+       struct hlist_node *first;
+};
+
+struct hlist_node {
+       struct hlist_node *next, **pprev;
+};
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/trace/events/lock.h b/tools/lib/lockdep/uinclude/trace/events/lock.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c
new file mode 100644 (file)
index 0000000..18bc271
--- /dev/null
@@ -0,0 +1,58 @@
+#include "symbol/kallsyms.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int kallsyms__parse(const char *filename, void *arg,
+                   int (*process_symbol)(void *arg, const char *name,
+                                         char type, u64 start))
+{
+       char *line = NULL;
+       size_t n;
+       int err = -1;
+       FILE *file = fopen(filename, "r");
+
+       if (file == NULL)
+               goto out_failure;
+
+       err = 0;
+
+       while (!feof(file)) {
+               u64 start;
+               int line_len, len;
+               char symbol_type;
+               char *symbol_name;
+
+               line_len = getline(&line, &n, file);
+               if (line_len < 0 || !line)
+                       break;
+
+               line[--line_len] = '\0'; /* \n */
+
+               len = hex2u64(line, &start);
+
+               len++;
+               if (len + 2 >= line_len)
+                       continue;
+
+               symbol_type = line[len];
+               len += 2;
+               symbol_name = line + len;
+               len = line_len - len;
+
+               if (len >= KSYM_NAME_LEN) {
+                       err = -1;
+                       break;
+               }
+
+               err = process_symbol(arg, symbol_name, symbol_type, start);
+               if (err)
+                       break;
+       }
+
+       free(line);
+       fclose(file);
+       return err;
+
+out_failure:
+       return -1;
+}
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
new file mode 100644 (file)
index 0000000..6084f5e
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_KALLSYMS_H_
+#define __TOOLS_KALLSYMS_H_ 1
+
+#include <elf.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+
+#ifndef KSYM_NAME_LEN
+#define KSYM_NAME_LEN 256
+#endif
+
+static inline u8 kallsyms2elf_type(char type)
+{
+       if (type == 'W')
+               return STB_WEAK;
+
+       return isupper(type) ? STB_GLOBAL : STB_LOCAL;
+}
+
+int kallsyms__parse(const char *filename, void *arg,
+                   int (*process_symbol)(void *arg, const char *name,
+                                         char type, u64 start));
+
+#endif /* __TOOLS_KALLSYMS_H_ */
index fc1502098595b8b960f262c4f789c15c247d0d61..56d52a33a3dfcff26838ddbf6ef1f5257bb9a331 100644 (file)
@@ -43,6 +43,32 @@ man_dir_SQ = '$(subst ','\'',$(man_dir))'
 export man_dir man_dir_SQ INSTALL
 export DESTDIR DESTDIR_SQ
 
+set_plugin_dir := 1
+
+# Set plugin_dir to preffered global plugin location
+# If we install under $HOME directory we go under
+# $(HOME)/.traceevent/plugins
+#
+# We dont set PLUGIN_DIR in case we install under $HOME
+# directory, because by default the code looks under:
+# $(HOME)/.traceevent/plugins by default.
+#
+ifeq ($(plugin_dir),)
+ifeq ($(prefix),$(HOME))
+override plugin_dir = $(HOME)/.traceevent/plugins
+set_plugin_dir := 0
+else
+override plugin_dir = $(prefix)/lib/traceevent/plugins
+endif
+endif
+
+ifeq ($(set_plugin_dir),1)
+PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)"
+PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
+endif
+
+include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include
+
 # copy a bit from Linux kbuild
 
 ifeq ("$(origin V)", "command line")
@@ -57,18 +83,13 @@ ifeq ("$(origin O)", "command line")
 endif
 
 ifeq ($(BUILD_SRC),)
-ifneq ($(BUILD_OUTPUT),)
+ifneq ($(OUTPUT),)
 
 define build_output
-       $(if $(VERBOSE:1=),@)+$(MAKE) -C $(BUILD_OUTPUT)        \
-       BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
+  $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
+  BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
 endef
 
-saved-output := $(BUILD_OUTPUT)
-BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
-$(if $(BUILD_OUTPUT),, \
-     $(error output directory "$(saved-output)" does not exist))
-
 all: sub-make
 
 $(MAKECMDGOALS): sub-make
@@ -80,7 +101,7 @@ sub-make: force
 # Leave processing to above invocation of make
 skip-makefile := 1
 
-endif # BUILD_OUTPUT
+endif # OUTPUT
 endif # BUILD_SRC
 
 # We process the rest of the Makefile if this is the final invocation of make
@@ -96,6 +117,7 @@ export prefix bindir src obj
 # Shell quotes
 bindir_SQ = $(subst ','\'',$(bindir))
 bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
+plugin_dir_SQ = $(subst ','\'',$(plugin_dir))
 
 LIB_FILE = libtraceevent.a libtraceevent.so
 
@@ -114,7 +136,7 @@ export Q VERBOSE
 
 EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
-INCLUDES = -I. $(CONFIG_INCLUDES)
+INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES)
 
 # Set compile option CFLAGS if not set elsewhere
 CFLAGS ?= -g -Wall
@@ -125,41 +147,14 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
 
 ifeq ($(VERBOSE),1)
   Q =
-  print_compile =
-  print_app_build =
-  print_fpic_compile =
-  print_shared_lib_compile =
-  print_plugin_obj_compile =
-  print_plugin_build =
-  print_install =
 else
   Q = @
-  print_compile =              echo '  CC       '$(OBJ);
-  print_app_build =            echo '  BUILD    '$(OBJ);
-  print_fpic_compile =         echo '  CC FPIC  '$(OBJ);
-  print_shared_lib_compile =   echo '  BUILD    SHARED LIB '$(OBJ);
-  print_plugin_obj_compile =   echo '  BUILD    PLUGIN OBJ '$(OBJ);
-  print_plugin_build =         echo '  BUILD    PLUGIN     '$(OBJ);
-  print_static_lib_build =     echo '  BUILD    STATIC LIB '$(OBJ);
-  print_install =              echo '  INSTALL  '$1'   to      $(DESTDIR_SQ)$2';
 endif
 
-do_fpic_compile =                                      \
-       ($(print_fpic_compile)                          \
-       $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
-
-do_app_build =                                         \
-       ($(print_app_build)                             \
-       $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
-
 do_compile_shared_library =                    \
        ($(print_shared_lib_compile)            \
        $(CC) --shared $^ -o $@)
 
-do_compile_plugin_obj =                                \
-       ($(print_plugin_obj_compile)            \
-       $(CC) -c $(CFLAGS) -fPIC -o $@ $<)
-
 do_plugin_build =                              \
        ($(print_plugin_build)                  \
        $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
@@ -169,23 +164,37 @@ do_build_static_lib =                             \
        $(RM) $@;  $(AR) rcs $@ $^)
 
 
-define do_compile
-       $(print_compile)                                                \
-       $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
-endef
+do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
 
 $(obj)/%.o: $(src)/%.c
-       $(Q)$(call do_compile)
+       $(call do_compile)
 
 %.o: $(src)/%.c
-       $(Q)$(call do_compile)
+       $(call do_compile)
 
-PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
+PEVENT_LIB_OBJS  = event-parse.o
+PEVENT_LIB_OBJS += event-plugin.o
+PEVENT_LIB_OBJS += trace-seq.o
+PEVENT_LIB_OBJS += parse-filter.o
+PEVENT_LIB_OBJS += parse-utils.o
 PEVENT_LIB_OBJS += kbuffer-parse.o
 
-ALL_OBJS = $(PEVENT_LIB_OBJS)
+PLUGIN_OBJS  = plugin_jbd2.o
+PLUGIN_OBJS += plugin_hrtimer.o
+PLUGIN_OBJS += plugin_kmem.o
+PLUGIN_OBJS += plugin_kvm.o
+PLUGIN_OBJS += plugin_mac80211.o
+PLUGIN_OBJS += plugin_sched_switch.o
+PLUGIN_OBJS += plugin_function.o
+PLUGIN_OBJS += plugin_xen.o
+PLUGIN_OBJS += plugin_scsi.o
+PLUGIN_OBJS += plugin_cfg80211.o
+
+PLUGINS := $(PLUGIN_OBJS:.o=.so)
+
+ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
 
-CMD_TARGETS = $(LIB_FILE)
+CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
 
 TARGETS = $(CMD_TARGETS)
 
@@ -195,32 +204,40 @@ all: all_cmd
 all_cmd: $(CMD_TARGETS)
 
 libtraceevent.so: $(PEVENT_LIB_OBJS)
-       $(Q)$(do_compile_shared_library)
+       $(QUIET_LINK)$(CC) --shared $^ -o $@
 
 libtraceevent.a: $(PEVENT_LIB_OBJS)
-       $(Q)$(do_build_static_lib)
+       $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
+
+plugins: $(PLUGINS)
 
 $(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS
-       $(Q)$(do_fpic_compile)
+       $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@
+
+$(PLUGIN_OBJS): %.o : $(src)/%.c
+       $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $<
+
+$(PLUGINS): %.so: %.o
+       $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<
 
 define make_version.h
-       (echo '/* This file is automatically generated. Do not modify. */';             \
-       echo \#define VERSION_CODE $(shell                                              \
-       expr $(VERSION) \* 256 + $(PATCHLEVEL));                                        \
-       echo '#define EXTRAVERSION ' $(EXTRAVERSION);                                   \
-       echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"';     \
-       echo '#define FILE_VERSION '$(FILE_VERSION);                                    \
-       ) > $1
+  (echo '/* This file is automatically generated. Do not modify. */';          \
+   echo \#define VERSION_CODE $(shell                                          \
+   expr $(VERSION) \* 256 + $(PATCHLEVEL));                                    \
+   echo '#define EXTRAVERSION ' $(EXTRAVERSION);                               \
+   echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \
+   echo '#define FILE_VERSION '$(FILE_VERSION);                                        \
+  ) > $1
 endef
 
 define update_version.h
-       ($(call make_version.h, $@.tmp);                \
-       if [ -r $@ ] && cmp -s $@ $@.tmp; then          \
-               rm -f $@.tmp;                           \
-       else                                            \
-               echo '  UPDATE                 $@';     \
-               mv -f $@.tmp $@;                        \
-       fi);
+  ($(call make_version.h, $@.tmp);             \
+    if [ -r $@ ] && cmp -s $@ $@.tmp; then     \
+      rm -f $@.tmp;                            \
+    else                                       \
+      echo '  UPDATE                 $@';      \
+      mv -f $@.tmp $@;                         \
+    fi);
 endef
 
 ep_version.h: force
@@ -229,13 +246,13 @@ ep_version.h: force
 VERSION_FILES = ep_version.h
 
 define update_dir
-       (echo $1 > $@.tmp;      \
-       if [ -r $@ ] && cmp -s $@ $@.tmp; then          \
-               rm -f $@.tmp;                           \
-       else                                            \
-               echo '  UPDATE                 $@';     \
-               mv -f $@.tmp $@;                        \
-       fi);
+  (echo $1 > $@.tmp;                           \
+   if [ -r $@ ] && cmp -s $@ $@.tmp; then      \
+     rm -f $@.tmp;                             \
+   else                                                \
+     echo '  UPDATE                 $@';       \
+     mv -f $@.tmp $@;                          \
+   fi);
 endef
 
 ## make deps
@@ -245,10 +262,10 @@ all_deps := $(all_objs:%.o=.%.d)
 
 # let .d file also depends on the source and header files
 define check_deps
-               @set -e; $(RM) $@; \
-               $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
-               sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
-               $(RM) $@.$$$$
+  @set -e; $(RM) $@; \
+  $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+  sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+  $(RM) $@.$$$$
 endef
 
 $(all_deps): .%.d: $(src)/%.c
@@ -283,27 +300,41 @@ TAGS:     force
        --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
 
 define do_install
-       $(print_install)                                \
        if [ ! -d '$(DESTDIR_SQ)$2' ]; then             \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
        fi;                                             \
        $(INSTALL) $1 '$(DESTDIR_SQ)$2'
 endef
 
-install_lib: all_cmd
-       $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
+define do_install_plugins
+       for plugin in $1; do                            \
+         $(call do_install,$$plugin,$(plugin_dir_SQ)); \
+       done
+endef
+
+install_lib: all_cmd install_plugins
+       $(call QUIET_INSTALL, $(LIB_FILE)) \
+               $(call do_install,$(LIB_FILE),$(bindir_SQ))
+
+install_plugins: $(PLUGINS)
+       $(call QUIET_INSTALL, trace_plugins) \
+               $(call do_install_plugins, $(PLUGINS))
 
 install: install_lib
 
 clean:
-       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
-       $(RM) TRACEEVENT-CFLAGS tags TAGS
+       $(call QUIET_CLEAN, libtraceevent) \
+               $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
+               $(RM) TRACEEVENT-CFLAGS tags TAGS
 
 endif # skip-makefile
 
-PHONY += force
+PHONY += force plugins
 force:
 
+plugins:
+       @echo > /dev/null
+
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable so we can use it in if_changed and friends.
 .PHONY: $(PHONY)
index 0362d575de7d185752b2a23a53845236c71510f6..1587ea392ad6d83acb0de14b1701db12fa4fc95c 100644 (file)
@@ -1606,6 +1606,24 @@ process_arg(struct event_format *event, struct print_arg *arg, char **tok)
 static enum event_type
 process_op(struct event_format *event, struct print_arg *arg, char **tok);
 
+/*
+ * For __print_symbolic() and __print_flags, we need to completely
+ * evaluate the first argument, which defines what to print next.
+ */
+static enum event_type
+process_field_arg(struct event_format *event, struct print_arg *arg, char **tok)
+{
+       enum event_type type;
+
+       type = process_arg(event, arg, tok);
+
+       while (type == EVENT_OP) {
+               type = process_op(event, arg, tok);
+       }
+
+       return type;
+}
+
 static enum event_type
 process_cond(struct event_format *event, struct print_arg *top, char **tok)
 {
@@ -2371,7 +2389,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok)
                goto out_free;
        }
 
-       type = process_arg(event, field, &token);
+       type = process_field_arg(event, field, &token);
 
        /* Handle operations in the first argument */
        while (type == EVENT_OP)
@@ -2424,7 +2442,8 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
                goto out_free;
        }
 
-       type = process_arg(event, field, &token);
+       type = process_field_arg(event, field, &token);
+
        if (test_type_token(type, token, EVENT_DELIM, ","))
                goto out_free_field;
 
@@ -2691,7 +2710,6 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
        struct print_arg *farg;
        enum event_type type;
        char *token;
-       const char *test;
        int i;
 
        arg->type = PRINT_FUNC;
@@ -2708,15 +2726,19 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
                }
 
                type = process_arg(event, farg, &token);
-               if (i < (func->nr_args - 1))
-                       test = ",";
-               else
-                       test = ")";
-
-               if (test_type_token(type, token, EVENT_DELIM, test)) {
-                       free_arg(farg);
-                       free_token(token);
-                       return EVENT_ERROR;
+               if (i < (func->nr_args - 1)) {
+                       if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
+                               warning("Error: function '%s()' expects %d arguments but event %s only uses %d",
+                                       func->name, func->nr_args,
+                                       event->name, i + 1);
+                               goto err;
+                       }
+               } else {
+                       if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
+                               warning("Error: function '%s()' only expects %d arguments but event %s has more",
+                                       func->name, func->nr_args, event->name);
+                               goto err;
+                       }
                }
 
                *next_arg = farg;
@@ -2728,6 +2750,11 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
        *tok = token;
 
        return type;
+
+err:
+       free_arg(farg);
+       free_token(token);
+       return EVENT_ERROR;
 }
 
 static enum event_type
@@ -3446,7 +3473,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                 * is in the bottom half of the 32 bit field.
                 */
                offset &= 0xffff;
-               val = (unsigned long long)(data + offset);
+               val = (unsigned long long)((unsigned long)data + offset);
                break;
        default: /* not sure what to do there */
                return 0;
@@ -4080,6 +4107,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
        unsigned long long val;
        struct func_map *func;
        const char *saveptr;
+       struct trace_seq p;
        char *bprint_fmt = NULL;
        char format[32];
        int show_func;
@@ -4287,8 +4315,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                format[len] = 0;
                                if (!len_as_arg)
                                        len_arg = -1;
-                               print_str_arg(s, data, size, event,
+                               /* Use helper trace_seq */
+                               trace_seq_init(&p);
+                               print_str_arg(&p, data, size, event,
                                              format, len_arg, arg);
+                               trace_seq_terminate(&p);
+                               trace_seq_puts(s, p.buffer);
                                arg = arg->next;
                                break;
                        default:
@@ -5097,8 +5129,38 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
        return ret;
 }
 
+static enum pevent_errno
+__pevent_parse_event(struct pevent *pevent,
+                    struct event_format **eventp,
+                    const char *buf, unsigned long size,
+                    const char *sys)
+{
+       int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
+       struct event_format *event = *eventp;
+
+       if (event == NULL)
+               return ret;
+
+       if (pevent && add_event(pevent, event)) {
+               ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               goto event_add_failed;
+       }
+
+#define PRINT_ARGS 0
+       if (PRINT_ARGS && event->print_fmt.args)
+               print_args(event->print_fmt.args);
+
+       return 0;
+
+event_add_failed:
+       pevent_free_format(event);
+       return ret;
+}
+
 /**
  * pevent_parse_format - parse the event format
+ * @pevent: the handle to the pevent
+ * @eventp: returned format
  * @buf: the buffer storing the event format string
  * @size: the size of @buf
  * @sys: the system the event belongs to
@@ -5110,10 +5172,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
  *
  * /sys/kernel/debug/tracing/events/.../.../format
  */
-enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
+enum pevent_errno pevent_parse_format(struct pevent *pevent,
+                                     struct event_format **eventp,
+                                     const char *buf,
                                      unsigned long size, const char *sys)
 {
-       return __pevent_parse_format(eventp, NULL, buf, size, sys);
+       return __pevent_parse_event(pevent, eventp, buf, size, sys);
 }
 
 /**
@@ -5134,25 +5198,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
                                     unsigned long size, const char *sys)
 {
        struct event_format *event = NULL;
-       int ret = __pevent_parse_format(&event, pevent, buf, size, sys);
-
-       if (event == NULL)
-               return ret;
-
-       if (add_event(pevent, event)) {
-               ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
-               goto event_add_failed;
-       }
-
-#define PRINT_ARGS 0
-       if (PRINT_ARGS && event->print_fmt.args)
-               print_args(event->print_fmt.args);
-
-       return 0;
-
-event_add_failed:
-       pevent_free_format(event);
-       return ret;
+       return __pevent_parse_event(pevent, &event, buf, size, sys);
 }
 
 #undef _PE
@@ -5184,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused,
 
        idx = errnum - __PEVENT_ERRNO__START - 1;
        msg = pevent_error_str[idx];
-
-       switch (errnum) {
-       case PEVENT_ERRNO__MEM_ALLOC_FAILED:
-       case PEVENT_ERRNO__PARSE_EVENT_FAILED:
-       case PEVENT_ERRNO__READ_ID_FAILED:
-       case PEVENT_ERRNO__READ_FORMAT_FAILED:
-       case PEVENT_ERRNO__READ_PRINT_FAILED:
-       case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
-       case PEVENT_ERRNO__INVALID_ARG_TYPE:
-               snprintf(buf, buflen, "%s", msg);
-               break;
-
-       default:
-               /* cannot reach here */
-               break;
-       }
+       snprintf(buf, buflen, "%s", msg);
 
        return 0;
 }
@@ -5529,6 +5560,52 @@ int pevent_register_print_function(struct pevent *pevent,
        return ret;
 }
 
+/**
+ * pevent_unregister_print_function - unregister a helper function
+ * @pevent: the handle to the pevent
+ * @func: the function to process the helper function
+ * @name: the name of the helper function
+ *
+ * This function removes existing print handler for function @name.
+ *
+ * Returns 0 if the handler was removed successully, -1 otherwise.
+ */
+int pevent_unregister_print_function(struct pevent *pevent,
+                                    pevent_func_handler func, char *name)
+{
+       struct pevent_function_handler *func_handle;
+
+       func_handle = find_func_handler(pevent, name);
+       if (func_handle && func_handle->func == func) {
+               remove_func_handler(pevent, name);
+               return 0;
+       }
+       return -1;
+}
+
+static struct event_format *pevent_search_event(struct pevent *pevent, int id,
+                                               const char *sys_name,
+                                               const char *event_name)
+{
+       struct event_format *event;
+
+       if (id >= 0) {
+               /* search by id */
+               event = pevent_find_event(pevent, id);
+               if (!event)
+                       return NULL;
+               if (event_name && (strcmp(event_name, event->name) != 0))
+                       return NULL;
+               if (sys_name && (strcmp(sys_name, event->system) != 0))
+                       return NULL;
+       } else {
+               event = pevent_find_event_by_name(pevent, sys_name, event_name);
+               if (!event)
+                       return NULL;
+       }
+       return event;
+}
+
 /**
  * pevent_register_event_handler - register a way to parse an event
  * @pevent: the handle to the pevent
@@ -5553,20 +5630,9 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
        struct event_format *event;
        struct event_handler *handle;
 
-       if (id >= 0) {
-               /* search by id */
-               event = pevent_find_event(pevent, id);
-               if (!event)
-                       goto not_found;
-               if (event_name && (strcmp(event_name, event->name) != 0))
-                       goto not_found;
-               if (sys_name && (strcmp(sys_name, event->system) != 0))
-                       goto not_found;
-       } else {
-               event = pevent_find_event_by_name(pevent, sys_name, event_name);
-               if (!event)
-                       goto not_found;
-       }
+       event = pevent_search_event(pevent, id, sys_name, event_name);
+       if (event == NULL)
+               goto not_found;
 
        pr_stat("overriding event (%d) %s:%s with new print handler",
                event->id, event->system, event->name);
@@ -5606,6 +5672,79 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
        return -1;
 }
 
+static int handle_matches(struct event_handler *handler, int id,
+                         const char *sys_name, const char *event_name,
+                         pevent_event_handler_func func, void *context)
+{
+       if (id >= 0 && id != handler->id)
+               return 0;
+
+       if (event_name && (strcmp(event_name, handler->event_name) != 0))
+               return 0;
+
+       if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
+               return 0;
+
+       if (func != handler->func || context != handler->context)
+               return 0;
+
+       return 1;
+}
+
+/**
+ * pevent_unregister_event_handler - unregister an existing event handler
+ * @pevent: the handle to the pevent
+ * @id: the id of the event to unregister
+ * @sys_name: the system name the handler belongs to
+ * @event_name: the name of the event handler
+ * @func: the function to call to parse the event information
+ * @context: the data to be passed to @func
+ *
+ * This function removes existing event handler (parser).
+ *
+ * If @id is >= 0, then it is used to find the event.
+ * else @sys_name and @event_name are used.
+ *
+ * Returns 0 if handler was removed successfully, -1 if event was not found.
+ */
+int pevent_unregister_event_handler(struct pevent *pevent, int id,
+                                   const char *sys_name, const char *event_name,
+                                   pevent_event_handler_func func, void *context)
+{
+       struct event_format *event;
+       struct event_handler *handle;
+       struct event_handler **next;
+
+       event = pevent_search_event(pevent, id, sys_name, event_name);
+       if (event == NULL)
+               goto not_found;
+
+       if (event->handler == func && event->context == context) {
+               pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
+                       event->id, event->system, event->name);
+
+               event->handler = NULL;
+               event->context = NULL;
+               return 0;
+       }
+
+not_found:
+       for (next = &pevent->handlers; *next; next = &(*next)->next) {
+               handle = *next;
+               if (handle_matches(handle, id, sys_name, event_name,
+                                  func, context))
+                       break;
+       }
+
+       if (!(*next))
+               return -1;
+
+       *next = handle->next;
+       free_handler(handle);
+
+       return 0;
+}
+
 /**
  * pevent_alloc - create a pevent handle
  */
index 8d73d2594f65de39c4a0c9d35c976847e30ab0fe..791c539374c726b7e4d3ad8f6f75aad575692787 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdbool.h>
 #include <stdarg.h>
 #include <regex.h>
+#include <string.h>
 
 #ifndef __maybe_unused
 #define __maybe_unused __attribute__((unused))
@@ -57,6 +58,12 @@ struct pevent_record {
 #endif
 };
 
+enum trace_seq_fail {
+       TRACE_SEQ__GOOD,
+       TRACE_SEQ__BUFFER_POISONED,
+       TRACE_SEQ__MEM_ALLOC_FAILED,
+};
+
 /*
  * Trace sequences are used to allow a function to call several other functions
  * to create a string of data to use (up to a max of PAGE_SIZE).
@@ -67,6 +74,7 @@ struct trace_seq {
        unsigned int            buffer_size;
        unsigned int            len;
        unsigned int            readpos;
+       enum trace_seq_fail     state;
 };
 
 void trace_seq_init(struct trace_seq *s);
@@ -97,7 +105,7 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s,
                                         void *context);
 
 typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
-typedef int (*pevent_plugin_unload_func)(void);
+typedef int (*pevent_plugin_unload_func)(struct pevent *pevent);
 
 struct plugin_option {
        struct plugin_option            *next;
@@ -122,7 +130,7 @@ struct plugin_option {
  * PEVENT_PLUGIN_UNLOADER:  (optional)
  *   The function called just before unloading
  *
- *   int PEVENT_PLUGIN_UNLOADER(void)
+ *   int PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
  *
  * PEVENT_PLUGIN_OPTIONS:  (optional)
  *   Plugin options that can be set before loading
@@ -355,12 +363,35 @@ enum pevent_flag {
        _PE(READ_FORMAT_FAILED, "failed to read event format"),               \
        _PE(READ_PRINT_FAILED,  "failed to read event print fmt"),            \
        _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\
-       _PE(INVALID_ARG_TYPE,   "invalid argument type")
+       _PE(INVALID_ARG_TYPE,   "invalid argument type"),                     \
+       _PE(INVALID_EXP_TYPE,   "invalid expression type"),                   \
+       _PE(INVALID_OP_TYPE,    "invalid operator type"),                     \
+       _PE(INVALID_EVENT_NAME, "invalid event name"),                        \
+       _PE(EVENT_NOT_FOUND,    "no event found"),                            \
+       _PE(SYNTAX_ERROR,       "syntax error"),                              \
+       _PE(ILLEGAL_RVALUE,     "illegal rvalue"),                            \
+       _PE(ILLEGAL_LVALUE,     "illegal lvalue for string comparison"),      \
+       _PE(INVALID_REGEX,      "regex did not compute"),                     \
+       _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"),             \
+       _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"),            \
+       _PE(REPARENT_NOT_OP,    "cannot reparent other than OP"),             \
+       _PE(REPARENT_FAILED,    "failed to reparent filter OP"),              \
+       _PE(BAD_FILTER_ARG,     "bad arg in filter tree"),                    \
+       _PE(UNEXPECTED_TYPE,    "unexpected type (not a value)"),             \
+       _PE(ILLEGAL_TOKEN,      "illegal token"),                             \
+       _PE(INVALID_PAREN,      "open parenthesis cannot come here"),         \
+       _PE(UNBALANCED_PAREN,   "unbalanced number of parenthesis"),          \
+       _PE(UNKNOWN_TOKEN,      "unknown token"),                             \
+       _PE(FILTER_NOT_FOUND,   "no filter found"),                           \
+       _PE(NOT_A_NUMBER,       "must have number field"),                    \
+       _PE(NO_FILTER,          "no filters exists"),                         \
+       _PE(FILTER_MISS,        "record does not match to filter")
 
 #undef _PE
 #define _PE(__code, __str) PEVENT_ERRNO__ ## __code
 enum pevent_errno {
        PEVENT_ERRNO__SUCCESS                   = 0,
+       PEVENT_ERRNO__FILTER_MATCH              = PEVENT_ERRNO__SUCCESS,
 
        /*
         * Choose an arbitrary negative big number not to clash with standard
@@ -377,6 +408,12 @@ enum pevent_errno {
 };
 #undef _PE
 
+struct plugin_list;
+
+struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
+void traceevent_unload_plugins(struct plugin_list *plugin_list,
+                              struct pevent *pevent);
+
 struct cmdline;
 struct cmdline_list;
 struct func_map;
@@ -522,6 +559,15 @@ __data2host8(struct pevent *pevent, unsigned long long data)
        __data2host8(pevent, __val);                            \
 })
 
+static inline int traceevent_host_bigendian(void)
+{
+       unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
+       unsigned int val;
+
+       memcpy(&val, str, 4);
+       return val == 0x01020304;
+}
+
 /* taken from kernel/trace/trace.h */
 enum trace_flag_type {
        TRACE_FLAG_IRQS_OFF             = 0x01,
@@ -547,7 +593,9 @@ int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long siz
 
 enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
                                     unsigned long size, const char *sys);
-enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
+enum pevent_errno pevent_parse_format(struct pevent *pevent,
+                                     struct event_format **eventp,
+                                     const char *buf,
                                      unsigned long size, const char *sys);
 void pevent_free_format(struct event_format *event);
 
@@ -576,10 +624,15 @@ int pevent_print_func_field(struct trace_seq *s, const char *fmt,
 int pevent_register_event_handler(struct pevent *pevent, int id,
                                  const char *sys_name, const char *event_name,
                                  pevent_event_handler_func func, void *context);
+int pevent_unregister_event_handler(struct pevent *pevent, int id,
+                                   const char *sys_name, const char *event_name,
+                                   pevent_event_handler_func func, void *context);
 int pevent_register_print_function(struct pevent *pevent,
                                   pevent_func_handler func,
                                   enum pevent_func_arg_type ret_type,
                                   char *name, ...);
+int pevent_unregister_print_function(struct pevent *pevent,
+                                    pevent_func_handler func, char *name);
 
 struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
 struct format_field *pevent_find_field(struct event_format *event, const char *name);
@@ -811,18 +864,22 @@ struct filter_type {
        struct filter_arg       *filter;
 };
 
+#define PEVENT_FILTER_ERROR_BUFSZ  1024
+
 struct event_filter {
        struct pevent           *pevent;
        int                     filters;
        struct filter_type      *event_filters;
+       char                    error_buffer[PEVENT_FILTER_ERROR_BUFSZ];
 };
 
 struct event_filter *pevent_filter_alloc(struct pevent *pevent);
 
-#define FILTER_NONE            -2
-#define FILTER_NOEXIST         -1
-#define FILTER_MISS            0
-#define FILTER_MATCH           1
+/* for backward compatibility */
+#define FILTER_NONE            PEVENT_ERRNO__FILTER_NOT_FOUND
+#define FILTER_NOEXIST         PEVENT_ERRNO__NO_FILTER
+#define FILTER_MISS            PEVENT_ERRNO__FILTER_MISS
+#define FILTER_MATCH           PEVENT_ERRNO__FILTER_MATCH
 
 enum filter_trivial_type {
        FILTER_TRIVIAL_FALSE,
@@ -830,20 +887,21 @@ enum filter_trivial_type {
        FILTER_TRIVIAL_BOTH,
 };
 
-int pevent_filter_add_filter_str(struct event_filter *filter,
-                                const char *filter_str,
-                                char **error_str);
+enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
+                                              const char *filter_str);
 
+enum pevent_errno pevent_filter_match(struct event_filter *filter,
+                                     struct pevent_record *record);
 
-int pevent_filter_match(struct event_filter *filter,
-                       struct pevent_record *record);
+int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
+                          char *buf, size_t buflen);
 
 int pevent_event_filtered(struct event_filter *filter,
                          int event_id);
 
 void pevent_filter_reset(struct event_filter *filter);
 
-void pevent_filter_clear_trivial(struct event_filter *filter,
+int pevent_filter_clear_trivial(struct event_filter *filter,
                                 enum filter_trivial_type type);
 
 void pevent_filter_free(struct event_filter *filter);
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
new file mode 100644 (file)
index 0000000..0c8bf67
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <string.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "event-parse.h"
+#include "event-utils.h"
+
+#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
+
+struct plugin_list {
+       struct plugin_list      *next;
+       char                    *name;
+       void                    *handle;
+};
+
+static void
+load_plugin(struct pevent *pevent, const char *path,
+           const char *file, void *data)
+{
+       struct plugin_list **plugin_list = data;
+       pevent_plugin_load_func func;
+       struct plugin_list *list;
+       const char *alias;
+       char *plugin;
+       void *handle;
+
+       plugin = malloc(strlen(path) + strlen(file) + 2);
+       if (!plugin) {
+               warning("could not allocate plugin memory\n");
+               return;
+       }
+
+       strcpy(plugin, path);
+       strcat(plugin, "/");
+       strcat(plugin, file);
+
+       handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
+       if (!handle) {
+               warning("could not load plugin '%s'\n%s\n",
+                       plugin, dlerror());
+               goto out_free;
+       }
+
+       alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
+       if (!alias)
+               alias = file;
+
+       func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
+       if (!func) {
+               warning("could not find func '%s' in plugin '%s'\n%s\n",
+                       PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
+               goto out_free;
+       }
+
+       list = malloc(sizeof(*list));
+       if (!list) {
+               warning("could not allocate plugin memory\n");
+               goto out_free;
+       }
+
+       list->next = *plugin_list;
+       list->handle = handle;
+       list->name = plugin;
+       *plugin_list = list;
+
+       pr_stat("registering plugin: %s", plugin);
+       func(pevent);
+       return;
+
+ out_free:
+       free(plugin);
+}
+
+static void
+load_plugins_dir(struct pevent *pevent, const char *suffix,
+                const char *path,
+                void (*load_plugin)(struct pevent *pevent,
+                                    const char *path,
+                                    const char *name,
+                                    void *data),
+                void *data)
+{
+       struct dirent *dent;
+       struct stat st;
+       DIR *dir;
+       int ret;
+
+       ret = stat(path, &st);
+       if (ret < 0)
+               return;
+
+       if (!S_ISDIR(st.st_mode))
+               return;
+
+       dir = opendir(path);
+       if (!dir)
+               return;
+
+       while ((dent = readdir(dir))) {
+               const char *name = dent->d_name;
+
+               if (strcmp(name, ".") == 0 ||
+                   strcmp(name, "..") == 0)
+                       continue;
+
+               /* Only load plugins that end in suffix */
+               if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
+                       continue;
+
+               load_plugin(pevent, path, name, data);
+       }
+
+       closedir(dir);
+}
+
+static void
+load_plugins(struct pevent *pevent, const char *suffix,
+            void (*load_plugin)(struct pevent *pevent,
+                                const char *path,
+                                const char *name,
+                                void *data),
+            void *data)
+{
+       char *home;
+       char *path;
+       char *envdir;
+
+       /*
+        * If a system plugin directory was defined,
+        * check that first.
+        */
+#ifdef PLUGIN_DIR
+       load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
+#endif
+
+       /*
+        * Next let the environment-set plugin directory
+        * override the system defaults.
+        */
+       envdir = getenv("TRACEEVENT_PLUGIN_DIR");
+       if (envdir)
+               load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
+
+       /*
+        * Now let the home directory override the environment
+        * or system defaults.
+        */
+       home = getenv("HOME");
+       if (!home)
+               return;
+
+       path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
+       if (!path) {
+               warning("could not allocate plugin memory\n");
+               return;
+       }
+
+       strcpy(path, home);
+       strcat(path, "/");
+       strcat(path, LOCAL_PLUGIN_DIR);
+
+       load_plugins_dir(pevent, suffix, path, load_plugin, data);
+
+       free(path);
+}
+
+struct plugin_list*
+traceevent_load_plugins(struct pevent *pevent)
+{
+       struct plugin_list *list = NULL;
+
+       load_plugins(pevent, ".so", load_plugin, &list);
+       return list;
+}
+
+void
+traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent)
+{
+       pevent_plugin_unload_func func;
+       struct plugin_list *list;
+
+       while (plugin_list) {
+               list = plugin_list;
+               plugin_list = list->next;
+               func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
+               if (func)
+                       func(pevent);
+               dlclose(list->handle);
+               free(list->name);
+               free(list);
+       }
+}
index e76c9acb92cd5ab693ee70bc7851fffd237a4a4e..d1dc2170e4023dbf8cfec33b386bcecd15972035 100644 (file)
 #include <ctype.h>
 
 /* Can be overridden */
-void die(const char *fmt, ...);
-void *malloc_or_die(unsigned int size);
 void warning(const char *fmt, ...);
 void pr_stat(const char *fmt, ...);
 void vpr_stat(const char *fmt, va_list ap);
 
 /* Always available */
-void __die(const char *fmt, ...);
 void __warning(const char *fmt, ...);
 void __pr_stat(const char *fmt, ...);
 
-void __vdie(const char *fmt, ...);
 void __vwarning(const char *fmt, ...);
 void __vpr_stat(const char *fmt, ...);
 
index 2500e75583fcc26e6380731d407dc6d985ba6929..b50234402fc2b368f39040a92ada39922f6464ee 100644 (file)
@@ -38,41 +38,31 @@ struct event_list {
        struct event_format     *event;
 };
 
-#define MAX_ERR_STR_SIZE 256
-
-static void show_error(char **error_str, const char *fmt, ...)
+static void show_error(char *error_buf, const char *fmt, ...)
 {
        unsigned long long index;
        const char *input;
-       char *error;
        va_list ap;
        int len;
        int i;
 
-       if (!error_str)
-               return;
-
        input = pevent_get_input_buf();
        index = pevent_get_input_buf_ptr();
        len = input ? strlen(input) : 0;
 
-       error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3);
-
        if (len) {
-               strcpy(error, input);
-               error[len] = '\n';
+               strcpy(error_buf, input);
+               error_buf[len] = '\n';
                for (i = 1; i < len && i < index; i++)
-                       error[len+i] = ' ';
-               error[len + i] = '^';
-               error[len + i + 1] = '\n';
+                       error_buf[len+i] = ' ';
+               error_buf[len + i] = '^';
+               error_buf[len + i + 1] = '\n';
                len += i+2;
        }
 
        va_start(ap, fmt);
-       vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
+       vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap);
        va_end(ap);
-
-       *error_str = error;
 }
 
 static void free_token(char *token)
@@ -95,7 +85,11 @@ static enum event_type read_token(char **tok)
            (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
            pevent_peek_char() == '~') {
                /* append it */
-               *tok = malloc_or_die(3);
+               *tok = malloc(3);
+               if (*tok == NULL) {
+                       free_token(token);
+                       return EVENT_ERROR;
+               }
                sprintf(*tok, "%c%c", *token, '~');
                free_token(token);
                /* Now remove the '~' from the buffer */
@@ -147,11 +141,13 @@ add_filter_type(struct event_filter *filter, int id)
        if (filter_type)
                return filter_type;
 
-       filter->event_filters = realloc(filter->event_filters,
-                                       sizeof(*filter->event_filters) *
-                                       (filter->filters + 1));
-       if (!filter->event_filters)
-               die("Could not allocate filter");
+       filter_type = realloc(filter->event_filters,
+                             sizeof(*filter->event_filters) *
+                             (filter->filters + 1));
+       if (!filter_type)
+               return NULL;
+
+       filter->event_filters = filter_type;
 
        for (i = 0; i < filter->filters; i++) {
                if (filter->event_filters[i].event_id > id)
@@ -182,7 +178,10 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
 {
        struct event_filter *filter;
 
-       filter = malloc_or_die(sizeof(*filter));
+       filter = malloc(sizeof(*filter));
+       if (filter == NULL)
+               return NULL;
+
        memset(filter, 0, sizeof(*filter));
        filter->pevent = pevent;
        pevent_ref(pevent);
@@ -192,12 +191,7 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
 
 static struct filter_arg *allocate_arg(void)
 {
-       struct filter_arg *arg;
-
-       arg = malloc_or_die(sizeof(*arg));
-       memset(arg, 0, sizeof(*arg));
-
-       return arg;
+       return calloc(1, sizeof(struct filter_arg));
 }
 
 static void free_arg(struct filter_arg *arg)
@@ -242,15 +236,19 @@ static void free_arg(struct filter_arg *arg)
        free(arg);
 }
 
-static void add_event(struct event_list **events,
+static int add_event(struct event_list **events,
                      struct event_format *event)
 {
        struct event_list *list;
 
-       list = malloc_or_die(sizeof(*list));
+       list = malloc(sizeof(*list));
+       if (list == NULL)
+               return -1;
+
        list->next = *events;
        *events = list;
        list->event = event;
+       return 0;
 }
 
 static int event_match(struct event_format *event,
@@ -265,7 +263,7 @@ static int event_match(struct event_format *event,
                !regexec(ereg, event->name, 0, NULL, 0);
 }
 
-static int
+static enum pevent_errno
 find_event(struct pevent *pevent, struct event_list **events,
           char *sys_name, char *event_name)
 {
@@ -273,6 +271,7 @@ find_event(struct pevent *pevent, struct event_list **events,
        regex_t ereg;
        regex_t sreg;
        int match = 0;
+       int fail = 0;
        char *reg;
        int ret;
        int i;
@@ -283,23 +282,31 @@ find_event(struct pevent *pevent, struct event_list **events,
                sys_name = NULL;
        }
 
-       reg = malloc_or_die(strlen(event_name) + 3);
+       reg = malloc(strlen(event_name) + 3);
+       if (reg == NULL)
+               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
        sprintf(reg, "^%s$", event_name);
 
        ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
        free(reg);
 
        if (ret)
-               return -1;
+               return PEVENT_ERRNO__INVALID_EVENT_NAME;
 
        if (sys_name) {
-               reg = malloc_or_die(strlen(sys_name) + 3);
+               reg = malloc(strlen(sys_name) + 3);
+               if (reg == NULL) {
+                       regfree(&ereg);
+                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               }
+
                sprintf(reg, "^%s$", sys_name);
                ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
                free(reg);
                if (ret) {
                        regfree(&ereg);
-                       return -1;
+                       return PEVENT_ERRNO__INVALID_EVENT_NAME;
                }
        }
 
@@ -307,7 +314,10 @@ find_event(struct pevent *pevent, struct event_list **events,
                event = pevent->events[i];
                if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
                        match = 1;
-                       add_event(events, event);
+                       if (add_event(events, event) < 0) {
+                               fail = 1;
+                               break;
+                       }
                }
        }
 
@@ -316,7 +326,9 @@ find_event(struct pevent *pevent, struct event_list **events,
                regfree(&sreg);
 
        if (!match)
-               return -1;
+               return PEVENT_ERRNO__EVENT_NOT_FOUND;
+       if (fail)
+               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
 
        return 0;
 }
@@ -332,14 +344,18 @@ static void free_events(struct event_list *events)
        }
 }
 
-static struct filter_arg *
+static enum pevent_errno
 create_arg_item(struct event_format *event, const char *token,
-               enum event_type type, char **error_str)
+               enum event_type type, struct filter_arg **parg, char *error_str)
 {
        struct format_field *field;
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (arg == NULL) {
+               show_error(error_str, "failed to allocate filter arg");
+               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+       }
 
        switch (type) {
 
@@ -349,8 +365,11 @@ create_arg_item(struct event_format *event, const char *token,
                arg->value.type =
                        type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
                arg->value.str = strdup(token);
-               if (!arg->value.str)
-                       die("malloc string");
+               if (!arg->value.str) {
+                       free_arg(arg);
+                       show_error(error_str, "failed to allocate string filter arg");
+                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               }
                break;
        case EVENT_ITEM:
                /* if it is a number, then convert it */
@@ -377,11 +396,11 @@ create_arg_item(struct event_format *event, const char *token,
                break;
        default:
                free_arg(arg);
-               show_error(error_str, "expected a value but found %s",
-                          token);
-               return NULL;
+               show_error(error_str, "expected a value but found %s", token);
+               return PEVENT_ERRNO__UNEXPECTED_TYPE;
        }
-       return arg;
+       *parg = arg;
+       return 0;
 }
 
 static struct filter_arg *
@@ -390,6 +409,9 @@ create_arg_op(enum filter_op_type btype)
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (!arg)
+               return NULL;
+
        arg->type = FILTER_ARG_OP;
        arg->op.type = btype;
 
@@ -402,6 +424,9 @@ create_arg_exp(enum filter_exp_type etype)
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (!arg)
+               return NULL;
+
        arg->type = FILTER_ARG_EXP;
        arg->op.type = etype;
 
@@ -414,6 +439,9 @@ create_arg_cmp(enum filter_exp_type etype)
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (!arg)
+               return NULL;
+
        /* Use NUM and change if necessary */
        arg->type = FILTER_ARG_NUM;
        arg->op.type = etype;
@@ -421,8 +449,8 @@ create_arg_cmp(enum filter_exp_type etype)
        return arg;
 }
 
-static int add_right(struct filter_arg *op, struct filter_arg *arg,
-                    char **error_str)
+static enum pevent_errno
+add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
 {
        struct filter_arg *left;
        char *str;
@@ -453,9 +481,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                case FILTER_ARG_FIELD:
                        break;
                default:
-                       show_error(error_str,
-                                  "Illegal rvalue");
-                       return -1;
+                       show_error(error_str, "Illegal rvalue");
+                       return PEVENT_ERRNO__ILLEGAL_RVALUE;
                }
 
                /*
@@ -502,7 +529,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                        if (left->type != FILTER_ARG_FIELD) {
                                show_error(error_str,
                                           "Illegal lvalue for string comparison");
-                               return -1;
+                               return PEVENT_ERRNO__ILLEGAL_LVALUE;
                        }
 
                        /* Make sure this is a valid string compare */
@@ -521,25 +548,31 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                                        show_error(error_str,
                                                   "RegEx '%s' did not compute",
                                                   str);
-                                       return -1;
+                                       return PEVENT_ERRNO__INVALID_REGEX;
                                }
                                break;
                        default:
                                show_error(error_str,
                                           "Illegal comparison for string");
-                               return -1;
+                               return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
                        }
 
                        op->type = FILTER_ARG_STR;
                        op->str.type = op_type;
                        op->str.field = left->field.field;
                        op->str.val = strdup(str);
-                       if (!op->str.val)
-                               die("malloc string");
+                       if (!op->str.val) {
+                               show_error(error_str, "Failed to allocate string filter");
+                               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       }
                        /*
                         * Need a buffer to copy data for tests
                         */
-                       op->str.buffer = malloc_or_die(op->str.field->size + 1);
+                       op->str.buffer = malloc(op->str.field->size + 1);
+                       if (!op->str.buffer) {
+                               show_error(error_str, "Failed to allocate string filter");
+                               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       }
                        /* Null terminate this buffer */
                        op->str.buffer[op->str.field->size] = 0;
 
@@ -557,7 +590,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                        case FILTER_CMP_NOT_REGEX:
                                show_error(error_str,
                                           "Op not allowed with integers");
-                               return -1;
+                               return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
 
                        default:
                                break;
@@ -577,9 +610,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
        return 0;
 
  out_fail:
-       show_error(error_str,
-                  "Syntax error");
-       return -1;
+       show_error(error_str, "Syntax error");
+       return PEVENT_ERRNO__SYNTAX_ERROR;
 }
 
 static struct filter_arg *
@@ -592,7 +624,7 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b)
        return arg;
 }
 
-static int add_left(struct filter_arg *op, struct filter_arg *arg)
+static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
 {
        switch (op->type) {
        case FILTER_ARG_EXP:
@@ -611,11 +643,11 @@ static int add_left(struct filter_arg *op, struct filter_arg *arg)
                /* left arg of compares must be a field */
                if (arg->type != FILTER_ARG_FIELD &&
                    arg->type != FILTER_ARG_BOOLEAN)
-                       return -1;
+                       return PEVENT_ERRNO__INVALID_ARG_TYPE;
                op->num.left = arg;
                break;
        default:
-               return -1;
+               return PEVENT_ERRNO__INVALID_ARG_TYPE;
        }
        return 0;
 }
@@ -728,15 +760,18 @@ enum filter_vals {
        FILTER_VAL_TRUE,
 };
 
-void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
-                 struct filter_arg *arg)
+static enum pevent_errno
+reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
+               struct filter_arg *arg, char *error_str)
 {
        struct filter_arg *other_child;
        struct filter_arg **ptr;
 
        if (parent->type != FILTER_ARG_OP &&
-           arg->type != FILTER_ARG_OP)
-               die("can not reparent other than OP");
+           arg->type != FILTER_ARG_OP) {
+               show_error(error_str, "can not reparent other than OP");
+               return PEVENT_ERRNO__REPARENT_NOT_OP;
+       }
 
        /* Get the sibling */
        if (old_child->op.right == arg) {
@@ -745,8 +780,10 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
        } else if (old_child->op.left == arg) {
                ptr = &old_child->op.left;
                other_child = old_child->op.right;
-       } else
-               die("Error in reparent op, find other child");
+       } else {
+               show_error(error_str, "Error in reparent op, find other child");
+               return PEVENT_ERRNO__REPARENT_FAILED;
+       }
 
        /* Detach arg from old_child */
        *ptr = NULL;
@@ -757,23 +794,29 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
                *parent = *arg;
                /* Free arg without recussion */
                free(arg);
-               return;
+               return 0;
        }
 
        if (parent->op.right == old_child)
                ptr = &parent->op.right;
        else if (parent->op.left == old_child)
                ptr = &parent->op.left;
-       else
-               die("Error in reparent op");
+       else {
+               show_error(error_str, "Error in reparent op");
+               return PEVENT_ERRNO__REPARENT_FAILED;
+       }
+
        *ptr = arg;
 
        free_arg(old_child);
+       return 0;
 }
 
-enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
+/* Returns either filter_vals (success) or pevent_errno (failfure) */
+static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
+                   char *error_str)
 {
-       enum filter_vals lval, rval;
+       int lval, rval;
 
        switch (arg->type) {
 
@@ -788,63 +831,68 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
                return FILTER_VAL_NORM;
 
        case FILTER_ARG_EXP:
-               lval = test_arg(arg, arg->exp.left);
+               lval = test_arg(arg, arg->exp.left, error_str);
                if (lval != FILTER_VAL_NORM)
                        return lval;
-               rval = test_arg(arg, arg->exp.right);
+               rval = test_arg(arg, arg->exp.right, error_str);
                if (rval != FILTER_VAL_NORM)
                        return rval;
                return FILTER_VAL_NORM;
 
        case FILTER_ARG_NUM:
-               lval = test_arg(arg, arg->num.left);
+               lval = test_arg(arg, arg->num.left, error_str);
                if (lval != FILTER_VAL_NORM)
                        return lval;
-               rval = test_arg(arg, arg->num.right);
+               rval = test_arg(arg, arg->num.right, error_str);
                if (rval != FILTER_VAL_NORM)
                        return rval;
                return FILTER_VAL_NORM;
 
        case FILTER_ARG_OP:
                if (arg->op.type != FILTER_OP_NOT) {
-                       lval = test_arg(arg, arg->op.left);
+                       lval = test_arg(arg, arg->op.left, error_str);
                        switch (lval) {
                        case FILTER_VAL_NORM:
                                break;
                        case FILTER_VAL_TRUE:
                                if (arg->op.type == FILTER_OP_OR)
                                        return FILTER_VAL_TRUE;
-                               rval = test_arg(arg, arg->op.right);
+                               rval = test_arg(arg, arg->op.right, error_str);
                                if (rval != FILTER_VAL_NORM)
                                        return rval;
 
-                               reparent_op_arg(parent, arg, arg->op.right);
-                               return FILTER_VAL_NORM;
+                               return reparent_op_arg(parent, arg, arg->op.right,
+                                                      error_str);
 
                        case FILTER_VAL_FALSE:
                                if (arg->op.type == FILTER_OP_AND)
                                        return FILTER_VAL_FALSE;
-                               rval = test_arg(arg, arg->op.right);
+                               rval = test_arg(arg, arg->op.right, error_str);
                                if (rval != FILTER_VAL_NORM)
                                        return rval;
 
-                               reparent_op_arg(parent, arg, arg->op.right);
-                               return FILTER_VAL_NORM;
+                               return reparent_op_arg(parent, arg, arg->op.right,
+                                                      error_str);
+
+                       default:
+                               return lval;
                        }
                }
 
-               rval = test_arg(arg, arg->op.right);
+               rval = test_arg(arg, arg->op.right, error_str);
                switch (rval) {
                case FILTER_VAL_NORM:
+               default:
                        break;
+
                case FILTER_VAL_TRUE:
                        if (arg->op.type == FILTER_OP_OR)
                                return FILTER_VAL_TRUE;
                        if (arg->op.type == FILTER_OP_NOT)
                                return FILTER_VAL_FALSE;
 
-                       reparent_op_arg(parent, arg, arg->op.left);
-                       return FILTER_VAL_NORM;
+                       return reparent_op_arg(parent, arg, arg->op.left,
+                                              error_str);
 
                case FILTER_VAL_FALSE:
                        if (arg->op.type == FILTER_OP_AND)
@@ -852,41 +900,56 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
                        if (arg->op.type == FILTER_OP_NOT)
                                return FILTER_VAL_TRUE;
 
-                       reparent_op_arg(parent, arg, arg->op.left);
-                       return FILTER_VAL_NORM;
+                       return reparent_op_arg(parent, arg, arg->op.left,
+                                              error_str);
                }
 
-               return FILTER_VAL_NORM;
+               return rval;
        default:
-               die("bad arg in filter tree");
+               show_error(error_str, "bad arg in filter tree");
+               return PEVENT_ERRNO__BAD_FILTER_ARG;
        }
        return FILTER_VAL_NORM;
 }
 
 /* Remove any unknown event fields */
-static struct filter_arg *collapse_tree(struct filter_arg *arg)
+static int collapse_tree(struct filter_arg *arg,
+                        struct filter_arg **arg_collapsed, char *error_str)
 {
-       enum filter_vals ret;
+       int ret;
 
-       ret = test_arg(arg, arg);
+       ret = test_arg(arg, arg, error_str);
        switch (ret) {
        case FILTER_VAL_NORM:
-               return arg;
+               break;
 
        case FILTER_VAL_TRUE:
        case FILTER_VAL_FALSE:
                free_arg(arg);
                arg = allocate_arg();
-               arg->type = FILTER_ARG_BOOLEAN;
-               arg->boolean.value = ret == FILTER_VAL_TRUE;
+               if (arg) {
+                       arg->type = FILTER_ARG_BOOLEAN;
+                       arg->boolean.value = ret == FILTER_VAL_TRUE;
+               } else {
+                       show_error(error_str, "Failed to allocate filter arg");
+                       ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               }
+               break;
+
+       default:
+               /* test_arg() already set the error_str */
+               free_arg(arg);
+               arg = NULL;
+               break;
        }
 
-       return arg;
+       *arg_collapsed = arg;
+       return ret;
 }
 
-static int
+static enum pevent_errno
 process_filter(struct event_format *event, struct filter_arg **parg,
-              char **error_str, int not)
+              char *error_str, int not)
 {
        enum event_type type;
        char *token = NULL;
@@ -898,7 +961,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
        enum filter_op_type btype;
        enum filter_exp_type etype;
        enum filter_cmp_type ctype;
-       int ret;
+       enum pevent_errno ret;
 
        *parg = NULL;
 
@@ -909,8 +972,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                case EVENT_SQUOTE:
                case EVENT_DQUOTE:
                case EVENT_ITEM:
-                       arg = create_arg_item(event, token, type, error_str);
-                       if (!arg)
+                       ret = create_arg_item(event, token, type, &arg, error_str);
+                       if (ret < 0)
                                goto fail;
                        if (!left_item)
                                left_item = arg;
@@ -923,20 +986,20 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                if (not) {
                                        arg = NULL;
                                        if (current_op)
-                                               goto fail_print;
+                                               goto fail_syntax;
                                        free(token);
                                        *parg = current_exp;
                                        return 0;
                                }
                        } else
-                               goto fail_print;
+                               goto fail_syntax;
                        arg = NULL;
                        break;
 
                case EVENT_DELIM:
                        if (*token == ',') {
-                               show_error(error_str,
-                                          "Illegal token ','");
+                               show_error(error_str, "Illegal token ','");
+                               ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
                                goto fail;
                        }
 
@@ -944,19 +1007,23 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                if (left_item) {
                                        show_error(error_str,
                                                   "Open paren can not come after item");
+                                       ret = PEVENT_ERRNO__INVALID_PAREN;
                                        goto fail;
                                }
                                if (current_exp) {
                                        show_error(error_str,
                                                   "Open paren can not come after expression");
+                                       ret = PEVENT_ERRNO__INVALID_PAREN;
                                        goto fail;
                                }
 
                                ret = process_filter(event, &arg, error_str, 0);
-                               if (ret != 1) {
-                                       if (ret == 0)
+                               if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
+                                       if (ret == 0) {
                                                show_error(error_str,
                                                           "Unbalanced number of '('");
+                                               ret = PEVENT_ERRNO__UNBALANCED_PAREN;
+                                       }
                                        goto fail;
                                }
                                ret = 0;
@@ -964,7 +1031,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                /* A not wants just one expression */
                                if (not) {
                                        if (current_op)
-                                               goto fail_print;
+                                               goto fail_syntax;
                                        *parg = arg;
                                        return 0;
                                }
@@ -979,19 +1046,19 @@ process_filter(struct event_format *event, struct filter_arg **parg,
 
                        } else { /* ')' */
                                if (!current_op && !current_exp)
-                                       goto fail_print;
+                                       goto fail_syntax;
 
                                /* Make sure everything is finished at this level */
                                if (current_exp && !check_op_done(current_exp))
-                                       goto fail_print;
+                                       goto fail_syntax;
                                if (current_op && !check_op_done(current_op))
-                                       goto fail_print;
+                                       goto fail_syntax;
 
                                if (current_op)
                                        *parg = current_op;
                                else
                                        *parg = current_exp;
-                               return 1;
+                               return PEVENT_ERRNO__UNBALANCED_PAREN;
                        }
                        break;
 
@@ -1003,21 +1070,22 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                        case OP_BOOL:
                                /* Logic ops need a left expression */
                                if (!current_exp && !current_op)
-                                       goto fail_print;
+                                       goto fail_syntax;
                                /* fall through */
                        case OP_NOT:
                                /* logic only processes ops and exp */
                                if (left_item)
-                                       goto fail_print;
+                                       goto fail_syntax;
                                break;
                        case OP_EXP:
                        case OP_CMP:
                                if (!left_item)
-                                       goto fail_print;
+                                       goto fail_syntax;
                                break;
                        case OP_NONE:
                                show_error(error_str,
                                           "Unknown op token %s", token);
+                               ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
                                goto fail;
                        }
 
@@ -1025,6 +1093,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                        switch (op_type) {
                        case OP_BOOL:
                                arg = create_arg_op(btype);
+                               if (arg == NULL)
+                                       goto fail_alloc;
                                if (current_op)
                                        ret = add_left(arg, current_op);
                                else
@@ -1035,6 +1105,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
 
                        case OP_NOT:
                                arg = create_arg_op(btype);
+                               if (arg == NULL)
+                                       goto fail_alloc;
                                if (current_op)
                                        ret = add_right(current_op, arg, error_str);
                                if (ret < 0)
@@ -1054,6 +1126,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                        arg = create_arg_exp(etype);
                                else
                                        arg = create_arg_cmp(ctype);
+                               if (arg == NULL)
+                                       goto fail_alloc;
 
                                if (current_op)
                                        ret = add_right(current_op, arg, error_str);
@@ -1062,7 +1136,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                ret = add_left(arg, left_item);
                                if (ret < 0) {
                                        arg = NULL;
-                                       goto fail_print;
+                                       goto fail_syntax;
                                }
                                current_exp = arg;
                                break;
@@ -1071,57 +1145,64 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                        }
                        arg = NULL;
                        if (ret < 0)
-                               goto fail_print;
+                               goto fail_syntax;
                        break;
                case EVENT_NONE:
                        break;
+               case EVENT_ERROR:
+                       goto fail_alloc;
                default:
-                       goto fail_print;
+                       goto fail_syntax;
                }
        } while (type != EVENT_NONE);
 
        if (!current_op && !current_exp)
-               goto fail_print;
+               goto fail_syntax;
 
        if (!current_op)
                current_op = current_exp;
 
-       current_op = collapse_tree(current_op);
+       ret = collapse_tree(current_op, parg, error_str);
+       if (ret < 0)
+               goto fail;
 
        *parg = current_op;
 
        return 0;
 
- fail_print:
+ fail_alloc:
+       show_error(error_str, "failed to allocate filter arg");
+       ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+       goto fail;
+ fail_syntax:
        show_error(error_str, "Syntax error");
+       ret = PEVENT_ERRNO__SYNTAX_ERROR;
  fail:
        free_arg(current_op);
        free_arg(current_exp);
        free_arg(arg);
        free(token);
-       return -1;
+       return ret;
 }
 
-static int
+static enum pevent_errno
 process_event(struct event_format *event, const char *filter_str,
-             struct filter_arg **parg, char **error_str)
+             struct filter_arg **parg, char *error_str)
 {
        int ret;
 
        pevent_buffer_init(filter_str, strlen(filter_str));
 
        ret = process_filter(event, parg, error_str, 0);
-       if (ret == 1) {
-               show_error(error_str,
-                          "Unbalanced number of ')'");
-               return -1;
-       }
        if (ret < 0)
                return ret;
 
        /* If parg is NULL, then make it into FALSE */
        if (!*parg) {
                *parg = allocate_arg();
+               if (*parg == NULL)
+                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
                (*parg)->type = FILTER_ARG_BOOLEAN;
                (*parg)->boolean.value = FILTER_FALSE;
        }
@@ -1129,13 +1210,13 @@ process_event(struct event_format *event, const char *filter_str,
        return 0;
 }
 
-static int filter_event(struct event_filter *filter,
-                       struct event_format *event,
-                       const char *filter_str, char **error_str)
+static enum pevent_errno
+filter_event(struct event_filter *filter, struct event_format *event,
+            const char *filter_str, char *error_str)
 {
        struct filter_type *filter_type;
        struct filter_arg *arg;
-       int ret;
+       enum pevent_errno ret;
 
        if (filter_str) {
                ret = process_event(event, filter_str, &arg, error_str);
@@ -1145,11 +1226,17 @@ static int filter_event(struct event_filter *filter,
        } else {
                /* just add a TRUE arg */
                arg = allocate_arg();
+               if (arg == NULL)
+                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
                arg->type = FILTER_ARG_BOOLEAN;
                arg->boolean.value = FILTER_TRUE;
        }
 
        filter_type = add_filter_type(filter, event->id);
+       if (filter_type == NULL)
+               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
        if (filter_type->filter)
                free_arg(filter_type->filter);
        filter_type->filter = arg;
@@ -1157,22 +1244,24 @@ static int filter_event(struct event_filter *filter,
        return 0;
 }
 
+static void filter_init_error_buf(struct event_filter *filter)
+{
+       /* clear buffer to reset show error */
+       pevent_buffer_init("", 0);
+       filter->error_buffer[0] = '\0';
+}
+
 /**
  * pevent_filter_add_filter_str - add a new filter
  * @filter: the event filter to add to
  * @filter_str: the filter string that contains the filter
- * @error_str: string containing reason for failed filter
- *
- * Returns 0 if the filter was successfully added
- *   -1 if there was an error.
  *
- * On error, if @error_str points to a string pointer,
- * it is set to the reason that the filter failed.
- * This string must be freed with "free".
+ * Returns 0 if the filter was successfully added or a
+ * negative error code.  Use pevent_filter_strerror() to see
+ * actual error message in case of error.
  */
-int pevent_filter_add_filter_str(struct event_filter *filter,
-                                const char *filter_str,
-                                char **error_str)
+enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
+                                              const char *filter_str)
 {
        struct pevent *pevent = filter->pevent;
        struct event_list *event;
@@ -1183,15 +1272,11 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
        char *event_name = NULL;
        char *sys_name = NULL;
        char *sp;
-       int rtn = 0;
+       enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
        int len;
        int ret;
 
-       /* clear buffer to reset show error */
-       pevent_buffer_init("", 0);
-
-       if (error_str)
-               *error_str = NULL;
+       filter_init_error_buf(filter);
 
        filter_start = strchr(filter_str, ':');
        if (filter_start)
@@ -1199,7 +1284,6 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
        else
                len = strlen(filter_str);
 
-
        do {
                next_event = strchr(filter_str, ',');
                if (next_event &&
@@ -1210,7 +1294,12 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
                else
                        len = strlen(filter_str);
 
-               this_event = malloc_or_die(len + 1);
+               this_event = malloc(len + 1);
+               if (this_event == NULL) {
+                       /* This can only happen when events is NULL, but still */
+                       free_events(events);
+                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               }
                memcpy(this_event, filter_str, len);
                this_event[len] = 0;
 
@@ -1223,27 +1312,18 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
                event_name = strtok_r(NULL, "/", &sp);
 
                if (!sys_name) {
-                       show_error(error_str, "No filter found");
                        /* This can only happen when events is NULL, but still */
                        free_events(events);
                        free(this_event);
-                       return -1;
+                       return PEVENT_ERRNO__FILTER_NOT_FOUND;
                }
 
                /* Find this event */
                ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
                if (ret < 0) {
-                       if (event_name)
-                               show_error(error_str,
-                                          "No event found under '%s.%s'",
-                                          sys_name, event_name);
-                       else
-                               show_error(error_str,
-                                          "No event found under '%s'",
-                                          sys_name);
                        free_events(events);
                        free(this_event);
-                       return -1;
+                       return ret;
                }
                free(this_event);
        } while (filter_str);
@@ -1255,7 +1335,7 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
        /* filter starts here */
        for (event = events; event; event = event->next) {
                ret = filter_event(filter, event->event, filter_start,
-                                  error_str);
+                                  filter->error_buffer);
                /* Failures are returned if a parse error happened */
                if (ret < 0)
                        rtn = ret;
@@ -1263,8 +1343,10 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
                if (ret >= 0 && pevent->test_filters) {
                        char *test;
                        test = pevent_filter_make_string(filter, event->event->id);
-                       printf(" '%s: %s'\n", event->event->name, test);
-                       free(test);
+                       if (test) {
+                               printf(" '%s: %s'\n", event->event->name, test);
+                               free(test);
+                       }
                }
        }
 
@@ -1281,6 +1363,32 @@ static void free_filter_type(struct filter_type *filter_type)
        free_arg(filter_type->filter);
 }
 
+/**
+ * pevent_filter_strerror - fill error message in a buffer
+ * @filter: the event filter contains error
+ * @err: the error code
+ * @buf: the buffer to be filled in
+ * @buflen: the size of the buffer
+ *
+ * Returns 0 if message was filled successfully, -1 if error
+ */
+int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
+                          char *buf, size_t buflen)
+{
+       if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
+               return -1;
+
+       if (strlen(filter->error_buffer) > 0) {
+               size_t len = snprintf(buf, buflen, "%s", filter->error_buffer);
+
+               if (len > buflen)
+                       return -1;
+               return 0;
+       }
+
+       return pevent_strerror(filter->pevent, err, buf, buflen);
+}
+
 /**
  * pevent_filter_remove_event - remove a filter for an event
  * @filter: the event filter to remove from
@@ -1374,6 +1482,9 @@ static int copy_filter_type(struct event_filter *filter,
        if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
                /* Add trivial event */
                arg = allocate_arg();
+               if (arg == NULL)
+                       return -1;
+
                arg->type = FILTER_ARG_BOOLEAN;
                if (strcmp(str, "TRUE") == 0)
                        arg->boolean.value = 1;
@@ -1381,6 +1492,9 @@ static int copy_filter_type(struct event_filter *filter,
                        arg->boolean.value = 0;
 
                filter_type = add_filter_type(filter, event->id);
+               if (filter_type == NULL)
+                       return -1;
+
                filter_type->filter = arg;
 
                free(str);
@@ -1482,8 +1596,10 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source
  * @type: remove only true, false, or both
  *
  * Removes filters that only contain a TRUE or FALES boolean arg.
+ *
+ * Returns 0 on success and -1 if there was a problem.
  */
-void pevent_filter_clear_trivial(struct event_filter *filter,
+int pevent_filter_clear_trivial(struct event_filter *filter,
                                 enum filter_trivial_type type)
 {
        struct filter_type *filter_type;
@@ -1492,13 +1608,15 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
        int i;
 
        if (!filter->filters)
-               return;
+               return 0;
 
        /*
         * Two steps, first get all ids with trivial filters.
         *  then remove those ids.
         */
        for (i = 0; i < filter->filters; i++) {
+               int *new_ids;
+
                filter_type = &filter->event_filters[i];
                if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
                        continue;
@@ -1513,19 +1631,24 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
                        break;
                }
 
-               ids = realloc(ids, sizeof(*ids) * (count + 1));
-               if (!ids)
-                       die("Can't allocate ids");
+               new_ids = realloc(ids, sizeof(*ids) * (count + 1));
+               if (!new_ids) {
+                       free(ids);
+                       return -1;
+               }
+
+               ids = new_ids;
                ids[count++] = filter_type->event_id;
        }
 
        if (!count)
-               return;
+               return 0;
 
        for (i = 0; i < count; i++)
                pevent_filter_remove_event(filter, ids[i]);
 
        free(ids);
+       return 0;
 }
 
 /**
@@ -1565,8 +1688,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter,
        }
 }
 
-static int test_filter(struct event_format *event,
-                      struct filter_arg *arg, struct pevent_record *record);
+static int test_filter(struct event_format *event, struct filter_arg *arg,
+                      struct pevent_record *record, enum pevent_errno *err);
 
 static const char *
 get_comm(struct event_format *event, struct pevent_record *record)
@@ -1612,15 +1735,24 @@ get_value(struct event_format *event,
 }
 
 static unsigned long long
-get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record);
+get_arg_value(struct event_format *event, struct filter_arg *arg,
+             struct pevent_record *record, enum pevent_errno *err);
 
 static unsigned long long
-get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
+get_exp_value(struct event_format *event, struct filter_arg *arg,
+             struct pevent_record *record, enum pevent_errno *err)
 {
        unsigned long long lval, rval;
 
-       lval = get_arg_value(event, arg->exp.left, record);
-       rval = get_arg_value(event, arg->exp.right, record);
+       lval = get_arg_value(event, arg->exp.left, record, err);
+       rval = get_arg_value(event, arg->exp.right, record, err);
+
+       if (*err) {
+               /*
+                * There was an error, no need to process anymore.
+                */
+               return 0;
+       }
 
        switch (arg->exp.type) {
        case FILTER_EXP_ADD:
@@ -1655,39 +1787,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_
 
        case FILTER_EXP_NOT:
        default:
-               die("error in exp");
+               if (!*err)
+                       *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
        }
        return 0;
 }
 
 static unsigned long long
-get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
+get_arg_value(struct event_format *event, struct filter_arg *arg,
+             struct pevent_record *record, enum pevent_errno *err)
 {
        switch (arg->type) {
        case FILTER_ARG_FIELD:
                return get_value(event, arg->field.field, record);
 
        case FILTER_ARG_VALUE:
-               if (arg->value.type != FILTER_NUMBER)
-                       die("must have number field!");
+               if (arg->value.type != FILTER_NUMBER) {
+                       if (!*err)
+                               *err = PEVENT_ERRNO__NOT_A_NUMBER;
+               }
                return arg->value.val;
 
        case FILTER_ARG_EXP:
-               return get_exp_value(event, arg, record);
+               return get_exp_value(event, arg, record, err);
 
        default:
-               die("oops in filter");
+               if (!*err)
+                       *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
        }
        return 0;
 }
 
-static int test_num(struct event_format *event,
-                   struct filter_arg *arg, struct pevent_record *record)
+static int test_num(struct event_format *event, struct filter_arg *arg,
+                   struct pevent_record *record, enum pevent_errno *err)
 {
        unsigned long long lval, rval;
 
-       lval = get_arg_value(event, arg->num.left, record);
-       rval = get_arg_value(event, arg->num.right, record);
+       lval = get_arg_value(event, arg->num.left, record, err);
+       rval = get_arg_value(event, arg->num.right, record, err);
+
+       if (*err) {
+               /*
+                * There was an error, no need to process anymore.
+                */
+               return 0;
+       }
 
        switch (arg->num.type) {
        case FILTER_CMP_EQ:
@@ -1709,7 +1853,8 @@ static int test_num(struct event_format *event,
                return lval <= rval;
 
        default:
-               /* ?? */
+               if (!*err)
+                       *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
                return 0;
        }
 }
@@ -1756,8 +1901,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r
        return val;
 }
 
-static int test_str(struct event_format *event,
-                   struct filter_arg *arg, struct pevent_record *record)
+static int test_str(struct event_format *event, struct filter_arg *arg,
+                   struct pevent_record *record, enum pevent_errno *err)
 {
        const char *val;
 
@@ -1781,48 +1926,57 @@ static int test_str(struct event_format *event,
                return regexec(&arg->str.reg, val, 0, NULL, 0);
 
        default:
-               /* ?? */
+               if (!*err)
+                       *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
                return 0;
        }
 }
 
-static int test_op(struct event_format *event,
-                  struct filter_arg *arg, struct pevent_record *record)
+static int test_op(struct event_format *event, struct filter_arg *arg,
+                  struct pevent_record *record, enum pevent_errno *err)
 {
        switch (arg->op.type) {
        case FILTER_OP_AND:
-               return test_filter(event, arg->op.left, record) &&
-                       test_filter(event, arg->op.right, record);
+               return test_filter(event, arg->op.left, record, err) &&
+                       test_filter(event, arg->op.right, record, err);
 
        case FILTER_OP_OR:
-               return test_filter(event, arg->op.left, record) ||
-                       test_filter(event, arg->op.right, record);
+               return test_filter(event, arg->op.left, record, err) ||
+                       test_filter(event, arg->op.right, record, err);
 
        case FILTER_OP_NOT:
-               return !test_filter(event, arg->op.right, record);
+               return !test_filter(event, arg->op.right, record, err);
 
        default:
-               /* ?? */
+               if (!*err)
+                       *err = PEVENT_ERRNO__INVALID_OP_TYPE;
                return 0;
        }
 }
 
-static int test_filter(struct event_format *event,
-                      struct filter_arg *arg, struct pevent_record *record)
+static int test_filter(struct event_format *event, struct filter_arg *arg,
+                      struct pevent_record *record, enum pevent_errno *err)
 {
+       if (*err) {
+               /*
+                * There was an error, no need to process anymore.
+                */
+               return 0;
+       }
+
        switch (arg->type) {
        case FILTER_ARG_BOOLEAN:
                /* easy case */
                return arg->boolean.value;
 
        case FILTER_ARG_OP:
-               return test_op(event, arg, record);
+               return test_op(event, arg, record, err);
 
        case FILTER_ARG_NUM:
-               return test_num(event, arg, record);
+               return test_num(event, arg, record, err);
 
        case FILTER_ARG_STR:
-               return test_str(event, arg, record);
+               return test_str(event, arg, record, err);
 
        case FILTER_ARG_EXP:
        case FILTER_ARG_VALUE:
@@ -1831,11 +1985,11 @@ static int test_filter(struct event_format *event,
                 * Expressions, fields and values evaluate
                 * to true if they return non zero
                 */
-               return !!get_arg_value(event, arg, record);
+               return !!get_arg_value(event, arg, record, err);
 
        default:
-               die("oops!");
-               /* ?? */
+               if (!*err)
+                       *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
                return 0;
        }
 }
@@ -1848,8 +2002,7 @@ static int test_filter(struct event_format *event,
  * Returns 1 if filter found for @event_id
  *   otherwise 0;
  */
-int pevent_event_filtered(struct event_filter *filter,
-                         int event_id)
+int pevent_event_filtered(struct event_filter *filter, int event_id)
 {
        struct filter_type *filter_type;
 
@@ -1866,31 +2019,38 @@ int pevent_event_filtered(struct event_filter *filter,
  * @filter: filter struct with filter information
  * @record: the record to test against the filter
  *
- * Returns:
- *  1 - filter found for event and @record matches
- *  0 - filter found for event and @record does not match
- * -1 - no filter found for @record's event
- * -2 - if no filters exist
+ * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
+ * FILTER_MATCH - filter found for event and @record matches
+ * FILTER_MISS  - filter found for event and @record does not match
+ * FILTER_NOT_FOUND - no filter found for @record's event
+ * NO_FILTER - if no filters exist
+ * otherwise - error occurred during test
  */
-int pevent_filter_match(struct event_filter *filter,
-                       struct pevent_record *record)
+enum pevent_errno pevent_filter_match(struct event_filter *filter,
+                                     struct pevent_record *record)
 {
        struct pevent *pevent = filter->pevent;
        struct filter_type *filter_type;
        int event_id;
+       int ret;
+       enum pevent_errno err = 0;
+
+       filter_init_error_buf(filter);
 
        if (!filter->filters)
-               return FILTER_NONE;
+               return PEVENT_ERRNO__NO_FILTER;
 
        event_id = pevent_data_type(pevent, record);
 
        filter_type = find_filter_type(filter, event_id);
-
        if (!filter_type)
-               return FILTER_NOEXIST;
+               return PEVENT_ERRNO__FILTER_NOT_FOUND;
+
+       ret = test_filter(filter_type->event, filter_type->filter, record, &err);
+       if (err)
+               return err;
 
-       return test_filter(filter_type->event, filter_type->filter, record) ?
-               FILTER_MATCH : FILTER_MISS;
+       return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
 }
 
 static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
@@ -1902,7 +2062,6 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
        int left_val = -1;
        int right_val = -1;
        int val;
-       int len;
 
        switch (arg->op.type) {
        case FILTER_OP_AND:
@@ -1949,11 +2108,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
                                default:
                                        break;
                                }
-                               str = malloc_or_die(6);
-                               if (val)
-                                       strcpy(str, "TRUE");
-                               else
-                                       strcpy(str, "FALSE");
+                               asprintf(&str, val ? "TRUE" : "FALSE");
                                break;
                        }
                }
@@ -1971,10 +2126,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
                        break;
                }
 
-               len = strlen(left) + strlen(right) + strlen(op) + 10;
-               str = malloc_or_die(len);
-               snprintf(str, len, "(%s) %s (%s)",
-                        left, op, right);
+               asprintf(&str, "(%s) %s (%s)", left, op, right);
                break;
 
        case FILTER_OP_NOT:
@@ -1990,16 +2142,10 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
                        right_val = 0;
                if (right_val >= 0) {
                        /* just return the opposite */
-                       str = malloc_or_die(6);
-                       if (right_val)
-                               strcpy(str, "FALSE");
-                       else
-                               strcpy(str, "TRUE");
+                       asprintf(&str, right_val ? "FALSE" : "TRUE");
                        break;
                }
-               len = strlen(right) + strlen(op) + 3;
-               str = malloc_or_die(len);
-               snprintf(str, len, "%s(%s)", op, right);
+               asprintf(&str, "%s(%s)", op, right);
                break;
 
        default:
@@ -2013,11 +2159,9 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
 
 static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
 {
-       char *str;
-
-       str = malloc_or_die(30);
+       char *str = NULL;
 
-       snprintf(str, 30, "%lld", arg->value.val);
+       asprintf(&str, "%lld", arg->value.val);
 
        return str;
 }
@@ -2033,7 +2177,6 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        char *rstr;
        char *op;
        char *str = NULL;
-       int len;
 
        lstr = arg_to_str(filter, arg->exp.left);
        rstr = arg_to_str(filter, arg->exp.right);
@@ -2072,12 +2215,11 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
                op = "^";
                break;
        default:
-               die("oops in exp");
+               op = "[ERROR IN EXPRESSION TYPE]";
+               break;
        }
 
-       len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
-       str = malloc_or_die(len);
-       snprintf(str, len, "%s %s %s", lstr, op, rstr);
+       asprintf(&str, "%s %s %s", lstr, op, rstr);
 out:
        free(lstr);
        free(rstr);
@@ -2091,7 +2233,6 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
        char *rstr;
        char *str = NULL;
        char *op = NULL;
-       int len;
 
        lstr = arg_to_str(filter, arg->num.left);
        rstr = arg_to_str(filter, arg->num.right);
@@ -2122,10 +2263,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
                if (!op)
                        op = "<=";
 
-               len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
-               str = malloc_or_die(len);
-               sprintf(str, "%s %s %s", lstr, op, rstr);
-
+               asprintf(&str, "%s %s %s", lstr, op, rstr);
                break;
 
        default:
@@ -2143,7 +2281,6 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
 {
        char *str = NULL;
        char *op = NULL;
-       int len;
 
        switch (arg->str.type) {
        case FILTER_CMP_MATCH:
@@ -2161,12 +2298,8 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
                if (!op)
                        op = "!~";
 
-               len = strlen(arg->str.field->name) + strlen(op) +
-                       strlen(arg->str.val) + 6;
-               str = malloc_or_die(len);
-               snprintf(str, len, "%s %s \"%s\"",
-                        arg->str.field->name,
-                        op, arg->str.val);
+               asprintf(&str, "%s %s \"%s\"",
+                        arg->str.field->name, op, arg->str.val);
                break;
 
        default:
@@ -2178,15 +2311,11 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
 
 static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
 {
-       char *str;
+       char *str = NULL;
 
        switch (arg->type) {
        case FILTER_ARG_BOOLEAN:
-               str = malloc_or_die(6);
-               if (arg->boolean.value)
-                       strcpy(str, "TRUE");
-               else
-                       strcpy(str, "FALSE");
+               asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE");
                return str;
 
        case FILTER_ARG_OP:
@@ -2221,7 +2350,7 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
  *
  * Returns a string that displays the filter contents.
  *  This string must be freed with free(str).
- *  NULL is returned if no filter is found.
+ *  NULL is returned if no filter is found or allocation failed.
  */
 char *
 pevent_filter_make_string(struct event_filter *filter, int event_id)
index bba701cf10e6e28bf2efde0f2089c37131d88d01..eda07fa31dca1058a72989669e1cc99bc5958ab3 100644 (file)
 
 #define __weak __attribute__((weak))
 
-void __vdie(const char *fmt, va_list ap)
-{
-       int ret = errno;
-
-       if (errno)
-               perror("trace-cmd");
-       else
-               ret = -1;
-
-       fprintf(stderr, "  ");
-       vfprintf(stderr, fmt, ap);
-
-       fprintf(stderr, "\n");
-       exit(ret);
-}
-
-void __die(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       __vdie(fmt, ap);
-       va_end(ap);
-}
-
-void __weak die(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       __vdie(fmt, ap);
-       va_end(ap);
-}
-
 void __vwarning(const char *fmt, va_list ap)
 {
        if (errno)
@@ -117,13 +83,3 @@ void __weak pr_stat(const char *fmt, ...)
        __vpr_stat(fmt, ap);
        va_end(ap);
 }
-
-void __weak *malloc_or_die(unsigned int size)
-{
-       void *data;
-
-       data = malloc(size);
-       if (!data)
-               die("malloc");
-       return data;
-}
diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c
new file mode 100644 (file)
index 0000000..c066b25
--- /dev/null
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <endian.h>
+#include "event-parse.h"
+
+static unsigned long long
+process___le16_to_cpup(struct trace_seq *s,
+                      unsigned long long *args)
+{
+       uint16_t *val = (uint16_t *) (unsigned long) args[0];
+       return val ? (long long) le16toh(*val) : 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_print_function(pevent,
+                                      process___le16_to_cpup,
+                                      PEVENT_FUNC_ARG_INT,
+                                      "__le16_to_cpup",
+                                      PEVENT_FUNC_ARG_PTR,
+                                      PEVENT_FUNC_ARG_VOID);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_print_function(pevent, process___le16_to_cpup,
+                                        "__le16_to_cpup");
+}
diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c
new file mode 100644 (file)
index 0000000..80ba4ff
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event-parse.h"
+#include "event-utils.h"
+
+static struct func_stack {
+       int size;
+       char **stack;
+} *fstack;
+
+static int cpus = -1;
+
+#define STK_BLK 10
+
+static void add_child(struct func_stack *stack, const char *child, int pos)
+{
+       int i;
+
+       if (!child)
+               return;
+
+       if (pos < stack->size)
+               free(stack->stack[pos]);
+       else {
+               char **ptr;
+
+               ptr = realloc(stack->stack, sizeof(char *) *
+                             (stack->size + STK_BLK));
+               if (!ptr) {
+                       warning("could not allocate plugin memory\n");
+                       return;
+               }
+
+               stack->stack = ptr;
+
+               for (i = stack->size; i < stack->size + STK_BLK; i++)
+                       stack->stack[i] = NULL;
+               stack->size += STK_BLK;
+       }
+
+       stack->stack[pos] = strdup(child);
+}
+
+static int add_and_get_index(const char *parent, const char *child, int cpu)
+{
+       int i;
+
+       if (cpu < 0)
+               return 0;
+
+       if (cpu > cpus) {
+               struct func_stack *ptr;
+
+               ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1));
+               if (!ptr) {
+                       warning("could not allocate plugin memory\n");
+                       return 0;
+               }
+
+               fstack = ptr;
+
+               /* Account for holes in the cpu count */
+               for (i = cpus + 1; i <= cpu; i++)
+                       memset(&fstack[i], 0, sizeof(fstack[i]));
+               cpus = cpu;
+       }
+
+       for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) {
+               if (strcmp(parent, fstack[cpu].stack[i]) == 0) {
+                       add_child(&fstack[cpu], child, i+1);
+                       return i;
+               }
+       }
+
+       /* Not found */
+       add_child(&fstack[cpu], parent, 0);
+       add_child(&fstack[cpu], child, 1);
+       return 0;
+}
+
+static int function_handler(struct trace_seq *s, struct pevent_record *record,
+                           struct event_format *event, void *context)
+{
+       struct pevent *pevent = event->pevent;
+       unsigned long long function;
+       unsigned long long pfunction;
+       const char *func;
+       const char *parent;
+       int index;
+
+       if (pevent_get_field_val(s, event, "ip", record, &function, 1))
+               return trace_seq_putc(s, '!');
+
+       func = pevent_find_function(pevent, function);
+
+       if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1))
+               return trace_seq_putc(s, '!');
+
+       parent = pevent_find_function(pevent, pfunction);
+
+       index = add_and_get_index(parent, func, record->cpu);
+
+       trace_seq_printf(s, "%*s", index*3, "");
+
+       if (func)
+               trace_seq_printf(s, "%s", func);
+       else
+               trace_seq_printf(s, "0x%llx", function);
+
+       trace_seq_printf(s, " <-- ");
+       if (parent)
+               trace_seq_printf(s, "%s", parent);
+       else
+               trace_seq_printf(s, "0x%llx", pfunction);
+
+       return 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_event_handler(pevent, -1, "ftrace", "function",
+                                     function_handler, NULL);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       int i, x;
+
+       pevent_unregister_event_handler(pevent, -1, "ftrace", "function",
+                                       function_handler, NULL);
+
+       for (i = 0; i <= cpus; i++) {
+               for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++)
+                       free(fstack[i].stack[x]);
+               free(fstack[i].stack);
+       }
+
+       free(fstack);
+       fstack = NULL;
+       cpus = -1;
+}
diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c
new file mode 100644 (file)
index 0000000..12bf14c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ * Copyright (C) 2009 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event-parse.h"
+
+static int timer_expire_handler(struct trace_seq *s,
+                               struct pevent_record *record,
+                               struct event_format *event, void *context)
+{
+       trace_seq_printf(s, "hrtimer=");
+
+       if (pevent_print_num_field(s, "0x%llx", event, "timer",
+                                  record, 0) == -1)
+               pevent_print_num_field(s, "0x%llx", event, "hrtimer",
+                                      record, 1);
+
+       trace_seq_printf(s, " now=");
+
+       pevent_print_num_field(s, "%llu", event, "now", record, 1);
+
+       pevent_print_func_field(s, " function=%s", event, "function",
+                               record, 0);
+       return 0;
+}
+
+static int timer_start_handler(struct trace_seq *s,
+                              struct pevent_record *record,
+                              struct event_format *event, void *context)
+{
+       trace_seq_printf(s, "hrtimer=");
+
+       if (pevent_print_num_field(s, "0x%llx", event, "timer",
+                                  record, 0) == -1)
+               pevent_print_num_field(s, "0x%llx", event, "hrtimer",
+                                      record, 1);
+
+       pevent_print_func_field(s, " function=%s", event, "function",
+                               record, 0);
+
+       trace_seq_printf(s, " expires=");
+       pevent_print_num_field(s, "%llu", event, "expires", record, 1);
+
+       trace_seq_printf(s, " softexpires=");
+       pevent_print_num_field(s, "%llu", event, "softexpires", record, 1);
+       return 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_event_handler(pevent, -1,
+                                     "timer", "hrtimer_expire_entry",
+                                     timer_expire_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "timer", "hrtimer_start",
+                                     timer_start_handler, NULL);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_event_handler(pevent, -1,
+                                       "timer", "hrtimer_expire_entry",
+                                       timer_expire_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "timer", "hrtimer_start",
+                                       timer_start_handler, NULL);
+}
diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c
new file mode 100644 (file)
index 0000000..0db714c
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event-parse.h"
+
+#define MINORBITS      20
+#define MINORMASK      ((1U << MINORBITS) - 1)
+
+#define MAJOR(dev)     ((unsigned int) ((dev) >> MINORBITS))
+#define MINOR(dev)     ((unsigned int) ((dev) & MINORMASK))
+
+static unsigned long long
+process_jbd2_dev_to_name(struct trace_seq *s,
+                        unsigned long long *args)
+{
+       unsigned int dev = args[0];
+
+       trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev));
+       return 0;
+}
+
+static unsigned long long
+process_jiffies_to_msecs(struct trace_seq *s,
+                        unsigned long long *args)
+{
+       unsigned long long jiffies = args[0];
+
+       trace_seq_printf(s, "%lld", jiffies);
+       return jiffies;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_print_function(pevent,
+                                      process_jbd2_dev_to_name,
+                                      PEVENT_FUNC_ARG_STRING,
+                                      "jbd2_dev_to_name",
+                                      PEVENT_FUNC_ARG_INT,
+                                      PEVENT_FUNC_ARG_VOID);
+
+       pevent_register_print_function(pevent,
+                                      process_jiffies_to_msecs,
+                                      PEVENT_FUNC_ARG_LONG,
+                                      "jiffies_to_msecs",
+                                      PEVENT_FUNC_ARG_LONG,
+                                      PEVENT_FUNC_ARG_VOID);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_print_function(pevent, process_jbd2_dev_to_name,
+                                        "jbd2_dev_to_name");
+
+       pevent_unregister_print_function(pevent, process_jiffies_to_msecs,
+                                        "jiffies_to_msecs");
+}
diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c
new file mode 100644 (file)
index 0000000..70650ff
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event-parse.h"
+
+static int call_site_handler(struct trace_seq *s, struct pevent_record *record,
+                            struct event_format *event, void *context)
+{
+       struct format_field *field;
+       unsigned long long val, addr;
+       void *data = record->data;
+       const char *func;
+
+       field = pevent_find_field(event, "call_site");
+       if (!field)
+               return 1;
+
+       if (pevent_read_number_field(field, data, &val))
+               return 1;
+
+       func = pevent_find_function(event->pevent, val);
+       if (!func)
+               return 1;
+
+       addr = pevent_find_function_address(event->pevent, val);
+
+       trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr));
+       return 1;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_event_handler(pevent, -1, "kmem", "kfree",
+                                     call_site_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kmem", "kmalloc",
+                                     call_site_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kmem", "kmalloc_node",
+                                     call_site_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
+                                     call_site_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kmem",
+                                     "kmem_cache_alloc_node",
+                                     call_site_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_free",
+                                     call_site_handler, NULL);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_event_handler(pevent, -1, "kmem", "kfree",
+                                       call_site_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc",
+                                       call_site_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc_node",
+                                       call_site_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
+                                       call_site_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kmem",
+                                       "kmem_cache_alloc_node",
+                                       call_site_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_free",
+                                       call_site_handler, NULL);
+}
diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c
new file mode 100644 (file)
index 0000000..9e0e8c6
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "event-parse.h"
+
+#ifdef HAVE_UDIS86
+
+#include <udis86.h>
+
+static ud_t ud;
+
+static void init_disassembler(void)
+{
+       ud_init(&ud);
+       ud_set_syntax(&ud, UD_SYN_ATT);
+}
+
+static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
+                              int cr0_pe, int eflags_vm,
+                              int cs_d, int cs_l)
+{
+       int mode;
+
+       if (!cr0_pe)
+               mode = 16;
+       else if (eflags_vm)
+               mode = 16;
+       else if (cs_l)
+               mode = 64;
+       else if (cs_d)
+               mode = 32;
+       else
+               mode = 16;
+
+       ud_set_pc(&ud, rip);
+       ud_set_mode(&ud, mode);
+       ud_set_input_buffer(&ud, insn, len);
+       ud_disassemble(&ud);
+       return ud_insn_asm(&ud);
+}
+
+#else
+
+static void init_disassembler(void)
+{
+}
+
+static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
+                              int cr0_pe, int eflags_vm,
+                              int cs_d, int cs_l)
+{
+       static char out[15*3+1];
+       int i;
+
+       for (i = 0; i < len; ++i)
+               sprintf(out + i * 3, "%02x ", insn[i]);
+       out[len*3-1] = '\0';
+       return out;
+}
+
+#endif
+
+
+#define VMX_EXIT_REASONS                       \
+       _ER(EXCEPTION_NMI,       0)             \
+       _ER(EXTERNAL_INTERRUPT,  1)             \
+       _ER(TRIPLE_FAULT,        2)             \
+       _ER(PENDING_INTERRUPT,   7)             \
+       _ER(NMI_WINDOW,          8)             \
+       _ER(TASK_SWITCH,         9)             \
+       _ER(CPUID,               10)            \
+       _ER(HLT,                 12)            \
+       _ER(INVD,                13)            \
+       _ER(INVLPG,              14)            \
+       _ER(RDPMC,               15)            \
+       _ER(RDTSC,               16)            \
+       _ER(VMCALL,              18)            \
+       _ER(VMCLEAR,             19)            \
+       _ER(VMLAUNCH,            20)            \
+       _ER(VMPTRLD,             21)            \
+       _ER(VMPTRST,             22)            \
+       _ER(VMREAD,              23)            \
+       _ER(VMRESUME,            24)            \
+       _ER(VMWRITE,             25)            \
+       _ER(VMOFF,               26)            \
+       _ER(VMON,                27)            \
+       _ER(CR_ACCESS,           28)            \
+       _ER(DR_ACCESS,           29)            \
+       _ER(IO_INSTRUCTION,      30)            \
+       _ER(MSR_READ,            31)            \
+       _ER(MSR_WRITE,           32)            \
+       _ER(MWAIT_INSTRUCTION,   36)            \
+       _ER(MONITOR_INSTRUCTION, 39)            \
+       _ER(PAUSE_INSTRUCTION,   40)            \
+       _ER(MCE_DURING_VMENTRY,  41)            \
+       _ER(TPR_BELOW_THRESHOLD, 43)            \
+       _ER(APIC_ACCESS,         44)            \
+       _ER(EOI_INDUCED,         45)            \
+       _ER(EPT_VIOLATION,       48)            \
+       _ER(EPT_MISCONFIG,       49)            \
+       _ER(INVEPT,              50)            \
+       _ER(PREEMPTION_TIMER,    52)            \
+       _ER(WBINVD,              54)            \
+       _ER(XSETBV,              55)            \
+       _ER(APIC_WRITE,          56)            \
+       _ER(INVPCID,             58)
+
+#define SVM_EXIT_REASONS \
+       _ER(EXIT_READ_CR0,      0x000)          \
+       _ER(EXIT_READ_CR3,      0x003)          \
+       _ER(EXIT_READ_CR4,      0x004)          \
+       _ER(EXIT_READ_CR8,      0x008)          \
+       _ER(EXIT_WRITE_CR0,     0x010)          \
+       _ER(EXIT_WRITE_CR3,     0x013)          \
+       _ER(EXIT_WRITE_CR4,     0x014)          \
+       _ER(EXIT_WRITE_CR8,     0x018)          \
+       _ER(EXIT_READ_DR0,      0x020)          \
+       _ER(EXIT_READ_DR1,      0x021)          \
+       _ER(EXIT_READ_DR2,      0x022)          \
+       _ER(EXIT_READ_DR3,      0x023)          \
+       _ER(EXIT_READ_DR4,      0x024)          \
+       _ER(EXIT_READ_DR5,      0x025)          \
+       _ER(EXIT_READ_DR6,      0x026)          \
+       _ER(EXIT_READ_DR7,      0x027)          \
+       _ER(EXIT_WRITE_DR0,     0x030)          \
+       _ER(EXIT_WRITE_DR1,     0x031)          \
+       _ER(EXIT_WRITE_DR2,     0x032)          \
+       _ER(EXIT_WRITE_DR3,     0x033)          \
+       _ER(EXIT_WRITE_DR4,     0x034)          \
+       _ER(EXIT_WRITE_DR5,     0x035)          \
+       _ER(EXIT_WRITE_DR6,     0x036)          \
+       _ER(EXIT_WRITE_DR7,     0x037)          \
+       _ER(EXIT_EXCP_BASE,     0x040)          \
+       _ER(EXIT_INTR,          0x060)          \
+       _ER(EXIT_NMI,           0x061)          \
+       _ER(EXIT_SMI,           0x062)          \
+       _ER(EXIT_INIT,          0x063)          \
+       _ER(EXIT_VINTR,         0x064)          \
+       _ER(EXIT_CR0_SEL_WRITE, 0x065)          \
+       _ER(EXIT_IDTR_READ,     0x066)          \
+       _ER(EXIT_GDTR_READ,     0x067)          \
+       _ER(EXIT_LDTR_READ,     0x068)          \
+       _ER(EXIT_TR_READ,       0x069)          \
+       _ER(EXIT_IDTR_WRITE,    0x06a)          \
+       _ER(EXIT_GDTR_WRITE,    0x06b)          \
+       _ER(EXIT_LDTR_WRITE,    0x06c)          \
+       _ER(EXIT_TR_WRITE,      0x06d)          \
+       _ER(EXIT_RDTSC,         0x06e)          \
+       _ER(EXIT_RDPMC,         0x06f)          \
+       _ER(EXIT_PUSHF,         0x070)          \
+       _ER(EXIT_POPF,          0x071)          \
+       _ER(EXIT_CPUID,         0x072)          \
+       _ER(EXIT_RSM,           0x073)          \
+       _ER(EXIT_IRET,          0x074)          \
+       _ER(EXIT_SWINT,         0x075)          \
+       _ER(EXIT_INVD,          0x076)          \
+       _ER(EXIT_PAUSE,         0x077)          \
+       _ER(EXIT_HLT,           0x078)          \
+       _ER(EXIT_INVLPG,        0x079)          \
+       _ER(EXIT_INVLPGA,       0x07a)          \
+       _ER(EXIT_IOIO,          0x07b)          \
+       _ER(EXIT_MSR,           0x07c)          \
+       _ER(EXIT_TASK_SWITCH,   0x07d)          \
+       _ER(EXIT_FERR_FREEZE,   0x07e)          \
+       _ER(EXIT_SHUTDOWN,      0x07f)          \
+       _ER(EXIT_VMRUN,         0x080)          \
+       _ER(EXIT_VMMCALL,       0x081)          \
+       _ER(EXIT_VMLOAD,        0x082)          \
+       _ER(EXIT_VMSAVE,        0x083)          \
+       _ER(EXIT_STGI,          0x084)          \
+       _ER(EXIT_CLGI,          0x085)          \
+       _ER(EXIT_SKINIT,        0x086)          \
+       _ER(EXIT_RDTSCP,        0x087)          \
+       _ER(EXIT_ICEBP,         0x088)          \
+       _ER(EXIT_WBINVD,        0x089)          \
+       _ER(EXIT_MONITOR,       0x08a)          \
+       _ER(EXIT_MWAIT,         0x08b)          \
+       _ER(EXIT_MWAIT_COND,    0x08c)          \
+       _ER(EXIT_NPF,           0x400)          \
+       _ER(EXIT_ERR,           -1)
+
+#define _ER(reason, val)       { #reason, val },
+struct str_values {
+       const char      *str;
+       int             val;
+};
+
+static struct str_values vmx_exit_reasons[] = {
+       VMX_EXIT_REASONS
+       { NULL, -1}
+};
+
+static struct str_values svm_exit_reasons[] = {
+       SVM_EXIT_REASONS
+       { NULL, -1}
+};
+
+static struct isa_exit_reasons {
+       unsigned isa;
+       struct str_values *strings;
+} isa_exit_reasons[] = {
+       { .isa = 1, .strings = vmx_exit_reasons },
+       { .isa = 2, .strings = svm_exit_reasons },
+       { }
+};
+
+static const char *find_exit_reason(unsigned isa, int val)
+{
+       struct str_values *strings = NULL;
+       int i;
+
+       for (i = 0; isa_exit_reasons[i].strings; ++i)
+               if (isa_exit_reasons[i].isa == isa) {
+                       strings = isa_exit_reasons[i].strings;
+                       break;
+               }
+       if (!strings)
+               return "UNKNOWN-ISA";
+       for (i = 0; strings[i].val >= 0; i++)
+               if (strings[i].val == val)
+                       break;
+       if (strings[i].str)
+               return strings[i].str;
+       return "UNKNOWN";
+}
+
+static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record,
+                           struct event_format *event, void *context)
+{
+       unsigned long long isa;
+       unsigned long long val;
+       unsigned long long info1 = 0, info2 = 0;
+
+       if (pevent_get_field_val(s, event, "exit_reason", record, &val, 1) < 0)
+               return -1;
+
+       if (pevent_get_field_val(s, event, "isa", record, &isa, 0) < 0)
+               isa = 1;
+
+       trace_seq_printf(s, "reason %s", find_exit_reason(isa, val));
+
+       pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1);
+
+       if (pevent_get_field_val(s, event, "info1", record, &info1, 0) >= 0
+           && pevent_get_field_val(s, event, "info2", record, &info2, 0) >= 0)
+               trace_seq_printf(s, " info %llx %llx", info1, info2);
+
+       return 0;
+}
+
+#define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
+#define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
+#define KVM_EMUL_INSN_F_CS_D   (1 << 2)
+#define KVM_EMUL_INSN_F_CS_L   (1 << 3)
+
+static int kvm_emulate_insn_handler(struct trace_seq *s,
+                                   struct pevent_record *record,
+                                   struct event_format *event, void *context)
+{
+       unsigned long long rip, csbase, len, flags, failed;
+       int llen;
+       uint8_t *insn;
+       const char *disasm;
+
+       if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0)
+               return -1;
+
+       if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
+               return -1;
+
+       if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0)
+               return -1;
+
+       if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0)
+               return -1;
+
+       if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0)
+               return -1;
+
+       insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1);
+       if (!insn)
+               return -1;
+
+       disasm = disassemble(insn, len, rip,
+                            flags & KVM_EMUL_INSN_F_CR0_PE,
+                            flags & KVM_EMUL_INSN_F_EFL_VM,
+                            flags & KVM_EMUL_INSN_F_CS_D,
+                            flags & KVM_EMUL_INSN_F_CS_L);
+
+       trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm,
+                        failed ? " FAIL" : "");
+       return 0;
+}
+
+union kvm_mmu_page_role {
+       unsigned word;
+       struct {
+               unsigned glevels:4;
+               unsigned level:4;
+               unsigned quadrant:2;
+               unsigned pad_for_nice_hex_output:6;
+               unsigned direct:1;
+               unsigned access:3;
+               unsigned invalid:1;
+               unsigned cr4_pge:1;
+               unsigned nxe:1;
+       };
+};
+
+static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
+                             struct event_format *event, void *context)
+{
+       unsigned long long val;
+       static const char *access_str[] = {
+               "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux"
+       };
+       union kvm_mmu_page_role role;
+
+       if (pevent_get_field_val(s, event, "role", record, &val, 1) < 0)
+               return -1;
+
+       role.word = (int)val;
+
+       /*
+        * We can only use the structure if file is of the same
+        * endianess.
+        */
+       if (pevent_is_file_bigendian(event->pevent) ==
+           pevent_is_host_bigendian(event->pevent)) {
+
+               trace_seq_printf(s, "%u/%u q%u%s %s%s %spge %snxe",
+                                role.level,
+                                role.glevels,
+                                role.quadrant,
+                                role.direct ? " direct" : "",
+                                access_str[role.access],
+                                role.invalid ? " invalid" : "",
+                                role.cr4_pge ? "" : "!",
+                                role.nxe ? "" : "!");
+       } else
+               trace_seq_printf(s, "WORD: %08x", role.word);
+
+       pevent_print_num_field(s, " root %u ",  event,
+                              "root_count", record, 1);
+
+       if (pevent_get_field_val(s, event, "unsync", record, &val, 1) < 0)
+               return -1;
+
+       trace_seq_printf(s, "%s%c",  val ? "unsync" : "sync", 0);
+       return 0;
+}
+
+static int kvm_mmu_get_page_handler(struct trace_seq *s,
+                                   struct pevent_record *record,
+                                   struct event_format *event, void *context)
+{
+       unsigned long long val;
+
+       if (pevent_get_field_val(s, event, "created", record, &val, 1) < 0)
+               return -1;
+
+       trace_seq_printf(s, "%s ", val ? "new" : "existing");
+
+       if (pevent_get_field_val(s, event, "gfn", record, &val, 1) < 0)
+               return -1;
+
+       trace_seq_printf(s, "sp gfn %llx ", val);
+       return kvm_mmu_print_role(s, record, event, context);
+}
+
+#define PT_WRITABLE_SHIFT 1
+#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT)
+
+static unsigned long long
+process_is_writable_pte(struct trace_seq *s, unsigned long long *args)
+{
+       unsigned long pte = args[0];
+       return pte & PT_WRITABLE_MASK;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       init_disassembler();
+
+       pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit",
+                                     kvm_exit_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
+                                     kvm_emulate_insn_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
+                                     kvm_mmu_get_page_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
+                                     kvm_mmu_print_role, NULL);
+
+       pevent_register_event_handler(pevent, -1,
+                                     "kvmmmu", "kvm_mmu_unsync_page",
+                                     kvm_mmu_print_role, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
+                                     kvm_mmu_print_role, NULL);
+
+       pevent_register_event_handler(pevent, -1, "kvmmmu",
+                       "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
+                       NULL);
+
+       pevent_register_print_function(pevent,
+                                      process_is_writable_pte,
+                                      PEVENT_FUNC_ARG_INT,
+                                      "is_writable_pte",
+                                      PEVENT_FUNC_ARG_LONG,
+                                      PEVENT_FUNC_ARG_VOID);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_exit",
+                                       kvm_exit_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
+                                       kvm_emulate_insn_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
+                                       kvm_mmu_get_page_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
+                                       kvm_mmu_print_role, NULL);
+
+       pevent_unregister_event_handler(pevent, -1,
+                                       "kvmmmu", "kvm_mmu_unsync_page",
+                                       kvm_mmu_print_role, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
+                                       kvm_mmu_print_role, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "kvmmmu",
+                       "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
+                       NULL);
+
+       pevent_unregister_print_function(pevent, process_is_writable_pte,
+                                        "is_writable_pte");
+}
diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c
new file mode 100644 (file)
index 0000000..7e15a0f
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2009 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event-parse.h"
+
+#define INDENT 65
+
+static void print_string(struct trace_seq *s, struct event_format *event,
+                        const char *name, const void *data)
+{
+       struct format_field *f = pevent_find_field(event, name);
+       int offset;
+       int length;
+
+       if (!f) {
+               trace_seq_printf(s, "NOTFOUND:%s", name);
+               return;
+       }
+
+       offset = f->offset;
+       length = f->size;
+
+       if (!strncmp(f->type, "__data_loc", 10)) {
+               unsigned long long v;
+               if (pevent_read_number_field(f, data, &v)) {
+                       trace_seq_printf(s, "invalid_data_loc");
+                       return;
+               }
+               offset = v & 0xffff;
+               length = v >> 16;
+       }
+
+       trace_seq_printf(s, "%.*s", length, (char *)data + offset);
+}
+
+#define SF(fn) pevent_print_num_field(s, fn ":%d", event, fn, record, 0)
+#define SFX(fn)        pevent_print_num_field(s, fn ":%#x", event, fn, record, 0)
+#define SP()   trace_seq_putc(s, ' ')
+
+static int drv_bss_info_changed(struct trace_seq *s,
+                               struct pevent_record *record,
+                               struct event_format *event, void *context)
+{
+       void *data = record->data;
+
+       print_string(s, event, "wiphy_name", data);
+       trace_seq_printf(s, " vif:");
+       print_string(s, event, "vif_name", data);
+       pevent_print_num_field(s, "(%d)", event, "vif_type", record, 1);
+
+       trace_seq_printf(s, "\n%*s", INDENT, "");
+       SF("assoc"); SP();
+       SF("aid"); SP();
+       SF("cts"); SP();
+       SF("shortpre"); SP();
+       SF("shortslot"); SP();
+       SF("dtimper"); SP();
+       trace_seq_printf(s, "\n%*s", INDENT, "");
+       SF("bcnint"); SP();
+       SFX("assoc_cap"); SP();
+       SFX("basic_rates"); SP();
+       SF("enable_beacon");
+       trace_seq_printf(s, "\n%*s", INDENT, "");
+       SF("ht_operation_mode");
+
+       return 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_event_handler(pevent, -1, "mac80211",
+                                     "drv_bss_info_changed",
+                                     drv_bss_info_changed, NULL);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_event_handler(pevent, -1, "mac80211",
+                                       "drv_bss_info_changed",
+                                       drv_bss_info_changed, NULL);
+}
diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c
new file mode 100644 (file)
index 0000000..f1ce600
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event-parse.h"
+
+static void write_state(struct trace_seq *s, int val)
+{
+       const char states[] = "SDTtZXxW";
+       int found = 0;
+       int i;
+
+       for (i = 0; i < (sizeof(states) - 1); i++) {
+               if (!(val & (1 << i)))
+                       continue;
+
+               if (found)
+                       trace_seq_putc(s, '|');
+
+               found = 1;
+               trace_seq_putc(s, states[i]);
+       }
+
+       if (!found)
+               trace_seq_putc(s, 'R');
+}
+
+static void write_and_save_comm(struct format_field *field,
+                               struct pevent_record *record,
+                               struct trace_seq *s, int pid)
+{
+       const char *comm;
+       int len;
+
+       comm = (char *)(record->data + field->offset);
+       len = s->len;
+       trace_seq_printf(s, "%.*s",
+                        field->size, comm);
+
+       /* make sure the comm has a \0 at the end. */
+       trace_seq_terminate(s);
+       comm = &s->buffer[len];
+
+       /* Help out the comm to ids. This will handle dups */
+       pevent_register_comm(field->event->pevent, comm, pid);
+}
+
+static int sched_wakeup_handler(struct trace_seq *s,
+                               struct pevent_record *record,
+                               struct event_format *event, void *context)
+{
+       struct format_field *field;
+       unsigned long long val;
+
+       if (pevent_get_field_val(s, event, "pid", record, &val, 1))
+               return trace_seq_putc(s, '!');
+
+       field = pevent_find_any_field(event, "comm");
+       if (field) {
+               write_and_save_comm(field, record, s, val);
+               trace_seq_putc(s, ':');
+       }
+       trace_seq_printf(s, "%lld", val);
+
+       if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0)
+               trace_seq_printf(s, " [%lld]", val);
+
+       if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0)
+               trace_seq_printf(s, " success=%lld", val);
+
+       if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0)
+               trace_seq_printf(s, " CPU:%03llu", val);
+
+       return 0;
+}
+
+static int sched_switch_handler(struct trace_seq *s,
+                               struct pevent_record *record,
+                               struct event_format *event, void *context)
+{
+       struct format_field *field;
+       unsigned long long val;
+
+       if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1))
+               return trace_seq_putc(s, '!');
+
+       field = pevent_find_any_field(event, "prev_comm");
+       if (field) {
+               write_and_save_comm(field, record, s, val);
+               trace_seq_putc(s, ':');
+       }
+       trace_seq_printf(s, "%lld ", val);
+
+       if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
+               trace_seq_printf(s, "[%lld] ", val);
+
+       if (pevent_get_field_val(s,  event, "prev_state", record, &val, 0) == 0)
+               write_state(s, val);
+
+       trace_seq_puts(s, " ==> ");
+
+       if (pevent_get_field_val(s, event, "next_pid", record, &val, 1))
+               return trace_seq_putc(s, '!');
+
+       field = pevent_find_any_field(event, "next_comm");
+       if (field) {
+               write_and_save_comm(field, record, s, val);
+               trace_seq_putc(s, ':');
+       }
+       trace_seq_printf(s, "%lld", val);
+
+       if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
+               trace_seq_printf(s, " [%lld]", val);
+
+       return 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_event_handler(pevent, -1, "sched", "sched_switch",
+                                     sched_switch_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup",
+                                     sched_wakeup_handler, NULL);
+
+       pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup_new",
+                                     sched_wakeup_handler, NULL);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_event_handler(pevent, -1, "sched", "sched_switch",
+                                       sched_switch_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup",
+                                       sched_wakeup_handler, NULL);
+
+       pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new",
+                                       sched_wakeup_handler, NULL);
+}
diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c
new file mode 100644 (file)
index 0000000..eda326f
--- /dev/null
@@ -0,0 +1,429 @@
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "event-parse.h"
+
+typedef unsigned long sector_t;
+typedef uint64_t u64;
+typedef unsigned int u32;
+
+/*
+ *      SCSI opcodes
+ */
+#define TEST_UNIT_READY                        0x00
+#define REZERO_UNIT                    0x01
+#define REQUEST_SENSE                  0x03
+#define FORMAT_UNIT                    0x04
+#define READ_BLOCK_LIMITS              0x05
+#define REASSIGN_BLOCKS                        0x07
+#define INITIALIZE_ELEMENT_STATUS      0x07
+#define READ_6                         0x08
+#define WRITE_6                                0x0a
+#define SEEK_6                         0x0b
+#define READ_REVERSE                   0x0f
+#define WRITE_FILEMARKS                        0x10
+#define SPACE                          0x11
+#define INQUIRY                                0x12
+#define RECOVER_BUFFERED_DATA          0x14
+#define MODE_SELECT                    0x15
+#define RESERVE                                0x16
+#define RELEASE                                0x17
+#define COPY                           0x18
+#define ERASE                          0x19
+#define MODE_SENSE                     0x1a
+#define START_STOP                     0x1b
+#define RECEIVE_DIAGNOSTIC             0x1c
+#define SEND_DIAGNOSTIC                        0x1d
+#define ALLOW_MEDIUM_REMOVAL           0x1e
+
+#define READ_FORMAT_CAPACITIES         0x23
+#define SET_WINDOW                     0x24
+#define READ_CAPACITY                  0x25
+#define READ_10                                0x28
+#define WRITE_10                       0x2a
+#define SEEK_10                                0x2b
+#define POSITION_TO_ELEMENT            0x2b
+#define WRITE_VERIFY                   0x2e
+#define VERIFY                         0x2f
+#define SEARCH_HIGH                    0x30
+#define SEARCH_EQUAL                   0x31
+#define SEARCH_LOW                     0x32
+#define SET_LIMITS                     0x33
+#define PRE_FETCH                      0x34
+#define READ_POSITION                  0x34
+#define SYNCHRONIZE_CACHE              0x35
+#define LOCK_UNLOCK_CACHE              0x36
+#define READ_DEFECT_DATA               0x37
+#define MEDIUM_SCAN                    0x38
+#define COMPARE                                0x39
+#define COPY_VERIFY                    0x3a
+#define WRITE_BUFFER                   0x3b
+#define READ_BUFFER                    0x3c
+#define UPDATE_BLOCK                   0x3d
+#define READ_LONG                      0x3e
+#define WRITE_LONG                     0x3f
+#define CHANGE_DEFINITION              0x40
+#define WRITE_SAME                     0x41
+#define UNMAP                          0x42
+#define READ_TOC                       0x43
+#define READ_HEADER                    0x44
+#define GET_EVENT_STATUS_NOTIFICATION  0x4a
+#define LOG_SELECT                     0x4c
+#define LOG_SENSE                      0x4d
+#define XDWRITEREAD_10                 0x53
+#define MODE_SELECT_10                 0x55
+#define RESERVE_10                     0x56
+#define RELEASE_10                     0x57
+#define MODE_SENSE_10                  0x5a
+#define PERSISTENT_RESERVE_IN          0x5e
+#define PERSISTENT_RESERVE_OUT         0x5f
+#define VARIABLE_LENGTH_CMD            0x7f
+#define REPORT_LUNS                    0xa0
+#define SECURITY_PROTOCOL_IN           0xa2
+#define MAINTENANCE_IN                 0xa3
+#define MAINTENANCE_OUT                        0xa4
+#define MOVE_MEDIUM                    0xa5
+#define EXCHANGE_MEDIUM                        0xa6
+#define READ_12                                0xa8
+#define WRITE_12                       0xaa
+#define READ_MEDIA_SERIAL_NUMBER       0xab
+#define WRITE_VERIFY_12                        0xae
+#define VERIFY_12                      0xaf
+#define SEARCH_HIGH_12                 0xb0
+#define SEARCH_EQUAL_12                        0xb1
+#define SEARCH_LOW_12                  0xb2
+#define SECURITY_PROTOCOL_OUT          0xb5
+#define READ_ELEMENT_STATUS            0xb8
+#define SEND_VOLUME_TAG                        0xb6
+#define WRITE_LONG_2                   0xea
+#define EXTENDED_COPY                  0x83
+#define RECEIVE_COPY_RESULTS           0x84
+#define ACCESS_CONTROL_IN              0x86
+#define ACCESS_CONTROL_OUT             0x87
+#define READ_16                                0x88
+#define WRITE_16                       0x8a
+#define READ_ATTRIBUTE                 0x8c
+#define WRITE_ATTRIBUTE                        0x8d
+#define VERIFY_16                      0x8f
+#define SYNCHRONIZE_CACHE_16           0x91
+#define WRITE_SAME_16                  0x93
+#define SERVICE_ACTION_IN              0x9e
+/* values for service action in */
+#define        SAI_READ_CAPACITY_16            0x10
+#define SAI_GET_LBA_STATUS             0x12
+/* values for VARIABLE_LENGTH_CMD service action codes
+ * see spc4r17 Section D.3.5, table D.7 and D.8 */
+#define VLC_SA_RECEIVE_CREDENTIAL      0x1800
+/* values for maintenance in */
+#define MI_REPORT_IDENTIFYING_INFORMATION              0x05
+#define MI_REPORT_TARGET_PGS                           0x0a
+#define MI_REPORT_ALIASES                              0x0b
+#define MI_REPORT_SUPPORTED_OPERATION_CODES            0x0c
+#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS  0x0d
+#define MI_REPORT_PRIORITY                             0x0e
+#define MI_REPORT_TIMESTAMP                            0x0f
+#define MI_MANAGEMENT_PROTOCOL_IN                      0x10
+/* value for MI_REPORT_TARGET_PGS ext header */
+#define MI_EXT_HDR_PARAM_FMT           0x20
+/* values for maintenance out */
+#define MO_SET_IDENTIFYING_INFORMATION 0x06
+#define MO_SET_TARGET_PGS              0x0a
+#define MO_CHANGE_ALIASES              0x0b
+#define MO_SET_PRIORITY                        0x0e
+#define MO_SET_TIMESTAMP               0x0f
+#define MO_MANAGEMENT_PROTOCOL_OUT     0x10
+/* values for variable length command */
+#define XDREAD_32                      0x03
+#define XDWRITE_32                     0x04
+#define XPWRITE_32                     0x06
+#define XDWRITEREAD_32                 0x07
+#define READ_32                                0x09
+#define VERIFY_32                      0x0a
+#define WRITE_32                       0x0b
+#define WRITE_SAME_32                  0x0d
+
+#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
+#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9])
+
+static const char *
+scsi_trace_misc(struct trace_seq *, unsigned char *, int);
+
+static const char *
+scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len;
+       sector_t lba = 0, txlen = 0;
+
+       lba |= ((cdb[1] & 0x1F) << 16);
+       lba |=  (cdb[2] << 8);
+       lba |=   cdb[3];
+       txlen = cdb[4];
+
+       trace_seq_printf(p, "lba=%llu txlen=%llu",
+                        (unsigned long long)lba, (unsigned long long)txlen);
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len;
+       sector_t lba = 0, txlen = 0;
+
+       lba |= (cdb[2] << 24);
+       lba |= (cdb[3] << 16);
+       lba |= (cdb[4] << 8);
+       lba |=  cdb[5];
+       txlen |= (cdb[7] << 8);
+       txlen |=  cdb[8];
+
+       trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
+                        (unsigned long long)lba, (unsigned long long)txlen,
+                        cdb[1] >> 5);
+
+       if (cdb[0] == WRITE_SAME)
+               trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
+
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len;
+       sector_t lba = 0, txlen = 0;
+
+       lba |= (cdb[2] << 24);
+       lba |= (cdb[3] << 16);
+       lba |= (cdb[4] << 8);
+       lba |=  cdb[5];
+       txlen |= (cdb[6] << 24);
+       txlen |= (cdb[7] << 16);
+       txlen |= (cdb[8] << 8);
+       txlen |=  cdb[9];
+
+       trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
+                        (unsigned long long)lba, (unsigned long long)txlen,
+                        cdb[1] >> 5);
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len;
+       sector_t lba = 0, txlen = 0;
+
+       lba |= ((u64)cdb[2] << 56);
+       lba |= ((u64)cdb[3] << 48);
+       lba |= ((u64)cdb[4] << 40);
+       lba |= ((u64)cdb[5] << 32);
+       lba |= (cdb[6] << 24);
+       lba |= (cdb[7] << 16);
+       lba |= (cdb[8] << 8);
+       lba |=  cdb[9];
+       txlen |= (cdb[10] << 24);
+       txlen |= (cdb[11] << 16);
+       txlen |= (cdb[12] << 8);
+       txlen |=  cdb[13];
+
+       trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
+                        (unsigned long long)lba, (unsigned long long)txlen,
+                        cdb[1] >> 5);
+
+       if (cdb[0] == WRITE_SAME_16)
+               trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
+
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len, *cmd;
+       sector_t lba = 0, txlen = 0;
+       u32 ei_lbrt = 0;
+
+       switch (SERVICE_ACTION32(cdb)) {
+       case READ_32:
+               cmd = "READ";
+               break;
+       case VERIFY_32:
+               cmd = "VERIFY";
+               break;
+       case WRITE_32:
+               cmd = "WRITE";
+               break;
+       case WRITE_SAME_32:
+               cmd = "WRITE_SAME";
+               break;
+       default:
+               trace_seq_printf(p, "UNKNOWN");
+               goto out;
+       }
+
+       lba |= ((u64)cdb[12] << 56);
+       lba |= ((u64)cdb[13] << 48);
+       lba |= ((u64)cdb[14] << 40);
+       lba |= ((u64)cdb[15] << 32);
+       lba |= (cdb[16] << 24);
+       lba |= (cdb[17] << 16);
+       lba |= (cdb[18] << 8);
+       lba |=  cdb[19];
+       ei_lbrt |= (cdb[20] << 24);
+       ei_lbrt |= (cdb[21] << 16);
+       ei_lbrt |= (cdb[22] << 8);
+       ei_lbrt |=  cdb[23];
+       txlen |= (cdb[28] << 24);
+       txlen |= (cdb[29] << 16);
+       txlen |= (cdb[30] << 8);
+       txlen |=  cdb[31];
+
+       trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u",
+                        cmd, (unsigned long long)lba,
+                        (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt);
+
+       if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
+               trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
+
+out:
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len;
+       unsigned int regions = cdb[7] << 8 | cdb[8];
+
+       trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len, *cmd;
+       sector_t lba = 0;
+       u32 alloc_len = 0;
+
+       switch (SERVICE_ACTION16(cdb)) {
+       case SAI_READ_CAPACITY_16:
+               cmd = "READ_CAPACITY_16";
+               break;
+       case SAI_GET_LBA_STATUS:
+               cmd = "GET_LBA_STATUS";
+               break;
+       default:
+               trace_seq_printf(p, "UNKNOWN");
+               goto out;
+       }
+
+       lba |= ((u64)cdb[2] << 56);
+       lba |= ((u64)cdb[3] << 48);
+       lba |= ((u64)cdb[4] << 40);
+       lba |= ((u64)cdb[5] << 32);
+       lba |= (cdb[6] << 24);
+       lba |= (cdb[7] << 16);
+       lba |= (cdb[8] << 8);
+       lba |=  cdb[9];
+       alloc_len |= (cdb[10] << 24);
+       alloc_len |= (cdb[11] << 16);
+       alloc_len |= (cdb[12] << 8);
+       alloc_len |=  cdb[13];
+
+       trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd,
+                        (unsigned long long)lba, alloc_len);
+
+out:
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+static const char *
+scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       switch (SERVICE_ACTION32(cdb)) {
+       case READ_32:
+       case VERIFY_32:
+       case WRITE_32:
+       case WRITE_SAME_32:
+               return scsi_trace_rw32(p, cdb, len);
+       default:
+               return scsi_trace_misc(p, cdb, len);
+       }
+}
+
+static const char *
+scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       const char *ret = p->buffer + p->len;
+
+       trace_seq_printf(p, "-");
+       trace_seq_putc(p, 0);
+       return ret;
+}
+
+const char *
+scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
+{
+       switch (cdb[0]) {
+       case READ_6:
+       case WRITE_6:
+               return scsi_trace_rw6(p, cdb, len);
+       case READ_10:
+       case VERIFY:
+       case WRITE_10:
+       case WRITE_SAME:
+               return scsi_trace_rw10(p, cdb, len);
+       case READ_12:
+       case VERIFY_12:
+       case WRITE_12:
+               return scsi_trace_rw12(p, cdb, len);
+       case READ_16:
+       case VERIFY_16:
+       case WRITE_16:
+       case WRITE_SAME_16:
+               return scsi_trace_rw16(p, cdb, len);
+       case UNMAP:
+               return scsi_trace_unmap(p, cdb, len);
+       case SERVICE_ACTION_IN:
+               return scsi_trace_service_action_in(p, cdb, len);
+       case VARIABLE_LENGTH_CMD:
+               return scsi_trace_varlen(p, cdb, len);
+       default:
+               return scsi_trace_misc(p, cdb, len);
+       }
+}
+
+unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s,
+                                               unsigned long long *args)
+{
+       scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]);
+       return 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_print_function(pevent,
+                                      process_scsi_trace_parse_cdb,
+                                      PEVENT_FUNC_ARG_STRING,
+                                      "scsi_trace_parse_cdb",
+                                      PEVENT_FUNC_ARG_PTR,
+                                      PEVENT_FUNC_ARG_PTR,
+                                      PEVENT_FUNC_ARG_INT,
+                                      PEVENT_FUNC_ARG_VOID);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_print_function(pevent, process_scsi_trace_parse_cdb,
+                                        "scsi_trace_parse_cdb");
+}
diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c
new file mode 100644 (file)
index 0000000..3a413ea
--- /dev/null
@@ -0,0 +1,136 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "event-parse.h"
+
+#define __HYPERVISOR_set_trap_table                    0
+#define __HYPERVISOR_mmu_update                                1
+#define __HYPERVISOR_set_gdt                           2
+#define __HYPERVISOR_stack_switch                      3
+#define __HYPERVISOR_set_callbacks                     4
+#define __HYPERVISOR_fpu_taskswitch                    5
+#define __HYPERVISOR_sched_op_compat                   6
+#define __HYPERVISOR_dom0_op                           7
+#define __HYPERVISOR_set_debugreg                      8
+#define __HYPERVISOR_get_debugreg                      9
+#define __HYPERVISOR_update_descriptor                 10
+#define __HYPERVISOR_memory_op                         12
+#define __HYPERVISOR_multicall                         13
+#define __HYPERVISOR_update_va_mapping                 14
+#define __HYPERVISOR_set_timer_op                      15
+#define __HYPERVISOR_event_channel_op_compat           16
+#define __HYPERVISOR_xen_version                       17
+#define __HYPERVISOR_console_io                                18
+#define __HYPERVISOR_physdev_op_compat                 19
+#define __HYPERVISOR_grant_table_op                    20
+#define __HYPERVISOR_vm_assist                         21
+#define __HYPERVISOR_update_va_mapping_otherdomain     22
+#define __HYPERVISOR_iret                              23 /* x86 only */
+#define __HYPERVISOR_vcpu_op                           24
+#define __HYPERVISOR_set_segment_base                  25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op                         26
+#define __HYPERVISOR_acm_op                            27
+#define __HYPERVISOR_nmi_op                            28
+#define __HYPERVISOR_sched_op                          29
+#define __HYPERVISOR_callback_op                       30
+#define __HYPERVISOR_xenoprof_op                       31
+#define __HYPERVISOR_event_channel_op                  32
+#define __HYPERVISOR_physdev_op                                33
+#define __HYPERVISOR_hvm_op                            34
+#define __HYPERVISOR_tmem_op                           38
+
+/* Architecture-specific hypercall definitions. */
+#define __HYPERVISOR_arch_0                            48
+#define __HYPERVISOR_arch_1                            49
+#define __HYPERVISOR_arch_2                            50
+#define __HYPERVISOR_arch_3                            51
+#define __HYPERVISOR_arch_4                            52
+#define __HYPERVISOR_arch_5                            53
+#define __HYPERVISOR_arch_6                            54
+#define __HYPERVISOR_arch_7                            55
+
+#define N(x)   [__HYPERVISOR_##x] = "("#x")"
+static const char *xen_hypercall_names[] = {
+       N(set_trap_table),
+       N(mmu_update),
+       N(set_gdt),
+       N(stack_switch),
+       N(set_callbacks),
+       N(fpu_taskswitch),
+       N(sched_op_compat),
+       N(dom0_op),
+       N(set_debugreg),
+       N(get_debugreg),
+       N(update_descriptor),
+       N(memory_op),
+       N(multicall),
+       N(update_va_mapping),
+       N(set_timer_op),
+       N(event_channel_op_compat),
+       N(xen_version),
+       N(console_io),
+       N(physdev_op_compat),
+       N(grant_table_op),
+       N(vm_assist),
+       N(update_va_mapping_otherdomain),
+       N(iret),
+       N(vcpu_op),
+       N(set_segment_base),
+       N(mmuext_op),
+       N(acm_op),
+       N(nmi_op),
+       N(sched_op),
+       N(callback_op),
+       N(xenoprof_op),
+       N(event_channel_op),
+       N(physdev_op),
+       N(hvm_op),
+
+/* Architecture-specific hypercall definitions. */
+       N(arch_0),
+       N(arch_1),
+       N(arch_2),
+       N(arch_3),
+       N(arch_4),
+       N(arch_5),
+       N(arch_6),
+       N(arch_7),
+};
+#undef N
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static const char *xen_hypercall_name(unsigned op)
+{
+       if (op < ARRAY_SIZE(xen_hypercall_names) &&
+           xen_hypercall_names[op] != NULL)
+               return xen_hypercall_names[op];
+
+       return "";
+}
+
+unsigned long long process_xen_hypercall_name(struct trace_seq *s,
+                                             unsigned long long *args)
+{
+       unsigned int op = args[0];
+
+       trace_seq_printf(s, "%s", xen_hypercall_name(op));
+       return 0;
+}
+
+int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+{
+       pevent_register_print_function(pevent,
+                                      process_xen_hypercall_name,
+                                      PEVENT_FUNC_ARG_STRING,
+                                      "xen_hypercall_name",
+                                      PEVENT_FUNC_ARG_INT,
+                                      PEVENT_FUNC_ARG_VOID);
+       return 0;
+}
+
+void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+{
+       pevent_unregister_print_function(pevent, process_xen_hypercall_name,
+                                        "xen_hypercall_name");
+}
index d7f2e68bc5b91d190e2ad5cd34388b45d957372a..ec3bd16a548881252d482e3f09e499a9bd12898d 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <stdarg.h>
 
+#include <asm/bug.h>
 #include "event-parse.h"
 #include "event-utils.h"
 
 #define TRACE_SEQ_POISON       ((void *)0xdeadbeef)
 #define TRACE_SEQ_CHECK(s)                                             \
 do {                                                                   \
-       if ((s)->buffer == TRACE_SEQ_POISON)                    \
-               die("Usage of trace_seq after it was destroyed");       \
+       if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON,                  \
+                     "Usage of trace_seq after it was destroyed"))     \
+               (s)->state = TRACE_SEQ__BUFFER_POISONED;                \
 } while (0)
 
+#define TRACE_SEQ_CHECK_RET_N(s, n)            \
+do {                                           \
+       TRACE_SEQ_CHECK(s);                     \
+       if ((s)->state != TRACE_SEQ__GOOD)      \
+               return n;                       \
+} while (0)
+
+#define TRACE_SEQ_CHECK_RET(s)   TRACE_SEQ_CHECK_RET_N(s, )
+#define TRACE_SEQ_CHECK_RET0(s)  TRACE_SEQ_CHECK_RET_N(s, 0)
+
 /**
  * trace_seq_init - initialize the trace_seq structure
  * @s: a pointer to the trace_seq structure to initialize
@@ -45,7 +57,11 @@ void trace_seq_init(struct trace_seq *s)
        s->len = 0;
        s->readpos = 0;
        s->buffer_size = TRACE_SEQ_BUF_SIZE;
-       s->buffer = malloc_or_die(s->buffer_size);
+       s->buffer = malloc(s->buffer_size);
+       if (s->buffer != NULL)
+               s->state = TRACE_SEQ__GOOD;
+       else
+               s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
 }
 
 /**
@@ -71,17 +87,23 @@ void trace_seq_destroy(struct trace_seq *s)
 {
        if (!s)
                return;
-       TRACE_SEQ_CHECK(s);
+       TRACE_SEQ_CHECK_RET(s);
        free(s->buffer);
        s->buffer = TRACE_SEQ_POISON;
 }
 
 static void expand_buffer(struct trace_seq *s)
 {
+       char *buf;
+
+       buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE);
+       if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) {
+               s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
+               return;
+       }
+
+       s->buffer = buf;
        s->buffer_size += TRACE_SEQ_BUF_SIZE;
-       s->buffer = realloc(s->buffer, s->buffer_size);
-       if (!s->buffer)
-               die("Can't allocate trace_seq buffer memory");
 }
 
 /**
@@ -105,9 +127,9 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
        int len;
        int ret;
 
-       TRACE_SEQ_CHECK(s);
-
  try_again:
+       TRACE_SEQ_CHECK_RET0(s);
+
        len = (s->buffer_size - 1) - s->len;
 
        va_start(ap, fmt);
@@ -141,9 +163,9 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
        int len;
        int ret;
 
-       TRACE_SEQ_CHECK(s);
-
  try_again:
+       TRACE_SEQ_CHECK_RET0(s);
+
        len = (s->buffer_size - 1) - s->len;
 
        ret = vsnprintf(s->buffer + s->len, len, fmt, args);
@@ -172,13 +194,15 @@ int trace_seq_puts(struct trace_seq *s, const char *str)
 {
        int len;
 
-       TRACE_SEQ_CHECK(s);
+       TRACE_SEQ_CHECK_RET0(s);
 
        len = strlen(str);
 
        while (len > ((s->buffer_size - 1) - s->len))
                expand_buffer(s);
 
+       TRACE_SEQ_CHECK_RET0(s);
+
        memcpy(s->buffer + s->len, str, len);
        s->len += len;
 
@@ -187,11 +211,13 @@ int trace_seq_puts(struct trace_seq *s, const char *str)
 
 int trace_seq_putc(struct trace_seq *s, unsigned char c)
 {
-       TRACE_SEQ_CHECK(s);
+       TRACE_SEQ_CHECK_RET0(s);
 
        while (s->len >= (s->buffer_size - 1))
                expand_buffer(s);
 
+       TRACE_SEQ_CHECK_RET0(s);
+
        s->buffer[s->len++] = c;
 
        return 1;
@@ -199,7 +225,7 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c)
 
 void trace_seq_terminate(struct trace_seq *s)
 {
-       TRACE_SEQ_CHECK(s);
+       TRACE_SEQ_CHECK_RET(s);
 
        /* There's always one character left on the buffer */
        s->buffer[s->len] = 0;
@@ -208,5 +234,16 @@ void trace_seq_terminate(struct trace_seq *s)
 int trace_seq_do_printf(struct trace_seq *s)
 {
        TRACE_SEQ_CHECK(s);
-       return printf("%.*s", s->len, s->buffer);
+
+       switch (s->state) {
+       case TRACE_SEQ__GOOD:
+               return printf("%.*s", s->len, s->buffer);
+       case TRACE_SEQ__BUFFER_POISONED:
+               puts("Usage of trace_seq after it was destroyed");
+               break;
+       case TRACE_SEQ__MEM_ALLOC_FAILED:
+               puts("Can't allocate trace_seq buffer memory");
+               break;
+       }
+       return -1;
 }
index 5032a142853ec40d4d4b95e17ec6bf15675e9d76..ac6ecbb3e6699a6cd0e02673cd7bdd7a25d35c01 100644 (file)
@@ -12,9 +12,9 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This command runs runs perf-buildid-list --with-hits, and collects the files
-with the buildids found so that analysis of perf.data contents can be possible
-on another machine.
+This command runs perf-buildid-list --with-hits, and collects the files with the
+buildids found so that analysis of perf.data contents can be possible on another
+machine.
 
 
 SEE ALSO
index 6a06cefe96427453ad3b21e1caf64889f5f9ea55..52276a6d2b750b8026217850aeed36990e8aedf7 100644 (file)
@@ -10,9 +10,9 @@ SYNOPSIS
 [verse]
 'perf kvm' [--host] [--guest] [--guestmount=<path>
        [--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]]
-       {top|record|report|diff|buildid-list}
+       {top|record|report|diff|buildid-list} [<options>]
 'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path>
-       | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat}
+       | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} [<options>]
 'perf kvm stat [record|report|live] [<options>]
 
 DESCRIPTION
@@ -24,10 +24,17 @@ There are a couple of variants of perf kvm:
   of an arbitrary workload.
 
   'perf kvm record <command>' to record the performance counter profile
-  of an arbitrary workload and save it into a perf data file. If both
-  --host and --guest are input, the perf data file name is perf.data.kvm.
-  If there is  no --host but --guest, the file name is perf.data.guest.
-  If there is no --guest but --host, the file name is perf.data.host.
+  of an arbitrary workload and save it into a perf data file. We set the
+  default behavior of perf kvm as --guest, so if neither --host nor --guest
+  is input, the perf data file name is perf.data.guest. If --host is input,
+  the perf data file name is perf.data.kvm. If you want to record data into
+  perf.data.host, please input --host --no-guest. The behaviors are shown as
+  following:
+    Default('')         ->  perf.data.guest
+    --host              ->  perf.data.kvm
+    --guest             ->  perf.data.guest
+    --host --guest      ->  perf.data.kvm
+    --host --no-guest   ->  perf.data.host
 
   'perf kvm report' to display the performance counter profile information
   recorded via perf kvm record.
@@ -37,7 +44,9 @@ There are a couple of variants of perf kvm:
 
   'perf kvm buildid-list' to  display the buildids found in a perf data file,
   so that other tools can be used to fetch packages with matching symbol tables
-  for use by perf report.
+  for use by perf report. As buildid is read from /sys/kernel/notes in os, then
+  if you want to list the buildid for guest, please make sure your perf data file
+  was captured with --guestmount in perf kvm record.
 
   'perf kvm stat <command>' to run a command and gather performance counter
   statistics.
@@ -58,14 +67,14 @@ There are a couple of variants of perf kvm:
 OPTIONS
 -------
 -i::
---input=::
+--input=<path>::
         Input file name.
 -o::
---output::
+--output=<path>::
         Output file name.
---host=::
+--host::
         Collect host side performance profile.
---guest=::
+--guest::
         Collect guest side performance profile.
 --guestmount=<path>::
        Guest os root file system mount directory. Users mounts guest os
@@ -84,6 +93,9 @@ OPTIONS
        kernel module information. Users copy it out from guest os.
 --guestvmlinux=<path>::
        Guest os kernel vmlinux.
+-v::
+--verbose::
+       Be more verbose (show counter open errors, etc).
 
 STAT REPORT OPTIONS
 -------------------
index 43b42c4f4a915ad96be76c737b63feee12925de2..c71b0f36d9e8d45285a5b2b1256876f4d6f27799 100644 (file)
@@ -57,6 +57,8 @@ OPTIONS
 -t::
 --tid=::
         Record events on existing thread ID (comma separated list).
+        This option also disables inheritance by default.  Enable it by adding
+        --inherit.
 
 -u::
 --uid=::
@@ -66,8 +68,7 @@ OPTIONS
 --realtime=::
        Collect data with this RT SCHED_FIFO priority.
 
--D::
---no-delay::
+--no-buffering::
        Collect data without buffering.
 
 -c::
@@ -201,11 +202,16 @@ abort events and some memory events in precise mode on modern Intel CPUs.
 --transaction::
 Record transaction flags for transaction related events.
 
---force-per-cpu::
-Force the use of per-cpu mmaps.  By default, when tasks are specified (i.e. -p,
--t or -u options) per-thread mmaps are created.  This option overrides that and
-forces per-cpu mmaps.  A side-effect of that is that inheritance is
-automatically enabled.  Add the -i option also to disable inheritance.
+--per-thread::
+Use per-thread mmaps.  By default per-cpu mmaps are created.  This option
+overrides that and uses per-thread mmaps.  A side-effect of that is that
+inheritance is automatically disabled.  --per-thread is ignored with a warning
+if combined with -a or -C options.
+
+-D::
+--delay=::
+After starting the program, wait msecs before measuring. This is useful to
+filter out the startup phase of the program, which is often very different.
 
 SEE ALSO
 --------
index 10a2798712511a26616ea618a91130a6ed467345..8eab8a4bdeb8bea5f712b4fe918d65acbce5e19c 100644 (file)
@@ -237,6 +237,15 @@ OPTIONS
        Do not show entries which have an overhead under that percent.
        (Default: 0).
 
+--header::
+       Show header information in the perf.data file.  This includes
+       various information like hostname, OS and perf version, cpu/mem
+       info, perf command line, event list and so on.  Currently only
+       --stdio output supports this feature.
+
+--header-only::
+       Show only perf.data header (forces --stdio).
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-annotate[1]
index e9cbfcddfa3f608ee19b2366802f7f405f78f535..05f9a0a6784cf850a689aa4a5f1daffe2f6bec6c 100644 (file)
@@ -115,7 +115,7 @@ OPTIONS
 -f::
 --fields::
         Comma separated list of fields to print. Options are:
-        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff.
+        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline.
         Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
         e.g., -f sw:comm,tid,time,ip,sym  and -f trace:time,cpu,trace
@@ -203,6 +203,18 @@ OPTIONS
 --show-kernel-path::
        Try to resolve the path of [kernel.kallsyms]
 
+--show-task-events
+       Display task related events (e.g. FORK, COMM, EXIT).
+
+--show-mmap-events
+       Display mmap related events (e.g. MMAP, MMAP2).
+
+--header
+       Show perf.data header.
+
+--header-only
+       Show only perf.data header.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
index 80c7da6732f294782d86c51df8e8ba9225bf1d04..29ee857c09c6a88e2aaeeda589a953840783e3b8 100644 (file)
@@ -133,7 +133,7 @@ use --per-core in addition to -a. (system-wide).  The output includes the
 core number and the number of online logical processors on that physical processor.
 
 -D msecs::
---initial-delay msecs::
+--delay msecs::
 After starting the program, wait msecs before measuring. This is useful to
 filter out the startup phase of the program, which is often very different.
 
index 3ff8bd4f0b4d94163d77231881b462e50bbd4e17..bc5990c33dc0dd3b0e81d3fcd0a9a80c2e1a6ce6 100644 (file)
@@ -8,8 +8,7 @@ perf-timechart - Tool to visualize total system behavior during a workload
 SYNOPSIS
 --------
 [verse]
-'perf timechart' record <command>
-'perf timechart' [<options>]
+'perf timechart' [<timechart options>] {record} [<record options>]
 
 DESCRIPTION
 -----------
@@ -21,8 +20,8 @@ There are two variants of perf timechart:
   'perf timechart' to turn a trace into a Scalable Vector Graphics file,
   that can be viewed with popular SVG viewers such as 'Inkscape'.
 
-OPTIONS
--------
+TIMECHART OPTIONS
+-----------------
 -o::
 --output=::
         Select the output file (default: output.svg)
@@ -35,6 +34,9 @@ OPTIONS
 -P::
 --power-only::
         Only output the CPU power section of the diagram
+-T::
+--tasks-only::
+        Don't output processor state transitions
 -p::
 --process::
         Select the processes to display, by name or PID
@@ -54,6 +56,38 @@ $ perf timechart
 
   Written 10.2 seconds of trace to output.svg.
 
+Record system-wide timechart:
+
+  $ perf timechart record
+
+  then generate timechart and highlight 'gcc' tasks:
+
+  $ perf timechart --highlight gcc
+
+-n::
+--proc-num::
+        Print task info for at least given number of tasks.
+-t::
+--topology::
+        Sort CPUs according to topology.
+--highlight=<duration_nsecs|task_name>::
+       Highlight tasks (using different color) that run more than given
+       duration or tasks with given name. If number is given it's interpreted
+       as number of nanoseconds. If non-numeric string is given it's
+       interpreted as task name.
+
+RECORD OPTIONS
+--------------
+-P::
+--power-only::
+        Record only power-related events
+-T::
+--tasks-only::
+        Record only tasks-related events
+-g::
+--callchain::
+        Do call-graph (stack chain/backtrace) recording
+
 SEE ALSO
 --------
 linkperf:perf-record[1]
index 7de01dd7968898c18e34f40914017ae549a3f618..cdd8d4946dba8f85b6ef6f56062067dd1b2dd622 100644 (file)
@@ -50,7 +50,6 @@ Default is to monitor all CPUS.
 --count-filter=<count>::
        Only display functions with more events than this.
 
--g::
 --group::
         Put the counters into a counter group.
 
@@ -143,12 +142,12 @@ Default is to monitor all CPUS.
 --asm-raw::
        Show raw instruction encoding of assembly instructions.
 
--G::
+-g::
        Enables call-graph (stack chain/backtrace) recording.
 
 --call-graph::
        Setup and enable call-graph (stack chain/backtrace) recording,
-       implies -G.
+       implies -g.
 
 --max-stack::
        Set the stack depth limit when parsing the callchain, anything
index 025de796067c8b1dc1af5dd15595197e50d8db0a..f41572d0dd76125b9ebc4b03fd0beb832192b39d 100644 (file)
@@ -1,7 +1,11 @@
 tools/perf
 tools/scripts
 tools/lib/traceevent
-tools/lib/lk
+tools/lib/api
+tools/lib/symbol/kallsyms.c
+tools/lib/symbol/kallsyms.h
+tools/include/asm/bug.h
+tools/include/linux/compiler.h
 include/linux/const.h
 include/linux/perf_event.h
 include/linux/rbtree.h
index 4835618a5608892054de87d497e45e644fdeb0da..cb2e5868c8e86404729ed8595a53262cb9e88fd7 100644 (file)
@@ -60,8 +60,11 @@ endef
 
 #
 # Needed if no target specified:
+# (Except for tags and TAGS targets. The reason is that the
+# Makefile does not treat tags/TAGS as targets but as files
+# and thus won't rebuilt them once they are in place.)
 #
-all:
+all tags TAGS:
        $(print_msg)
        $(make)
 
@@ -71,9 +74,17 @@ all:
 clean:
        $(make)
 
+#
+# The build-test target is not really parallel, don't print the jobs info:
+#
+build-test:
+       @$(MAKE) -f tests/make --no-print-directory
+
 #
 # All other targets get passed through:
 #
 %:
        $(print_msg)
        $(make)
+
+.PHONY: tags TAGS
index 7fc8f179cae74d08e2cc507031c773009723bb00..7257e7e9e38a5e625f2fa562836ff3793d0275c4 100644 (file)
@@ -76,6 +76,7 @@ $(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
 
 CC = $(CROSS_COMPILE)gcc
 AR = $(CROSS_COMPILE)ar
+PKG_CONFIG = $(CROSS_COMPILE)pkg-config
 
 RM      = rm -f
 LN      = ln -f
@@ -86,7 +87,7 @@ FLEX    = flex
 BISON   = bison
 STRIP   = strip
 
-LK_DIR          = $(srctree)/tools/lib/lk/
+LIB_DIR          = $(srctree)/tools/lib/api/
 TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
 
 # include config/Makefile by default and rule out
@@ -105,7 +106,7 @@ ifeq ($(config),1)
 include config/Makefile
 endif
 
-export prefix bindir sharedir sysconfdir
+export prefix bindir sharedir sysconfdir DESTDIR
 
 # sparse is architecture-neutral, which means that we need to tell it
 # explicitly what architecture to check for. Fix this up for yours..
@@ -127,20 +128,20 @@ strip-libs = $(filter-out -l%,$(1))
 ifneq ($(OUTPUT),)
   TE_PATH=$(OUTPUT)
 ifneq ($(subdir),)
-  LK_PATH=$(OUTPUT)/../lib/lk/
+  LIB_PATH=$(OUTPUT)/../lib/api/
 else
-  LK_PATH=$(OUTPUT)
+  LIB_PATH=$(OUTPUT)
 endif
 else
   TE_PATH=$(TRACE_EVENT_DIR)
-  LK_PATH=$(LK_DIR)
+  LIB_PATH=$(LIB_DIR)
 endif
 
 LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
 export LIBTRACEEVENT
 
-LIBLK = $(LK_PATH)liblk.a
-export LIBLK
+LIBAPIKFS = $(LIB_PATH)libapikfs.a
+export LIBAPIKFS
 
 # python extension build directories
 PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
@@ -151,7 +152,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
 python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
 
 PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
-PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
+PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS)
 
 $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
        $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
@@ -202,6 +203,7 @@ $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
 
 LIB_FILE=$(OUTPUT)libperf.a
 
+LIB_H += ../lib/symbol/kallsyms.h
 LIB_H += ../../include/uapi/linux/perf_event.h
 LIB_H += ../../include/linux/rbtree.h
 LIB_H += ../../include/linux/list.h
@@ -210,7 +212,7 @@ 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
-LIB_H += util/include/linux/compiler.h
+LIB_H += ../include/linux/compiler.h
 LIB_H += util/include/linux/const.h
 LIB_H += util/include/linux/ctype.h
 LIB_H += util/include/linux/kernel.h
@@ -225,7 +227,7 @@ LIB_H += util/include/linux/string.h
 LIB_H += util/include/linux/types.h
 LIB_H += util/include/linux/linkage.h
 LIB_H += util/include/asm/asm-offsets.h
-LIB_H += util/include/asm/bug.h
+LIB_H += ../include/asm/bug.h
 LIB_H += util/include/asm/byteorder.h
 LIB_H += util/include/asm/hweight.h
 LIB_H += util/include/asm/swab.h
@@ -312,6 +314,7 @@ LIB_OBJS += $(OUTPUT)util/evlist.o
 LIB_OBJS += $(OUTPUT)util/evsel.o
 LIB_OBJS += $(OUTPUT)util/exec_cmd.o
 LIB_OBJS += $(OUTPUT)util/help.o
+LIB_OBJS += $(OUTPUT)util/kallsyms.o
 LIB_OBJS += $(OUTPUT)util/levenshtein.o
 LIB_OBJS += $(OUTPUT)util/parse-options.o
 LIB_OBJS += $(OUTPUT)util/parse-events.o
@@ -353,6 +356,7 @@ LIB_OBJS += $(OUTPUT)util/pmu-bison.o
 LIB_OBJS += $(OUTPUT)util/trace-event-read.o
 LIB_OBJS += $(OUTPUT)util/trace-event-info.o
 LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
+LIB_OBJS += $(OUTPUT)util/trace-event.o
 LIB_OBJS += $(OUTPUT)util/svghelper.o
 LIB_OBJS += $(OUTPUT)util/sort.o
 LIB_OBJS += $(OUTPUT)util/hist.o
@@ -438,7 +442,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
 BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
 
-PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
+PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
 
 # We choose to avoid "if .. else if .. else .. endif endif"
 # because maintaining the nesting to match is a pain.  If
@@ -486,6 +490,7 @@ ifndef NO_SLANG
   LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
   LIB_OBJS += $(OUTPUT)ui/browsers/map.o
   LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/header.o
   LIB_OBJS += $(OUTPUT)ui/tui/setup.o
   LIB_OBJS += $(OUTPUT)ui/tui/util.o
   LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
@@ -671,6 +676,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
 $(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
 
+$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
+       $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
+
 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
@@ -710,26 +718,33 @@ $(LIB_FILE): $(LIB_OBJS)
 # libtraceevent.a
 TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
 
-$(LIBTRACEEVENT): $(TE_SOURCES)
-       $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a
+LIBTRACEEVENT_FLAGS  = $(QUIET_SUBDIR1) O=$(OUTPUT)
+LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)"
+LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
+
+$(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS
+       $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins
 
 $(LIBTRACEEVENT)-clean:
        $(call QUIET_CLEAN, libtraceevent)
        @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
 
-LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch])
+install-traceevent-plugins: $(LIBTRACEEVENT)
+       $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
+
+LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch])
 
 # if subdir is set, we've been called from above so target has been built
 # already
-$(LIBLK): $(LIBLK_SOURCES)
+$(LIBAPIKFS): $(LIBAPIKFS_SOURCES)
 ifeq ($(subdir),)
-       $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
+       $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a
 endif
 
-$(LIBLK)-clean:
+$(LIBAPIKFS)-clean:
 ifeq ($(subdir),)
-       $(call QUIET_CLEAN, liblk)
-       @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null
+       $(call QUIET_CLEAN, libapikfs)
+       @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
 endif
 
 help:
@@ -785,7 +800,7 @@ cscope:
 
 ### Detect prefix changes
 TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
-             $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
+             $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ)
 
 $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
        @FLAGS='$(TRACK_CFLAGS)'; \
@@ -840,16 +855,16 @@ ifndef NO_LIBPYTHON
                $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
                $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
 endif
-       $(call QUIET_INSTALL, bash_completion-script) \
+       $(call QUIET_INSTALL, perf_completion-script) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
-               $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
+               $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
        $(call QUIET_INSTALL, tests) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
                $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
                $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
 
-install: install-bin try-install-man
+install: install-bin try-install-man install-traceevent-plugins
 
 install-python_ext:
        $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
@@ -868,12 +883,11 @@ config-clean:
        $(call QUIET_CLEAN, config)
        @$(MAKE) -C config/feature-checks clean >/dev/null
 
-clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean 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, Documentation)
-       @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
+       $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
        $(python-clean)
 
 #
index aacef07ebf31525227b372e6c40e9a3039c5d580..42faf369211c853f21f87cd037df5e9f4683b4f7 100644 (file)
@@ -154,8 +154,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
                }
                if (lookup_path(buf))
                        goto out;
-               free(buf);
-               buf = NULL;
+               zfree(&buf);
        }
 
        if (!strcmp(arch, "arm"))
index 4087ab19823c2f843c50e18d7b8e5042a079032f..0da603b79b617f6e11699cc133a35e01614edc9d 100644 (file)
@@ -69,15 +69,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
        if (he == NULL)
                return -ENOMEM;
 
-       ret = 0;
-       if (he->ms.sym != NULL) {
-               struct annotation *notes = symbol__annotation(he->ms.sym);
-               if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
-                       return -ENOMEM;
-
-               ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
-       }
-
+       ret = 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);
        return ret;
@@ -188,8 +180,7 @@ find_next:
                         * symbol, free he->ms.sym->src to signal we already
                         * processed this symbol.
                         */
-                       free(notes->src);
-                       notes->src = NULL;
+                       zfree(&notes->src);
                }
        }
 }
@@ -241,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
                perf_session__fprintf_dsos(session, stdout);
 
        total_nr_samples = 0;
-       list_for_each_entry(pos, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, pos) {
                struct hists *hists = &pos->hists;
                u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
 
@@ -373,7 +364,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
 
        if (argc) {
                /*
-                * Special case: if there's an argument left then assume tha
+                * Special case: if there's an argument left then assume that
                 * it's a symbol filter:
                 */
                if (argc > 1)
index 3b67ea2444bd4abf8314ef5c40c7d4b3e731c455..a77e31246c00ba1841a0b8447d97a04302f2ea3b 100644 (file)
@@ -356,9 +356,10 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
 {
        struct perf_evsel *e;
 
-       list_for_each_entry(e, &evlist->entries, node)
+       evlist__for_each(evlist, e) {
                if (perf_evsel__match2(evsel, e))
                        return e;
+       }
 
        return NULL;
 }
@@ -367,7 +368,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                struct hists *hists = &evsel->hists;
 
                hists__collapse_resort(hists, NULL);
@@ -614,7 +615,7 @@ static void data_process(void)
        struct perf_evsel *evsel_base;
        bool first = true;
 
-       list_for_each_entry(evsel_base, &evlist_base->entries, node) {
+       evlist__for_each(evlist_base, evsel_base) {
                struct data__file *d;
                int i;
 
@@ -654,7 +655,7 @@ static void data__free(struct data__file *d)
        for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
                struct diff_hpp_fmt *fmt = &d->fmt[col];
 
-               free(fmt->header);
+               zfree(&fmt->header);
        }
 }
 
@@ -769,6 +770,81 @@ static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
        return ret;
 }
 
+static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
+                               struct perf_hpp *hpp, struct hist_entry *he,
+                               int comparison_method)
+{
+       struct diff_hpp_fmt *dfmt =
+               container_of(fmt, struct diff_hpp_fmt, fmt);
+       struct hist_entry *pair = get_pair_fmt(he, dfmt);
+       double diff;
+       s64 wdiff;
+       char pfmt[20] = " ";
+
+       if (!pair)
+               goto dummy_print;
+
+       switch (comparison_method) {
+       case COMPUTE_DELTA:
+               if (pair->diff.computed)
+                       diff = pair->diff.period_ratio_delta;
+               else
+                       diff = compute_delta(he, pair);
+
+               if (fabs(diff) < 0.01)
+                       goto dummy_print;
+               scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
+               return percent_color_snprintf(hpp->buf, hpp->size,
+                                       pfmt, diff);
+       case COMPUTE_RATIO:
+               if (he->dummy)
+                       goto dummy_print;
+               if (pair->diff.computed)
+                       diff = pair->diff.period_ratio;
+               else
+                       diff = compute_ratio(he, pair);
+
+               scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width);
+               return value_color_snprintf(hpp->buf, hpp->size,
+                                       pfmt, diff);
+       case COMPUTE_WEIGHTED_DIFF:
+               if (he->dummy)
+                       goto dummy_print;
+               if (pair->diff.computed)
+                       wdiff = pair->diff.wdiff;
+               else
+                       wdiff = compute_wdiff(he, pair);
+
+               scnprintf(pfmt, 20, "%%14ld", dfmt->header_width);
+               return color_snprintf(hpp->buf, hpp->size,
+                               get_percent_color(wdiff),
+                               pfmt, wdiff);
+       default:
+               BUG_ON(1);
+       }
+dummy_print:
+       return scnprintf(hpp->buf, hpp->size, "%*s",
+                       dfmt->header_width, pfmt);
+}
+
+static int hpp__color_delta(struct perf_hpp_fmt *fmt,
+                       struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA);
+}
+
+static int hpp__color_ratio(struct perf_hpp_fmt *fmt,
+                       struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO);
+}
+
+static int hpp__color_wdiff(struct perf_hpp_fmt *fmt,
+                       struct perf_hpp *hpp, struct hist_entry *he)
+{
+       return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF);
+}
+
 static void
 hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
 {
@@ -940,8 +1016,22 @@ static void data__hpp_register(struct data__file *d, int idx)
        fmt->entry  = hpp__entry_global;
 
        /* TODO more colors */
-       if (idx == PERF_HPP_DIFF__BASELINE)
+       switch (idx) {
+       case PERF_HPP_DIFF__BASELINE:
                fmt->color = hpp__color_baseline;
+               break;
+       case PERF_HPP_DIFF__DELTA:
+               fmt->color = hpp__color_delta;
+               break;
+       case PERF_HPP_DIFF__RATIO:
+               fmt->color = hpp__color_ratio;
+               break;
+       case PERF_HPP_DIFF__WEIGHTED_DIFF:
+               fmt->color = hpp__color_wdiff;
+               break;
+       default:
+               break;
+       }
 
        init_header(d, dfmt);
        perf_hpp__column_register(fmt);
@@ -1000,8 +1090,7 @@ static int data_init(int argc, const char **argv)
                        data__files_cnt = argc;
                        use_default = false;
                }
-       } else if (symbol_conf.default_guest_vmlinux_name ||
-                  symbol_conf.default_guest_kallsyms) {
+       } else if (perf_guest) {
                defaults[0] = "perf.data.host";
                defaults[1] = "perf.data.guest";
        }
index 20b0f12763b091fd392366865ab113f9aa66a3c7..c99e0de7e54a7549b6d19bf4e6025f5d7daf1198 100644 (file)
@@ -29,7 +29,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
        if (session == NULL)
                return -ENOMEM;
 
-       list_for_each_entry(pos, &session->evlist->entries, node)
+       evlist__for_each(session->evlist, pos)
                perf_evsel__fprintf(pos, details, stdout);
 
        perf_session__delete(session);
index 6a2508589460bfc1fec37c10163cf44b95a2ddfc..b3466018bbd7b514811dd6a5e2bad10ed275eb5b 100644 (file)
 #include <linux/list.h>
 
 struct perf_inject {
-       struct perf_tool tool;
-       bool             build_ids;
-       bool             sched_stat;
-       const char       *input_name;
-       int              pipe_output,
-                        output;
-       u64              bytes_written;
-       struct list_head samples;
+       struct perf_tool        tool;
+       bool                    build_ids;
+       bool                    sched_stat;
+       const char              *input_name;
+       struct perf_data_file   output;
+       u64                     bytes_written;
+       struct list_head        samples;
 };
 
 struct event_entry {
@@ -42,21 +41,14 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
                                    union perf_event *event)
 {
        struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
-       uint32_t size;
-       void *buf = event;
+       ssize_t size;
 
-       size = event->header.size;
-
-       while (size) {
-               int ret = write(inject->output, buf, size);
-               if (ret < 0)
-                       return -errno;
-
-               size -= ret;
-               buf += ret;
-               inject->bytes_written += ret;
-       }
+       size = perf_data_file__write(&inject->output, event,
+                                    event->header.size);
+       if (size < 0)
+               return -errno;
 
+       inject->bytes_written += size;
        return 0;
 }
 
@@ -80,7 +72,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
        if (ret)
                return ret;
 
-       if (!inject->pipe_output)
+       if (&inject->output.is_pipe)
                return 0;
 
        return perf_event__repipe_synth(tool, event);
@@ -355,6 +347,7 @@ static int __cmd_inject(struct perf_inject *inject)
                .path = inject->input_name,
                .mode = PERF_DATA_MODE_READ,
        };
+       struct perf_data_file *file_out = &inject->output;
 
        signal(SIGINT, sig_handler);
 
@@ -376,7 +369,7 @@ static int __cmd_inject(struct perf_inject *inject)
 
                inject->tool.ordered_samples = true;
 
-               list_for_each_entry(evsel, &session->evlist->entries, node) {
+               evlist__for_each(session->evlist, evsel) {
                        const char *name = perf_evsel__name(evsel);
 
                        if (!strcmp(name, "sched:sched_switch")) {
@@ -391,14 +384,14 @@ static int __cmd_inject(struct perf_inject *inject)
                }
        }
 
-       if (!inject->pipe_output)
-               lseek(inject->output, session->header.data_offset, SEEK_SET);
+       if (!file_out->is_pipe)
+               lseek(file_out->fd, session->header.data_offset, SEEK_SET);
 
        ret = perf_session__process_events(session, &inject->tool);
 
-       if (!inject->pipe_output) {
+       if (!file_out->is_pipe) {
                session->header.data_size = inject->bytes_written;
-               perf_session__write_header(session, session->evlist, inject->output, true);
+               perf_session__write_header(session, session->evlist, file_out->fd, true);
        }
 
        perf_session__delete(session);
@@ -427,14 +420,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                },
                .input_name  = "-",
                .samples = LIST_HEAD_INIT(inject.samples),
+               .output = {
+                       .path = "-",
+                       .mode = PERF_DATA_MODE_WRITE,
+               },
        };
-       const char *output_name = "-";
        const struct option options[] = {
                OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
                            "Inject build-ids into the output stream"),
                OPT_STRING('i', "input", &inject.input_name, "file",
                           "input file name"),
-               OPT_STRING('o', "output", &output_name, "file",
+               OPT_STRING('o', "output", &inject.output.path, "file",
                           "output file name"),
                OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
                            "Merge sched-stat and sched-switch for getting events "
@@ -456,16 +452,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
        if (argc)
                usage_with_options(inject_usage, options);
 
-       if (!strcmp(output_name, "-")) {
-               inject.pipe_output = 1;
-               inject.output = STDOUT_FILENO;
-       } else {
-               inject.output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC,
-                                                 S_IRUSR | S_IWUSR);
-               if (inject.output < 0) {
-                       perror("failed to create output file");
-                       return -1;
-               }
+       if (perf_data_file__open(&inject.output)) {
+               perror("failed to create output file");
+               return -1;
        }
 
        if (symbol__init() < 0)
index f8bf5f244d77dded7e19fff4bf2101d859265a6c..a7350519c63f528cfb627d736867742b57b1a2e8 100644 (file)
@@ -13,7 +13,7 @@
 #include "util/parse-options.h"
 #include "util/trace-event.h"
 #include "util/debug.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include "util/tool.h"
 #include "util/stat.h"
 #include "util/top.h"
@@ -89,7 +89,7 @@ struct exit_reasons_table {
 
 struct perf_kvm_stat {
        struct perf_tool    tool;
-       struct perf_record_opts opts;
+       struct record_opts  opts;
        struct perf_evlist  *evlist;
        struct perf_session *session;
 
@@ -1158,9 +1158,7 @@ out:
        if (kvm->timerfd >= 0)
                close(kvm->timerfd);
 
-       if (pollfds)
-               free(pollfds);
-
+       free(pollfds);
        return err;
 }
 
@@ -1176,7 +1174,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
         * Note: exclude_{guest,host} do not apply here.
         *       This command processes KVM tracepoints from host only
         */
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                struct perf_event_attr *attr = &pos->attr;
 
                /* make sure these *are* set */
@@ -1232,7 +1230,7 @@ static int read_events(struct perf_kvm_stat *kvm)
                .ordered_samples        = true,
        };
        struct perf_data_file file = {
-               .path = input_name,
+               .path = kvm->file_name,
                .mode = PERF_DATA_MODE_READ,
        };
 
@@ -1558,10 +1556,8 @@ out:
        if (kvm->session)
                perf_session__delete(kvm->session);
        kvm->session = NULL;
-       if (kvm->evlist) {
-               perf_evlist__delete_maps(kvm->evlist);
+       if (kvm->evlist)
                perf_evlist__delete(kvm->evlist);
-       }
 
        return err;
 }
@@ -1690,6 +1686,8 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
                           "file", "file saving guest os /proc/kallsyms"),
                OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
                           "file", "file saving guest os /proc/modules"),
+               OPT_INCR('v', "verbose", &verbose,
+                           "be more verbose (show counter open errors, etc)"),
                OPT_END()
        };
 
@@ -1711,12 +1709,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
                perf_guest = 1;
 
        if (!file_name) {
-               if (perf_host && !perf_guest)
-                       file_name = strdup("perf.data.host");
-               else if (!perf_host && perf_guest)
-                       file_name = strdup("perf.data.guest");
-               else
-                       file_name = strdup("perf.data.kvm");
+               file_name = get_filename_for_perf_kvm();
 
                if (!file_name) {
                        pr_err("Failed to allocate memory for filename\n");
index 31c00f186da127fa6fca4157d839426886008c07..2e3ade69a58e7f1755ef49de2e47ea819cd9bf60 100644 (file)
@@ -62,7 +62,6 @@ static int
 dump_raw_samples(struct perf_tool *tool,
                 union perf_event *event,
                 struct perf_sample *sample,
-                struct perf_evsel *evsel __maybe_unused,
                 struct machine *machine)
 {
        struct perf_mem *mem = container_of(tool, struct perf_mem, tool);
@@ -112,10 +111,10 @@ dump_raw_samples(struct perf_tool *tool,
 static int process_sample_event(struct perf_tool *tool,
                                union perf_event *event,
                                struct perf_sample *sample,
-                               struct perf_evsel *evsel,
+                               struct perf_evsel *evsel __maybe_unused,
                                struct machine *machine)
 {
-       return dump_raw_samples(tool, event, sample, evsel, machine);
+       return dump_raw_samples(tool, event, sample, machine);
 }
 
 static int report_raw_events(struct perf_mem *mem)
index 6ea9e85bdc00ca02a50735abf0ac304107dd1727..78948882e3de72c9a521f1d3c6d3bff29f2e493d 100644 (file)
@@ -37,7 +37,7 @@
 #include "util/strfilter.h"
 #include "util/symbol.h"
 #include "util/debug.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include "util/parse-options.h"
 #include "util/probe-finder.h"
 #include "util/probe-event.h"
@@ -59,7 +59,7 @@ static struct {
        struct perf_probe_event events[MAX_PROBES];
        struct strlist *dellist;
        struct line_range line_range;
-       const char *target;
+       char *target;
        int max_probe_points;
        struct strfilter *filter;
 } params;
@@ -98,7 +98,10 @@ static int set_target(const char *ptr)
         * short module name.
         */
        if (!params.target && ptr && *ptr == '/') {
-               params.target = ptr;
+               params.target = strdup(ptr);
+               if (!params.target)
+                       return -ENOMEM;
+
                found = 1;
                buf = ptr + (strlen(ptr) - 3);
 
@@ -116,6 +119,9 @@ static int parse_probe_event_argv(int argc, const char **argv)
        char *buf;
 
        found_target = set_target(argv[0]);
+       if (found_target < 0)
+               return found_target;
+
        if (found_target && argc == 1)
                return 0;
 
@@ -169,6 +175,7 @@ static int opt_set_target(const struct option *opt, const char *str,
                        int unset __maybe_unused)
 {
        int ret = -ENOENT;
+       char *tmp;
 
        if  (str && !params.target) {
                if (!strcmp(opt->long_name, "exec"))
@@ -180,7 +187,19 @@ static int opt_set_target(const struct option *opt, const char *str,
                else
                        return ret;
 
-               params.target = str;
+               /* Expand given path to absolute path, except for modulename */
+               if (params.uprobes || strchr(str, '/')) {
+                       tmp = realpath(str, NULL);
+                       if (!tmp) {
+                               pr_warning("Failed to get the absolute path of %s: %m\n", str);
+                               return ret;
+                       }
+               } else {
+                       tmp = strdup(str);
+                       if (!tmp)
+                               return -ENOMEM;
+               }
+               params.target = tmp;
                ret = 0;
        }
 
@@ -204,7 +223,6 @@ static int opt_show_lines(const struct option *opt __maybe_unused,
 
        params.show_lines = true;
        ret = parse_line_range_desc(str, &params.line_range);
-       INIT_LIST_HEAD(&params.line_range.line_list);
 
        return ret;
 }
@@ -250,7 +268,28 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
        return 0;
 }
 
-int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
+static void init_params(void)
+{
+       line_range__init(&params.line_range);
+}
+
+static void cleanup_params(void)
+{
+       int i;
+
+       for (i = 0; i < params.nevents; i++)
+               clear_perf_probe_event(params.events + i);
+       if (params.dellist)
+               strlist__delete(params.dellist);
+       line_range__clear(&params.line_range);
+       free(params.target);
+       if (params.filter)
+               strfilter__delete(params.filter);
+       memset(&params, 0, sizeof(params));
+}
+
+static int
+__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        const char * const probe_usage[] = {
                "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
@@ -404,6 +443,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
                ret = show_available_funcs(params.target, params.filter,
                                        params.uprobes);
                strfilter__delete(params.filter);
+               params.filter = NULL;
                if (ret < 0)
                        pr_err("  Error: Failed to show functions."
                               " (%d)\n", ret);
@@ -411,7 +451,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
        }
 
 #ifdef HAVE_DWARF_SUPPORT
-       if (params.show_lines && !params.uprobes) {
+       if (params.show_lines) {
                if (params.mod_events) {
                        pr_err("  Error: Don't use --line with"
                               " --add/--del.\n");
@@ -443,6 +483,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
                                          params.filter,
                                          params.show_ext_vars);
                strfilter__delete(params.filter);
+               params.filter = NULL;
                if (ret < 0)
                        pr_err("  Error: Failed to show vars. (%d)\n", ret);
                return ret;
@@ -451,7 +492,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 
        if (params.dellist) {
                ret = del_perf_probe_events(params.dellist);
-               strlist__delete(params.dellist);
                if (ret < 0) {
                        pr_err("  Error: Failed to delete events. (%d)\n", ret);
                        return ret;
@@ -470,3 +510,14 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
        }
        return 0;
 }
+
+int cmd_probe(int argc, const char **argv, const char *prefix)
+{
+       int ret;
+
+       init_params();
+       ret = __cmd_probe(argc, argv, prefix);
+       cleanup_params();
+
+       return ret;
+}
index 7c8020a32784abcd6d44223dc3a5586f7ba7f3f0..3c394bf16fa8cd86ce01d3d5852bab8a078f5ae4 100644 (file)
@@ -62,9 +62,9 @@ static void __handle_on_exit_funcs(void)
 }
 #endif
 
-struct perf_record {
+struct record {
        struct perf_tool        tool;
-       struct perf_record_opts opts;
+       struct record_opts      opts;
        u64                     bytes_written;
        struct perf_data_file   file;
        struct perf_evlist      *evlist;
@@ -76,46 +76,27 @@ struct perf_record {
        long                    samples;
 };
 
-static int do_write_output(struct perf_record *rec, void *buf, size_t size)
+static int record__write(struct record *rec, void *bf, size_t size)
 {
-       struct perf_data_file *file = &rec->file;
-
-       while (size) {
-               ssize_t ret = write(file->fd, buf, size);
-
-               if (ret < 0) {
-                       pr_err("failed to write perf data, error: %m\n");
-                       return -1;
-               }
-
-               size -= ret;
-               buf += ret;
-
-               rec->bytes_written += ret;
+       if (perf_data_file__write(rec->session->file, bf, size) < 0) {
+               pr_err("failed to write perf data, error: %m\n");
+               return -1;
        }
 
+       rec->bytes_written += size;
        return 0;
 }
 
-static int write_output(struct perf_record *rec, void *buf, size_t size)
-{
-       return do_write_output(rec, buf, size);
-}
-
 static int process_synthesized_event(struct perf_tool *tool,
                                     union perf_event *event,
                                     struct perf_sample *sample __maybe_unused,
                                     struct machine *machine __maybe_unused)
 {
-       struct perf_record *rec = container_of(tool, struct perf_record, tool);
-       if (write_output(rec, event, event->header.size) < 0)
-               return -1;
-
-       return 0;
+       struct record *rec = container_of(tool, struct record, tool);
+       return record__write(rec, event, event->header.size);
 }
 
-static int perf_record__mmap_read(struct perf_record *rec,
-                                  struct perf_mmap *md)
+static int record__mmap_read(struct record *rec, struct perf_mmap *md)
 {
        unsigned int head = perf_mmap__read_head(md);
        unsigned int old = md->prev;
@@ -136,7 +117,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
                size = md->mask + 1 - (old & md->mask);
                old += size;
 
-               if (write_output(rec, buf, size) < 0) {
+               if (record__write(rec, buf, size) < 0) {
                        rc = -1;
                        goto out;
                }
@@ -146,7 +127,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
        size = head - old;
        old += size;
 
-       if (write_output(rec, buf, size) < 0) {
+       if (record__write(rec, buf, size) < 0) {
                rc = -1;
                goto out;
        }
@@ -171,9 +152,9 @@ static void sig_handler(int sig)
        signr = sig;
 }
 
-static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
+static void record__sig_exit(int exit_status __maybe_unused, void *arg)
 {
-       struct perf_record *rec = arg;
+       struct record *rec = arg;
        int status;
 
        if (rec->evlist->workload.pid > 0) {
@@ -191,18 +172,18 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
        signal(signr, SIG_DFL);
 }
 
-static int perf_record__open(struct perf_record *rec)
+static int record__open(struct record *rec)
 {
        char msg[512];
        struct perf_evsel *pos;
        struct perf_evlist *evlist = rec->evlist;
        struct perf_session *session = rec->session;
-       struct perf_record_opts *opts = &rec->opts;
+       struct record_opts *opts = &rec->opts;
        int rc = 0;
 
        perf_evlist__config(evlist, opts);
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
 try_again:
                if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
                        if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
@@ -232,7 +213,7 @@ try_again:
                               "Consider increasing "
                               "/proc/sys/kernel/perf_event_mlock_kb,\n"
                               "or try again with a smaller value of -m/--mmap_pages.\n"
-                              "(current value: %d)\n", opts->mmap_pages);
+                              "(current value: %u)\n", opts->mmap_pages);
                        rc = -errno;
                } else {
                        pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
@@ -247,7 +228,7 @@ out:
        return rc;
 }
 
-static int process_buildids(struct perf_record *rec)
+static int process_buildids(struct record *rec)
 {
        struct perf_data_file *file  = &rec->file;
        struct perf_session *session = rec->session;
@@ -262,9 +243,9 @@ static int process_buildids(struct perf_record *rec)
                                              size, &build_id__mark_dso_hit_ops);
 }
 
-static void perf_record__exit(int status, void *arg)
+static void record__exit(int status, void *arg)
 {
-       struct perf_record *rec = arg;
+       struct record *rec = arg;
        struct perf_data_file *file = &rec->file;
 
        if (status != 0)
@@ -320,14 +301,14 @@ static struct perf_event_header finished_round_event = {
        .type = PERF_RECORD_FINISHED_ROUND,
 };
 
-static int perf_record__mmap_read_all(struct perf_record *rec)
+static int record__mmap_read_all(struct record *rec)
 {
        int i;
        int rc = 0;
 
        for (i = 0; i < rec->evlist->nr_mmaps; i++) {
                if (rec->evlist->mmap[i].base) {
-                       if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
+                       if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
                                rc = -1;
                                goto out;
                        }
@@ -335,16 +316,14 @@ static int perf_record__mmap_read_all(struct perf_record *rec)
        }
 
        if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
-               rc = write_output(rec, &finished_round_event,
-                                 sizeof(finished_round_event));
+               rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
 
 out:
        return rc;
 }
 
-static void perf_record__init_features(struct perf_record *rec)
+static void record__init_features(struct record *rec)
 {
-       struct perf_evlist *evsel_list = rec->evlist;
        struct perf_session *session = rec->session;
        int feat;
 
@@ -354,32 +333,46 @@ static void perf_record__init_features(struct perf_record *rec)
        if (rec->no_buildid)
                perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
 
-       if (!have_tracepoints(&evsel_list->entries))
+       if (!have_tracepoints(&rec->evlist->entries))
                perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
 
        if (!rec->opts.branch_stack)
                perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
 }
 
-static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
+static volatile int workload_exec_errno;
+
+/*
+ * perf_evlist__prepare_workload will send a SIGUSR1
+ * if the fork fails, since we asked by setting its
+ * want_signal to true.
+ */
+static void workload_exec_failed_signal(int signo, siginfo_t *info,
+                                       void *ucontext __maybe_unused)
+{
+       workload_exec_errno = info->si_value.sival_int;
+       done = 1;
+       signr = signo;
+       child_finished = 1;
+}
+
+static int __cmd_record(struct record *rec, int argc, const char **argv)
 {
        int err;
        unsigned long waking = 0;
        const bool forks = argc > 0;
        struct machine *machine;
        struct perf_tool *tool = &rec->tool;
-       struct perf_record_opts *opts = &rec->opts;
-       struct perf_evlist *evsel_list = rec->evlist;
+       struct record_opts *opts = &rec->opts;
        struct perf_data_file *file = &rec->file;
        struct perf_session *session;
        bool disabled = false;
 
        rec->progname = argv[0];
 
-       on_exit(perf_record__sig_exit, rec);
+       on_exit(record__sig_exit, rec);
        signal(SIGCHLD, sig_handler);
        signal(SIGINT, sig_handler);
-       signal(SIGUSR1, sig_handler);
        signal(SIGTERM, sig_handler);
 
        session = perf_session__new(file, false, NULL);
@@ -390,37 +383,37 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 
        rec->session = session;
 
-       perf_record__init_features(rec);
+       record__init_features(rec);
 
        if (forks) {
-               err = perf_evlist__prepare_workload(evsel_list, &opts->target,
+               err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
                                                    argv, file->is_pipe,
-                                                   true);
+                                                   workload_exec_failed_signal);
                if (err < 0) {
                        pr_err("Couldn't run the workload!\n");
                        goto out_delete_session;
                }
        }
 
-       if (perf_record__open(rec) != 0) {
+       if (record__open(rec) != 0) {
                err = -1;
                goto out_delete_session;
        }
 
-       if (!evsel_list->nr_groups)
+       if (!rec->evlist->nr_groups)
                perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
 
        /*
-        * perf_session__delete(session) will be called at perf_record__exit()
+        * perf_session__delete(session) will be called at record__exit()
         */
-       on_exit(perf_record__exit, rec);
+       on_exit(record__exit, rec);
 
        if (file->is_pipe) {
                err = perf_header__write_pipe(file->fd);
                if (err < 0)
                        goto out_delete_session;
        } else {
-               err = perf_session__write_header(session, evsel_list,
+               err = perf_session__write_header(session, rec->evlist,
                                                 file->fd, false);
                if (err < 0)
                        goto out_delete_session;
@@ -444,7 +437,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                        goto out_delete_session;
                }
 
-               if (have_tracepoints(&evsel_list->entries)) {
+               if (have_tracepoints(&rec->evlist->entries)) {
                        /*
                         * FIXME err <= 0 here actually means that
                         * there were no tracepoints so its not really
@@ -453,7 +446,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                         * return this more properly and also
                         * propagate errors that now are calling die()
                         */
-                       err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list,
+                       err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist,
                                                                  process_synthesized_event);
                        if (err <= 0) {
                                pr_err("Couldn't record tracing data.\n");
@@ -485,7 +478,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                                         perf_event__synthesize_guest_os, tool);
        }
 
-       err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads,
+       err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
                                            process_synthesized_event, opts->sample_address);
        if (err != 0)
                goto out_delete_session;
@@ -506,19 +499,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
         * (apart from group members) have enable_on_exec=1 set,
         * so don't spoil it by prematurely enabling them.
         */
-       if (!target__none(&opts->target))
-               perf_evlist__enable(evsel_list);
+       if (!target__none(&opts->target) && !opts->initial_delay)
+               perf_evlist__enable(rec->evlist);
 
        /*
         * Let the child rip
         */
        if (forks)
-               perf_evlist__start_workload(evsel_list);
+               perf_evlist__start_workload(rec->evlist);
+
+       if (opts->initial_delay) {
+               usleep(opts->initial_delay * 1000);
+               perf_evlist__enable(rec->evlist);
+       }
 
        for (;;) {
                int hits = rec->samples;
 
-               if (perf_record__mmap_read_all(rec) < 0) {
+               if (record__mmap_read_all(rec) < 0) {
                        err = -1;
                        goto out_delete_session;
                }
@@ -526,7 +524,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                if (hits == rec->samples) {
                        if (done)
                                break;
-                       err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
+                       err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1);
                        waking++;
                }
 
@@ -536,11 +534,19 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                 * disable events in this case.
                 */
                if (done && !disabled && !target__none(&opts->target)) {
-                       perf_evlist__disable(evsel_list);
+                       perf_evlist__disable(rec->evlist);
                        disabled = true;
                }
        }
 
+       if (forks && workload_exec_errno) {
+               char msg[512];
+               const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
+               pr_err("Workload failed: %s\n", emsg);
+               err = -1;
+               goto out_delete_session;
+       }
+
        if (quiet || signr == SIGUSR1)
                return 0;
 
@@ -677,7 +683,7 @@ static int get_stack_size(char *str, unsigned long *_size)
 }
 #endif /* HAVE_LIBUNWIND_SUPPORT */
 
-int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
+int record_parse_callchain(const char *arg, struct record_opts *opts)
 {
        char *tok, *name, *saveptr = NULL;
        char *buf;
@@ -733,7 +739,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
        return ret;
 }
 
-static void callchain_debug(struct perf_record_opts *opts)
+static void callchain_debug(struct record_opts *opts)
 {
        pr_debug("callchain: type %d\n", opts->call_graph);
 
@@ -746,7 +752,7 @@ int record_parse_callchain_opt(const struct option *opt,
                               const char *arg,
                               int unset)
 {
-       struct perf_record_opts *opts = opt->value;
+       struct record_opts *opts = opt->value;
        int ret;
 
        /* --no-call-graph */
@@ -767,7 +773,7 @@ int record_callchain_opt(const struct option *opt,
                         const char *arg __maybe_unused,
                         int unset __maybe_unused)
 {
-       struct perf_record_opts *opts = opt->value;
+       struct record_opts *opts = opt->value;
 
        if (opts->call_graph == CALLCHAIN_NONE)
                opts->call_graph = CALLCHAIN_FP;
@@ -783,8 +789,8 @@ static const char * const record_usage[] = {
 };
 
 /*
- * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
- * because we need to have access to it in perf_record__exit, that is called
+ * XXX Ideally would be local to cmd_record() and passed to a record__new
+ * because we need to have access to it in record__exit, that is called
  * after cmd_record() exits, but since record_options need to be accessible to
  * builtin-script, leave it here.
  *
@@ -792,7 +798,7 @@ static const char * const record_usage[] = {
  *
  * Just say no to tons of global variables, sigh.
  */
-static struct perf_record record = {
+static struct record record = {
        .opts = {
                .mmap_pages          = UINT_MAX,
                .user_freq           = UINT_MAX,
@@ -800,6 +806,7 @@ static struct perf_record record = {
                .freq                = 4000,
                .target              = {
                        .uses_mmap   = true,
+                       .default_per_cpu = true,
                },
        },
 };
@@ -815,7 +822,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp";
 /*
  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
  * with it and switch to use the library functions in perf_evlist that came
- * from builtin-record.c, i.e. use perf_record_opts,
+ * from builtin-record.c, i.e. use record_opts,
  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
  * using pipes, etc.
  */
@@ -831,7 +838,7 @@ const struct option record_options[] = {
                    "record events on existing thread id"),
        OPT_INTEGER('r', "realtime", &record.realtime_prio,
                    "collect data with this RT SCHED_FIFO priority"),
-       OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
+       OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
                    "collect data without buffering"),
        OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
                    "collect raw sample records from all opened counters"),
@@ -842,8 +849,9 @@ const struct option record_options[] = {
        OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
        OPT_STRING('o', "output", &record.file.path, "file",
                    "output file name"),
-       OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
-                   "child tasks do not inherit counters"),
+       OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
+                       &record.opts.no_inherit_set,
+                       "child tasks do not inherit counters"),
        OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
        OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
                     "number of mmap data pages",
@@ -874,6 +882,8 @@ const struct option record_options[] = {
        OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
                     "monitor event in cgroup name only",
                     parse_cgroups),
+       OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
+                 "ms to wait before starting measurement after program start"),
        OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
                   "user to profile"),
 
@@ -888,24 +898,21 @@ const struct option record_options[] = {
                    "sample by weight (on special events only)"),
        OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
                    "sample transaction flags (special events only)"),
-       OPT_BOOLEAN(0, "force-per-cpu", &record.opts.target.force_per_cpu,
-                   "force the use of per-cpu mmaps"),
+       OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
+                   "use per-thread mmaps"),
        OPT_END()
 };
 
 int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        int err = -ENOMEM;
-       struct perf_evlist *evsel_list;
-       struct perf_record *rec = &record;
+       struct record *rec = &record;
        char errbuf[BUFSIZ];
 
-       evsel_list = perf_evlist__new();
-       if (evsel_list == NULL)
+       rec->evlist = perf_evlist__new();
+       if (rec->evlist == NULL)
                return -ENOMEM;
 
-       rec->evlist = evsel_list;
-
        argc = parse_options(argc, argv, record_options, record_usage,
                            PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc && target__none(&rec->opts.target))
@@ -932,12 +939,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
        if (rec->no_buildid_cache || rec->no_buildid)
                disable_buildid_cache();
 
-       if (evsel_list->nr_entries == 0 &&
-           perf_evlist__add_default(evsel_list) < 0) {
+       if (rec->evlist->nr_entries == 0 &&
+           perf_evlist__add_default(rec->evlist) < 0) {
                pr_err("Not enough memory for event selector list\n");
                goto out_symbol_exit;
        }
 
+       if (rec->opts.target.tid && !rec->opts.no_inherit_set)
+               rec->opts.no_inherit = true;
+
        err = target__validate(&rec->opts.target);
        if (err) {
                target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
@@ -956,20 +966,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
        }
 
        err = -ENOMEM;
-       if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
+       if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
                usage_with_options(record_usage, record_options);
 
-       if (perf_record_opts__config(&rec->opts)) {
+       if (record_opts__config(&rec->opts)) {
                err = -EINVAL;
-               goto out_free_fd;
+               goto out_symbol_exit;
        }
 
        err = __cmd_record(&record, argc, argv);
-
-       perf_evlist__munmap(evsel_list);
-       perf_evlist__close(evsel_list);
-out_free_fd:
-       perf_evlist__delete_maps(evsel_list);
 out_symbol_exit:
        symbol__exit();
        return err;
index 8cf8e66ba594156fc85a1ddca5b0b0305544ae23..3c53ec268fbc52a5298f390a83e3802eecd156a6 100644 (file)
@@ -39,7 +39,7 @@
 #include <dlfcn.h>
 #include <linux/bitmap.h>
 
-struct perf_report {
+struct report {
        struct perf_tool        tool;
        struct perf_session     *session;
        bool                    force, use_tui, use_gtk, use_stdio;
@@ -49,6 +49,8 @@ struct perf_report {
        bool                    show_threads;
        bool                    inverted_callchain;
        bool                    mem_mode;
+       bool                    header;
+       bool                    header_only;
        int                     max_stack;
        struct perf_read_values show_threads_values;
        const char              *pretty_printing_style;
@@ -58,14 +60,14 @@ struct perf_report {
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
-static int perf_report_config(const char *var, const char *value, void *cb)
+static int report__config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "report.group")) {
                symbol_conf.event_group = perf_config_bool(var, value);
                return 0;
        }
        if (!strcmp(var, "report.percent-limit")) {
-               struct perf_report *rep = cb;
+               struct report *rep = cb;
                rep->min_percent = strtof(value, NULL);
                return 0;
        }
@@ -73,31 +75,22 @@ static int perf_report_config(const char *var, const char *value, void *cb)
        return perf_default_config(var, value, cb);
 }
 
-static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
-                                          struct addr_location *al,
-                                          struct perf_sample *sample,
-                                          struct perf_evsel *evsel,
-                                          struct machine *machine,
-                                          union perf_event *event)
+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)
 {
-       struct perf_report *rep = container_of(tool, struct perf_report, tool);
+       struct report *rep = container_of(tool, struct report, tool);
        struct symbol *parent = NULL;
        u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-       int err = 0;
        struct hist_entry *he;
        struct mem_info *mi, *mx;
        uint64_t cost;
+       int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
 
-       if ((sort__has_parent || symbol_conf.use_callchain) &&
-           sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
-                                                sample, &parent, al,
-                                                rep->max_stack);
-               if (err)
-                       return err;
-       }
+       if (err)
+               return err;
 
-       mi = machine__resolve_mem(machine, al->thread, sample, cpumode);
+       mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode);
        if (!mi)
                return -ENOMEM;
 
@@ -120,77 +113,36 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
        if (!he)
                return -ENOMEM;
 
-       /*
-        * In the TUI browser, we are doing integrated annotation,
-        * so we don't allocate the extra space needed because the stdio
-        * code will not use it.
-        */
-       if (sort__has_sym && he->ms.sym && use_browser > 0) {
-               struct annotation *notes = symbol__annotation(he->ms.sym);
-
-               assert(evsel != NULL);
-
-               if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
-                       goto out;
-
-               err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
-               if (err)
-                       goto out;
-       }
+       err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+       if (err)
+               goto out;
 
-       if (sort__has_sym && he->mem_info->daddr.sym && use_browser > 0) {
-               struct annotation *notes;
-
-               mx = he->mem_info;
-
-               notes = symbol__annotation(mx->daddr.sym);
-               if (notes->src == NULL && symbol__alloc_hist(mx->daddr.sym) < 0)
-                       goto out;
-
-               err = symbol__inc_addr_samples(mx->daddr.sym,
-                                              mx->daddr.map,
-                                              evsel->idx,
-                                              mx->daddr.al_addr);
-               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);
-       err = 0;
-
-       if (symbol_conf.use_callchain) {
-               err = callchain_append(he->callchain,
-                                      &callchain_cursor,
-                                      sample->period);
-       }
+       err = hist_entry__append_callchain(he, sample);
 out:
        return err;
 }
 
-static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
-                                       struct addr_location *al,
-                                       struct perf_sample *sample,
-                                       struct perf_evsel *evsel,
-                                     struct machine *machine)
+static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al,
+                                        struct perf_sample *sample, struct perf_evsel *evsel)
 {
-       struct perf_report *rep = container_of(tool, struct perf_report, tool);
+       struct report *rep = container_of(tool, struct report, tool);
        struct symbol *parent = NULL;
-       int err = 0;
        unsigned i;
        struct hist_entry *he;
        struct branch_info *bi, *bx;
+       int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
 
-       if ((sort__has_parent || symbol_conf.use_callchain)
-           && sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
-                                                sample, &parent, al,
-                                                rep->max_stack);
-               if (err)
-                       return err;
-       }
+       if (err)
+               return err;
 
-       bi = machine__resolve_bstack(machine, al->thread,
+       bi = machine__resolve_bstack(al->machine, al->thread,
                                     sample->branch_stack);
        if (!bi)
                return -ENOMEM;
@@ -212,35 +164,15 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
                he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
                                        1, 1, 0);
                if (he) {
-                       struct annotation *notes;
                        bx = he->branch_info;
-                       if (bx->from.sym && use_browser == 1 && sort__has_sym) {
-                               notes = symbol__annotation(bx->from.sym);
-                               if (!notes->src
-                                   && symbol__alloc_hist(bx->from.sym) < 0)
-                                       goto out;
-
-                               err = symbol__inc_addr_samples(bx->from.sym,
-                                                              bx->from.map,
-                                                              evsel->idx,
-                                                              bx->from.al_addr);
-                               if (err)
-                                       goto out;
-                       }
+                       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 (bx->to.sym && use_browser == 1 && sort__has_sym) {
-                               notes = symbol__annotation(bx->to.sym);
-                               if (!notes->src
-                                   && symbol__alloc_hist(bx->to.sym) < 0)
-                                       goto out;
-
-                               err = symbol__inc_addr_samples(bx->to.sym,
-                                                              bx->to.map,
-                                                              evsel->idx,
-                                                              bx->to.al_addr);
-                               if (err)
-                                       goto out;
-                       }
                        evsel->hists.stats.total_period += 1;
                        hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
                } else
@@ -252,24 +184,16 @@ out:
        return err;
 }
 
-static int perf_evsel__add_hist_entry(struct perf_tool *tool,
-                                     struct perf_evsel *evsel,
-                                     struct addr_location *al,
-                                     struct perf_sample *sample,
-                                     struct machine *machine)
+static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
+                                 struct addr_location *al, struct perf_sample *sample)
 {
-       struct perf_report *rep = container_of(tool, struct perf_report, tool);
+       struct report *rep = container_of(tool, struct report, tool);
        struct symbol *parent = NULL;
-       int err = 0;
        struct hist_entry *he;
+       int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
 
-       if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
-                                                sample, &parent, al,
-                                                rep->max_stack);
-               if (err)
-                       return err;
-       }
+       if (err)
+               return err;
 
        he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
                                sample->period, sample->weight,
@@ -277,30 +201,11 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool,
        if (he == NULL)
                return -ENOMEM;
 
-       if (symbol_conf.use_callchain) {
-               err = callchain_append(he->callchain,
-                                      &callchain_cursor,
-                                      sample->period);
-               if (err)
-                       return err;
-       }
-       /*
-        * Only in the TUI browser we are doing integrated annotation,
-        * so we don't allocated the extra space needed because the stdio
-        * code will not use it.
-        */
-       if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) {
-               struct annotation *notes = symbol__annotation(he->ms.sym);
-
-               assert(evsel != NULL);
-
-               err = -ENOMEM;
-               if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
-                       goto out;
-
-               err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
-       }
+       err = hist_entry__append_callchain(he, sample);
+       if (err)
+               goto out;
 
+       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:
@@ -314,13 +219,13 @@ static int process_sample_event(struct perf_tool *tool,
                                struct perf_evsel *evsel,
                                struct machine *machine)
 {
-       struct perf_report *rep = container_of(tool, struct perf_report, tool);
+       struct report *rep = container_of(tool, struct report, tool);
        struct addr_location al;
        int ret;
 
        if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
-               fprintf(stderr, "problem processing %d event, skipping it.\n",
-                       event->header.type);
+               pr_debug("problem processing %d event, skipping it.\n",
+                        event->header.type);
                return -1;
        }
 
@@ -331,21 +236,18 @@ static int process_sample_event(struct perf_tool *tool,
                return 0;
 
        if (sort__mode == SORT_MODE__BRANCH) {
-               ret = perf_report__add_branch_hist_entry(tool, &al, sample,
-                                                        evsel, machine);
+               ret = report__add_branch_hist_entry(tool, &al, sample, evsel);
                if (ret < 0)
                        pr_debug("problem adding lbr entry, skipping event\n");
        } else if (rep->mem_mode == 1) {
-               ret = perf_report__add_mem_hist_entry(tool, &al, sample,
-                                                     evsel, machine, event);
+               ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event);
                if (ret < 0)
                        pr_debug("problem adding mem entry, skipping event\n");
        } else {
                if (al.map != NULL)
                        al.map->dso->hit = 1;
 
-               ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample,
-                                                machine);
+               ret = report__add_hist_entry(tool, evsel, &al, sample);
                if (ret < 0)
                        pr_debug("problem incrementing symbol period, skipping event\n");
        }
@@ -358,7 +260,7 @@ static int process_read_event(struct perf_tool *tool,
                              struct perf_evsel *evsel,
                              struct machine *machine __maybe_unused)
 {
-       struct perf_report *rep = container_of(tool, struct perf_report, tool);
+       struct report *rep = container_of(tool, struct report, tool);
 
        if (rep->show_threads) {
                const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
@@ -377,7 +279,7 @@ static int process_read_event(struct perf_tool *tool,
 }
 
 /* For pipe mode, sample_type is not currently set */
-static int perf_report__setup_sample_type(struct perf_report *rep)
+static int report__setup_sample_type(struct report *rep)
 {
        struct perf_session *session = rep->session;
        u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
@@ -422,8 +324,7 @@ static void sig_handler(int sig __maybe_unused)
        session_done = 1;
 }
 
-static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
-                                             struct hists *hists,
+static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
                                              const char *evname, FILE *fp)
 {
        size_t ret;
@@ -460,12 +361,12 @@ static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
 }
 
 static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
-                                        struct perf_report *rep,
+                                        struct report *rep,
                                         const char *help)
 {
        struct perf_evsel *pos;
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                struct hists *hists = &pos->hists;
                const char *evname = perf_evsel__name(pos);
 
@@ -473,7 +374,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
                    !perf_evsel__is_group_leader(pos))
                        continue;
 
-               hists__fprintf_nr_sample_events(rep, hists, evname, stdout);
+               hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
                hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
                fprintf(stdout, "\n\n");
        }
@@ -493,43 +394,11 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
        return 0;
 }
 
-static int __cmd_report(struct perf_report *rep)
+static void report__warn_kptr_restrict(const struct report *rep)
 {
-       int ret = -EINVAL;
-       u64 nr_samples;
-       struct perf_session *session = rep->session;
-       struct perf_evsel *pos;
-       struct map *kernel_map;
-       struct kmap *kernel_kmap;
-       const char *help = "For a higher level overview, try: perf report --sort comm,dso";
-       struct ui_progress prog;
-       struct perf_data_file *file = session->file;
-
-       signal(SIGINT, sig_handler);
+       struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
+       struct kmap *kernel_kmap = map__kmap(kernel_map);
 
-       if (rep->cpu_list) {
-               ret = perf_session__cpu_bitmap(session, rep->cpu_list,
-                                              rep->cpu_bitmap);
-               if (ret)
-                       return ret;
-       }
-
-       if (use_browser <= 0)
-               perf_session__fprintf_info(session, stdout, rep->show_full_info);
-
-       if (rep->show_threads)
-               perf_read_values_init(&rep->show_threads_values);
-
-       ret = perf_report__setup_sample_type(rep);
-       if (ret)
-               return ret;
-
-       ret = perf_session__process_events(session, &rep->tool);
-       if (ret)
-               return ret;
-
-       kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION];
-       kernel_kmap = map__kmap(kernel_map);
        if (kernel_map == NULL ||
            (kernel_map->dso->hit &&
             (kernel_kmap->ref_reloc_sym == NULL ||
@@ -552,26 +421,73 @@ static int __cmd_report(struct perf_report *rep)
 "Samples in kernel modules can't be resolved as well.\n\n",
                desc);
        }
+}
 
-       if (verbose > 3)
-               perf_session__fprintf(session, stdout);
+static int report__gtk_browse_hists(struct report *rep, const char *help)
+{
+       int (*hist_browser)(struct perf_evlist *evlist, const char *help,
+                           struct hist_browser_timer *timer, float min_pcnt);
 
-       if (verbose > 2)
-               perf_session__fprintf_dsos(session, stdout);
+       hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");
 
-       if (dump_trace) {
-               perf_session__fprintf_nr_events(session, stdout);
-               return 0;
+       if (hist_browser == NULL) {
+               ui__error("GTK browser not found!\n");
+               return -1;
        }
 
-       nr_samples = 0;
-       list_for_each_entry(pos, &session->evlist->entries, node)
+       return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
+}
+
+static int report__browse_hists(struct report *rep)
+{
+       int ret;
+       struct perf_session *session = rep->session;
+       struct perf_evlist *evlist = session->evlist;
+       const char *help = "For a higher level overview, try: perf report --sort comm,dso";
+
+       switch (use_browser) {
+       case 1:
+               ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
+                                                   rep->min_percent,
+                                                   &session->header.env);
+               /*
+                * Usually "ret" is the last pressed key, and we only
+                * care if the key notifies us to switch data file.
+                */
+               if (ret != K_SWITCH_INPUT_DATA)
+                       ret = 0;
+               break;
+       case 2:
+               ret = report__gtk_browse_hists(rep, help);
+               break;
+       default:
+               ret = perf_evlist__tty_browse_hists(evlist, rep, help);
+               break;
+       }
+
+       return ret;
+}
+
+static u64 report__collapse_hists(struct report *rep)
+{
+       struct ui_progress prog;
+       struct perf_evsel *pos;
+       u64 nr_samples = 0;
+       /*
+        * Count number of histogram entries to use when showing progress,
+        * reusing nr_samples variable.
+        */
+       evlist__for_each(rep->session->evlist, pos)
                nr_samples += pos->hists.nr_entries;
 
        ui_progress__init(&prog, nr_samples, "Merging related events...");
-
+       /*
+        * Count total number of samples, will be used to check if this
+        * session had any.
+        */
        nr_samples = 0;
-       list_for_each_entry(pos, &session->evlist->entries, node) {
+
+       evlist__for_each(rep->session->evlist, pos) {
                struct hists *hists = &pos->hists;
 
                if (pos->idx == 0)
@@ -589,8 +505,57 @@ static int __cmd_report(struct perf_report *rep)
                        hists__link(leader_hists, hists);
                }
        }
+
        ui_progress__finish();
 
+       return nr_samples;
+}
+
+static int __cmd_report(struct report *rep)
+{
+       int ret;
+       u64 nr_samples;
+       struct perf_session *session = rep->session;
+       struct perf_evsel *pos;
+       struct perf_data_file *file = session->file;
+
+       signal(SIGINT, sig_handler);
+
+       if (rep->cpu_list) {
+               ret = perf_session__cpu_bitmap(session, rep->cpu_list,
+                                              rep->cpu_bitmap);
+               if (ret)
+                       return ret;
+       }
+
+       if (rep->show_threads)
+               perf_read_values_init(&rep->show_threads_values);
+
+       ret = report__setup_sample_type(rep);
+       if (ret)
+               return ret;
+
+       ret = perf_session__process_events(session, &rep->tool);
+       if (ret)
+               return ret;
+
+       report__warn_kptr_restrict(rep);
+
+       if (use_browser == 0) {
+               if (verbose > 3)
+                       perf_session__fprintf(session, stdout);
+
+               if (verbose > 2)
+                       perf_session__fprintf_dsos(session, stdout);
+
+               if (dump_trace) {
+                       perf_session__fprintf_nr_events(session, stdout);
+                       return 0;
+               }
+       }
+
+       nr_samples = report__collapse_hists(rep);
+
        if (session_done())
                return 0;
 
@@ -599,47 +564,16 @@ static int __cmd_report(struct perf_report *rep)
                return 0;
        }
 
-       list_for_each_entry(pos, &session->evlist->entries, node)
+       evlist__for_each(session->evlist, pos)
                hists__output_resort(&pos->hists);
 
-       if (use_browser > 0) {
-               if (use_browser == 1) {
-                       ret = perf_evlist__tui_browse_hists(session->evlist,
-                                                       help, NULL,
-                                                       rep->min_percent,
-                                                       &session->header.env);
-                       /*
-                        * Usually "ret" is the last pressed key, and we only
-                        * care if the key notifies us to switch data file.
-                        */
-                       if (ret != K_SWITCH_INPUT_DATA)
-                               ret = 0;
-
-               } else if (use_browser == 2) {
-                       int (*hist_browser)(struct perf_evlist *,
-                                           const char *,
-                                           struct hist_browser_timer *,
-                                           float min_pcnt);
-
-                       hist_browser = dlsym(perf_gtk_handle,
-                                            "perf_evlist__gtk_browse_hists");
-                       if (hist_browser == NULL) {
-                               ui__error("GTK browser not found!\n");
-                               return ret;
-                       }
-                       hist_browser(session->evlist, help, NULL,
-                                    rep->min_percent);
-               }
-       } else
-               perf_evlist__tty_browse_hists(session->evlist, rep, help);
-
-       return ret;
+       return report__browse_hists(rep);
 }
 
 static int
 parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 {
-       struct perf_report *rep = (struct perf_report *)opt->value;
+       struct report *rep = (struct report *)opt->value;
        char *tok, *tok2;
        char *endptr;
 
@@ -721,7 +655,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
                return -1;
 setup:
        if (callchain_register_param(&callchain_param) < 0) {
-               fprintf(stderr, "Can't register callchain params\n");
+               pr_err("Can't register callchain params\n");
                return -1;
        }
        return 0;
@@ -759,7 +693,7 @@ static int
 parse_percent_limit(const struct option *opt, const char *str,
                    int unset __maybe_unused)
 {
-       struct perf_report *rep = opt->value;
+       struct report *rep = opt->value;
 
        rep->min_percent = strtof(str, NULL);
        return 0;
@@ -777,7 +711,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                "perf report [<options>]",
                NULL
        };
-       struct perf_report report = {
+       struct report report = {
                .tool = {
                        .sample          = process_sample_event,
                        .mmap            = perf_event__process_mmap,
@@ -820,6 +754,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
        OPT_BOOLEAN(0, "stdio", &report.use_stdio,
                    "Use the stdio interface"),
+       OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
+       OPT_BOOLEAN(0, "header-only", &report.header_only,
+                   "Show only data header."),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
                   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
                   " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
@@ -890,7 +827,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                .mode  = PERF_DATA_MODE_READ,
        };
 
-       perf_config(perf_report_config, &report);
+       perf_config(report__config, &report);
 
        argc = parse_options(argc, argv, options, report_usage, 0);
 
@@ -940,7 +877,7 @@ repeat:
        }
        if (report.mem_mode) {
                if (sort__mode == SORT_MODE__BRANCH) {
-                       fprintf(stderr, "branch and mem mode incompatible\n");
+                       pr_err("branch and mem mode incompatible\n");
                        goto error;
                }
                sort__mode = SORT_MODE__MEMORY;
@@ -963,6 +900,10 @@ repeat:
                        goto error;
        }
 
+       /* Force tty output for header output. */
+       if (report.header || report.header_only)
+               use_browser = 0;
+
        if (strcmp(input_name, "-") != 0)
                setup_browser(true);
        else {
@@ -970,6 +911,16 @@ repeat:
                perf_hpp__init();
        }
 
+       if (report.header || report.header_only) {
+               perf_session__fprintf_info(session, stdout,
+                                          report.show_full_info);
+               if (report.header_only)
+                       return 0;
+       } else if (use_browser == 0) {
+               fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
+                     stdout);
+       }
+
        /*
         * Only in the TUI browser we are doing integrated annotation,
         * so don't allocate extra space that won't be used in the stdio
index 0f3c65518a2c669a9b83ad255d1018368de6ec69..6a76a07b67890c253fbb1e227e9aaa980b499779 100644 (file)
@@ -469,7 +469,7 @@ static void *thread_func(void *ctx)
        char comm2[22];
        int fd;
 
-       free(parms);
+       zfree(&parms);
 
        sprintf(comm2, ":%s", this_task->comm);
        prctl(PR_SET_NAME, comm2);
index baf17989a216137064e089d4e2f65fef07a4357f..9e9c91f5b7fae97de166583b46bd801fc4ccc2f1 100644 (file)
@@ -43,6 +43,7 @@ enum perf_output_field {
        PERF_OUTPUT_DSO             = 1U << 9,
        PERF_OUTPUT_ADDR            = 1U << 10,
        PERF_OUTPUT_SYMOFFSET       = 1U << 11,
+       PERF_OUTPUT_SRCLINE         = 1U << 12,
 };
 
 struct output_option {
@@ -61,6 +62,7 @@ struct output_option {
        {.str = "dso",   .field = PERF_OUTPUT_DSO},
        {.str = "addr",  .field = PERF_OUTPUT_ADDR},
        {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
+       {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
 };
 
 /* default set to maintain compatibility with current format */
@@ -210,6 +212,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                       "to DSO.\n");
                return -EINVAL;
        }
+       if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
+               pr_err("Display of source line number requested but sample IP is not\n"
+                      "selected. Hence, no address to lookup the source line number.\n");
+               return -EINVAL;
+       }
 
        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
                perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
@@ -245,6 +252,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
 
        if (PRINT_FIELD(SYMOFFSET))
                output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
+
+       if (PRINT_FIELD(SRCLINE))
+               output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE;
 }
 
 /*
@@ -280,6 +290,30 @@ static int perf_session__check_output_opt(struct perf_session *session)
                set_print_ip_opts(&evsel->attr);
        }
 
+       /*
+        * set default for tracepoints to print symbols only
+        * if callchains are present
+        */
+       if (symbol_conf.use_callchain &&
+           !output[PERF_TYPE_TRACEPOINT].user_set) {
+               struct perf_event_attr *attr;
+
+               j = PERF_TYPE_TRACEPOINT;
+               evsel = perf_session__find_first_evtype(session, j);
+               if (evsel == NULL)
+                       goto out;
+
+               attr = &evsel->attr;
+
+               if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
+                       output[j].fields |= PERF_OUTPUT_IP;
+                       output[j].fields |= PERF_OUTPUT_SYM;
+                       output[j].fields |= PERF_OUTPUT_DSO;
+                       set_print_ip_opts(attr);
+               }
+       }
+
+out:
        return 0;
 }
 
@@ -288,7 +322,6 @@ static void print_sample_start(struct perf_sample *sample,
                               struct perf_evsel *evsel)
 {
        struct perf_event_attr *attr = &evsel->attr;
-       const char *evname = NULL;
        unsigned long secs;
        unsigned long usecs;
        unsigned long long nsecs;
@@ -323,11 +356,6 @@ static void print_sample_start(struct perf_sample *sample,
                usecs = nsecs / NSECS_PER_USEC;
                printf("%5lu.%06lu: ", secs, usecs);
        }
-
-       if (PRINT_FIELD(EVNAME)) {
-               evname = perf_evsel__name(evsel);
-               printf("%s: ", evname ? evname : "[unknown]");
-       }
 }
 
 static bool is_bts_event(struct perf_event_attr *attr)
@@ -395,8 +423,8 @@ static void print_sample_addr(union perf_event *event,
 static void print_sample_bts(union perf_event *event,
                             struct perf_sample *sample,
                             struct perf_evsel *evsel,
-                            struct machine *machine,
-                            struct thread *thread)
+                            struct thread *thread,
+                            struct addr_location *al)
 {
        struct perf_event_attr *attr = &evsel->attr;
 
@@ -406,7 +434,7 @@ static void print_sample_bts(union perf_event *event,
                        printf(" ");
                else
                        printf("\n");
-               perf_evsel__print_ip(evsel, event, sample, machine,
+               perf_evsel__print_ip(evsel, sample, al,
                                     output[attr->type].print_ip_opts,
                                     PERF_MAX_STACK_DEPTH);
        }
@@ -417,15 +445,14 @@ static void print_sample_bts(union perf_event *event,
        if (PRINT_FIELD(ADDR) ||
            ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
             !output[attr->type].user_set))
-               print_sample_addr(event, sample, machine, thread, attr);
+               print_sample_addr(event, sample, al->machine, thread, attr);
 
        printf("\n");
 }
 
 static void process_event(union perf_event *event, struct perf_sample *sample,
-                         struct perf_evsel *evsel, struct machine *machine,
-                         struct thread *thread,
-                         struct addr_location *al __maybe_unused)
+                         struct perf_evsel *evsel, struct thread *thread,
+                         struct addr_location *al)
 {
        struct perf_event_attr *attr = &evsel->attr;
 
@@ -434,8 +461,13 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 
        print_sample_start(sample, thread, evsel);
 
+       if (PRINT_FIELD(EVNAME)) {
+               const char *evname = perf_evsel__name(evsel);
+               printf("%s: ", evname ? evname : "[unknown]");
+       }
+
        if (is_bts_event(attr)) {
-               print_sample_bts(event, sample, evsel, machine, thread);
+               print_sample_bts(event, sample, evsel, thread, al);
                return;
        }
 
@@ -443,7 +475,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
                event_format__print(evsel->tp_format, sample->cpu,
                                    sample->raw_data, sample->raw_size);
        if (PRINT_FIELD(ADDR))
-               print_sample_addr(event, sample, machine, thread, attr);
+               print_sample_addr(event, sample, al->machine, thread, attr);
 
        if (PRINT_FIELD(IP)) {
                if (!symbol_conf.use_callchain)
@@ -451,7 +483,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
                else
                        printf("\n");
 
-               perf_evsel__print_ip(evsel, event, sample, machine,
+               perf_evsel__print_ip(evsel, sample, al,
                                     output[attr->type].print_ip_opts,
                                     PERF_MAX_STACK_DEPTH);
        }
@@ -540,7 +572,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
        if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
                return 0;
 
-       scripting_ops->process_event(event, sample, evsel, machine, thread, &al);
+       scripting_ops->process_event(event, sample, evsel, thread, &al);
 
        evsel->hists.stats.total_period += sample->period;
        return 0;
@@ -549,6 +581,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 struct perf_script {
        struct perf_tool        tool;
        struct perf_session     *session;
+       bool                    show_task_events;
+       bool                    show_mmap_events;
 };
 
 static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -569,7 +603,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
        if (evsel->attr.type >= PERF_TYPE_MAX)
                return 0;
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                if (pos->attr.type == evsel->attr.type && pos != evsel)
                        return 0;
        }
@@ -579,6 +613,163 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
        return perf_evsel__check_attr(evsel, scr->session);
 }
 
+static int process_comm_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+       int ret = -1;
+
+       thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing COMM event, skipping it.\n");
+               return -1;
+       }
+
+       if (perf_event__process_comm(tool, event, sample, machine) < 0)
+               goto out;
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->comm.tid;
+               sample->pid = event->comm.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+       ret = 0;
+
+out:
+       return ret;
+}
+
+static int process_fork_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       if (perf_event__process_fork(tool, event, sample, machine) < 0)
+               return -1;
+
+       thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing FORK event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = event->fork.time;
+               sample->tid = event->fork.tid;
+               sample->pid = event->fork.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       return 0;
+}
+static int process_exit_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing EXIT event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->comm.tid;
+               sample->pid = event->comm.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       if (perf_event__process_exit(tool, event, sample, machine) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int process_mmap_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       if (perf_event__process_mmap(tool, event, sample, machine) < 0)
+               return -1;
+
+       thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing MMAP event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->mmap.tid;
+               sample->pid = event->mmap.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       return 0;
+}
+
+static int process_mmap2_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
+               return -1;
+
+       thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing MMAP2 event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->mmap2.tid;
+               sample->pid = event->mmap2.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       return 0;
+}
+
 static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
@@ -590,6 +781,17 @@ static int __cmd_script(struct perf_script *script)
 
        signal(SIGINT, sig_handler);
 
+       /* override event processing functions */
+       if (script->show_task_events) {
+               script->tool.comm = process_comm_event;
+               script->tool.fork = process_fork_event;
+               script->tool.exit = process_exit_event;
+       }
+       if (script->show_mmap_events) {
+               script->tool.mmap = process_mmap_event;
+               script->tool.mmap2 = process_mmap2_event;
+       }
+
        ret = perf_session__process_events(script->session, &script->tool);
 
        if (debug_mode)
@@ -900,9 +1102,9 @@ static struct script_desc *script_desc__new(const char *name)
 
 static void script_desc__delete(struct script_desc *s)
 {
-       free(s->name);
-       free(s->half_liner);
-       free(s->args);
+       zfree(&s->name);
+       zfree(&s->half_liner);
+       zfree(&s->args);
        free(s);
 }
 
@@ -1107,8 +1309,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
                        snprintf(evname, len + 1, "%s", p);
 
                        match = 0;
-                       list_for_each_entry(pos,
-                                       &session->evlist->entries, node) {
+                       evlist__for_each(session->evlist, pos) {
                                if (!strcmp(perf_evsel__name(pos), evname)) {
                                        match = 1;
                                        break;
@@ -1290,6 +1491,8 @@ static int have_cmd(int argc, const char **argv)
 int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        bool show_full_info = false;
+       bool header = false;
+       bool header_only = false;
        char *rec_script_path = NULL;
        char *rep_script_path = NULL;
        struct perf_session *session;
@@ -1328,6 +1531,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_STRING('i', "input", &input_name, "file", "input file name"),
        OPT_BOOLEAN('d', "debug-mode", &debug_mode,
                   "do various checks like samples ordering and lost events"),
+       OPT_BOOLEAN(0, "header", &header, "Show data header."),
+       OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
                   "file", "vmlinux pathname"),
        OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
@@ -1352,6 +1557,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                    "display extended information from perf.data file"),
        OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
                    "Show the path of [kernel.kallsyms]"),
+       OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,
+                   "Show the fork/comm/exit events"),
+       OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
+                   "Show the mmap events"),
        OPT_END()
        };
        const char * const script_usage[] = {
@@ -1540,6 +1749,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
        if (session == NULL)
                return -ENOMEM;
 
+       if (header || header_only) {
+               perf_session__fprintf_info(session, stdout, show_full_info);
+               if (header_only)
+                       return 0;
+       }
+
        script.session = session;
 
        if (cpu_list) {
@@ -1547,9 +1762,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                        return -1;
        }
 
-       if (!script_name && !generate_script_lang)
-               perf_session__fprintf_info(session, stdout, show_full_info);
-
        if (!no_callchain)
                symbol_conf.use_callchain = true;
        else
@@ -1588,7 +1800,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                        return -1;
                }
 
-               err = scripting_ops->generate_script(session->pevent,
+               err = scripting_ops->generate_script(session->tevent.pevent,
                                                     "perf-script");
                goto out;
        }
index ee0d565f83e300f57d21d465a9f65180f5a74618..8b0e1c9234d9c65798873cf84306c8d16fecfb5d 100644 (file)
@@ -138,6 +138,7 @@ static const char           *post_cmd                       = NULL;
 static bool                    sync_run                        = false;
 static unsigned int            interval                        = 0;
 static unsigned int            initial_delay                   = 0;
+static unsigned int            unit_width                      = 4; /* strlen("unit") */
 static bool                    forever                         = false;
 static struct timespec         ref_time;
 static struct cpu_map          *aggr_map;
@@ -184,8 +185,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 
 static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 {
-       free(evsel->priv);
-       evsel->priv = NULL;
+       zfree(&evsel->priv);
 }
 
 static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
@@ -207,15 +207,14 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
 
 static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 {
-       free(evsel->prev_raw_counts);
-       evsel->prev_raw_counts = NULL;
+       zfree(&evsel->prev_raw_counts);
 }
 
 static void perf_evlist__free_stats(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                perf_evsel__free_stat_priv(evsel);
                perf_evsel__free_counts(evsel);
                perf_evsel__free_prev_raw_counts(evsel);
@@ -226,7 +225,7 @@ static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
                    perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 ||
                    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0))
@@ -260,7 +259,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                perf_evsel__reset_stat_priv(evsel);
                perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel));
        }
@@ -327,13 +326,13 @@ static struct perf_evsel *nth_evsel(int n)
 
        /* Assumes this only called when evsel_list does not change anymore. */
        if (!array) {
-               list_for_each_entry(ev, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, ev)
                        array_len++;
                array = malloc(array_len * sizeof(void *));
                if (!array)
                        exit(ENOMEM);
                j = 0;
-               list_for_each_entry(ev, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, ev)
                        array[j++] = ev;
        }
        if (n < array_len)
@@ -441,13 +440,13 @@ static void print_interval(void)
        char prefix[64];
 
        if (aggr_mode == AGGR_GLOBAL) {
-               list_for_each_entry(counter, &evsel_list->entries, node) {
+               evlist__for_each(evsel_list, counter) {
                        ps = counter->priv;
                        memset(ps->res_stats, 0, sizeof(ps->res_stats));
                        read_counter_aggr(counter);
                }
        } else  {
-               list_for_each_entry(counter, &evsel_list->entries, node) {
+               evlist__for_each(evsel_list, counter) {
                        ps = counter->priv;
                        memset(ps->res_stats, 0, sizeof(ps->res_stats));
                        read_counter(counter);
@@ -461,17 +460,17 @@ static void print_interval(void)
        if (num_print_interval == 0 && !csv_output) {
                switch (aggr_mode) {
                case AGGR_SOCKET:
-                       fprintf(output, "#           time socket cpus             counts events\n");
+                       fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
                        break;
                case AGGR_CORE:
-                       fprintf(output, "#           time core         cpus             counts events\n");
+                       fprintf(output, "#           time core         cpus             counts %*s events\n", unit_width, "unit");
                        break;
                case AGGR_NONE:
-                       fprintf(output, "#           time CPU                 counts events\n");
+                       fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
                        break;
                case AGGR_GLOBAL:
                default:
-                       fprintf(output, "#           time             counts events\n");
+                       fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
                }
        }
 
@@ -484,12 +483,12 @@ static void print_interval(void)
                print_aggr(prefix);
                break;
        case AGGR_NONE:
-               list_for_each_entry(counter, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, counter)
                        print_counter(counter, prefix);
                break;
        case AGGR_GLOBAL:
        default:
-               list_for_each_entry(counter, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, counter)
                        print_counter_aggr(counter, prefix);
        }
 
@@ -505,17 +504,31 @@ static void handle_initial_delay(void)
                        nthreads = thread_map__nr(evsel_list->threads);
 
                usleep(initial_delay * 1000);
-               list_for_each_entry(counter, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, counter)
                        perf_evsel__enable(counter, ncpus, nthreads);
        }
 }
 
+static volatile int workload_exec_errno;
+
+/*
+ * perf_evlist__prepare_workload will send a SIGUSR1
+ * if the fork fails, since we asked by setting its
+ * want_signal to true.
+ */
+static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
+                                       void *ucontext __maybe_unused)
+{
+       workload_exec_errno = info->si_value.sival_int;
+}
+
 static int __run_perf_stat(int argc, const char **argv)
 {
        char msg[512];
        unsigned long long t0, t1;
        struct perf_evsel *counter;
        struct timespec ts;
+       size_t l;
        int status = 0;
        const bool forks = (argc > 0);
 
@@ -528,8 +541,8 @@ static int __run_perf_stat(int argc, const char **argv)
        }
 
        if (forks) {
-               if (perf_evlist__prepare_workload(evsel_list, &target, argv,
-                                                 false, false) < 0) {
+               if (perf_evlist__prepare_workload(evsel_list, &target, argv, false,
+                                                 workload_exec_failed_signal) < 0) {
                        perror("failed to prepare workload");
                        return -1;
                }
@@ -539,7 +552,7 @@ static int __run_perf_stat(int argc, const char **argv)
        if (group)
                perf_evlist__set_leader(evsel_list);
 
-       list_for_each_entry(counter, &evsel_list->entries, node) {
+       evlist__for_each(evsel_list, counter) {
                if (create_perf_stat_counter(counter) < 0) {
                        /*
                         * PPC returns ENXIO for HW counters until 2.6.37
@@ -565,6 +578,10 @@ static int __run_perf_stat(int argc, const char **argv)
                        return -1;
                }
                counter->supported = true;
+
+               l = strlen(counter->unit);
+               if (l > unit_width)
+                       unit_width = l;
        }
 
        if (perf_evlist__apply_filters(evsel_list)) {
@@ -590,6 +607,13 @@ static int __run_perf_stat(int argc, const char **argv)
                        }
                }
                wait(&status);
+
+               if (workload_exec_errno) {
+                       const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
+                       pr_err("Workload failed: %s\n", emsg);
+                       return -1;
+               }
+
                if (WIFSIGNALED(status))
                        psignal(WTERMSIG(status), argv[0]);
        } else {
@@ -606,13 +630,13 @@ static int __run_perf_stat(int argc, const char **argv)
        update_stats(&walltime_nsecs_stats, t1 - t0);
 
        if (aggr_mode == AGGR_GLOBAL) {
-               list_for_each_entry(counter, &evsel_list->entries, node) {
+               evlist__for_each(evsel_list, counter) {
                        read_counter_aggr(counter);
                        perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
                                             thread_map__nr(evsel_list->threads));
                }
        } else {
-               list_for_each_entry(counter, &evsel_list->entries, node) {
+               evlist__for_each(evsel_list, counter) {
                        read_counter(counter);
                        perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
                }
@@ -621,7 +645,7 @@ static int __run_perf_stat(int argc, const char **argv)
        return WEXITSTATUS(status);
 }
 
-static int run_perf_stat(int argc __maybe_unused, const char **argv)
+static int run_perf_stat(int argc, const char **argv)
 {
        int ret;
 
@@ -704,14 +728,25 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
        double msecs = avg / 1e6;
-       const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s";
+       const char *fmt_v, *fmt_n;
        char name[25];
 
+       fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
+       fmt_n = csv_output ? "%s" : "%-25s";
+
        aggr_printout(evsel, cpu, nr);
 
        scnprintf(name, sizeof(name), "%s%s",
                  perf_evsel__name(evsel), csv_output ? "" : " (msec)");
-       fprintf(output, fmt, msecs, csv_sep, name);
+
+       fprintf(output, fmt_v, msecs, csv_sep);
+
+       if (csv_output)
+               fprintf(output, "%s%s", evsel->unit, csv_sep);
+       else
+               fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep);
+
+       fprintf(output, fmt_n, name);
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,21 +943,31 @@ static void print_ll_cache_misses(int cpu,
 static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
        double total, ratio = 0.0, total2;
+       double sc =  evsel->scale;
        const char *fmt;
 
-       if (csv_output)
-               fmt = "%.0f%s%s";
-       else if (big_num)
-               fmt = "%'18.0f%s%-25s";
-       else
-               fmt = "%18.0f%s%-25s";
+       if (csv_output) {
+               fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
+       } else {
+               if (big_num)
+                       fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
+               else
+                       fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
+       }
 
        aggr_printout(evsel, cpu, nr);
 
        if (aggr_mode == AGGR_GLOBAL)
                cpu = 0;
 
-       fprintf(output, fmt, avg, csv_sep, perf_evsel__name(evsel));
+       fprintf(output, fmt, avg, csv_sep);
+
+       if (evsel->unit)
+               fprintf(output, "%-*s%s",
+                       csv_output ? 0 : unit_width,
+                       evsel->unit, csv_sep);
+
+       fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -941,7 +986,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 
                if (total && avg) {
                        ratio = total / avg;
-                       fprintf(output, "\n                                             #   %5.2f  stalled cycles per insn", ratio);
+                       fprintf(output, "\n");
+                       if (aggr_mode == AGGR_NONE)
+                               fprintf(output, "        ");
+                       fprintf(output, "                                                  #   %5.2f  stalled cycles per insn", ratio);
                }
 
        } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
@@ -1061,6 +1109,7 @@ static void print_aggr(char *prefix)
 {
        struct perf_evsel *counter;
        int cpu, cpu2, s, s2, id, nr;
+       double uval;
        u64 ena, run, val;
 
        if (!(aggr_map || aggr_get_id))
@@ -1068,7 +1117,7 @@ static void print_aggr(char *prefix)
 
        for (s = 0; s < aggr_map->nr; s++) {
                id = aggr_map->map[s];
-               list_for_each_entry(counter, &evsel_list->entries, node) {
+               evlist__for_each(evsel_list, counter) {
                        val = ena = run = 0;
                        nr = 0;
                        for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1087,11 +1136,17 @@ static void print_aggr(char *prefix)
                        if (run == 0 || ena == 0) {
                                aggr_printout(counter, id, nr);
 
-                               fprintf(output, "%*s%s%*s",
+                               fprintf(output, "%*s%s",
                                        csv_output ? 0 : 18,
                                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                                       csv_sep,
-                                       csv_output ? 0 : -24,
+                                       csv_sep);
+
+                               fprintf(output, "%-*s%s",
+                                       csv_output ? 0 : unit_width,
+                                       counter->unit, csv_sep);
+
+                               fprintf(output, "%*s",
+                                       csv_output ? 0 : -25,
                                        perf_evsel__name(counter));
 
                                if (counter->cgrp)
@@ -1101,11 +1156,12 @@ static void print_aggr(char *prefix)
                                fputc('\n', output);
                                continue;
                        }
+                       uval = val * counter->scale;
 
                        if (nsec_counter(counter))
-                               nsec_printout(id, nr, counter, val);
+                               nsec_printout(id, nr, counter, uval);
                        else
-                               abs_printout(id, nr, counter, val);
+                               abs_printout(id, nr, counter, uval);
 
                        if (!csv_output) {
                                print_noise(counter, 1.0);
@@ -1128,16 +1184,21 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
        struct perf_stat *ps = counter->priv;
        double avg = avg_stats(&ps->res_stats[0]);
        int scaled = counter->counts->scaled;
+       double uval;
 
        if (prefix)
                fprintf(output, "%s", prefix);
 
        if (scaled == -1) {
-               fprintf(output, "%*s%s%*s",
+               fprintf(output, "%*s%s",
                        csv_output ? 0 : 18,
                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                       csv_sep,
-                       csv_output ? 0 : -24,
+                       csv_sep);
+               fprintf(output, "%-*s%s",
+                       csv_output ? 0 : unit_width,
+                       counter->unit, csv_sep);
+               fprintf(output, "%*s",
+                       csv_output ? 0 : -25,
                        perf_evsel__name(counter));
 
                if (counter->cgrp)
@@ -1147,10 +1208,12 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
                return;
        }
 
+       uval = avg * counter->scale;
+
        if (nsec_counter(counter))
-               nsec_printout(-1, 0, counter, avg);
+               nsec_printout(-1, 0, counter, uval);
        else
-               abs_printout(-1, 0, counter, avg);
+               abs_printout(-1, 0, counter, uval);
 
        print_noise(counter, avg);
 
@@ -1177,6 +1240,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 static void print_counter(struct perf_evsel *counter, char *prefix)
 {
        u64 ena, run, val;
+       double uval;
        int cpu;
 
        for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1188,14 +1252,20 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                        fprintf(output, "%s", prefix);
 
                if (run == 0 || ena == 0) {
-                       fprintf(output, "CPU%*d%s%*s%s%*s",
+                       fprintf(output, "CPU%*d%s%*s%s",
                                csv_output ? 0 : -4,
                                perf_evsel__cpus(counter)->map[cpu], csv_sep,
                                csv_output ? 0 : 18,
                                counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                               csv_sep,
-                               csv_output ? 0 : -24,
-                               perf_evsel__name(counter));
+                               csv_sep);
+
+                               fprintf(output, "%-*s%s",
+                                       csv_output ? 0 : unit_width,
+                                       counter->unit, csv_sep);
+
+                               fprintf(output, "%*s",
+                                       csv_output ? 0 : -25,
+                                       perf_evsel__name(counter));
 
                        if (counter->cgrp)
                                fprintf(output, "%s%s",
@@ -1205,10 +1275,12 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                        continue;
                }
 
+               uval = val * counter->scale;
+
                if (nsec_counter(counter))
-                       nsec_printout(cpu, 0, counter, val);
+                       nsec_printout(cpu, 0, counter, uval);
                else
-                       abs_printout(cpu, 0, counter, val);
+                       abs_printout(cpu, 0, counter, uval);
 
                if (!csv_output) {
                        print_noise(counter, 1.0);
@@ -1256,11 +1328,11 @@ static void print_stat(int argc, const char **argv)
                print_aggr(NULL);
                break;
        case AGGR_GLOBAL:
-               list_for_each_entry(counter, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, counter)
                        print_counter_aggr(counter, NULL);
                break;
        case AGGR_NONE:
-               list_for_each_entry(counter, &evsel_list->entries, node)
+               evlist__for_each(evsel_list, counter)
                        print_counter(counter, NULL);
                break;
        default:
@@ -1710,14 +1782,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        if (interval && interval < 100) {
                pr_err("print interval must be >= 100ms\n");
                parse_options_usage(stat_usage, options, "I", 1);
-               goto out_free_maps;
+               goto out;
        }
 
        if (perf_evlist__alloc_stats(evsel_list, interval))
-               goto out_free_maps;
+               goto out;
 
        if (perf_stat_init_aggr_mode())
-               goto out_free_maps;
+               goto out;
 
        /*
         * We dont want to block the signals - that would cause
@@ -1749,8 +1821,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                print_stat(argc, argv);
 
        perf_evlist__free_stats(evsel_list);
-out_free_maps:
-       perf_evlist__delete_maps(evsel_list);
 out:
        perf_evlist__delete(evsel_list);
        return status;
index 41c9bde2fb67f1418faceaaf86475a163694bdeb..652af0b66a625305deac34b0f18ec2e5ccf1d8f0 100644 (file)
 #define SUPPORT_OLD_POWER_EVENTS 1
 #define PWR_EVENT_EXIT -1
 
-
-static unsigned int    numcpus;
-static u64             min_freq;       /* Lowest CPU frequency seen */
-static u64             max_freq;       /* Highest CPU frequency seen */
-static u64             turbo_frequency;
-
-static u64             first_time, last_time;
-
-static bool            power_only;
-
-
 struct per_pid;
-struct per_pidcomm;
-
-struct cpu_sample;
 struct power_event;
 struct wake_event;
 
-struct sample_wrapper;
+struct timechart {
+       struct perf_tool        tool;
+       struct per_pid          *all_data;
+       struct power_event      *power_events;
+       struct wake_event       *wake_events;
+       int                     proc_num;
+       unsigned int            numcpus;
+       u64                     min_freq,       /* Lowest CPU frequency seen */
+                               max_freq,       /* Highest CPU frequency seen */
+                               turbo_frequency,
+                               first_time, last_time;
+       bool                    power_only,
+                               tasks_only,
+                               with_backtrace,
+                               topology;
+};
+
+struct per_pidcomm;
+struct cpu_sample;
 
 /*
  * Datastructure layout:
@@ -124,10 +128,9 @@ struct cpu_sample {
        u64 end_time;
        int type;
        int cpu;
+       const char *backtrace;
 };
 
-static struct per_pid *all_data;
-
 #define CSTATE 1
 #define PSTATE 2
 
@@ -145,12 +148,9 @@ struct wake_event {
        int waker;
        int wakee;
        u64 time;
+       const char *backtrace;
 };
 
-static struct power_event    *power_events;
-static struct wake_event     *wake_events;
-
-struct process_filter;
 struct process_filter {
        char                    *name;
        int                     pid;
@@ -160,9 +160,9 @@ struct process_filter {
 static struct process_filter *process_filter;
 
 
-static struct per_pid *find_create_pid(int pid)
+static struct per_pid *find_create_pid(struct timechart *tchart, int pid)
 {
-       struct per_pid *cursor = all_data;
+       struct per_pid *cursor = tchart->all_data;
 
        while (cursor) {
                if (cursor->pid == pid)
@@ -172,16 +172,16 @@ static struct per_pid *find_create_pid(int pid)
        cursor = zalloc(sizeof(*cursor));
        assert(cursor != NULL);
        cursor->pid = pid;
-       cursor->next = all_data;
-       all_data = cursor;
+       cursor->next = tchart->all_data;
+       tchart->all_data = cursor;
        return cursor;
 }
 
-static void pid_set_comm(int pid, char *comm)
+static void pid_set_comm(struct timechart *tchart, int pid, char *comm)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
-       p = find_create_pid(pid);
+       p = find_create_pid(tchart, pid);
        c = p->all;
        while (c) {
                if (c->comm && strcmp(c->comm, comm) == 0) {
@@ -203,14 +203,14 @@ static void pid_set_comm(int pid, char *comm)
        p->all = c;
 }
 
-static void pid_fork(int pid, int ppid, u64 timestamp)
+static void pid_fork(struct timechart *tchart, int pid, int ppid, u64 timestamp)
 {
        struct per_pid *p, *pp;
-       p = find_create_pid(pid);
-       pp = find_create_pid(ppid);
+       p = find_create_pid(tchart, pid);
+       pp = find_create_pid(tchart, ppid);
        p->ppid = ppid;
        if (pp->current && pp->current->comm && !p->current)
-               pid_set_comm(pid, pp->current->comm);
+               pid_set_comm(tchart, pid, pp->current->comm);
 
        p->start_time = timestamp;
        if (p->current) {
@@ -219,23 +219,24 @@ static void pid_fork(int pid, int ppid, u64 timestamp)
        }
 }
 
-static void pid_exit(int pid, u64 timestamp)
+static void pid_exit(struct timechart *tchart, int pid, u64 timestamp)
 {
        struct per_pid *p;
-       p = find_create_pid(pid);
+       p = find_create_pid(tchart, pid);
        p->end_time = timestamp;
        if (p->current)
                p->current->end_time = timestamp;
 }
 
-static void
-pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end)
+static void pid_put_sample(struct timechart *tchart, int pid, int type,
+                          unsigned int cpu, u64 start, u64 end,
+                          const char *backtrace)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
        struct cpu_sample *sample;
 
-       p = find_create_pid(pid);
+       p = find_create_pid(tchart, pid);
        c = p->current;
        if (!c) {
                c = zalloc(sizeof(*c));
@@ -252,6 +253,7 @@ pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end)
        sample->type = type;
        sample->next = c->samples;
        sample->cpu = cpu;
+       sample->backtrace = backtrace;
        c->samples = sample;
 
        if (sample->type == TYPE_RUNNING && end > start && start > 0) {
@@ -272,84 +274,47 @@ static int cpus_cstate_state[MAX_CPUS];
 static u64 cpus_pstate_start_times[MAX_CPUS];
 static u64 cpus_pstate_state[MAX_CPUS];
 
-static int process_comm_event(struct perf_tool *tool __maybe_unused,
+static int process_comm_event(struct perf_tool *tool,
                              union perf_event *event,
                              struct perf_sample *sample __maybe_unused,
                              struct machine *machine __maybe_unused)
 {
-       pid_set_comm(event->comm.tid, event->comm.comm);
+       struct timechart *tchart = container_of(tool, struct timechart, tool);
+       pid_set_comm(tchart, event->comm.tid, event->comm.comm);
        return 0;
 }
 
-static int process_fork_event(struct perf_tool *tool __maybe_unused,
+static int process_fork_event(struct perf_tool *tool,
                              union perf_event *event,
                              struct perf_sample *sample __maybe_unused,
                              struct machine *machine __maybe_unused)
 {
-       pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
+       struct timechart *tchart = container_of(tool, struct timechart, tool);
+       pid_fork(tchart, event->fork.pid, event->fork.ppid, event->fork.time);
        return 0;
 }
 
-static int process_exit_event(struct perf_tool *tool __maybe_unused,
+static int process_exit_event(struct perf_tool *tool,
                              union perf_event *event,
                              struct perf_sample *sample __maybe_unused,
                              struct machine *machine __maybe_unused)
 {
-       pid_exit(event->fork.pid, event->fork.time);
+       struct timechart *tchart = container_of(tool, struct timechart, tool);
+       pid_exit(tchart, event->fork.pid, event->fork.time);
        return 0;
 }
 
-struct trace_entry {
-       unsigned short          type;
-       unsigned char           flags;
-       unsigned char           preempt_count;
-       int                     pid;
-       int                     lock_depth;
-};
-
 #ifdef SUPPORT_OLD_POWER_EVENTS
 static int use_old_power_events;
-struct power_entry_old {
-       struct trace_entry te;
-       u64     type;
-       u64     value;
-       u64     cpu_id;
-};
 #endif
 
-struct power_processor_entry {
-       struct trace_entry te;
-       u32     state;
-       u32     cpu_id;
-};
-
-#define TASK_COMM_LEN 16
-struct wakeup_entry {
-       struct trace_entry te;
-       char comm[TASK_COMM_LEN];
-       int   pid;
-       int   prio;
-       int   success;
-};
-
-struct sched_switch {
-       struct trace_entry te;
-       char prev_comm[TASK_COMM_LEN];
-       int  prev_pid;
-       int  prev_prio;
-       long prev_state; /* Arjan weeps. */
-       char next_comm[TASK_COMM_LEN];
-       int  next_pid;
-       int  next_prio;
-};
-
 static void c_state_start(int cpu, u64 timestamp, int state)
 {
        cpus_cstate_start_times[cpu] = timestamp;
        cpus_cstate_state[cpu] = state;
 }
 
-static void c_state_end(int cpu, u64 timestamp)
+static void c_state_end(struct timechart *tchart, int cpu, u64 timestamp)
 {
        struct power_event *pwr = zalloc(sizeof(*pwr));
 
@@ -361,12 +326,12 @@ static void c_state_end(int cpu, u64 timestamp)
        pwr->end_time = timestamp;
        pwr->cpu = cpu;
        pwr->type = CSTATE;
-       pwr->next = power_events;
+       pwr->next = tchart->power_events;
 
-       power_events = pwr;
+       tchart->power_events = pwr;
 }
 
-static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
+static void p_state_change(struct timechart *tchart, int cpu, u64 timestamp, u64 new_freq)
 {
        struct power_event *pwr;
 
@@ -382,73 +347,78 @@ static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
        pwr->end_time = timestamp;
        pwr->cpu = cpu;
        pwr->type = PSTATE;
-       pwr->next = power_events;
+       pwr->next = tchart->power_events;
 
        if (!pwr->start_time)
-               pwr->start_time = first_time;
+               pwr->start_time = tchart->first_time;
 
-       power_events = pwr;
+       tchart->power_events = pwr;
 
        cpus_pstate_state[cpu] = new_freq;
        cpus_pstate_start_times[cpu] = timestamp;
 
-       if ((u64)new_freq > max_freq)
-               max_freq = new_freq;
+       if ((u64)new_freq > tchart->max_freq)
+               tchart->max_freq = new_freq;
 
-       if (new_freq < min_freq || min_freq == 0)
-               min_freq = new_freq;
+       if (new_freq < tchart->min_freq || tchart->min_freq == 0)
+               tchart->min_freq = new_freq;
 
-       if (new_freq == max_freq - 1000)
-                       turbo_frequency = max_freq;
+       if (new_freq == tchart->max_freq - 1000)
+               tchart->turbo_frequency = tchart->max_freq;
 }
 
-static void
-sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te)
+static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp,
+                        int waker, int wakee, u8 flags, const char *backtrace)
 {
        struct per_pid *p;
-       struct wakeup_entry *wake = (void *)te;
        struct wake_event *we = zalloc(sizeof(*we));
 
        if (!we)
                return;
 
        we->time = timestamp;
-       we->waker = pid;
+       we->waker = waker;
+       we->backtrace = backtrace;
 
-       if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ))
+       if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ))
                we->waker = -1;
 
-       we->wakee = wake->pid;
-       we->next = wake_events;
-       wake_events = we;
-       p = find_create_pid(we->wakee);
+       we->wakee = wakee;
+       we->next = tchart->wake_events;
+       tchart->wake_events = we;
+       p = find_create_pid(tchart, we->wakee);
 
        if (p && p->current && p->current->state == TYPE_NONE) {
                p->current->state_since = timestamp;
                p->current->state = TYPE_WAITING;
        }
        if (p && p->current && p->current->state == TYPE_BLOCKED) {
-               pid_put_sample(p->pid, p->current->state, cpu, p->current->state_since, timestamp);
+               pid_put_sample(tchart, p->pid, p->current->state, cpu,
+                              p->current->state_since, timestamp, NULL);
                p->current->state_since = timestamp;
                p->current->state = TYPE_WAITING;
        }
 }
 
-static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
+static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp,
+                        int prev_pid, int next_pid, u64 prev_state,
+                        const char *backtrace)
 {
        struct per_pid *p = NULL, *prev_p;
-       struct sched_switch *sw = (void *)te;
-
 
-       prev_p = find_create_pid(sw->prev_pid);
+       prev_p = find_create_pid(tchart, prev_pid);
 
-       p = find_create_pid(sw->next_pid);
+       p = find_create_pid(tchart, next_pid);
 
        if (prev_p->current && prev_p->current->state != TYPE_NONE)
-               pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, prev_p->current->state_since, timestamp);
+               pid_put_sample(tchart, prev_pid, TYPE_RUNNING, cpu,
+                              prev_p->current->state_since, timestamp,
+                              backtrace);
        if (p && p->current) {
                if (p->current->state != TYPE_NONE)
-                       pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp);
+                       pid_put_sample(tchart, next_pid, p->current->state, cpu,
+                                      p->current->state_since, timestamp,
+                                      backtrace);
 
                p->current->state_since = timestamp;
                p->current->state = TYPE_RUNNING;
@@ -457,109 +427,211 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
        if (prev_p->current) {
                prev_p->current->state = TYPE_NONE;
                prev_p->current->state_since = timestamp;
-               if (sw->prev_state & 2)
+               if (prev_state & 2)
                        prev_p->current->state = TYPE_BLOCKED;
-               if (sw->prev_state == 0)
+               if (prev_state == 0)
                        prev_p->current->state = TYPE_WAITING;
        }
 }
 
-typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
-                                 struct perf_sample *sample);
+static const char *cat_backtrace(union perf_event *event,
+                                struct perf_sample *sample,
+                                struct machine *machine)
+{
+       struct addr_location al;
+       unsigned int i;
+       char *p = NULL;
+       size_t p_len;
+       u8 cpumode = PERF_RECORD_MISC_USER;
+       struct addr_location tal;
+       struct ip_callchain *chain = sample->callchain;
+       FILE *f = open_memstream(&p, &p_len);
+
+       if (!f) {
+               perror("open_memstream error");
+               return NULL;
+       }
+
+       if (!chain)
+               goto exit;
 
-static int process_sample_event(struct perf_tool *tool __maybe_unused,
-                               union perf_event *event __maybe_unused,
+       if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
+               fprintf(stderr, "problem processing %d event, skipping it.\n",
+                       event->header.type);
+               goto exit;
+       }
+
+       for (i = 0; i < chain->nr; i++) {
+               u64 ip;
+
+               if (callchain_param.order == ORDER_CALLEE)
+                       ip = chain->ips[i];
+               else
+                       ip = chain->ips[chain->nr - i - 1];
+
+               if (ip >= PERF_CONTEXT_MAX) {
+                       switch (ip) {
+                       case PERF_CONTEXT_HV:
+                               cpumode = PERF_RECORD_MISC_HYPERVISOR;
+                               break;
+                       case PERF_CONTEXT_KERNEL:
+                               cpumode = PERF_RECORD_MISC_KERNEL;
+                               break;
+                       case PERF_CONTEXT_USER:
+                               cpumode = PERF_RECORD_MISC_USER;
+                               break;
+                       default:
+                               pr_debug("invalid callchain context: "
+                                        "%"PRId64"\n", (s64) ip);
+
+                               /*
+                                * It seems the callchain is corrupted.
+                                * Discard all.
+                                */
+                               zfree(&p);
+                               goto exit;
+                       }
+                       continue;
+               }
+
+               tal.filtered = false;
+               thread__find_addr_location(al.thread, machine, cpumode,
+                                          MAP__FUNCTION, ip, &tal);
+
+               if (tal.sym)
+                       fprintf(f, "..... %016" PRIx64 " %s\n", ip,
+                               tal.sym->name);
+               else
+                       fprintf(f, "..... %016" PRIx64 "\n", ip);
+       }
+
+exit:
+       fclose(f);
+
+       return p;
+}
+
+typedef int (*tracepoint_handler)(struct timechart *tchart,
+                                 struct perf_evsel *evsel,
+                                 struct perf_sample *sample,
+                                 const char *backtrace);
+
+static int process_sample_event(struct perf_tool *tool,
+                               union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_evsel *evsel,
-                               struct machine *machine __maybe_unused)
+                               struct machine *machine)
 {
+       struct timechart *tchart = container_of(tool, struct timechart, tool);
+
        if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
-               if (!first_time || first_time > sample->time)
-                       first_time = sample->time;
-               if (last_time < sample->time)
-                       last_time = sample->time;
+               if (!tchart->first_time || tchart->first_time > sample->time)
+                       tchart->first_time = sample->time;
+               if (tchart->last_time < sample->time)
+                       tchart->last_time = sample->time;
        }
 
-       if (sample->cpu > numcpus)
-               numcpus = sample->cpu;
-
        if (evsel->handler != NULL) {
                tracepoint_handler f = evsel->handler;
-               return f(evsel, sample);
+               return f(tchart, evsel, sample,
+                        cat_backtrace(event, sample, machine));
        }
 
        return 0;
 }
 
 static int
-process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused,
-                       struct perf_sample *sample)
+process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
+                       struct perf_evsel *evsel,
+                       struct perf_sample *sample,
+                       const char *backtrace __maybe_unused)
 {
-       struct power_processor_entry *ppe = sample->raw_data;
+       u32 state = perf_evsel__intval(evsel, sample, "state");
+       u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
 
-       if (ppe->state == (u32) PWR_EVENT_EXIT)
-               c_state_end(ppe->cpu_id, sample->time);
+       if (state == (u32)PWR_EVENT_EXIT)
+               c_state_end(tchart, cpu_id, sample->time);
        else
-               c_state_start(ppe->cpu_id, sample->time, ppe->state);
+               c_state_start(cpu_id, sample->time, state);
        return 0;
 }
 
 static int
-process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused,
-                            struct perf_sample *sample)
+process_sample_cpu_frequency(struct timechart *tchart,
+                            struct perf_evsel *evsel,
+                            struct perf_sample *sample,
+                            const char *backtrace __maybe_unused)
 {
-       struct power_processor_entry *ppe = sample->raw_data;
+       u32 state = perf_evsel__intval(evsel, sample, "state");
+       u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
 
-       p_state_change(ppe->cpu_id, sample->time, ppe->state);
+       p_state_change(tchart, cpu_id, sample->time, state);
        return 0;
 }
 
 static int
-process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused,
-                           struct perf_sample *sample)
+process_sample_sched_wakeup(struct timechart *tchart,
+                           struct perf_evsel *evsel,
+                           struct perf_sample *sample,
+                           const char *backtrace)
 {
-       struct trace_entry *te = sample->raw_data;
+       u8 flags = perf_evsel__intval(evsel, sample, "common_flags");
+       int waker = perf_evsel__intval(evsel, sample, "common_pid");
+       int wakee = perf_evsel__intval(evsel, sample, "pid");
 
-       sched_wakeup(sample->cpu, sample->time, sample->pid, te);
+       sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace);
        return 0;
 }
 
 static int
-process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused,
-                           struct perf_sample *sample)
+process_sample_sched_switch(struct timechart *tchart,
+                           struct perf_evsel *evsel,
+                           struct perf_sample *sample,
+                           const char *backtrace)
 {
-       struct trace_entry *te = sample->raw_data;
+       int prev_pid = perf_evsel__intval(evsel, sample, "prev_pid");
+       int next_pid = perf_evsel__intval(evsel, sample, "next_pid");
+       u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state");
 
-       sched_switch(sample->cpu, sample->time, te);
+       sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid,
+                    prev_state, backtrace);
        return 0;
 }
 
 #ifdef SUPPORT_OLD_POWER_EVENTS
 static int
-process_sample_power_start(struct perf_evsel *evsel __maybe_unused,
-                          struct perf_sample *sample)
+process_sample_power_start(struct timechart *tchart __maybe_unused,
+                          struct perf_evsel *evsel,
+                          struct perf_sample *sample,
+                          const char *backtrace __maybe_unused)
 {
-       struct power_entry_old *peo = sample->raw_data;
+       u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
+       u64 value = perf_evsel__intval(evsel, sample, "value");
 
-       c_state_start(peo->cpu_id, sample->time, peo->value);
+       c_state_start(cpu_id, sample->time, value);
        return 0;
 }
 
 static int
-process_sample_power_end(struct perf_evsel *evsel __maybe_unused,
-                        struct perf_sample *sample)
+process_sample_power_end(struct timechart *tchart,
+                        struct perf_evsel *evsel __maybe_unused,
+                        struct perf_sample *sample,
+                        const char *backtrace __maybe_unused)
 {
-       c_state_end(sample->cpu, sample->time);
+       c_state_end(tchart, sample->cpu, sample->time);
        return 0;
 }
 
 static int
-process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused,
-                              struct perf_sample *sample)
+process_sample_power_frequency(struct timechart *tchart,
+                              struct perf_evsel *evsel,
+                              struct perf_sample *sample,
+                              const char *backtrace __maybe_unused)
 {
-       struct power_entry_old *peo = sample->raw_data;
+       u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
+       u64 value = perf_evsel__intval(evsel, sample, "value");
 
-       p_state_change(peo->cpu_id, sample->time, peo->value);
+       p_state_change(tchart, cpu_id, sample->time, value);
        return 0;
 }
 #endif /* SUPPORT_OLD_POWER_EVENTS */
@@ -568,12 +640,12 @@ process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused,
  * After the last sample we need to wrap up the current C/P state
  * and close out each CPU for these.
  */
-static void end_sample_processing(void)
+static void end_sample_processing(struct timechart *tchart)
 {
        u64 cpu;
        struct power_event *pwr;
 
-       for (cpu = 0; cpu <= numcpus; cpu++) {
+       for (cpu = 0; cpu <= tchart->numcpus; cpu++) {
                /* C state */
 #if 0
                pwr = zalloc(sizeof(*pwr));
@@ -582,12 +654,12 @@ static void end_sample_processing(void)
 
                pwr->state = cpus_cstate_state[cpu];
                pwr->start_time = cpus_cstate_start_times[cpu];
-               pwr->end_time = last_time;
+               pwr->end_time = tchart->last_time;
                pwr->cpu = cpu;
                pwr->type = CSTATE;
-               pwr->next = power_events;
+               pwr->next = tchart->power_events;
 
-               power_events = pwr;
+               tchart->power_events = pwr;
 #endif
                /* P state */
 
@@ -597,32 +669,32 @@ static void end_sample_processing(void)
 
                pwr->state = cpus_pstate_state[cpu];
                pwr->start_time = cpus_pstate_start_times[cpu];
-               pwr->end_time = last_time;
+               pwr->end_time = tchart->last_time;
                pwr->cpu = cpu;
                pwr->type = PSTATE;
-               pwr->next = power_events;
+               pwr->next = tchart->power_events;
 
                if (!pwr->start_time)
-                       pwr->start_time = first_time;
+                       pwr->start_time = tchart->first_time;
                if (!pwr->state)
-                       pwr->state = min_freq;
-               power_events = pwr;
+                       pwr->state = tchart->min_freq;
+               tchart->power_events = pwr;
        }
 }
 
 /*
  * Sort the pid datastructure
  */
-static void sort_pids(void)
+static void sort_pids(struct timechart *tchart)
 {
        struct per_pid *new_list, *p, *cursor, *prev;
        /* sort by ppid first, then by pid, lowest to highest */
 
        new_list = NULL;
 
-       while (all_data) {
-               p = all_data;
-               all_data = p->next;
+       while (tchart->all_data) {
+               p = tchart->all_data;
+               tchart->all_data = p->next;
                p->next = NULL;
 
                if (new_list == NULL) {
@@ -655,14 +727,14 @@ static void sort_pids(void)
                                prev->next = p;
                }
        }
-       all_data = new_list;
+       tchart->all_data = new_list;
 }
 
 
-static void draw_c_p_states(void)
+static void draw_c_p_states(struct timechart *tchart)
 {
        struct power_event *pwr;
-       pwr = power_events;
+       pwr = tchart->power_events;
 
        /*
         * two pass drawing so that the P state bars are on top of the C state blocks
@@ -673,30 +745,30 @@ static void draw_c_p_states(void)
                pwr = pwr->next;
        }
 
-       pwr = power_events;
+       pwr = tchart->power_events;
        while (pwr) {
                if (pwr->type == PSTATE) {
                        if (!pwr->state)
-                               pwr->state = min_freq;
+                               pwr->state = tchart->min_freq;
                        svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
                }
                pwr = pwr->next;
        }
 }
 
-static void draw_wakeups(void)
+static void draw_wakeups(struct timechart *tchart)
 {
        struct wake_event *we;
        struct per_pid *p;
        struct per_pidcomm *c;
 
-       we = wake_events;
+       we = tchart->wake_events;
        while (we) {
                int from = 0, to = 0;
                char *task_from = NULL, *task_to = NULL;
 
                /* locate the column of the waker and wakee */
-               p = all_data;
+               p = tchart->all_data;
                while (p) {
                        if (p->pid == we->waker || p->pid == we->wakee) {
                                c = p->all;
@@ -739,11 +811,12 @@ static void draw_wakeups(void)
                }
 
                if (we->waker == -1)
-                       svg_interrupt(we->time, to);
+                       svg_interrupt(we->time, to, we->backtrace);
                else if (from && to && abs(from - to) == 1)
-                       svg_wakeline(we->time, from, to);
+                       svg_wakeline(we->time, from, to, we->backtrace);
                else
-                       svg_partial_wakeline(we->time, from, task_from, to, task_to);
+                       svg_partial_wakeline(we->time, from, task_from, to,
+                                            task_to, we->backtrace);
                we = we->next;
 
                free(task_from);
@@ -751,19 +824,25 @@ static void draw_wakeups(void)
        }
 }
 
-static void draw_cpu_usage(void)
+static void draw_cpu_usage(struct timechart *tchart)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
        struct cpu_sample *sample;
-       p = all_data;
+       p = tchart->all_data;
        while (p) {
                c = p->all;
                while (c) {
                        sample = c->samples;
                        while (sample) {
-                               if (sample->type == TYPE_RUNNING)
-                                       svg_process(sample->cpu, sample->start_time, sample->end_time, "sample", c->comm);
+                               if (sample->type == TYPE_RUNNING) {
+                                       svg_process(sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   p->pid,
+                                                   c->comm,
+                                                   sample->backtrace);
+                               }
 
                                sample = sample->next;
                        }
@@ -773,16 +852,16 @@ static void draw_cpu_usage(void)
        }
 }
 
-static void draw_process_bars(void)
+static void draw_process_bars(struct timechart *tchart)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
        struct cpu_sample *sample;
        int Y = 0;
 
-       Y = 2 * numcpus + 2;
+       Y = 2 * tchart->numcpus + 2;
 
-       p = all_data;
+       p = tchart->all_data;
        while (p) {
                c = p->all;
                while (c) {
@@ -796,11 +875,20 @@ static void draw_process_bars(void)
                        sample = c->samples;
                        while (sample) {
                                if (sample->type == TYPE_RUNNING)
-                                       svg_sample(Y, sample->cpu, sample->start_time, sample->end_time);
+                                       svg_running(Y, sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   sample->backtrace);
                                if (sample->type == TYPE_BLOCKED)
-                                       svg_box(Y, sample->start_time, sample->end_time, "blocked");
+                                       svg_blocked(Y, sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   sample->backtrace);
                                if (sample->type == TYPE_WAITING)
-                                       svg_waiting(Y, sample->start_time, sample->end_time);
+                                       svg_waiting(Y, sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   sample->backtrace);
                                sample = sample->next;
                        }
 
@@ -853,21 +941,21 @@ static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
        return 0;
 }
 
-static int determine_display_tasks_filtered(void)
+static int determine_display_tasks_filtered(struct timechart *tchart)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
        int count = 0;
 
-       p = all_data;
+       p = tchart->all_data;
        while (p) {
                p->display = 0;
                if (p->start_time == 1)
-                       p->start_time = first_time;
+                       p->start_time = tchart->first_time;
 
                /* no exit marker, task kept running to the end */
                if (p->end_time == 0)
-                       p->end_time = last_time;
+                       p->end_time = tchart->last_time;
 
                c = p->all;
 
@@ -875,7 +963,7 @@ static int determine_display_tasks_filtered(void)
                        c->display = 0;
 
                        if (c->start_time == 1)
-                               c->start_time = first_time;
+                               c->start_time = tchart->first_time;
 
                        if (passes_filter(p, c)) {
                                c->display = 1;
@@ -884,7 +972,7 @@ static int determine_display_tasks_filtered(void)
                        }
 
                        if (c->end_time == 0)
-                               c->end_time = last_time;
+                               c->end_time = tchart->last_time;
 
                        c = c->next;
                }
@@ -893,25 +981,25 @@ static int determine_display_tasks_filtered(void)
        return count;
 }
 
-static int determine_display_tasks(u64 threshold)
+static int determine_display_tasks(struct timechart *tchart, u64 threshold)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
        int count = 0;
 
        if (process_filter)
-               return determine_display_tasks_filtered();
+               return determine_display_tasks_filtered(tchart);
 
-       p = all_data;
+       p = tchart->all_data;
        while (p) {
                p->display = 0;
                if (p->start_time == 1)
-                       p->start_time = first_time;
+                       p->start_time = tchart->first_time;
 
                /* no exit marker, task kept running to the end */
                if (p->end_time == 0)
-                       p->end_time = last_time;
-               if (p->total_time >= threshold && !power_only)
+                       p->end_time = tchart->last_time;
+               if (p->total_time >= threshold)
                        p->display = 1;
 
                c = p->all;
@@ -920,15 +1008,15 @@ static int determine_display_tasks(u64 threshold)
                        c->display = 0;
 
                        if (c->start_time == 1)
-                               c->start_time = first_time;
+                               c->start_time = tchart->first_time;
 
-                       if (c->total_time >= threshold && !power_only) {
+                       if (c->total_time >= threshold) {
                                c->display = 1;
                                count++;
                        }
 
                        if (c->end_time == 0)
-                               c->end_time = last_time;
+                               c->end_time = tchart->last_time;
 
                        c = c->next;
                }
@@ -941,45 +1029,74 @@ static int determine_display_tasks(u64 threshold)
 
 #define TIME_THRESH 10000000
 
-static void write_svg_file(const char *filename)
+static void write_svg_file(struct timechart *tchart, const char *filename)
 {
        u64 i;
        int count;
+       int thresh = TIME_THRESH;
 
-       numcpus++;
-
+       if (tchart->power_only)
+               tchart->proc_num = 0;
 
-       count = determine_display_tasks(TIME_THRESH);
+       /* We'd like to show at least proc_num tasks;
+        * be less picky if we have fewer */
+       do {
+               count = determine_display_tasks(tchart, thresh);
+               thresh /= 10;
+       } while (!process_filter && thresh && count < tchart->proc_num);
 
-       /* We'd like to show at least 15 tasks; be less picky if we have fewer */
-       if (count < 15)
-               count = determine_display_tasks(TIME_THRESH / 10);
-
-       open_svg(filename, numcpus, count, first_time, last_time);
+       open_svg(filename, tchart->numcpus, count, tchart->first_time, tchart->last_time);
 
        svg_time_grid();
        svg_legenda();
 
-       for (i = 0; i < numcpus; i++)
-               svg_cpu_box(i, max_freq, turbo_frequency);
+       for (i = 0; i < tchart->numcpus; i++)
+               svg_cpu_box(i, tchart->max_freq, tchart->turbo_frequency);
 
-       draw_cpu_usage();
-       draw_process_bars();
-       draw_c_p_states();
-       draw_wakeups();
+       draw_cpu_usage(tchart);
+       if (tchart->proc_num)
+               draw_process_bars(tchart);
+       if (!tchart->tasks_only)
+               draw_c_p_states(tchart);
+       if (tchart->proc_num)
+               draw_wakeups(tchart);
 
        svg_close();
 }
 
-static int __cmd_timechart(const char *output_name)
+static int process_header(struct perf_file_section *section __maybe_unused,
+                         struct perf_header *ph,
+                         int feat,
+                         int fd __maybe_unused,
+                         void *data)
+{
+       struct timechart *tchart = data;
+
+       switch (feat) {
+       case HEADER_NRCPUS:
+               tchart->numcpus = ph->env.nr_cpus_avail;
+               break;
+
+       case HEADER_CPU_TOPOLOGY:
+               if (!tchart->topology)
+                       break;
+
+               if (svg_build_topology_map(ph->env.sibling_cores,
+                                          ph->env.nr_sibling_cores,
+                                          ph->env.sibling_threads,
+                                          ph->env.nr_sibling_threads))
+                       fprintf(stderr, "problem building topology\n");
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int __cmd_timechart(struct timechart *tchart, const char *output_name)
 {
-       struct perf_tool perf_timechart = {
-               .comm            = process_comm_event,
-               .fork            = process_fork_event,
-               .exit            = process_exit_event,
-               .sample          = process_sample_event,
-               .ordered_samples = true,
-       };
        const struct perf_evsel_str_handler power_tracepoints[] = {
                { "power:cpu_idle",             process_sample_cpu_idle },
                { "power:cpu_frequency",        process_sample_cpu_frequency },
@@ -997,12 +1114,17 @@ static int __cmd_timechart(const char *output_name)
        };
 
        struct perf_session *session = perf_session__new(&file, false,
-                                                        &perf_timechart);
+                                                        &tchart->tool);
        int ret = -EINVAL;
 
        if (session == NULL)
                return -ENOMEM;
 
+       (void)perf_header__process_sections(&session->header,
+                                           perf_data_file__fd(session->file),
+                                           tchart,
+                                           process_header);
+
        if (!perf_session__has_traces(session, "timechart record"))
                goto out_delete;
 
@@ -1012,69 +1134,111 @@ static int __cmd_timechart(const char *output_name)
                goto out_delete;
        }
 
-       ret = perf_session__process_events(session, &perf_timechart);
+       ret = perf_session__process_events(session, &tchart->tool);
        if (ret)
                goto out_delete;
 
-       end_sample_processing();
+       end_sample_processing(tchart);
 
-       sort_pids();
+       sort_pids(tchart);
 
-       write_svg_file(output_name);
+       write_svg_file(tchart, output_name);
 
        pr_info("Written %2.1f seconds of trace to %s.\n",
-               (last_time - first_time) / 1000000000.0, output_name);
+               (tchart->last_time - tchart->first_time) / 1000000000.0, output_name);
 out_delete:
        perf_session__delete(session);
        return ret;
 }
 
-static int __cmd_record(int argc, const char **argv)
+static int timechart__record(struct timechart *tchart, int argc, const char **argv)
 {
-#ifdef SUPPORT_OLD_POWER_EVENTS
-       const char * const record_old_args[] = {
+       unsigned int rec_argc, i, j;
+       const char **rec_argv;
+       const char **p;
+       unsigned int record_elems;
+
+       const char * const common_args[] = {
                "record", "-a", "-R", "-c", "1",
+       };
+       unsigned int common_args_nr = ARRAY_SIZE(common_args);
+
+       const char * const backtrace_args[] = {
+               "-g",
+       };
+       unsigned int backtrace_args_no = ARRAY_SIZE(backtrace_args);
+
+       const char * const power_args[] = {
+               "-e", "power:cpu_frequency",
+               "-e", "power:cpu_idle",
+       };
+       unsigned int power_args_nr = ARRAY_SIZE(power_args);
+
+       const char * const old_power_args[] = {
+#ifdef SUPPORT_OLD_POWER_EVENTS
                "-e", "power:power_start",
                "-e", "power:power_end",
                "-e", "power:power_frequency",
-               "-e", "sched:sched_wakeup",
-               "-e", "sched:sched_switch",
-       };
 #endif
-       const char * const record_new_args[] = {
-               "record", "-a", "-R", "-c", "1",
-               "-e", "power:cpu_frequency",
-               "-e", "power:cpu_idle",
+       };
+       unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args);
+
+       const char * const tasks_args[] = {
                "-e", "sched:sched_wakeup",
                "-e", "sched:sched_switch",
        };
-       unsigned int rec_argc, i, j;
-       const char **rec_argv;
-       const char * const *record_args = record_new_args;
-       unsigned int record_elems = ARRAY_SIZE(record_new_args);
+       unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args);
 
 #ifdef SUPPORT_OLD_POWER_EVENTS
        if (!is_valid_tracepoint("power:cpu_idle") &&
            is_valid_tracepoint("power:power_start")) {
                use_old_power_events = 1;
-               record_args = record_old_args;
-               record_elems = ARRAY_SIZE(record_old_args);
+               power_args_nr = 0;
+       } else {
+               old_power_args_nr = 0;
        }
 #endif
 
-       rec_argc = record_elems + argc - 1;
+       if (tchart->power_only)
+               tasks_args_nr = 0;
+
+       if (tchart->tasks_only) {
+               power_args_nr = 0;
+               old_power_args_nr = 0;
+       }
+
+       if (!tchart->with_backtrace)
+               backtrace_args_no = 0;
+
+       record_elems = common_args_nr + tasks_args_nr +
+               power_args_nr + old_power_args_nr + backtrace_args_no;
+
+       rec_argc = record_elems + argc;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
        if (rec_argv == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < record_elems; i++)
-               rec_argv[i] = strdup(record_args[i]);
+       p = rec_argv;
+       for (i = 0; i < common_args_nr; i++)
+               *p++ = strdup(common_args[i]);
+
+       for (i = 0; i < backtrace_args_no; i++)
+               *p++ = strdup(backtrace_args[i]);
+
+       for (i = 0; i < tasks_args_nr; i++)
+               *p++ = strdup(tasks_args[i]);
+
+       for (i = 0; i < power_args_nr; i++)
+               *p++ = strdup(power_args[i]);
 
-       for (j = 1; j < (unsigned int)argc; j++, i++)
-               rec_argv[i] = argv[j];
+       for (i = 0; i < old_power_args_nr; i++)
+               *p++ = strdup(old_power_args[i]);
 
-       return cmd_record(i, rec_argv, NULL);
+       for (j = 1; j < (unsigned int)argc; j++)
+               *p++ = argv[j];
+
+       return cmd_record(rec_argc, rec_argv, NULL);
 }
 
 static int
@@ -1086,20 +1250,56 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
        return 0;
 }
 
+static int
+parse_highlight(const struct option *opt __maybe_unused, const char *arg,
+               int __maybe_unused unset)
+{
+       unsigned long duration = strtoul(arg, NULL, 0);
+
+       if (svg_highlight || svg_highlight_name)
+               return -1;
+
+       if (duration)
+               svg_highlight = duration;
+       else
+               svg_highlight_name = strdup(arg);
+
+       return 0;
+}
+
 int cmd_timechart(int argc, const char **argv,
                  const char *prefix __maybe_unused)
 {
+       struct timechart tchart = {
+               .tool = {
+                       .comm            = process_comm_event,
+                       .fork            = process_fork_event,
+                       .exit            = process_exit_event,
+                       .sample          = process_sample_event,
+                       .ordered_samples = true,
+               },
+               .proc_num = 15,
+       };
        const char *output_name = "output.svg";
-       const struct option options[] = {
+       const struct option timechart_options[] = {
        OPT_STRING('i', "input", &input_name, "file", "input file name"),
        OPT_STRING('o', "output", &output_name, "file", "output file name"),
        OPT_INTEGER('w', "width", &svg_page_width, "page width"),
-       OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
+       OPT_CALLBACK(0, "highlight", NULL, "duration or task name",
+                     "highlight tasks. Pass duration in ns or process name.",
+                      parse_highlight),
+       OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
+       OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
+                   "output processes data only"),
        OPT_CALLBACK('p', "process", NULL, "process",
                      "process selector. Pass a pid or process name.",
                       parse_process),
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                    "Look for files with symbols relative to this directory"),
+       OPT_INTEGER('n', "proc-num", &tchart.proc_num,
+                   "min. number of tasks to print"),
+       OPT_BOOLEAN('t', "topology", &tchart.topology,
+                   "sort CPUs according to topology"),
        OPT_END()
        };
        const char * const timechart_usage[] = {
@@ -1107,17 +1307,41 @@ int cmd_timechart(int argc, const char **argv,
                NULL
        };
 
-       argc = parse_options(argc, argv, options, timechart_usage,
+       const struct option record_options[] = {
+       OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
+       OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
+                   "output processes data only"),
+       OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
+       OPT_END()
+       };
+       const char * const record_usage[] = {
+               "perf timechart record [<options>]",
+               NULL
+       };
+       argc = parse_options(argc, argv, timechart_options, timechart_usage,
                        PARSE_OPT_STOP_AT_NON_OPTION);
 
+       if (tchart.power_only && tchart.tasks_only) {
+               pr_err("-P and -T options cannot be used at the same time.\n");
+               return -1;
+       }
+
        symbol__init();
 
-       if (argc && !strncmp(argv[0], "rec", 3))
-               return __cmd_record(argc, argv);
-       else if (argc)
-               usage_with_options(timechart_usage, options);
+       if (argc && !strncmp(argv[0], "rec", 3)) {
+               argc = parse_options(argc, argv, record_options, record_usage,
+                                    PARSE_OPT_STOP_AT_NON_OPTION);
+
+               if (tchart.power_only && tchart.tasks_only) {
+                       pr_err("-P and -T options cannot be used at the same time.\n");
+                       return -1;
+               }
+
+               return timechart__record(&tchart, argc, argv);
+       } else if (argc)
+               usage_with_options(timechart_usage, timechart_options);
 
        setup_pager();
 
-       return __cmd_timechart(output_name);
+       return __cmd_timechart(&tchart, output_name);
 }
index 71e6402729a8616bf9b9fe8e2141ea08ac0bbca2..76cd510d34d023bf3c580ec2b3e2e217d8831cba 100644 (file)
@@ -189,21 +189,18 @@ static void perf_top__record_precise_ip(struct perf_top *top,
        if (pthread_mutex_trylock(&notes->lock))
                return;
 
-       if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
-               pthread_mutex_unlock(&notes->lock);
-               pr_err("Not enough memory for annotating '%s' symbol!\n",
-                      sym->name);
-               sleep(1);
-               return;
-       }
-
        ip = he->ms.map->map_ip(he->ms.map, ip);
-       err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
+       err = hist_entry__inc_addr_samples(he, counter, ip);
 
        pthread_mutex_unlock(&notes->lock);
 
        if (err == -ERANGE && !he->ms.map->erange_warned)
                ui__warn_map_erange(he->ms.map, sym, ip);
+       else if (err == -ENOMEM) {
+               pr_err("Not enough memory for annotating '%s' symbol!\n",
+                      sym->name);
+               sleep(1);
+       }
 }
 
 static void perf_top__show_details(struct perf_top *top)
@@ -485,7 +482,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
 
                                fprintf(stderr, "\nAvailable events:");
 
-                               list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
+                               evlist__for_each(top->evlist, top->sym_evsel)
                                        fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
 
                                prompt_integer(&counter, "Enter details event counter");
@@ -496,7 +493,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
                                        sleep(1);
                                        break;
                                }
-                               list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
+                               evlist__for_each(top->evlist, top->sym_evsel)
                                        if (top->sym_evsel->idx == counter)
                                                break;
                        } else
@@ -578,7 +575,7 @@ static void *display_thread_tui(void *arg)
         * Zooming in/out UIDs. For now juse use whatever the user passed
         * via --uid.
         */
-       list_for_each_entry(pos, &top->evlist->entries, node)
+       evlist__for_each(top->evlist, pos)
                pos->hists.uid_filter_str = top->record_opts.target.uid_str;
 
        perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
@@ -634,26 +631,9 @@ repeat:
        return NULL;
 }
 
-/* Tag samples to be skipped. */
-static const char *skip_symbols[] = {
-       "intel_idle",
-       "default_idle",
-       "native_safe_halt",
-       "cpu_idle",
-       "enter_idle",
-       "exit_idle",
-       "mwait_idle",
-       "mwait_idle_with_hints",
-       "poll_idle",
-       "ppc64_runlatch_off",
-       "pseries_dedicated_idle_sleep",
-       NULL
-};
-
 static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
 {
        const char *name = sym->name;
-       int i;
 
        /*
         * ppc64 uses function descriptors and appends a '.' to the
@@ -671,12 +651,8 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
            strstr(name, "_text_end"))
                return 1;
 
-       for (i = 0; skip_symbols[i]; i++) {
-               if (!strcmp(skip_symbols[i], name)) {
-                       sym->ignore = true;
-                       break;
-               }
-       }
+       if (symbol__is_idle(sym))
+               sym->ignore = true;
 
        return 0;
 }
@@ -767,15 +743,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
        if (al.sym == NULL || !al.sym->ignore) {
                struct hist_entry *he;
 
-               if ((sort__has_parent || symbol_conf.use_callchain) &&
-                   sample->callchain) {
-                       err = machine__resolve_callchain(machine, evsel,
-                                                        al.thread, sample,
-                                                        &parent, &al,
-                                                        top->max_stack);
-                       if (err)
-                               return;
-               }
+               err = sample__resolve_callchain(sample, &parent, evsel, &al,
+                                               top->max_stack);
+               if (err)
+                       return;
 
                he = perf_evsel__add_hist_entry(evsel, &al, sample);
                if (he == NULL) {
@@ -783,12 +754,9 @@ static void perf_event__process_sample(struct perf_tool *tool,
                        return;
                }
 
-               if (symbol_conf.use_callchain) {
-                       err = callchain_append(he->callchain, &callchain_cursor,
-                                              sample->period);
-                       if (err)
-                               return;
-               }
+               err = hist_entry__append_callchain(he, sample);
+               if (err)
+                       return;
 
                if (sort__has_sym)
                        perf_top__record_precise_ip(top, he, evsel->idx, ip);
@@ -878,11 +846,11 @@ static int perf_top__start_counters(struct perf_top *top)
        char msg[512];
        struct perf_evsel *counter;
        struct perf_evlist *evlist = top->evlist;
-       struct perf_record_opts *opts = &top->record_opts;
+       struct record_opts *opts = &top->record_opts;
 
        perf_evlist__config(evlist, opts);
 
-       list_for_each_entry(counter, &evlist->entries, node) {
+       evlist__for_each(evlist, counter) {
 try_again:
                if (perf_evsel__open(counter, top->evlist->cpus,
                                     top->evlist->threads) < 0) {
@@ -930,7 +898,7 @@ static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused)
 
 static int __cmd_top(struct perf_top *top)
 {
-       struct perf_record_opts *opts = &top->record_opts;
+       struct record_opts *opts = &top->record_opts;
        pthread_t thread;
        int ret;
 
@@ -1052,7 +1020,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                .max_stack           = PERF_MAX_STACK_DEPTH,
                .sym_pcnt_filter     = 5,
        };
-       struct perf_record_opts *opts = &top.record_opts;
+       struct record_opts *opts = &top.record_opts;
        struct target *target = &opts->target;
        const struct option options[] = {
        OPT_CALLBACK('e', "event", &top.evlist, "event",
@@ -1084,7 +1052,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                            "dump the symbol table used for profiling"),
        OPT_INTEGER('f', "count-filter", &top.count_filter,
                    "only display functions with more events than this"),
-       OPT_BOOLEAN('g', "group", &opts->group,
+       OPT_BOOLEAN(0, "group", &opts->group,
                            "put the counters into a counter group"),
        OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
                    "child tasks do not inherit counters"),
@@ -1105,7 +1073,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                   " abort, in_tx, transaction"),
        OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
                    "Show a column with the number of samples"),
-       OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
+       OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts,
                           NULL, "enables call-graph recording",
                           &callchain_opt),
        OPT_CALLBACK(0, "call-graph", &top.record_opts,
@@ -1195,7 +1163,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        if (!top.evlist->nr_entries &&
            perf_evlist__add_default(top.evlist) < 0) {
                ui__error("Not enough memory for event selector list\n");
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        symbol_conf.nr_events = top.evlist->nr_entries;
@@ -1203,9 +1171,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
        if (top.delay_secs < 1)
                top.delay_secs = 1;
 
-       if (perf_record_opts__config(opts)) {
+       if (record_opts__config(opts)) {
                status = -EINVAL;
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        top.sym_evsel = perf_evlist__first(top.evlist);
@@ -1230,8 +1198,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 
        status = __cmd_top(&top);
 
-out_delete_maps:
-       perf_evlist__delete_maps(top.evlist);
 out_delete_evlist:
        perf_evlist__delete(top.evlist);
 
index 8be17fc462baff466a6aa25682f804c4b5fdd1dc..896f27047ed6178fd6aed5566863fb4f4c251e84 100644 (file)
@@ -11,6 +11,8 @@
 #include "util/intlist.h"
 #include "util/thread_map.h"
 #include "util/stat.h"
+#include "trace-event.h"
+#include "util/parse-events.h"
 
 #include <libaudit.h>
 #include <stdlib.h>
@@ -144,8 +146,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
 
 static void perf_evsel__delete_priv(struct perf_evsel *evsel)
 {
-       free(evsel->priv);
-       evsel->priv = NULL;
+       zfree(&evsel->priv);
        perf_evsel__delete(evsel);
 }
 
@@ -163,8 +164,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
        return -ENOMEM;
 
 out_delete:
-       free(evsel->priv);
-       evsel->priv = NULL;
+       zfree(&evsel->priv);
        return -ENOENT;
 }
 
@@ -172,6 +172,10 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
 {
        struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
 
+       /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
+       if (evsel == NULL)
+               evsel = perf_evsel__newtp("syscalls", direction);
+
        if (evsel) {
                if (perf_evsel__init_syscall_tp(evsel, handler))
                        goto out_delete;
@@ -1153,29 +1157,30 @@ struct trace {
                int             max;
                struct syscall  *table;
        } syscalls;
-       struct perf_record_opts opts;
+       struct record_opts      opts;
        struct machine          *host;
        u64                     base_time;
-       bool                    full_time;
        FILE                    *output;
        unsigned long           nr_events;
        struct strlist          *ev_qualifier;
-       bool                    not_ev_qualifier;
-       bool                    live;
        const char              *last_vfs_getname;
        struct intlist          *tid_list;
        struct intlist          *pid_list;
+       double                  duration_filter;
+       double                  runtime_ms;
+       struct {
+               u64             vfs_getname,
+                               proc_getname;
+       } stats;
+       bool                    not_ev_qualifier;
+       bool                    live;
+       bool                    full_time;
        bool                    sched;
        bool                    multiple_threads;
        bool                    summary;
        bool                    summary_only;
        bool                    show_comm;
        bool                    show_tool_stats;
-       double                  duration_filter;
-       double                  runtime_ms;
-       struct {
-               u64             vfs_getname, proc_getname;
-       } stats;
 };
 
 static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
@@ -1272,10 +1277,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
        size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
        struct thread_trace *ttrace = arg->thread->priv;
 
-       if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
-               free(ttrace->paths.table[fd]);
-               ttrace->paths.table[fd] = NULL;
-       }
+       if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
+               zfree(&ttrace->paths.table[fd]);
 
        return printed;
 }
@@ -1430,11 +1433,11 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        sc->fmt  = syscall_fmt__find(sc->name);
 
        snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
-       sc->tp_format = event_format__new("syscalls", tp_name);
+       sc->tp_format = trace_event__tp_format("syscalls", tp_name);
 
        if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
                snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
-               sc->tp_format = event_format__new("syscalls", tp_name);
+               sc->tp_format = trace_event__tp_format("syscalls", tp_name);
        }
 
        if (sc->tp_format == NULL)
@@ -1764,8 +1767,10 @@ static int trace__process_sample(struct perf_tool *tool,
        if (!trace->full_time && trace->base_time == 0)
                trace->base_time = sample->time;
 
-       if (handler)
+       if (handler) {
+               ++trace->nr_events;
                handler(trace, evsel, sample);
+       }
 
        return err;
 }
@@ -1800,10 +1805,11 @@ static int trace__record(int argc, const char **argv)
                "-R",
                "-m", "1024",
                "-c", "1",
-               "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
+               "-e",
        };
 
-       rec_argc = ARRAY_SIZE(record_args) + argc;
+       /* +1 is for the event string below */
+       rec_argc = ARRAY_SIZE(record_args) + 1 + argc;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
        if (rec_argv == NULL)
@@ -1812,6 +1818,17 @@ static int trace__record(int argc, const char **argv)
        for (i = 0; i < ARRAY_SIZE(record_args); i++)
                rec_argv[i] = record_args[i];
 
+       /* event string may be different for older kernels - e.g., RHEL6 */
+       if (is_valid_tracepoint("raw_syscalls:sys_enter"))
+               rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
+       else if (is_valid_tracepoint("syscalls:sys_enter"))
+               rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit";
+       else {
+               pr_err("Neither raw_syscalls nor syscalls events exist.\n");
+               return -1;
+       }
+       i++;
+
        for (j = 0; j < (unsigned int)argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -1869,7 +1886,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
        err = trace__symbols_init(trace, evlist);
        if (err < 0) {
                fprintf(trace->output, "Problems initializing symbol libraries!\n");
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        perf_evlist__config(evlist, &trace->opts);
@@ -1879,10 +1896,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 
        if (forks) {
                err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
-                                                   argv, false, false);
+                                                   argv, false, NULL);
                if (err < 0) {
                        fprintf(trace->output, "Couldn't run the workload!\n");
-                       goto out_delete_maps;
+                       goto out_delete_evlist;
                }
        }
 
@@ -1890,10 +1907,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
        if (err < 0)
                goto out_error_open;
 
-       err = perf_evlist__mmap(evlist, UINT_MAX, false);
+       err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
        if (err < 0) {
                fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
-               goto out_close_evlist;
+               goto out_delete_evlist;
        }
 
        perf_evlist__enable(evlist);
@@ -1977,11 +1994,6 @@ out_disable:
                }
        }
 
-       perf_evlist__munmap(evlist);
-out_close_evlist:
-       perf_evlist__close(evlist);
-out_delete_maps:
-       perf_evlist__delete_maps(evlist);
 out_delete_evlist:
        perf_evlist__delete(evlist);
 out:
@@ -2047,6 +2059,10 @@ static int trace__replay(struct trace *trace)
 
        evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
                                                     "raw_syscalls:sys_enter");
+       /* older kernels have syscalls tp versus raw_syscalls */
+       if (evsel == NULL)
+               evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
+                                                            "syscalls:sys_enter");
        if (evsel == NULL) {
                pr_err("Data file does not have raw_syscalls:sys_enter event\n");
                goto out;
@@ -2060,6 +2076,9 @@ static int trace__replay(struct trace *trace)
 
        evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
                                                     "raw_syscalls:sys_exit");
+       if (evsel == NULL)
+               evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
+                                                            "syscalls:sys_exit");
        if (evsel == NULL) {
                pr_err("Data file does not have raw_syscalls:sys_exit event\n");
                goto out;
@@ -2158,7 +2177,6 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
        size_t printed = data->printed;
        struct trace *trace = data->trace;
        struct thread_trace *ttrace = thread->priv;
-       const char *color;
        double ratio;
 
        if (ttrace == NULL)
@@ -2166,17 +2184,9 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
 
        ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 50.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 25.0)
-               color = PERF_COLOR_GREEN;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
-
-       printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
+       printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
        printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
-       printed += color_fprintf(fp, color, "%.1f%%", ratio);
+       printed += fprintf(fp, "%.1f%%", ratio);
        printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
        printed += thread__dump_stats(ttrace, trace, fp);
 
@@ -2248,7 +2258,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
                        },
                        .user_freq     = UINT_MAX,
                        .user_interval = ULLONG_MAX,
-                       .no_delay      = true,
+                       .no_buffering  = true,
                        .mmap_pages    = 1024,
                },
                .output = stdout,
index f7d11a811c743e6e2836270f4579124007140d32..d604e50fc167b232ad50c3c7cde967c9a0ccd0cf 100644 (file)
@@ -1,28 +1,26 @@
-uname_M := $(shell uname -m 2>/dev/null || echo not)
 
-ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
-                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
-                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-                                  -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
-NO_PERF_REGS := 1
-CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
+ifeq ($(src-perf),)
+src-perf := $(srctree)/tools/perf
+endif
 
-# Additional ARCH settings for x86
-ifeq ($(ARCH),i386)
-  override ARCH := x86
-  NO_PERF_REGS := 0
-  LIBUNWIND_LIBS = -lunwind -lunwind-x86
+ifeq ($(obj-perf),)
+obj-perf := $(OUTPUT)
 endif
 
-ifeq ($(ARCH),x86_64)
-  override ARCH := x86
-  IS_X86_64 := 0
-  ifeq (, $(findstring m32,$(CFLAGS)))
-    IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
-  endif
+ifneq ($(obj-perf),)
+obj-perf := $(abspath $(obj-perf))/
+endif
+
+LIB_INCLUDE := $(srctree)/tools/lib/
+CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
+
+include $(src-perf)/config/Makefile.arch
+
+NO_PERF_REGS := 1
+
+# Additional ARCH settings for x86
+ifeq ($(ARCH),x86)
   ifeq (${IS_X86_64}, 1)
-    RAW_ARCH := x86_64
     CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
     ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
     LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
@@ -36,24 +34,31 @@ ifeq ($(ARCH),arm)
   LIBUNWIND_LIBS = -lunwind -lunwind-arm
 endif
 
-ifeq ($(NO_PERF_REGS),0)
-  CFLAGS += -DHAVE_PERF_REGS_SUPPORT
-endif
-
-ifeq ($(src-perf),)
-src-perf := $(srctree)/tools/perf
-endif
+ifeq ($(LIBUNWIND_LIBS),)
+  NO_LIBUNWIND := 1
+else
+  #
+  # For linking with debug library, run like:
+  #
+  #   make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
+  #
+  ifdef LIBUNWIND_DIR
+    LIBUNWIND_CFLAGS  = -I$(LIBUNWIND_DIR)/include
+    LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
+  endif
+  LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
 
-ifeq ($(obj-perf),)
-obj-perf := $(OUTPUT)
+  # Set per-feature check compilation flags
+  FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
+  FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
+  FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
+  FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
 endif
 
-ifneq ($(obj-perf),)
-obj-perf := $(abspath $(obj-perf))/
+ifeq ($(NO_PERF_REGS),0)
+  CFLAGS += -DHAVE_PERF_REGS_SUPPORT
 endif
 
-LIB_INCLUDE := $(srctree)/tools/lib/
-
 # include ARCH specific config
 -include $(src-perf)/arch/$(ARCH)/Makefile
 
@@ -102,7 +107,7 @@ endif
 
 feature_check = $(eval $(feature_check_code))
 define feature_check_code
-  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
+  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
 endef
 
 feature_set = $(eval $(feature_set_code))
@@ -141,16 +146,26 @@ CORE_FEATURE_TESTS =                      \
        libslang                        \
        libunwind                       \
        on-exit                         \
-       stackprotector                  \
        stackprotector-all              \
        timerfd
 
+# 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
+# mentioned in this list we need to refactor this ;-).
+set_test_all_flags = $(eval $(set_test_all_flags_code))
+define set_test_all_flags_code
+  FEATURE_CHECK_CFLAGS-all  += $(FEATURE_CHECK_CFLAGS-$(1))
+  FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
+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),)
+ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),)
   test-all-failed := 1
 else
   test-all-failed := 0
@@ -180,7 +195,7 @@ ifeq ($(feature-all), 1)
   #
   $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
 else
-  $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1)
+  $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1)
   $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
 endif
 
@@ -209,10 +224,6 @@ ifeq ($(feature-stackprotector-all), 1)
   CFLAGS += -fstack-protector-all
 endif
 
-ifeq ($(feature-stackprotector), 1)
-  CFLAGS += -Wstack-protector
-endif
-
 ifeq ($(DEBUG),0)
   ifeq ($(feature-fortify-source), 1)
     CFLAGS += -D_FORTIFY_SOURCE=2
@@ -221,6 +232,7 @@ endif
 
 CFLAGS += -I$(src-perf)/util/include
 CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
+CFLAGS += -I$(srctree)/tools/include/
 CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi
 CFLAGS += -I$(srctree)/arch/$(ARCH)/include
 CFLAGS += -I$(srctree)/include/uapi
@@ -310,21 +322,7 @@ ifndef NO_LIBELF
   endif # NO_DWARF
 endif # NO_LIBELF
 
-ifeq ($(LIBUNWIND_LIBS),)
-  NO_LIBUNWIND := 1
-endif
-
 ifndef NO_LIBUNWIND
-  #
-  # For linking with debug library, run like:
-  #
-  #   make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
-  #
-  ifdef LIBUNWIND_DIR
-    LIBUNWIND_CFLAGS  := -I$(LIBUNWIND_DIR)/include
-    LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
-  endif
-
   ifneq ($(feature-libunwind), 1)
     msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
     NO_LIBUNWIND := 1
@@ -339,14 +337,12 @@ ifndef NO_LIBUNWIND
       # non-ARM has no dwarf_find_debug_frame() function:
       CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
     endif
-  endif
-endif
 
-ifndef NO_LIBUNWIND
-  CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
-  EXTLIBS += $(LIBUNWIND_LIBS)
-  CFLAGS += $(LIBUNWIND_CFLAGS)
-  LDFLAGS += $(LIBUNWIND_LDFLAGS)
+    CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
+    EXTLIBS += $(LIBUNWIND_LIBS)
+    CFLAGS += $(LIBUNWIND_CFLAGS)
+    LDFLAGS += $(LIBUNWIND_LDFLAGS)
+  endif # ifneq ($(feature-libunwind), 1)
 endif
 
 ifndef NO_LIBAUDIT
@@ -376,7 +372,7 @@ ifndef NO_SLANG
 endif
 
 ifndef NO_GTK2
-  FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
+  FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
   ifneq ($(feature-gtk2), 1)
     msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
     NO_GTK2 := 1
@@ -385,8 +381,8 @@ ifndef NO_GTK2
       GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT
     endif
     CFLAGS += -DHAVE_GTK2_SUPPORT
-    GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
-    GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
+    GTK_CFLAGS += $(shell $(PKG_CONFIG) --cflags gtk+-2.0 2>/dev/null)
+    GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk+-2.0 2>/dev/null)
     EXTLIBS += -ldl
   endif
 endif
@@ -533,7 +529,7 @@ endif
 
 ifndef NO_LIBNUMA
   ifeq ($(feature-libnuma), 0)
-    msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev);
+    msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev);
     NO_LIBNUMA := 1
   else
     CFLAGS += -DHAVE_LIBNUMA_SUPPORT
@@ -598,3 +594,11 @@ else
 perfexec_instdir = $(prefix)/$(perfexecdir)
 endif
 perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
+
+# If we install to $(HOME) we keep the traceevent default:
+# $(HOME)/.traceevent/plugins
+# Otherwise we install plugins into the global $(libdir).
+ifdef DESTDIR
+plugindir=$(libdir)/traceevent/plugins
+plugindir_SQ= $(subst ','\'',$(prefix)/$(plugindir))
+endif
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
new file mode 100644 (file)
index 0000000..fef8ae9
--- /dev/null
@@ -0,0 +1,22 @@
+
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
+                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
+                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
+                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+                                  -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
+
+# Additional ARCH settings for x86
+ifeq ($(ARCH),i386)
+  override ARCH := x86
+endif
+
+ifeq ($(ARCH),x86_64)
+  override ARCH := x86
+  IS_X86_64 := 0
+  ifeq (, $(findstring m32,$(CFLAGS)))
+    IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
+    RAW_ARCH := x86_64
+  endif
+endif
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore
new file mode 100644 (file)
index 0000000..80f3da0
--- /dev/null
@@ -0,0 +1,2 @@
+*.d
+*.bin
index 87e790017c6988b856e3b4e8b47f572a9d8beea9..12e551346fa6414d7b85c69fcee0b224283fdc0c 100644 (file)
@@ -1,95 +1,92 @@
 
 FILES=                                 \
-       test-all                        \
-       test-backtrace                  \
-       test-bionic                     \
-       test-dwarf                      \
-       test-fortify-source             \
-       test-glibc                      \
-       test-gtk2                       \
-       test-gtk2-infobar               \
-       test-hello                      \
-       test-libaudit                   \
-       test-libbfd                     \
-       test-liberty                    \
-       test-liberty-z                  \
-       test-cplus-demangle             \
-       test-libelf                     \
-       test-libelf-getphdrnum          \
-       test-libelf-mmap                \
-       test-libnuma                    \
-       test-libperl                    \
-       test-libpython                  \
-       test-libpython-version          \
-       test-libslang                   \
-       test-libunwind                  \
-       test-libunwind-debug-frame      \
-       test-on-exit                    \
-       test-stackprotector-all         \
-       test-stackprotector             \
-       test-timerfd
-
-CC := $(CC) -MD
+       test-all.bin                    \
+       test-backtrace.bin              \
+       test-bionic.bin                 \
+       test-dwarf.bin                  \
+       test-fortify-source.bin         \
+       test-glibc.bin                  \
+       test-gtk2.bin                   \
+       test-gtk2-infobar.bin           \
+       test-hello.bin                  \
+       test-libaudit.bin               \
+       test-libbfd.bin                 \
+       test-liberty.bin                \
+       test-liberty-z.bin              \
+       test-cplus-demangle.bin         \
+       test-libelf.bin                 \
+       test-libelf-getphdrnum.bin      \
+       test-libelf-mmap.bin            \
+       test-libnuma.bin                \
+       test-libperl.bin                \
+       test-libpython.bin              \
+       test-libpython-version.bin      \
+       test-libslang.bin               \
+       test-libunwind.bin              \
+       test-libunwind-debug-frame.bin  \
+       test-on-exit.bin                \
+       test-stackprotector-all.bin     \
+       test-timerfd.bin
+
+CC := $(CROSS_COMPILE)gcc -MD
+PKG_CONFIG := $(CROSS_COMPILE)pkg-config
 
 all: $(FILES)
 
-BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
+BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
 
 ###############################
 
-test-all:
-       $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
+test-all.bin:
+       $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
 
-test-hello:
+test-hello.bin:
        $(BUILD)
 
-test-stackprotector-all:
+test-stackprotector-all.bin:
        $(BUILD) -Werror -fstack-protector-all
 
-test-stackprotector:
-       $(BUILD) -Werror -fstack-protector -Wstack-protector
-
-test-fortify-source:
+test-fortify-source.bin:
        $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
 
-test-bionic:
+test-bionic.bin:
        $(BUILD)
 
-test-libelf:
+test-libelf.bin:
        $(BUILD) -lelf
 
-test-glibc:
+test-glibc.bin:
        $(BUILD)
 
-test-dwarf:
+test-dwarf.bin:
        $(BUILD) -ldw
 
-test-libelf-mmap:
+test-libelf-mmap.bin:
        $(BUILD) -lelf
 
-test-libelf-getphdrnum:
+test-libelf-getphdrnum.bin:
        $(BUILD) -lelf
 
-test-libnuma:
+test-libnuma.bin:
        $(BUILD) -lnuma
 
-test-libunwind:
-       $(BUILD) $(LIBUNWIND_LIBS) -lelf
+test-libunwind.bin:
+       $(BUILD) -lelf
 
-test-libunwind-debug-frame:
-       $(BUILD) $(LIBUNWIND_LIBS) -lelf
+test-libunwind-debug-frame.bin:
+       $(BUILD) -lelf
 
-test-libaudit:
+test-libaudit.bin:
        $(BUILD) -laudit
 
-test-libslang:
+test-libslang.bin:
        $(BUILD) -I/usr/include/slang -lslang
 
-test-gtk2:
-       $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
+test-gtk2.bin:
+       $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
 
-test-gtk2-infobar:
-       $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
+test-gtk2-infobar.bin:
+       $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
 
 grep-libs  = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
@@ -100,7 +97,7 @@ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
 
-test-libperl:
+test-libperl.bin:
        $(BUILD) $(FLAGS_PERL_EMBED)
 
 override PYTHON := python
@@ -117,31 +114,31 @@ PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
 PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
 FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
 
-test-libpython:
+test-libpython.bin:
        $(BUILD) $(FLAGS_PYTHON_EMBED)
 
-test-libpython-version:
+test-libpython-version.bin:
        $(BUILD) $(FLAGS_PYTHON_EMBED)
 
-test-libbfd:
+test-libbfd.bin:
        $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
 
-test-liberty:
+test-liberty.bin:
        $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
 
-test-liberty-z:
+test-liberty-z.bin:
        $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
 
-test-cplus-demangle:
+test-cplus-demangle.bin:
        $(BUILD) -liberty
 
-test-on-exit:
+test-on-exit.bin:
        $(BUILD)
 
-test-backtrace:
+test-backtrace.bin:
        $(BUILD)
 
-test-timerfd:
+test-timerfd.bin:
        $(BUILD)
 
 -include *.d
index 59e7a705e146d4eb8ea029ebf74878411f8e3898..9b8a544155bbdf2a628f21f400dda8e65f9d51a7 100644 (file)
 # include "test-timerfd.c"
 #undef main
 
+#define main main_test_stackprotector_all
+# include "test-stackprotector-all.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -106,6 +110,7 @@ int main(int argc, char *argv[])
        main_test_backtrace();
        main_test_libnuma();
        main_test_timerfd();
+       main_test_stackprotector_all();
 
        return 0;
 }
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
deleted file mode 100644 (file)
index c9f398d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(void)
-{
-       return puts("hi");
-}
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c
deleted file mode 100644 (file)
index c9f398d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(void)
-{
-       return puts("hi");
-}
index f168debc5be268a75456a3639ccbf120ded594a2..4d985e0f03f584f666fb74b86efd095a064ebaae 100644 (file)
@@ -178,10 +178,3 @@ endef
 _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
 _gea_warn = $(warning The path '$(1)' is not executable.)
 _gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
-
-ifneq ($(findstring $(MAKEFLAGS),s),s)
-  ifneq ($(V),1)
-    QUIET_CLEAN                = @printf '  CLEAN    %s\n' $1;
-    QUIET_INSTALL      = @printf '  INSTALL  %s\n' $1;
-  endif
-endif
similarity index 63%
rename from tools/perf/bash_completion
rename to tools/perf/perf-completion.sh
index 62e157db2e2b01e9400f9348d671fd9ba7267104..496e2abb54824e3fbcc937e3cfc267ea3bfa82b0 100644 (file)
@@ -1,4 +1,4 @@
-# perf completion
+# perf bash and zsh completion
 
 # Taken from git.git's completion script.
 __my_reassemble_comp_words_by_ref()
@@ -89,37 +89,117 @@ __ltrim_colon_completions()
        fi
 }
 
-type perf &>/dev/null &&
-_perf()
+__perfcomp ()
 {
-       local cur words cword prev cmd
+       COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
+}
 
-       COMPREPLY=()
-       _get_comp_words_by_ref -n =: cur words cword prev
+__perfcomp_colon ()
+{
+       __perfcomp "$1" "$2"
+       __ltrim_colon_completions $cur
+}
+
+__perf_main ()
+{
+       local cmd
 
        cmd=${words[0]}
+       COMPREPLY=()
 
        # List perf subcommands or long options
        if [ $cword -eq 1 ]; then
                if [[ $cur == --* ]]; then
-                       COMPREPLY=( $( compgen -W '--help --version \
+                       __perfcomp '--help --version \
                        --exec-path --html-path --paginate --no-pager \
-                       --perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
+                       --perf-dir --work-tree --debugfs-dir' -- "$cur"
                else
                        cmds=$($cmd --list-cmds)
-                       COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+                       __perfcomp "$cmds" "$cur"
                fi
        # List possible events for -e option
        elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
                evts=$($cmd list --raw-dump)
-               COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
-               __ltrim_colon_completions $cur
+               __perfcomp_colon "$evts" "$cur"
+       # List subcommands for 'perf kvm'
+       elif [[ $prev == "kvm" ]]; then
+               subcmds="top record report diff buildid-list stat"
+               __perfcomp_colon "$subcmds" "$cur"
        # List long option names
        elif [[ $cur == --* ]];  then
                subcmd=${words[1]}
                opts=$($cmd $subcmd --list-opts)
-               COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
+               __perfcomp "$opts" "$cur"
        fi
+}
+
+if [[ -n ${ZSH_VERSION-} ]]; then
+       autoload -U +X compinit && compinit
+
+       __perfcomp ()
+       {
+               emulate -L zsh
+
+               local c IFS=$' \t\n'
+               local -a array
+
+               for c in ${=1}; do
+                       case $c in
+                       --*=*|*.) ;;
+                       *) c="$c " ;;
+                       esac
+                       array[${#array[@]}+1]="$c"
+               done
+
+               compset -P '*[=:]'
+               compadd -Q -S '' -a -- array && _ret=0
+       }
+
+       __perfcomp_colon ()
+       {
+               emulate -L zsh
+
+               local cur_="${2-$cur}"
+               local c IFS=$' \t\n'
+               local -a array
+
+               if [[ "$cur_" == *:* ]]; then
+                       local colon_word=${cur_%"${cur_##*:}"}
+               fi
+
+               for c in ${=1}; do
+                       case $c in
+                       --*=*|*.) ;;
+                       *) c="$c " ;;
+                       esac
+                       array[$#array+1]=${c#"$colon_word"}
+               done
+
+               compset -P '*[=:]'
+               compadd -Q -S '' -a -- array && _ret=0
+       }
+
+       _perf ()
+       {
+               local _ret=1 cur cword prev
+               cur=${words[CURRENT]}
+               prev=${words[CURRENT-1]}
+               let cword=CURRENT-1
+               emulate ksh -c __perf_main
+               let _ret && _default && _ret=0
+               return _ret
+       }
+
+       compdef _perf perf
+       return
+fi
+
+type perf &>/dev/null &&
+_perf()
+{
+       local cur words cword prev
+       _get_comp_words_by_ref -n =: cur words cword prev
+       __perf_main
 } &&
 
 complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
index 8b38b4e80ec2c6f6de581022143c989ed6a0e955..431798a4110d6a63a9e802ddeef2b2a701bea2a2 100644 (file)
@@ -13,7 +13,7 @@
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include <pthread.h>
 
 const char perf_usage_string[] =
index b079304bd53daa87ca61a428f4611046741f58e6..3c2f213e979d45d5d1d2c701a6f2b8875e36e13a 100644 (file)
@@ -247,13 +247,14 @@ enum perf_call_graph_mode {
        CALLCHAIN_DWARF
 };
 
-struct perf_record_opts {
+struct record_opts {
        struct target target;
        int          call_graph;
        bool         group;
        bool         inherit_stat;
-       bool         no_delay;
+       bool         no_buffering;
        bool         no_inherit;
+       bool         no_inherit_set;
        bool         no_samples;
        bool         raw_samples;
        bool         sample_address;
@@ -268,6 +269,7 @@ struct perf_record_opts {
        u64          user_interval;
        u16          stack_dump_size;
        bool         sample_transaction;
+       unsigned     initial_delay;
 };
 
 #endif
index 9079a25cd643cdabaf570d19131e4cc0e4fef7f6..44edcb2edcd50b7c4696477e88f6e12176555303 100644 (file)
@@ -3,5 +3,5 @@ command = record
 args    = -i kill >/dev/null 2>&1
 
 [event:base-record]
-sample_type=259
+sample_type=263
 inherit=0
index 85d4919dd62313e64ee508d08cb47b255c4ce0f0..653a8fe2db951d0509d41c26aa11e82550207231 100644 (file)
@@ -391,7 +391,7 @@ static int do_test_code_reading(bool try_kcore)
        struct machines machines;
        struct machine *machine;
        struct thread *thread;
-       struct perf_record_opts opts = {
+       struct record_opts opts = {
                .mmap_pages          = UINT_MAX,
                .user_freq           = UINT_MAX,
                .user_interval       = ULLONG_MAX,
@@ -540,14 +540,11 @@ static int do_test_code_reading(bool try_kcore)
                err = TEST_CODE_READING_OK;
 out_err:
        if (evlist) {
-               perf_evlist__munmap(evlist);
-               perf_evlist__close(evlist);
                perf_evlist__delete(evlist);
-       }
-       if (cpus)
+       } else {
                cpu_map__delete(cpus);
-       if (threads)
                thread_map__delete(threads);
+       }
        machines__destroy_kernel_maps(&machines);
        machine__delete_threads(machine);
        machines__exit(&machines);
index 0197bda9c461c582659d91a80dd074149c4584e8..465cdbc345cf935d4abc7ea5bb465937659c3929 100644 (file)
@@ -79,7 +79,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
        }
 
        err = 0;
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
                        --err;
                        pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
index 173bf42cc03e73e8291e4a6a7cf99f5d8d6d3107..2b6519e0e36f09bdbdeac4865fed851f82a3a1ac 100644 (file)
@@ -208,7 +208,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
         * However the second evsel also has a collapsed entry for
         * "bash [libc] malloc" so total 9 entries will be in the tree.
         */
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
                        const union perf_event event = {
                                .header = {
@@ -466,7 +466,7 @@ int test__hists_link(void)
        if (err < 0)
                goto out;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                hists__collapse_resort(&evsel->hists, NULL);
 
                if (verbose > 2)
index 376c35608534a41dce87354c1741e5b29fbdd612..497957f269d8161f54b39574b5145e0dfc86ff4d 100644 (file)
@@ -51,7 +51,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
  */
 int test__keep_tracking(void)
 {
-       struct perf_record_opts opts = {
+       struct record_opts opts = {
                .mmap_pages          = UINT_MAX,
                .user_freq           = UINT_MAX,
                .user_interval       = ULLONG_MAX,
@@ -142,14 +142,11 @@ int test__keep_tracking(void)
 out_err:
        if (evlist) {
                perf_evlist__disable(evlist);
-               perf_evlist__munmap(evlist);
-               perf_evlist__close(evlist);
                perf_evlist__delete(evlist);
-       }
-       if (cpus)
+       } else {
                cpu_map__delete(cpus);
-       if (threads)
                thread_map__delete(threads);
+       }
 
        return err;
 }
index 2ca0abf1b2b6090165a4ccdb091729da4e7a1c48..00544b8b644b3bf28c97e392955bfcdb36a509fb 100644 (file)
@@ -1,6 +1,16 @@
 PERF := .
 MK   := Makefile
 
+include config/Makefile.arch
+
+# FIXME looks like x86 is the only arch running tests ;-)
+# we need some IS_(32/64) flag to make this generic
+ifeq ($(IS_X86_64),1)
+lib = lib64
+else
+lib = lib
+endif
+
 has = $(shell which $1 2>/dev/null)
 
 # standard single make variable specified
@@ -106,10 +116,36 @@ 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_install       := test -x $$TMP_DEST/bin/perf
-test_make_install_O     := $(test_make_install)
-test_make_install_bin   := $(test_make_install)
-test_make_install_bin_O := $(test_make_install)
+define test_dest_files
+  for file in $(1); do                         \
+    if [ ! -x $$TMP_DEST/$$file ]; then                \
+      echo "  failed to find: $$file";         \
+    fi                                         \
+  done
+endef
+
+installed_files_bin := bin/perf
+installed_files_bin += etc/bash_completion.d/perf
+installed_files_bin += libexec/perf-core/perf-archive
+
+installed_files_plugins := $(lib)/traceevent/plugins/plugin_cfg80211.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_scsi.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_xen.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_function.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_sched_switch.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_mac80211.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_kvm.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_kmem.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_hrtimer.so
+installed_files_plugins += $(lib)/traceevent/plugins/plugin_jbd2.so
+
+installed_files_all := $(installed_files_bin)
+installed_files_all += $(installed_files_plugins)
+
+test_make_install       := $(call test_dest_files,$(installed_files_all))
+test_make_install_O     := $(call test_dest_files,$(installed_files_all))
+test_make_install_bin   := $(call test_dest_files,$(installed_files_bin))
+test_make_install_bin_O := $(call test_dest_files,$(installed_files_bin))
 
 # FIXME nothing gets installed
 test_make_install_man    := test -f $$TMP_DEST/share/man/man1/perf.1
@@ -162,7 +198,7 @@ $(run):
        cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \
        echo "- $@: $$cmd" && echo $$cmd > $@ && \
        ( eval $$cmd ) >> $@ 2>&1; \
-       echo "  test: $(call test,$@)"; \
+       echo "  test: $(call test,$@)" >> $@ 2>&1; \
        $(call test,$@) && \
        rm -f $@ \
        rm -rf $$TMP_DEST
@@ -174,16 +210,22 @@ $(run_O):
        cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \
        echo "- $@: $$cmd" && echo $$cmd > $@ && \
        ( eval $$cmd ) >> $@ 2>&1 && \
-       echo "  test: $(call test_O,$@)"; \
+       echo "  test: $(call test_O,$@)" >> $@ 2>&1; \
        $(call test_O,$@) && \
        rm -f $@ && \
        rm -rf $$TMP_O \
        rm -rf $$TMP_DEST
 
-all: $(run) $(run_O)
+tarpkg:
+       @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \
+       echo "- $@: $$cmd" && echo $$cmd > $@ && \
+       ( eval $$cmd ) >> $@ 2>&1
+       
+
+all: $(run) $(run_O) tarpkg
        @echo OK
 
 out: $(run_O)
        @echo OK
 
-.PHONY: all $(run) $(run_O) clean
+.PHONY: all $(run) $(run_O) tarpkg clean
index d64ab79c6d35c920917ca2d68cd0d3436ff03912..142263492f6fe9234c8f4ba3141568e36f1bd38d 100644 (file)
@@ -68,7 +68,7 @@ int test__basic_mmap(void)
                evsels[i] = perf_evsel__newtp("syscalls", name);
                if (evsels[i] == NULL) {
                        pr_debug("perf_evsel__new\n");
-                       goto out_free_evlist;
+                       goto out_delete_evlist;
                }
 
                evsels[i]->attr.wakeup_events = 1;
@@ -80,7 +80,7 @@ int test__basic_mmap(void)
                        pr_debug("failed to open counter: %s, "
                                 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                                 strerror(errno));
-                       goto out_close_fd;
+                       goto out_delete_evlist;
                }
 
                nr_events[i] = 0;
@@ -90,7 +90,7 @@ int test__basic_mmap(void)
        if (perf_evlist__mmap(evlist, 128, true) < 0) {
                pr_debug("failed to mmap events: %d (%s)\n", errno,
                         strerror(errno));
-               goto out_close_fd;
+               goto out_delete_evlist;
        }
 
        for (i = 0; i < nsyscalls; ++i)
@@ -105,13 +105,13 @@ int test__basic_mmap(void)
                if (event->header.type != PERF_RECORD_SAMPLE) {
                        pr_debug("unexpected %s event\n",
                                 perf_event__name(event->header.type));
-                       goto out_munmap;
+                       goto out_delete_evlist;
                }
 
                err = perf_evlist__parse_sample(evlist, event, &sample);
                if (err) {
                        pr_err("Can't parse sample, err = %d\n", err);
-                       goto out_munmap;
+                       goto out_delete_evlist;
                }
 
                err = -1;
@@ -119,30 +119,27 @@ int test__basic_mmap(void)
                if (evsel == NULL) {
                        pr_debug("event with id %" PRIu64
                                 " doesn't map to an evsel\n", sample.id);
-                       goto out_munmap;
+                       goto out_delete_evlist;
                }
                nr_events[evsel->idx]++;
                perf_evlist__mmap_consume(evlist, 0);
        }
 
        err = 0;
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
                        pr_debug("expected %d %s events, got %d\n",
                                 expected_nr_events[evsel->idx],
                                 perf_evsel__name(evsel), nr_events[evsel->idx]);
                        err = -1;
-                       goto out_munmap;
+                       goto out_delete_evlist;
                }
        }
 
-out_munmap:
-       perf_evlist__munmap(evlist);
-out_close_fd:
-       for (i = 0; i < nsyscalls; ++i)
-               perf_evsel__close_fd(evsels[i], 1, threads->nr);
-out_free_evlist:
+out_delete_evlist:
        perf_evlist__delete(evlist);
+       cpus    = NULL;
+       threads = NULL;
 out_free_cpus:
        cpu_map__delete(cpus);
 out_free_threads:
index 41cc0badb74b9475377b00264287168a30c0d016..c505ef2af245901639a04e453432b78c5adb5f8b 100644 (file)
@@ -6,15 +6,15 @@
 
 int test__syscall_open_tp_fields(void)
 {
-       struct perf_record_opts opts = {
+       struct record_opts opts = {
                .target = {
                        .uid = UINT_MAX,
                        .uses_mmap = true,
                },
-               .no_delay   = true,
-               .freq       = 1,
-               .mmap_pages = 256,
-               .raw_samples = true,
+               .no_buffering = true,
+               .freq         = 1,
+               .mmap_pages   = 256,
+               .raw_samples  = true,
        };
        const char *filename = "/etc/passwd";
        int flags = O_RDONLY | O_DIRECTORY;
@@ -48,13 +48,13 @@ int test__syscall_open_tp_fields(void)
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n", strerror(errno));
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        err = perf_evlist__mmap(evlist, UINT_MAX, false);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
-               goto out_close_evlist;
+               goto out_delete_evlist;
        }
 
        perf_evlist__enable(evlist);
@@ -85,7 +85,7 @@ int test__syscall_open_tp_fields(void)
                                err = perf_evsel__parse_sample(evsel, event, &sample);
                                if (err) {
                                        pr_err("Can't parse sample, err = %d\n", err);
-                                       goto out_munmap;
+                                       goto out_delete_evlist;
                                }
 
                                tp_flags = perf_evsel__intval(evsel, &sample, "flags");
@@ -93,7 +93,7 @@ int test__syscall_open_tp_fields(void)
                                if (flags != tp_flags) {
                                        pr_debug("%s: Expected flags=%#x, got %#x\n",
                                                 __func__, flags, tp_flags);
-                                       goto out_munmap;
+                                       goto out_delete_evlist;
                                }
 
                                goto out_ok;
@@ -105,17 +105,11 @@ int test__syscall_open_tp_fields(void)
 
                if (++nr_polls > 5) {
                        pr_debug("%s: no events!\n", __func__);
-                       goto out_munmap;
+                       goto out_delete_evlist;
                }
        }
 out_ok:
        err = 0;
-out_munmap:
-       perf_evlist__munmap(evlist);
-out_close_evlist:
-       perf_evlist__close(evlist);
-out_delete_maps:
-       perf_evlist__delete_maps(evlist);
 out_delete_evlist:
        perf_evlist__delete(evlist);
 out:
index 3cbd104960871705778f37450f0e33d117430f07..4db0ae617d7080cd7c97467a15fbe36d9bcedf30 100644 (file)
@@ -3,7 +3,7 @@
 #include "evsel.h"
 #include "evlist.h"
 #include "fs.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include "tests.h"
 #include <linux/hw_breakpoint.h>
 
@@ -30,7 +30,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
        TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                TEST_ASSERT_VAL("wrong type",
                        PERF_TYPE_TRACEPOINT == evsel->attr.type);
                TEST_ASSERT_VAL("wrong sample_type",
@@ -201,7 +201,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
 
        TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                TEST_ASSERT_VAL("wrong exclude_user",
                                !evsel->attr.exclude_user);
                TEST_ASSERT_VAL("wrong exclude_kernel",
@@ -1385,10 +1385,10 @@ static int test_event(struct evlist_test *e)
        if (ret) {
                pr_debug("failed to parse event '%s', err %d\n",
                         e->name, ret);
-               return ret;
+       } else {
+               ret = e->check(evlist);
        }
-
-       ret = e->check(evlist);
+       
        perf_evlist__delete(evlist);
 
        return ret;
index 93a62b06c3afac27f7398f1572430cf29868b9d5..aca1a83dd13a946e8f47456725c3b725cfb4b25c 100644 (file)
@@ -34,14 +34,14 @@ realloc:
 
 int test__PERF_RECORD(void)
 {
-       struct perf_record_opts opts = {
+       struct record_opts opts = {
                .target = {
                        .uid = UINT_MAX,
                        .uses_mmap = true,
                },
-               .no_delay   = true,
-               .freq       = 10,
-               .mmap_pages = 256,
+               .no_buffering = true,
+               .freq         = 10,
+               .mmap_pages   = 256,
        };
        cpu_set_t cpu_mask;
        size_t cpu_mask_size = sizeof(cpu_mask);
@@ -83,11 +83,10 @@ int test__PERF_RECORD(void)
         * so that we have time to open the evlist (calling sys_perf_event_open
         * on all the fds) and then mmap them.
         */
-       err = perf_evlist__prepare_workload(evlist, &opts.target, argv,
-                                           false, false);
+       err = perf_evlist__prepare_workload(evlist, &opts.target, argv, false, NULL);
        if (err < 0) {
                pr_debug("Couldn't run the workload!\n");
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        /*
@@ -102,7 +101,7 @@ int test__PERF_RECORD(void)
        err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
        if (err < 0) {
                pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        cpu = err;
@@ -112,7 +111,7 @@ int test__PERF_RECORD(void)
         */
        if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
                pr_debug("sched_setaffinity: %s\n", strerror(errno));
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        /*
@@ -122,7 +121,7 @@ int test__PERF_RECORD(void)
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("perf_evlist__open: %s\n", strerror(errno));
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        /*
@@ -133,7 +132,7 @@ int test__PERF_RECORD(void)
        err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
        if (err < 0) {
                pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
-               goto out_close_evlist;
+               goto out_delete_evlist;
        }
 
        /*
@@ -166,7 +165,7 @@ int test__PERF_RECORD(void)
                                        if (verbose)
                                                perf_event__fprintf(event, stderr);
                                        pr_debug("Couldn't parse sample\n");
-                                       goto out_err;
+                                       goto out_delete_evlist;
                                }
 
                                if (verbose) {
@@ -303,12 +302,6 @@ found_exit:
                pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
                ++errs;
        }
-out_err:
-       perf_evlist__munmap(evlist);
-out_close_evlist:
-       perf_evlist__close(evlist);
-out_delete_maps:
-       perf_evlist__delete_maps(evlist);
 out_delete_evlist:
        perf_evlist__delete(evlist);
 out:
diff --git a/tools/perf/tests/perf-targz-src-pkg b/tools/perf/tests/perf-targz-src-pkg
new file mode 100755 (executable)
index 0000000..238aa39
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Test one of the main kernel Makefile targets to generate a perf sources tarball
+# suitable for build outside the full kernel sources.
+#
+# This is to test that the tools/perf/MANIFEST file lists all the files needed to
+# be in such tarball, which sometimes gets broken when we move files around,
+# like when we made some files that were in tools/perf/ available to other tools/
+# codebases by moving it to tools/include/, etc.
+
+PERF=$1
+cd ${PERF}/../..
+make perf-targz-src-pkg > /dev/null
+TARBALL=$(ls -rt perf-*.tar.gz)
+TMP_DEST=$(mktemp -d)
+tar xf ${TARBALL} -C $TMP_DEST
+rm -f ${TARBALL}
+cd - > /dev/null
+make -C $TMP_DEST/perf*/tools/perf > /dev/null 2>&1
+RC=$?
+rm -rf ${TMP_DEST}
+exit $RC
index 4ca1b938f6a620380f8cae76435f8ad6b142eecd..47146d388dbffac3e6a90b6e1f6595083dfa1839 100644 (file)
@@ -46,7 +46,7 @@ static u64 rdtsc(void)
  */
 int test__perf_time_to_tsc(void)
 {
-       struct perf_record_opts opts = {
+       struct record_opts opts = {
                .mmap_pages          = UINT_MAX,
                .user_freq           = UINT_MAX,
                .user_interval       = ULLONG_MAX,
@@ -166,14 +166,8 @@ next_event:
 out_err:
        if (evlist) {
                perf_evlist__disable(evlist);
-               perf_evlist__munmap(evlist);
-               perf_evlist__close(evlist);
                perf_evlist__delete(evlist);
        }
-       if (cpus)
-               cpu_map__delete(cpus);
-       if (threads)
-               thread_map__delete(threads);
 
        return err;
 }
index 6664a7cd828c11585cfa12c7f9104e776ddf100a..983d6b8562a89f06f30f0aebd32e8b522f6b35fe 100644 (file)
@@ -45,7 +45,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
        evsel = perf_evsel__new(&attr);
        if (evsel == NULL) {
                pr_debug("perf_evsel__new\n");
-               goto out_free_evlist;
+               goto out_delete_evlist;
        }
        perf_evlist__add(evlist, evsel);
 
@@ -54,7 +54,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
        if (!evlist->cpus || !evlist->threads) {
                err = -ENOMEM;
                pr_debug("Not enough memory to create thread/cpu maps\n");
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        if (perf_evlist__open(evlist)) {
@@ -63,14 +63,14 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
                err = -errno;
                pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
                         strerror(errno), knob, (u64)attr.sample_freq);
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        err = perf_evlist__mmap(evlist, 128, true);
        if (err < 0) {
                pr_debug("failed to mmap event: %d (%s)\n", errno,
                         strerror(errno));
-               goto out_close_evlist;
+               goto out_delete_evlist;
        }
 
        perf_evlist__enable(evlist);
@@ -90,7 +90,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
                err = perf_evlist__parse_sample(evlist, event, &sample);
                if (err < 0) {
                        pr_debug("Error during parse sample\n");
-                       goto out_unmap_evlist;
+                       goto out_delete_evlist;
                }
 
                total_periods += sample.period;
@@ -105,13 +105,7 @@ next_event:
                err = -1;
        }
 
-out_unmap_evlist:
-       perf_evlist__munmap(evlist);
-out_close_evlist:
-       perf_evlist__close(evlist);
-out_delete_maps:
-       perf_evlist__delete_maps(evlist);
-out_free_evlist:
+out_delete_evlist:
        perf_evlist__delete(evlist);
        return err;
 }
index d09ab579119ebb1b701d80f4f377e54122670bf5..5ff3db318f12ae5971d3916fc49599e14fd51075 100644 (file)
@@ -9,12 +9,21 @@
 static int exited;
 static int nr_exit;
 
-static void sig_handler(int sig)
+static void sig_handler(int sig __maybe_unused)
 {
        exited = 1;
+}
 
-       if (sig == SIGUSR1)
-               nr_exit = -1;
+/*
+ * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
+ * we asked by setting its exec_error to this handler.
+ */
+static void workload_exec_failed_signal(int signo __maybe_unused,
+                                       siginfo_t *info __maybe_unused,
+                                       void *ucontext __maybe_unused)
+{
+       exited  = 1;
+       nr_exit = -1;
 }
 
 /*
@@ -35,7 +44,6 @@ int test__task_exit(void)
        const char *argv[] = { "true", NULL };
 
        signal(SIGCHLD, sig_handler);
-       signal(SIGUSR1, sig_handler);
 
        evlist = perf_evlist__new_default();
        if (evlist == NULL) {
@@ -54,13 +62,14 @@ int test__task_exit(void)
        if (!evlist->cpus || !evlist->threads) {
                err = -ENOMEM;
                pr_debug("Not enough memory to create thread/cpu maps\n");
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
-       err = perf_evlist__prepare_workload(evlist, &target, argv, false, true);
+       err = perf_evlist__prepare_workload(evlist, &target, argv, false,
+                                           workload_exec_failed_signal);
        if (err < 0) {
                pr_debug("Couldn't run the workload!\n");
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        evsel = perf_evlist__first(evlist);
@@ -74,13 +83,13 @@ int test__task_exit(void)
        err = perf_evlist__open(evlist);
        if (err < 0) {
                pr_debug("Couldn't open the evlist: %s\n", strerror(-err));
-               goto out_delete_maps;
+               goto out_delete_evlist;
        }
 
        if (perf_evlist__mmap(evlist, 128, true) < 0) {
                pr_debug("failed to mmap events: %d (%s)\n", errno,
                         strerror(errno));
-               goto out_close_evlist;
+               goto out_delete_evlist;
        }
 
        perf_evlist__start_workload(evlist);
@@ -103,11 +112,7 @@ retry:
                err = -1;
        }
 
-       perf_evlist__munmap(evlist);
-out_close_evlist:
-       perf_evlist__close(evlist);
-out_delete_maps:
-       perf_evlist__delete_maps(evlist);
+out_delete_evlist:
        perf_evlist__delete(evlist);
        return err;
 }
index cbaa7af45513660d0fda1d1b6cbea8fa0a39b2ec..d11541d4d7d7ffcddad8d093b2e79f697967292a 100644 (file)
@@ -256,8 +256,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
        __ui_browser__show_title(browser, title);
 
        browser->title = title;
-       free(browser->helpline);
-       browser->helpline = NULL;
+       zfree(&browser->helpline);
 
        va_start(ap, helpline);
        err = vasprintf(&browser->helpline, helpline, ap);
@@ -268,12 +267,11 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
        return err ? 0 : -1;
 }
 
-void ui_browser__hide(struct ui_browser *browser __maybe_unused)
+void ui_browser__hide(struct ui_browser *browser)
 {
        pthread_mutex_lock(&ui__lock);
        ui_helpline__pop();
-       free(browser->helpline);
-       browser->helpline = NULL;
+       zfree(&browser->helpline);
        pthread_mutex_unlock(&ui__lock);
 }
 
index 7d45d2f536013e49e230aee7856d9aeaf3964f6b..118cca29dd26b5e52f73d1806e247febe590e841 100644 (file)
@@ -59,6 +59,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text);
 bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
 int ui_browser__input_window(const char *title, const char *text, char *input,
                             const char *exit_msg, int delay_sec);
+struct perf_session_env;
+int tui__header_window(struct perf_session_env *env);
 
 void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
 unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
new file mode 100644 (file)
index 0000000..89c16b9
--- /dev/null
@@ -0,0 +1,127 @@
+#include "util/cache.h"
+#include "util/debug.h"
+#include "ui/browser.h"
+#include "ui/ui.h"
+#include "ui/util.h"
+#include "ui/libslang.h"
+#include "util/header.h"
+#include "util/session.h"
+
+static void ui_browser__argv_write(struct ui_browser *browser,
+                                  void *entry, int row)
+{
+       char **arg = entry;
+       char *str = *arg;
+       char empty[] = " ";
+       bool current_entry = ui_browser__is_current_entry(browser, row);
+       unsigned long offset = (unsigned long)browser->priv;
+
+       if (offset >= strlen(str))
+               str = empty;
+       else
+               str = str + offset;
+
+       ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+                                                      HE_COLORSET_NORMAL);
+
+       slsmg_write_nstring(str, browser->width);
+}
+
+static int list_menu__run(struct ui_browser *menu)
+{
+       int key;
+       unsigned long offset;
+       const char help[] =
+       "h/?/F1        Show this window\n"
+       "UP/DOWN/PGUP\n"
+       "PGDN/SPACE\n"
+       "LEFT/RIGHT    Navigate\n"
+       "q/ESC/CTRL+C  Exit browser";
+
+       if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
+               return -1;
+
+       while (1) {
+               key = ui_browser__run(menu, 0);
+
+               switch (key) {
+               case K_RIGHT:
+                       offset = (unsigned long)menu->priv;
+                       offset += 10;
+                       menu->priv = (void *)offset;
+                       continue;
+               case K_LEFT:
+                       offset = (unsigned long)menu->priv;
+                       if (offset >= 10)
+                               offset -= 10;
+                       menu->priv = (void *)offset;
+                       continue;
+               case K_F1:
+               case 'h':
+               case '?':
+                       ui_browser__help_window(menu, help);
+                       continue;
+               case K_ESC:
+               case 'q':
+               case CTRL('c'):
+                       key = -1;
+                       break;
+               default:
+                       continue;
+               }
+
+               break;
+       }
+
+       ui_browser__hide(menu);
+       return key;
+}
+
+static int ui__list_menu(int argc, char * const argv[])
+{
+       struct ui_browser menu = {
+               .entries    = (void *)argv,
+               .refresh    = ui_browser__argv_refresh,
+               .seek       = ui_browser__argv_seek,
+               .write      = ui_browser__argv_write,
+               .nr_entries = argc,
+       };
+
+       return list_menu__run(&menu);
+}
+
+int tui__header_window(struct perf_session_env *env)
+{
+       int i, argc = 0;
+       char **argv;
+       struct perf_session *session;
+       char *ptr, *pos;
+       size_t size;
+       FILE *fp = open_memstream(&ptr, &size);
+
+       session = container_of(env, struct perf_session, header.env);
+       perf_header__fprintf_info(session, fp, true);
+       fclose(fp);
+
+       for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
+               argc++;
+
+       argv = calloc(argc + 1, sizeof(*argv));
+       if (argv == NULL)
+               goto out;
+
+       argv[0] = pos = ptr;
+       for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
+               *pos++ = '\0';
+               argv[i] = pos;
+       }
+
+       BUG_ON(i != argc + 1);
+
+       ui__list_menu(argc, argv);
+
+out:
+       free(argv);
+       free(ptr);
+       return 0;
+}
index a440e03cd8c235402b626526b41676b3ad95488b..b720b92eba6eb95cc7dd9bd4a57693f0a79d91b9 100644 (file)
@@ -1267,10 +1267,8 @@ static inline void free_popup_options(char **options, int n)
 {
        int i;
 
-       for (i = 0; i < n; ++i) {
-               free(options[i]);
-               options[i] = NULL;
-       }
+       for (i = 0; i < n; ++i)
+               zfree(&options[i]);
 }
 
 /* Check whether the browser is for 'top' or 'report' */
@@ -1329,7 +1327,7 @@ static int switch_data_file(void)
 
                        abs_path[nr_options] = strdup(path);
                        if (!abs_path[nr_options]) {
-                               free(options[nr_options]);
+                               zfree(&options[nr_options]);
                                ui__warning("Can't search all data files due to memory shortage.\n");
                                fclose(file);
                                break;
@@ -1400,6 +1398,36 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
        char script_opt[64];
        int delay_secs = hbt ? hbt->refresh : 0;
 
+#define HIST_BROWSER_HELP_COMMON                                       \
+       "h/?/F1        Show this window\n"                              \
+       "UP/DOWN/PGUP\n"                                                \
+       "PGDN/SPACE    Navigate\n"                                      \
+       "q/ESC/CTRL+C  Exit browser\n\n"                                \
+       "For multiple event sessions:\n\n"                              \
+       "TAB/UNTAB     Switch events\n\n"                               \
+       "For symbolic views (--sort has sym):\n\n"                      \
+       "->            Zoom into DSO/Threads & Annotate current symbol\n" \
+       "<-            Zoom out\n"                                      \
+       "a             Annotate current symbol\n"                       \
+       "C             Collapse all callchains\n"                       \
+       "d             Zoom into current DSO\n"                         \
+       "E             Expand all callchains\n"                         \
+
+       /* help messages are sorted by lexical order of the hotkey */
+       const char report_help[] = HIST_BROWSER_HELP_COMMON
+       "i             Show header information\n"
+       "P             Print histograms to perf.hist.N\n"
+       "r             Run available scripts\n"
+       "s             Switch to another data file in PWD\n"
+       "t             Zoom into current Thread\n"
+       "V             Verbose (DSO names in callchains, etc)\n"
+       "/             Filter symbol by name";
+       const char top_help[] = HIST_BROWSER_HELP_COMMON
+       "P             Print histograms to perf.hist.N\n"
+       "t             Zoom into current Thread\n"
+       "V             Verbose (DSO names in callchains, etc)\n"
+       "/             Filter symbol by name";
+
        if (browser == NULL)
                return -1;
 
@@ -1484,29 +1512,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                        if (is_report_browser(hbt))
                                goto do_data_switch;
                        continue;
+               case 'i':
+                       /* env->arch is NULL for live-mode (i.e. perf top) */
+                       if (env->arch)
+                               tui__header_window(env);
+                       continue;
                case K_F1:
                case 'h':
                case '?':
                        ui_browser__help_window(&browser->b,
-                                       "h/?/F1        Show this window\n"
-                                       "UP/DOWN/PGUP\n"
-                                       "PGDN/SPACE    Navigate\n"
-                                       "q/ESC/CTRL+C  Exit browser\n\n"
-                                       "For multiple event sessions:\n\n"
-                                       "TAB/UNTAB Switch events\n\n"
-                                       "For symbolic views (--sort has sym):\n\n"
-                                       "->            Zoom into DSO/Threads & Annotate current symbol\n"
-                                       "<-            Zoom out\n"
-                                       "a             Annotate current symbol\n"
-                                       "C             Collapse all callchains\n"
-                                       "E             Expand all callchains\n"
-                                       "d             Zoom into current DSO\n"
-                                       "t             Zoom into current Thread\n"
-                                       "r             Run available scripts('perf report' only)\n"
-                                       "s             Switch to another data file in PWD ('perf report' only)\n"
-                                       "P             Print histograms to perf.hist.N\n"
-                                       "V             Verbose (DSO names in callchains, etc)\n"
-                                       "/             Filter symbol by name");
+                               is_report_browser(hbt) ? report_help : top_help);
                        continue;
                case K_ENTER:
                case K_RIGHT:
@@ -1923,7 +1938,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
 
        ui_helpline__push("Press ESC to exit");
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                const char *ev_name = perf_evsel__name(pos);
                size_t line_len = strlen(ev_name) + 7;
 
@@ -1955,9 +1970,10 @@ single_entry:
                struct perf_evsel *pos;
 
                nr_entries = 0;
-               list_for_each_entry(pos, &evlist->entries, node)
+               evlist__for_each(evlist, pos) {
                        if (perf_evsel__is_group_leader(pos))
                                nr_entries++;
+               }
 
                if (nr_entries == 1)
                        goto single_entry;
index d63c68ea02a87e1adfbfaa2ea41ec52b373a0a0c..402d2bd30b0998859cc5349d62b824b0a58dcbe1 100644 (file)
@@ -173,8 +173,7 @@ int script_browse(const char *script_opt)
        if (script.b.width > AVERAGE_LINE_LEN)
                script.b.width = AVERAGE_LINE_LEN;
 
-       if (line)
-               free(line);
+       free(line);
        pclose(fp);
 
        script.nr_lines = nr_entries;
index 2ca66cc1160f4be05a06ae7d5e1a7210ce2c7f07..5b95c44f34354215ba597c19d736d3e63c559d1e 100644 (file)
@@ -375,7 +375,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 
        gtk_container_add(GTK_CONTAINER(window), vbox);
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                struct hists *hists = &pos->hists;
                const char *evname = perf_evsel__name(pos);
                GtkWidget *scrolled_window;
index 696c1fbe42482db03b4fb460b488860435a4edf5..52e7fc48af9f488088785b8e216e05f6b22546fc 100644 (file)
@@ -23,8 +23,7 @@ int perf_gtk__deactivate_context(struct perf_gtk_context **ctx)
        if (!perf_gtk__is_active_context(*ctx))
                return -1;
 
-       free(*ctx);
-       *ctx = NULL;
+       zfree(ctx);
        return 0;
 }
 
index c244cb524ef2cc9d4e3eafabe065c8eef60b60a6..831fbb77d1ff010ab786ff12ee747aaf8873bcbe 100644 (file)
@@ -510,7 +510,7 @@ print_entries:
 
        free(line);
 out:
-       free(rem_sq_bracket);
+       zfree(&rem_sq_bracket);
 
        return ret;
 }
index 092902e30cee5c17a05748633fc01f858d0e0348..bf890f72fe8040097671c2e7ffad732b39bd715a 100644 (file)
@@ -92,6 +92,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
                t = sep + 1;
        }
 
+       pthread_mutex_lock(&ui__lock);
+
        max_len += 2;
        nr_lines += 8;
        y = SLtt_Screen_Rows / 2 - nr_lines / 2;
@@ -120,13 +122,19 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
        SLsmg_write_nstring((char *)exit_msg, max_len);
        SLsmg_refresh();
 
+       pthread_mutex_unlock(&ui__lock);
+
        x += 2;
        len = 0;
        key = ui__getch(delay_secs);
        while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+               pthread_mutex_lock(&ui__lock);
+
                if (key == K_BKSPC) {
-                       if (len == 0)
+                       if (len == 0) {
+                               pthread_mutex_unlock(&ui__lock);
                                goto next_key;
+                       }
                        SLsmg_gotorc(y, x + --len);
                        SLsmg_write_char(' ');
                } else {
@@ -136,6 +144,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
                }
                SLsmg_refresh();
 
+               pthread_mutex_unlock(&ui__lock);
+
                /* XXX more graceful overflow handling needed */
                if (len == sizeof(buf) - 1) {
                        ui_helpline__push("maximum size of symbol name reached!");
@@ -174,6 +184,8 @@ int ui__question_window(const char *title, const char *text,
                t = sep + 1;
        }
 
+       pthread_mutex_lock(&ui__lock);
+
        max_len += 2;
        nr_lines += 4;
        y = SLtt_Screen_Rows / 2 - nr_lines / 2,
@@ -195,6 +207,9 @@ int ui__question_window(const char *title, const char *text,
        SLsmg_gotorc(y + nr_lines - 1, x);
        SLsmg_write_nstring((char *)exit_msg, max_len);
        SLsmg_refresh();
+
+       pthread_mutex_unlock(&ui__lock);
+
        return ui__getch(delay_secs);
 }
 
@@ -215,9 +230,7 @@ static int __ui__warning(const char *title, const char *format, va_list args)
        if (vasprintf(&s, format, args) > 0) {
                int key;
 
-               pthread_mutex_lock(&ui__lock);
                key = ui__question_window(title, s, "Press any key...", 0);
-               pthread_mutex_unlock(&ui__lock);
                free(s);
                return key;
        }
index e6d134773d0a498d2b62e18391d0de5c746dd149..c0b43ee40d95674fb5a5602c6f287ba2d8d8c5f5 100644 (file)
@@ -55,8 +55,7 @@ int split_cmdline(char *cmdline, const char ***argv)
                                src++;
                                c = cmdline[src];
                                if (!c) {
-                                       free(*argv);
-                                       *argv = NULL;
+                                       zfree(argv);
                                        return error("cmdline ends with \\");
                                }
                        }
@@ -68,8 +67,7 @@ int split_cmdline(char *cmdline, const char ***argv)
        cmdline[dst] = 0;
 
        if (quoted) {
-               free(*argv);
-               *argv = NULL;
+               zfree(argv);
                return error("unclosed quote");
        }
 
index cf6242c92ee244ab45498993cab477af7950853f..469eb679fb9d09d9e96e8687cc2051fa44f86565 100644 (file)
@@ -26,10 +26,10 @@ static int disasm_line__parse(char *line, char **namep, char **rawp);
 
 static void ins__delete(struct ins_operands *ops)
 {
-       free(ops->source.raw);
-       free(ops->source.name);
-       free(ops->target.raw);
-       free(ops->target.name);
+       zfree(&ops->source.raw);
+       zfree(&ops->source.name);
+       zfree(&ops->target.raw);
+       zfree(&ops->target.name);
 }
 
 static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
@@ -185,8 +185,7 @@ static int lock__parse(struct ins_operands *ops)
        return 0;
 
 out_free_ops:
-       free(ops->locked.ops);
-       ops->locked.ops = NULL;
+       zfree(&ops->locked.ops);
        return 0;
 }
 
@@ -205,9 +204,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
 
 static void lock__delete(struct ins_operands *ops)
 {
-       free(ops->locked.ops);
-       free(ops->target.raw);
-       free(ops->target.name);
+       zfree(&ops->locked.ops);
+       zfree(&ops->target.raw);
+       zfree(&ops->target.name);
 }
 
 static struct ins_ops lock_ops = {
@@ -256,8 +255,7 @@ static int mov__parse(struct ins_operands *ops)
        return 0;
 
 out_free_source:
-       free(ops->source.raw);
-       ops->source.raw = NULL;
+       zfree(&ops->source.raw);
        return -1;
 }
 
@@ -464,17 +462,12 @@ void symbol__annotate_zero_histograms(struct symbol *sym)
        pthread_mutex_unlock(&notes->lock);
 }
 
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
-                            int evidx, u64 addr)
+static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+                                     struct annotation *notes, int evidx, u64 addr)
 {
        unsigned offset;
-       struct annotation *notes;
        struct sym_hist *h;
 
-       notes = symbol__annotation(sym);
-       if (notes->src == NULL)
-               return -ENOMEM;
-
        pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
 
        if (addr < sym->start || addr > sym->end)
@@ -491,6 +484,33 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
        return 0;
 }
 
+static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+                                   int evidx, u64 addr)
+{
+       struct annotation *notes;
+
+       if (sym == NULL || use_browser != 1 || !sort__has_sym)
+               return 0;
+
+       notes = symbol__annotation(sym);
+       if (notes->src == NULL) {
+               if (symbol__alloc_hist(sym) < 0)
+                       return -ENOMEM;
+       }
+
+       return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
+}
+
+int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
+{
+       return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
+}
+
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
+{
+       return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
+}
+
 static void disasm_line__init_ins(struct disasm_line *dl)
 {
        dl->ins = ins__find(dl->name);
@@ -538,8 +558,7 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)
        return 0;
 
 out_free_name:
-       free(*namep);
-       *namep = NULL;
+       zfree(namep);
        return -1;
 }
 
@@ -564,7 +583,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs
        return dl;
 
 out_free_line:
-       free(dl->line);
+       zfree(&dl->line);
 out_delete:
        free(dl);
        return NULL;
@@ -572,8 +591,8 @@ out_delete:
 
 void disasm_line__free(struct disasm_line *dl)
 {
-       free(dl->line);
-       free(dl->name);
+       zfree(&dl->line);
+       zfree(&dl->name);
        if (dl->ins && dl->ins->ops->free)
                dl->ins->ops->free(&dl->ops);
        else
@@ -900,7 +919,7 @@ fallback:
                 * cache, or is just a kallsyms file, well, lets hope that this
                 * DSO is the same as when 'perf record' ran.
                 */
-               filename = dso->long_name;
+               filename = (char *)dso->long_name;
                snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
                         symbol_conf.symfs, filename);
                free_filename = false;
@@ -1091,8 +1110,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
                src_line = (void *)src_line + sizeof_src_line;
        }
 
-       free(notes->src->lines);
-       notes->src->lines = NULL;
+       zfree(&notes->src->lines);
 }
 
 /* Get the filename:line for the colored entries */
@@ -1376,3 +1394,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
 
        return 0;
 }
+
+int hist_entry__annotate(struct hist_entry *he, size_t privsize)
+{
+       return symbol__annotate(he->ms.sym, he->ms.map, privsize);
+}
index 834b7b57b7884f7b833291caa6bcaad2a1eff1d1..b2aef59d6bb29741dff0dbee40fa0c1d04f1cf65 100644 (file)
@@ -132,12 +132,17 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
        return &a->annotation;
 }
 
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
-                            int evidx, u64 addr);
+int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx);
+
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
+
 int symbol__alloc_hist(struct symbol *sym);
 void symbol__annotate_zero_histograms(struct symbol *sym);
 
 int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
+
+int hist_entry__annotate(struct hist_entry *he, size_t privsize);
+
 int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym);
 int symbol__annotate_printf(struct symbol *sym, struct map *map,
                            struct perf_evsel *evsel, bool full_paths,
index a92770c98cc7c00dac6fdd57258eb120960a5294..6baabe63182ba1b79a7a3c19c954b1a213da2c30 100644 (file)
@@ -89,7 +89,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
        return raw - build_id;
 }
 
-char *dso__build_id_filename(struct dso *dso, char *bf, size_t size)
+char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
 {
        char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 
index 929f28a7c14dc05cb1c3fd174e17520dda95b7ec..845ef865eced46c24eda848d828100cd06dc43ae 100644 (file)
@@ -10,7 +10,7 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
 struct dso;
 
 int build_id__sprintf(const u8 *build_id, int len, char *bf);
-char *dso__build_id_filename(struct dso *dso, char *bf, size_t size);
+char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
 
 int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
                           struct perf_sample *sample, struct perf_evsel *evsel,
index e3970e3eaacf45bc7a10db4a86314c2fdd79fbb5..8d9db454f1a9740c44c4136146c5c6dd308a6281 100644 (file)
 #include <errno.h>
 #include <math.h>
 
+#include "asm/bug.h"
+
 #include "hist.h"
 #include "util.h"
+#include "sort.h"
+#include "machine.h"
 #include "callchain.h"
 
 __thread struct callchain_cursor callchain_cursor;
@@ -356,19 +360,14 @@ append_chain_children(struct callchain_node *root,
        /* lookup in childrens */
        while (*p) {
                s64 ret;
-               struct callchain_list *cnode;
 
                parent = *p;
                rnode = rb_entry(parent, struct callchain_node, rb_node_in);
-               cnode = list_first_entry(&rnode->val, struct callchain_list,
-                                        list);
 
-               /* just check first entry */
-               ret = match_chain(node, cnode);
-               if (ret == 0) {
-                       append_chain(rnode, cursor, period);
+               /* If at least first entry matches, rely to children */
+               ret = append_chain(rnode, cursor, period);
+               if (ret == 0)
                        goto inc_children_hit;
-               }
 
                if (ret < 0)
                        p = &parent->rb_left;
@@ -389,11 +388,11 @@ append_chain(struct callchain_node *root,
             struct callchain_cursor *cursor,
             u64 period)
 {
-       struct callchain_cursor_node *curr_snap = cursor->curr;
        struct callchain_list *cnode;
        u64 start = cursor->pos;
        bool found = false;
        u64 matches;
+       int cmp = 0;
 
        /*
         * Lookup in the current node
@@ -408,7 +407,8 @@ append_chain(struct callchain_node *root,
                if (!node)
                        break;
 
-               if (match_chain(node, cnode) != 0)
+               cmp = match_chain(node, cnode);
+               if (cmp)
                        break;
 
                found = true;
@@ -418,9 +418,8 @@ append_chain(struct callchain_node *root,
 
        /* matches not, relay no the parent */
        if (!found) {
-               cursor->curr = curr_snap;
-               cursor->pos = start;
-               return -1;
+               WARN_ONCE(!cmp, "Chain comparison error\n");
+               return cmp;
        }
 
        matches = cursor->pos - start;
@@ -531,3 +530,24 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
 
        return 0;
 }
+
+int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
+                             struct perf_evsel *evsel, struct addr_location *al,
+                             int max_stack)
+{
+       if (sample->callchain == NULL)
+               return 0;
+
+       if (symbol_conf.use_callchain || sort__has_parent) {
+               return machine__resolve_callchain(al->machine, evsel, al->thread,
+                                                 sample, parent, al, max_stack);
+       }
+       return 0;
+}
+
+int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
+{
+       if (!symbol_conf.use_callchain)
+               return 0;
+       return callchain_append(he->callchain, &callchain_cursor, sample->period);
+}
index 4f7f989876ec7ba9b5a505334c15160e7e36aa40..8ad97e9b119fb414e0cf73a945c01be0acf93583 100644 (file)
@@ -145,10 +145,16 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
 }
 
 struct option;
+struct hist_entry;
 
-int record_parse_callchain(const char *arg, struct perf_record_opts *opts);
+int record_parse_callchain(const char *arg, struct record_opts *opts);
 int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
 int record_callchain_opt(const struct option *opt, const char *arg, int unset);
 
+int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
+                             struct perf_evsel *evsel, struct addr_location *al,
+                             int max_stack);
+int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
+
 extern const char record_callchain_help[];
 #endif /* __PERF_CALLCHAIN_H */
index 96bbda1ddb838d050ba5facf7c71ba4f8a5a1bc9..88f7be3994321f8ef717262909ac6c38853fc691 100644 (file)
@@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
        /*
         * check if cgrp is already defined, if so we reuse it
         */
-       list_for_each_entry(counter, &evlist->entries, node) {
+       evlist__for_each(evlist, counter) {
                cgrp = counter->cgrp;
                if (!cgrp)
                        continue;
@@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
         * if add cgroup N, then need to find event N
         */
        n = 0;
-       list_for_each_entry(counter, &evlist->entries, node) {
+       evlist__for_each(evlist, counter) {
                if (n == nr_cgroups)
                        goto found;
                n++;
@@ -133,7 +133,7 @@ void close_cgroup(struct cgroup_sel *cgrp)
        /* XXX: not reentrant */
        if (--cgrp->refcnt == 0) {
                close(cgrp->fd);
-               free(cgrp->name);
+               zfree(&cgrp->name);
                free(cgrp);
        }
 }
index 66e44a5019d538fff04d338bbf304b3dccecb4e2..87b8672eb4134cab6d29b3a2accda19093edb9aa 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/kernel.h>
 #include "cache.h"
 #include "color.h"
+#include <math.h>
 
 int perf_use_color_default = -1;
 
@@ -298,10 +299,10 @@ const char *get_percent_color(double percent)
         * entries in green - and keep the low overhead places
         * normal:
         */
-       if (percent >= MIN_RED)
+       if (fabs(percent) >= MIN_RED)
                color = PERF_COLOR_RED;
        else {
-               if (percent > MIN_GREEN)
+               if (fabs(percent) > MIN_GREEN)
                        color = PERF_COLOR_GREEN;
        }
        return color;
@@ -318,15 +319,19 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
        return r;
 }
 
+int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
+{
+       const char *color = get_percent_color(value);
+       return color_snprintf(bf, size, color, fmt, value);
+}
+
 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
 {
        va_list args;
        double percent;
-       const char *color;
 
        va_start(args, fmt);
        percent = va_arg(args, double);
        va_end(args);
-       color = get_percent_color(percent);
-       return color_snprintf(bf, size, color, fmt, percent);
+       return value_color_snprintf(bf, size, fmt, percent);
 }
index fced3840e99c53bda892a466068c78e57c5982eb..7ff30a62a132296a6f82de9fea62629defa8e658 100644 (file)
@@ -39,6 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
 int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
 int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
 int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
+int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
 int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
 const char *get_percent_color(double percent);
index ee0df0e24cdbd4f37e33aaa088c3b1465941d4b1..f9e777629e21cd1780fad2dc891f4c24d637787e 100644 (file)
@@ -21,7 +21,7 @@ static void comm_str__put(struct comm_str *cs)
 {
        if (!--cs->ref) {
                rb_erase(&cs->rb_node, &comm_str_root);
-               free(cs->str);
+               zfree(&cs->str);
                free(cs);
        }
 }
@@ -94,19 +94,20 @@ struct comm *comm__new(const char *str, u64 timestamp)
        return comm;
 }
 
-void comm__override(struct comm *comm, const char *str, u64 timestamp)
+int comm__override(struct comm *comm, const char *str, u64 timestamp)
 {
-       struct comm_str *old = comm->comm_str;
+       struct comm_str *new, *old = comm->comm_str;
 
-       comm->comm_str = comm_str__findnew(str, &comm_str_root);
-       if (!comm->comm_str) {
-               comm->comm_str = old;
-               return;
-       }
+       new = comm_str__findnew(str, &comm_str_root);
+       if (!new)
+               return -ENOMEM;
 
-       comm->start = timestamp;
-       comm_str__get(comm->comm_str);
+       comm_str__get(new);
        comm_str__put(old);
+       comm->comm_str = new;
+       comm->start = timestamp;
+
+       return 0;
 }
 
 void comm__free(struct comm *comm)
index 7a86e5656710a76176a2b00eb8891d24ef117edd..fac5bd51befc4c4a2b6aafe5cd21220829334673 100644 (file)
@@ -16,6 +16,6 @@ struct comm {
 void comm__free(struct comm *comm);
 struct comm *comm__new(const char *str, u64 timestamp);
 const char *comm__str(const struct comm *comm);
-void comm__override(struct comm *comm, const char *str, u64 timestamp);
+int comm__override(struct comm *comm, const char *str, u64 timestamp);
 
 #endif  /* __PERF_COMM_H */
index 7d09faf85cf16f2b4c9dead1f4e3b36a5c7c9c06..1fbcd8bdc11b8b387c4f9f2f1a57ae6807e9e92c 100644 (file)
@@ -118,3 +118,9 @@ void perf_data_file__close(struct perf_data_file *file)
 {
        close(file->fd);
 }
+
+ssize_t perf_data_file__write(struct perf_data_file *file,
+                             void *buf, size_t size)
+{
+       return writen(file->fd, buf, size);
+}
index 8c2df80152a519f02c2e699bf703840ce46efd1c..2b15d0c95c7f312de08a36a05b08c8356b039616 100644 (file)
@@ -9,12 +9,12 @@ enum perf_data_mode {
 };
 
 struct perf_data_file {
-       const char *path;
-       int fd;
-       bool is_pipe;
-       bool force;
-       unsigned long size;
-       enum perf_data_mode mode;
+       const char              *path;
+       int                      fd;
+       bool                     is_pipe;
+       bool                     force;
+       unsigned long            size;
+       enum perf_data_mode      mode;
 };
 
 static inline bool perf_data_file__is_read(struct perf_data_file *file)
@@ -44,5 +44,7 @@ static inline unsigned long perf_data_file__size(struct perf_data_file *file)
 
 int perf_data_file__open(struct perf_data_file *file);
 void perf_data_file__close(struct perf_data_file *file);
+ssize_t perf_data_file__write(struct perf_data_file *file,
+                             void *buf, size_t size);
 
 #endif /* __PERF_DATA_H */
index 399e74c34c1aa5220ecc29bd0d33cca2d2a3ac82..299b55586502feb8fc57da0e5b452e30d9dfbe9b 100644 (file)
 int verbose;
 bool dump_trace = false, quiet = false;
 
-int eprintf(int level, const char *fmt, ...)
+static int _eprintf(int level, const char *fmt, va_list args)
 {
-       va_list args;
        int ret = 0;
 
        if (verbose >= level) {
-               va_start(args, fmt);
                if (use_browser >= 1)
                        ui_helpline__vshow(fmt, args);
                else
                        ret = vfprintf(stderr, fmt, args);
-               va_end(args);
        }
 
        return ret;
 }
 
+int eprintf(int level, const char *fmt, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = _eprintf(level, fmt, args);
+       va_end(args);
+
+       return ret;
+}
+
+/*
+ * Overloading libtraceevent standard info print
+ * function, display with -v in perf.
+ */
+void pr_stat(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       _eprintf(1, fmt, args);
+       va_end(args);
+       eprintf(1, "\n");
+}
+
 int dump_printf(const char *fmt, ...)
 {
        va_list args;
index efbd98805ad0b0086996298b698122a2b0ceb018..443694c36b03c50e639ac087664764200a71646c 100644 (file)
@@ -17,4 +17,6 @@ void trace_event(union perf_event *event);
 int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 
+void pr_stat(const char *fmt, ...);
+
 #endif /* __PERF_DEBUG_H */
index af4c687cc49b54279c95c10ed48fe12843700658..4045d086d9d957823af08d79db4d8407fb9a460f 100644 (file)
@@ -28,8 +28,9 @@ char dso__symtab_origin(const struct dso *dso)
        return origin[dso->symtab_type];
 }
 
-int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
-                         char *root_dir, char *file, size_t size)
+int dso__read_binary_type_filename(const struct dso *dso,
+                                  enum dso_binary_type type,
+                                  char *root_dir, char *filename, size_t size)
 {
        char build_id_hex[BUILD_ID_SIZE * 2 + 1];
        int ret = 0;
@@ -38,36 +39,36 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
        case DSO_BINARY_TYPE__DEBUGLINK: {
                char *debuglink;
 
-               strncpy(file, dso->long_name, size);
-               debuglink = file + dso->long_name_len;
-               while (debuglink != file && *debuglink != '/')
+               strncpy(filename, dso->long_name, size);
+               debuglink = filename + dso->long_name_len;
+               while (debuglink != filename && *debuglink != '/')
                        debuglink--;
                if (*debuglink == '/')
                        debuglink++;
                filename__read_debuglink(dso->long_name, debuglink,
-                                        size - (debuglink - file));
+                                        size - (debuglink - filename));
                }
                break;
        case DSO_BINARY_TYPE__BUILD_ID_CACHE:
                /* skip the locally configured cache if a symfs is given */
                if (symbol_conf.symfs[0] ||
-                   (dso__build_id_filename(dso, file, size) == NULL))
+                   (dso__build_id_filename(dso, filename, size) == NULL))
                        ret = -1;
                break;
 
        case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
-               snprintf(file, size, "%s/usr/lib/debug%s.debug",
+               snprintf(filename, size, "%s/usr/lib/debug%s.debug",
                         symbol_conf.symfs, dso->long_name);
                break;
 
        case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
-               snprintf(file, size, "%s/usr/lib/debug%s",
+               snprintf(filename, size, "%s/usr/lib/debug%s",
                         symbol_conf.symfs, dso->long_name);
                break;
 
        case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
        {
-               char *last_slash;
+               const char *last_slash;
                size_t len;
                size_t dir_size;
 
@@ -75,14 +76,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
                while (last_slash != dso->long_name && *last_slash != '/')
                        last_slash--;
 
-               len = scnprintf(file, size, "%s", symbol_conf.symfs);
+               len = scnprintf(filename, size, "%s", symbol_conf.symfs);
                dir_size = last_slash - dso->long_name + 2;
                if (dir_size > (size - len)) {
                        ret = -1;
                        break;
                }
-               len += scnprintf(file + len, dir_size, "%s",  dso->long_name);
-               len += scnprintf(file + len , size - len, ".debug%s",
+               len += scnprintf(filename + len, dir_size, "%s",  dso->long_name);
+               len += scnprintf(filename + len , size - len, ".debug%s",
                                                                last_slash);
                break;
        }
@@ -96,7 +97,7 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
                build_id__sprintf(dso->build_id,
                                  sizeof(dso->build_id),
                                  build_id_hex);
-               snprintf(file, size,
+               snprintf(filename, size,
                         "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
                         symbol_conf.symfs, build_id_hex, build_id_hex + 2);
                break;
@@ -104,23 +105,23 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
        case DSO_BINARY_TYPE__VMLINUX:
        case DSO_BINARY_TYPE__GUEST_VMLINUX:
        case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
-               snprintf(file, size, "%s%s",
+               snprintf(filename, size, "%s%s",
                         symbol_conf.symfs, dso->long_name);
                break;
 
        case DSO_BINARY_TYPE__GUEST_KMODULE:
-               snprintf(file, size, "%s%s%s", symbol_conf.symfs,
+               snprintf(filename, size, "%s%s%s", symbol_conf.symfs,
                         root_dir, dso->long_name);
                break;
 
        case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
-               snprintf(file, size, "%s%s", symbol_conf.symfs,
+               snprintf(filename, size, "%s%s", symbol_conf.symfs,
                         dso->long_name);
                break;
 
        case DSO_BINARY_TYPE__KCORE:
        case DSO_BINARY_TYPE__GUEST_KCORE:
-               snprintf(file, size, "%s", dso->long_name);
+               snprintf(filename, size, "%s", dso->long_name);
                break;
 
        default:
@@ -137,19 +138,18 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
 
 static int open_dso(struct dso *dso, struct machine *machine)
 {
-       char *root_dir = (char *) "";
-       char *name;
        int fd;
+       char *root_dir = (char *)"";
+       char *name = malloc(PATH_MAX);
 
-       name = malloc(PATH_MAX);
        if (!name)
                return -ENOMEM;
 
        if (machine)
                root_dir = machine->root_dir;
 
-       if (dso__binary_type_file(dso, dso->data_type,
-                                 root_dir, name, PATH_MAX)) {
+       if (dso__read_binary_type_filename(dso, dso->binary_type,
+                                           root_dir, name, PATH_MAX)) {
                free(name);
                return -EINVAL;
        }
@@ -161,26 +161,26 @@ static int open_dso(struct dso *dso, struct machine *machine)
 
 int dso__data_fd(struct dso *dso, struct machine *machine)
 {
-       static enum dso_binary_type binary_type_data[] = {
+       enum dso_binary_type binary_type_data[] = {
                DSO_BINARY_TYPE__BUILD_ID_CACHE,
                DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
                DSO_BINARY_TYPE__NOT_FOUND,
        };
        int i = 0;
 
-       if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
+       if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND)
                return open_dso(dso, machine);
 
        do {
                int fd;
 
-               dso->data_type = binary_type_data[i++];
+               dso->binary_type = binary_type_data[i++];
 
                fd = open_dso(dso, machine);
                if (fd >= 0)
                        return fd;
 
-       } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
+       } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
 
        return -EINVAL;
 }
@@ -200,11 +200,10 @@ dso_cache__free(struct rb_root *root)
        }
 }
 
-static struct dso_cache*
-dso_cache__find(struct rb_root *root, u64 offset)
+static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
 {
-       struct rb_node **p = &root->rb_node;
-       struct rb_node *parent = NULL;
+       struct rb_node * const *p = &root->rb_node;
+       const struct rb_node *parent = NULL;
        struct dso_cache *cache;
 
        while (*p != NULL) {
@@ -379,32 +378,63 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
         * processing we had no idea this was the kernel dso.
         */
        if (dso != NULL) {
-               dso__set_short_name(dso, short_name);
+               dso__set_short_name(dso, short_name, false);
                dso->kernel = dso_type;
        }
 
        return dso;
 }
 
-void dso__set_long_name(struct dso *dso, char *name)
+void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
 {
        if (name == NULL)
                return;
-       dso->long_name = name;
-       dso->long_name_len = strlen(name);
+
+       if (dso->long_name_allocated)
+               free((char *)dso->long_name);
+
+       dso->long_name           = name;
+       dso->long_name_len       = strlen(name);
+       dso->long_name_allocated = name_allocated;
 }
 
-void dso__set_short_name(struct dso *dso, const char *name)
+void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
 {
        if (name == NULL)
                return;
-       dso->short_name = name;
-       dso->short_name_len = strlen(name);
+
+       if (dso->short_name_allocated)
+               free((char *)dso->short_name);
+
+       dso->short_name           = name;
+       dso->short_name_len       = strlen(name);
+       dso->short_name_allocated = name_allocated;
 }
 
 static void dso__set_basename(struct dso *dso)
 {
-       dso__set_short_name(dso, basename(dso->long_name));
+       /*
+        * basename() may modify path buffer, so we must pass
+        * a copy.
+        */
+       char *base, *lname = strdup(dso->long_name);
+
+       if (!lname)
+               return;
+
+       /*
+        * basename() may return a pointer to internal
+        * storage which is reused in subsequent calls
+        * so copy the result.
+        */
+       base = strdup(basename(lname));
+
+       free(lname);
+
+       if (!base)
+               return;
+
+       dso__set_short_name(dso, base, true);
 }
 
 int dso__name_len(const struct dso *dso)
@@ -439,18 +469,19 @@ struct dso *dso__new(const char *name)
        if (dso != NULL) {
                int i;
                strcpy(dso->name, name);
-               dso__set_long_name(dso, dso->name);
-               dso__set_short_name(dso, dso->name);
+               dso__set_long_name(dso, dso->name, false);
+               dso__set_short_name(dso, dso->name, false);
                for (i = 0; i < MAP__NR_TYPES; ++i)
                        dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
                dso->cache = RB_ROOT;
                dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
-               dso->data_type   = DSO_BINARY_TYPE__NOT_FOUND;
+               dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
                dso->loaded = 0;
                dso->rel = 0;
                dso->sorted_by_name = 0;
                dso->has_build_id = 0;
                dso->has_srcline = 1;
+               dso->a2l_fails = 1;
                dso->kernel = DSO_TYPE_USER;
                dso->needs_swap = DSO_SWAP__UNSET;
                INIT_LIST_HEAD(&dso->node);
@@ -464,11 +495,20 @@ void dso__delete(struct dso *dso)
        int i;
        for (i = 0; i < MAP__NR_TYPES; ++i)
                symbols__delete(&dso->symbols[i]);
-       if (dso->sname_alloc)
-               free((char *)dso->short_name);
-       if (dso->lname_alloc)
-               free(dso->long_name);
+
+       if (dso->short_name_allocated) {
+               zfree((char **)&dso->short_name);
+               dso->short_name_allocated = false;
+       }
+
+       if (dso->long_name_allocated) {
+               zfree((char **)&dso->long_name);
+               dso->long_name_allocated = false;
+       }
+
        dso_cache__free(&dso->cache);
+       dso__free_a2l(dso);
+       zfree(&dso->symsrc_filename);
        free(dso);
 }
 
@@ -543,7 +583,7 @@ void dsos__add(struct list_head *head, struct dso *dso)
        list_add_tail(&dso->node, head);
 }
 
-struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short)
+struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short)
 {
        struct dso *pos;
 
index 9ac666abbe7ef988f30630c053f9c4e709eb3edb..cd7d6f078cddf618e40e709eab6c1d93750e155a 100644 (file)
@@ -77,23 +77,26 @@ struct dso {
        struct rb_root   symbols[MAP__NR_TYPES];
        struct rb_root   symbol_names[MAP__NR_TYPES];
        struct rb_root   cache;
+       void             *a2l;
+       char             *symsrc_filename;
+       unsigned int     a2l_fails;
        enum dso_kernel_type    kernel;
        enum dso_swap_type      needs_swap;
        enum dso_binary_type    symtab_type;
-       enum dso_binary_type    data_type;
+       enum dso_binary_type    binary_type;
        u8               adjust_symbols:1;
        u8               has_build_id:1;
        u8               has_srcline:1;
        u8               hit:1;
        u8               annotate_warned:1;
-       u8               sname_alloc:1;
-       u8               lname_alloc:1;
+       u8               short_name_allocated:1;
+       u8               long_name_allocated:1;
        u8               sorted_by_name;
        u8               loaded;
        u8               rel;
        u8               build_id[BUILD_ID_SIZE];
        const char       *short_name;
-       char             *long_name;
+       const char       *long_name;
        u16              long_name_len;
        u16              short_name_len;
        char             name[0];
@@ -107,8 +110,8 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type)
 struct dso *dso__new(const char *name);
 void dso__delete(struct dso *dso);
 
-void dso__set_short_name(struct dso *dso, const char *name);
-void dso__set_long_name(struct dso *dso, char *name);
+void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated);
+void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated);
 
 int dso__name_len(const struct dso *dso);
 
@@ -125,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso,
 int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
 
 char dso__symtab_origin(const struct dso *dso);
-int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
-                         char *root_dir, char *file, size_t size);
+int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
+                                  char *root_dir, char *filename, size_t size);
 
 int dso__data_fd(struct dso *dso, struct machine *machine);
 ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
@@ -140,7 +143,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
                                const char *short_name, int dso_type);
 
 void dsos__add(struct list_head *head, struct dso *dso);
-struct dso *dsos__find(struct list_head *head, const char *name,
+struct dso *dsos__find(const struct list_head *head, const char *name,
                       bool cmp_short);
 struct dso *__dsos__findnew(struct list_head *head, const char *name);
 bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
@@ -156,14 +159,16 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
 
 static inline bool dso__is_vmlinux(struct dso *dso)
 {
-       return dso->data_type == DSO_BINARY_TYPE__VMLINUX ||
-              dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX;
+       return dso->binary_type == DSO_BINARY_TYPE__VMLINUX ||
+              dso->binary_type == DSO_BINARY_TYPE__GUEST_VMLINUX;
 }
 
 static inline bool dso__is_kcore(struct dso *dso)
 {
-       return dso->data_type == DSO_BINARY_TYPE__KCORE ||
-              dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE;
+       return dso->binary_type == DSO_BINARY_TYPE__KCORE ||
+              dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
 }
 
+void dso__free_a2l(struct dso *dso);
+
 #endif /* __PERF_DSO */
index bb788c109fe6efa4ecb2ae5784efa49cf33bca73..1fc1c2f04772fa06b9f7624c9f378e0e2f748d0f 100644 (file)
@@ -7,6 +7,7 @@
 #include "strlist.h"
 #include "thread.h"
 #include "thread_map.h"
+#include "symbol/kallsyms.h"
 
 static const char *perf_event__names[] = {
        [0]                                     = "TOTAL",
@@ -105,8 +106,12 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
 
        memset(&event->comm, 0, sizeof(event->comm));
 
-       tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
-                                        sizeof(event->comm.comm));
+       if (machine__is_host(machine))
+               tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
+                                                sizeof(event->comm.comm));
+       else
+               tgid = machine->pid;
+
        if (tgid < 0)
                goto out;
 
@@ -128,7 +133,11 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
                goto out;
        }
 
-       snprintf(filename, sizeof(filename), "/proc/%d/task", 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) {
@@ -166,18 +175,22 @@ out:
        return tgid;
 }
 
-static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
-                                             union perf_event *event,
-                                             pid_t pid, pid_t tgid,
-                                             perf_event__handler_t process,
-                                             struct machine *machine,
-                                             bool mmap_data)
+int perf_event__synthesize_mmap_events(struct perf_tool *tool,
+                                      union perf_event *event,
+                                      pid_t pid, pid_t tgid,
+                                      perf_event__handler_t process,
+                                      struct machine *machine,
+                                      bool mmap_data)
 {
        char filename[PATH_MAX];
        FILE *fp;
        int rc = 0;
 
-       snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
+       if (machine__is_default_guest(machine))
+               return 0;
+
+       snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
+                machine->root_dir, pid);
 
        fp = fopen(filename, "r");
        if (fp == NULL) {
@@ -217,7 +230,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                /*
                 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
                 */
-               event->header.misc = PERF_RECORD_MISC_USER;
+               if (machine__is_host(machine))
+                       event->header.misc = PERF_RECORD_MISC_USER;
+               else
+                       event->header.misc = PERF_RECORD_MISC_GUEST_USER;
 
                if (prot[2] != 'x') {
                        if (!mmap_data || prot[0] != 'r')
@@ -386,6 +402,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                                   struct machine *machine, bool mmap_data)
 {
        DIR *proc;
+       char proc_path[PATH_MAX];
        struct dirent dirent, *next;
        union perf_event *comm_event, *mmap_event;
        int err = -1;
@@ -398,7 +415,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
        if (mmap_event == NULL)
                goto out_free_comm;
 
-       proc = opendir("/proc");
+       if (machine__is_default_guest(machine))
+               return 0;
+
+       snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
+       proc = opendir(proc_path);
+
        if (proc == NULL)
                goto out_free_mmap;
 
@@ -637,6 +659,7 @@ void thread__find_addr_map(struct thread *thread,
        struct map_groups *mg = &thread->mg;
        bool load_map = false;
 
+       al->machine = machine;
        al->thread = thread;
        al->addr = addr;
        al->cpumode = cpumode;
@@ -657,15 +680,10 @@ void thread__find_addr_map(struct thread *thread,
                al->level = 'g';
                mg = &machine->kmaps;
                load_map = true;
+       } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
+               al->level = 'u';
        } else {
-               /*
-                * 'u' means guest os user space.
-                * TODO: We don't support guest user space. Might support late.
-                */
-               if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest)
-                       al->level = 'u';
-               else
-                       al->level = 'H';
+               al->level = 'H';
                al->map = NULL;
 
                if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
@@ -732,8 +750,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
        if (thread == NULL)
                return -1;
 
-       if (symbol_conf.comm_list &&
-           !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
+       if (thread__is_filtered(thread))
                goto out_filtered;
 
        dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
index 30fec9901e440b459e49b1b6e8d584cc6e0e15a8..faf6e219be21f5ec73d85b568592279fb47e1fa1 100644 (file)
@@ -266,6 +266,13 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
                                  const struct perf_sample *sample,
                                  bool swapped);
 
+int perf_event__synthesize_mmap_events(struct perf_tool *tool,
+                                      union perf_event *event,
+                                      pid_t pid, pid_t tgid,
+                                      perf_event__handler_t process,
+                                      struct machine *machine,
+                                      bool mmap_data);
+
 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
index bbc746aa571663d92e989bb5f3f2703c31c9a193..40bd2c04df8ad7cb02e713e4f02a832850b0a43f 100644 (file)
@@ -7,7 +7,7 @@
  * Released under the GPL v2. (and only v2, not any later version)
  */
 #include "util.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include <poll.h>
 #include "cpumap.h"
 #include "thread_map.h"
@@ -81,7 +81,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node)
+       evlist__for_each(evlist, evsel)
                perf_evsel__calc_id_pos(evsel);
 
        perf_evlist__set_id_pos(evlist);
@@ -91,7 +91,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 {
        struct perf_evsel *pos, *n;
 
-       list_for_each_entry_safe(pos, n, &evlist->entries, node) {
+       evlist__for_each_safe(evlist, n, pos) {
                list_del_init(&pos->node);
                perf_evsel__delete(pos);
        }
@@ -101,14 +101,18 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
-       free(evlist->mmap);
-       free(evlist->pollfd);
-       evlist->mmap = NULL;
-       evlist->pollfd = NULL;
+       zfree(&evlist->mmap);
+       zfree(&evlist->pollfd);
 }
 
 void perf_evlist__delete(struct perf_evlist *evlist)
 {
+       perf_evlist__munmap(evlist);
+       perf_evlist__close(evlist);
+       cpu_map__delete(evlist->cpus);
+       thread_map__delete(evlist->threads);
+       evlist->cpus = NULL;
+       evlist->threads = NULL;
        perf_evlist__purge(evlist);
        perf_evlist__exit(evlist);
        free(evlist);
@@ -144,7 +148,7 @@ void __perf_evlist__set_leader(struct list_head *list)
 
        leader->nr_members = evsel->idx - leader->idx + 1;
 
-       list_for_each_entry(evsel, list, node) {
+       __evlist__for_each(list, evsel) {
                evsel->leader = leader;
        }
 }
@@ -203,7 +207,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
        return 0;
 
 out_delete_partial_list:
-       list_for_each_entry_safe(evsel, n, &head, node)
+       __evlist__for_each_safe(&head, n, evsel)
                perf_evsel__delete(evsel);
        return -1;
 }
@@ -224,7 +228,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (evsel->attr.type   == PERF_TYPE_TRACEPOINT &&
                    (int)evsel->attr.config == id)
                        return evsel;
@@ -239,7 +243,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
                    (strcmp(evsel->name, name) == 0))
                        return evsel;
@@ -269,7 +273,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
        int nr_threads = thread_map__nr(evlist->threads);
 
        for (cpu = 0; cpu < nr_cpus; cpu++) {
-               list_for_each_entry(pos, &evlist->entries, node) {
+               evlist__for_each(evlist, pos) {
                        if (!perf_evsel__is_group_leader(pos) || !pos->fd)
                                continue;
                        for (thread = 0; thread < nr_threads; thread++)
@@ -287,7 +291,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
        int nr_threads = thread_map__nr(evlist->threads);
 
        for (cpu = 0; cpu < nr_cpus; cpu++) {
-               list_for_each_entry(pos, &evlist->entries, node) {
+               evlist__for_each(evlist, pos) {
                        if (!perf_evsel__is_group_leader(pos) || !pos->fd)
                                continue;
                        for (thread = 0; thread < nr_threads; thread++)
@@ -584,11 +588,13 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
 {
        int i;
 
+       if (evlist->mmap == NULL)
+               return;
+
        for (i = 0; i < evlist->nr_mmaps; i++)
                __perf_evlist__munmap(evlist, i);
 
-       free(evlist->mmap);
-       evlist->mmap = NULL;
+       zfree(&evlist->mmap);
 }
 
 static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
@@ -624,7 +630,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                int fd = FD(evsel, cpu, thread);
 
                if (*output == -1) {
@@ -732,11 +738,13 @@ static long parse_pages_arg(const char *str, unsigned long min,
                        return -EINVAL;
        }
 
-       if ((pages == 0) && (min == 0)) {
+       if (pages == 0 && min == 0) {
                /* leave number of pages at 0 */
-       } else if (pages < (1UL << 31) && !is_power_of_2(pages)) {
+       } else if (!is_power_of_2(pages)) {
                /* round pages up to next power of 2 */
-               pages = next_pow2(pages);
+               pages = next_pow2_l(pages);
+               if (!pages)
+                       return -EINVAL;
                pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
                        pages * page_size, pages);
        }
@@ -754,7 +762,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
        unsigned long max = UINT_MAX;
        long pages;
 
-       if (max < SIZE_MAX / page_size)
+       if (max > SIZE_MAX / page_size)
                max = SIZE_MAX / page_size;
 
        pages = parse_pages_arg(str, 1, max);
@@ -798,7 +806,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
        pr_debug("mmap size %zuB\n", evlist->mmap_len);
        mask = evlist->mmap_len - page_size - 1;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
                    evsel->sample_id == NULL &&
                    perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
@@ -819,11 +827,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
        if (evlist->threads == NULL)
                return -1;
 
-       if (target->force_per_cpu)
-               evlist->cpus = cpu_map__new(target->cpu_list);
-       else if (target__has_task(target))
-               evlist->cpus = cpu_map__dummy_new();
-       else if (!target__has_cpu(target) && !target->uses_mmap)
+       if (target__uses_dummy_map(target))
                evlist->cpus = cpu_map__dummy_new();
        else
                evlist->cpus = cpu_map__new(target->cpu_list);
@@ -838,14 +842,6 @@ out_delete_threads:
        return -1;
 }
 
-void perf_evlist__delete_maps(struct perf_evlist *evlist)
-{
-       cpu_map__delete(evlist->cpus);
-       thread_map__delete(evlist->threads);
-       evlist->cpus    = NULL;
-       evlist->threads = NULL;
-}
-
 int perf_evlist__apply_filters(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
@@ -853,7 +849,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist)
        const int ncpus = cpu_map__nr(evlist->cpus),
                  nthreads = thread_map__nr(evlist->threads);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (evsel->filter == NULL)
                        continue;
 
@@ -872,7 +868,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
        const int ncpus = cpu_map__nr(evlist->cpus),
                  nthreads = thread_map__nr(evlist->threads);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
                if (err)
                        break;
@@ -891,7 +887,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
        if (evlist->id_pos < 0 || evlist->is_pos < 0)
                return false;
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                if (pos->id_pos != evlist->id_pos ||
                    pos->is_pos != evlist->is_pos)
                        return false;
@@ -907,7 +903,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
        if (evlist->combined_sample_type)
                return evlist->combined_sample_type;
 
-       list_for_each_entry(evsel, &evlist->entries, node)
+       evlist__for_each(evlist, evsel)
                evlist->combined_sample_type |= evsel->attr.sample_type;
 
        return evlist->combined_sample_type;
@@ -925,7 +921,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
        u64 read_format = first->attr.read_format;
        u64 sample_type = first->attr.sample_type;
 
-       list_for_each_entry_continue(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                if (read_format != pos->attr.read_format)
                        return false;
        }
@@ -982,7 +978,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
 {
        struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
 
-       list_for_each_entry_continue(pos, &evlist->entries, node) {
+       evlist__for_each_continue(evlist, pos) {
                if (first->attr.sample_id_all != pos->attr.sample_id_all)
                        return false;
        }
@@ -1008,7 +1004,7 @@ void perf_evlist__close(struct perf_evlist *evlist)
        int ncpus = cpu_map__nr(evlist->cpus);
        int nthreads = thread_map__nr(evlist->threads);
 
-       list_for_each_entry_reverse(evsel, &evlist->entries, node)
+       evlist__for_each_reverse(evlist, evsel)
                perf_evsel__close(evsel, ncpus, nthreads);
 }
 
@@ -1019,7 +1015,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
 
        perf_evlist__update_id_pos(evlist);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
                if (err < 0)
                        goto out_err;
@@ -1034,7 +1030,7 @@ out_err:
 
 int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
                                  const char *argv[], bool pipe_output,
-                                 bool want_signal)
+                                 void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
 {
        int child_ready_pipe[2], go_pipe[2];
        char bf;
@@ -1078,12 +1074,25 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
 
                execvp(argv[0], (char **)argv);
 
-               perror(argv[0]);
-               if (want_signal)
-                       kill(getppid(), SIGUSR1);
+               if (exec_error) {
+                       union sigval val;
+
+                       val.sival_int = errno;
+                       if (sigqueue(getppid(), SIGUSR1, val))
+                               perror(argv[0]);
+               } else
+                       perror(argv[0]);
                exit(-1);
        }
 
+       if (exec_error) {
+               struct sigaction act = {
+                       .sa_flags     = SA_SIGINFO,
+                       .sa_sigaction = exec_error,
+               };
+               sigaction(SIGUSR1, &act, NULL);
+       }
+
        if (target__none(target))
                evlist->threads->map[0] = evlist->workload.pid;
 
@@ -1145,7 +1154,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
        struct perf_evsel *evsel;
        size_t printed = 0;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
                                   perf_evsel__name(evsel));
        }
@@ -1193,8 +1202,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
                                    "Error:\t%s.\n"
                                    "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
 
-               if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value))
-                       break;
+               value = perf_event_paranoid();
 
                printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
 
@@ -1215,3 +1223,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
 
        return 0;
 }
+
+void perf_evlist__to_front(struct perf_evlist *evlist,
+                          struct perf_evsel *move_evsel)
+{
+       struct perf_evsel *evsel, *n;
+       LIST_HEAD(move);
+
+       if (move_evsel == perf_evlist__first(evlist))
+               return;
+
+       evlist__for_each_safe(evlist, n, evsel) {
+               if (evsel->leader == move_evsel->leader)
+                       list_move_tail(&evsel->node, &move);
+       }
+
+       list_splice(&move, &evlist->entries);
+}
index 649d6ea98a84a0dfb91b5dbfb55a96292ca9703a..f5173cd63693cc7944b500a65a0b407567512143 100644 (file)
@@ -12,7 +12,7 @@
 struct pollfd;
 struct thread_map;
 struct cpu_map;
-struct perf_record_opts;
+struct record_opts;
 
 #define PERF_EVLIST__HLIST_BITS 8
 #define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -97,14 +97,14 @@ void perf_evlist__close(struct perf_evlist *evlist);
 
 void perf_evlist__set_id_pos(struct perf_evlist *evlist);
 bool perf_can_sample_identifier(void);
-void perf_evlist__config(struct perf_evlist *evlist,
-                        struct perf_record_opts *opts);
-int perf_record_opts__config(struct perf_record_opts *opts);
+void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts);
+int record_opts__config(struct record_opts *opts);
 
 int perf_evlist__prepare_workload(struct perf_evlist *evlist,
                                  struct target *target,
                                  const char *argv[], bool pipe_output,
-                                 bool want_signal);
+                                 void (*exec_error)(int signo, siginfo_t *info,
+                                                    void *ucontext));
 int perf_evlist__start_workload(struct perf_evlist *evlist);
 
 int perf_evlist__parse_mmap_pages(const struct option *opt,
@@ -135,7 +135,6 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
 }
 
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
-void perf_evlist__delete_maps(struct perf_evlist *evlist);
 int perf_evlist__apply_filters(struct perf_evlist *evlist);
 
 void __perf_evlist__set_leader(struct list_head *list);
@@ -193,4 +192,74 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md,
        pc->data_tail = tail;
 }
 
+bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
+void perf_evlist__to_front(struct perf_evlist *evlist,
+                          struct perf_evsel *move_evsel);
+
+/**
+ * __evlist__for_each - iterate thru all the evsels
+ * @list: list_head instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define __evlist__for_each(list, evsel) \
+        list_for_each_entry(evsel, list, node)
+
+/**
+ * evlist__for_each - iterate thru all the evsels
+ * @evlist: evlist instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define evlist__for_each(evlist, evsel) \
+       __evlist__for_each(&(evlist)->entries, evsel)
+
+/**
+ * __evlist__for_each_continue - continue iteration thru all the evsels
+ * @list: list_head instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define __evlist__for_each_continue(list, evsel) \
+        list_for_each_entry_continue(evsel, list, node)
+
+/**
+ * evlist__for_each_continue - continue iteration thru all the evsels
+ * @evlist: evlist instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define evlist__for_each_continue(evlist, evsel) \
+       __evlist__for_each_continue(&(evlist)->entries, evsel)
+
+/**
+ * __evlist__for_each_reverse - iterate thru all the evsels in reverse order
+ * @list: list_head instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define __evlist__for_each_reverse(list, evsel) \
+        list_for_each_entry_reverse(evsel, list, node)
+
+/**
+ * evlist__for_each_reverse - iterate thru all the evsels in reverse order
+ * @evlist: evlist instance to iterate
+ * @evsel: struct evsel iterator
+ */
+#define evlist__for_each_reverse(evlist, evsel) \
+       __evlist__for_each_reverse(&(evlist)->entries, evsel)
+
+/**
+ * __evlist__for_each_safe - safely iterate thru all the evsels
+ * @list: list_head instance to iterate
+ * @tmp: struct evsel temp iterator
+ * @evsel: struct evsel iterator
+ */
+#define __evlist__for_each_safe(list, tmp, evsel) \
+        list_for_each_entry_safe(evsel, tmp, list, node)
+
+/**
+ * evlist__for_each_safe - safely iterate thru all the evsels
+ * @evlist: evlist instance to iterate
+ * @evsel: struct evsel iterator
+ * @tmp: struct evsel temp iterator
+ */
+#define evlist__for_each_safe(evlist, tmp, evsel) \
+       __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
+
 #endif /* __PERF_EVLIST_H */
index 46dd4c2a41ce7e0a844e0b691c134e3ce23f55e6..22e18a26b7e6c778aefe5fb44c0cd518b5ff798d 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <byteswap.h>
 #include <linux/bitops.h>
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include <traceevent/event-parse.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/perf_event.h>
@@ -23,6 +23,7 @@
 #include "target.h"
 #include "perf_regs.h"
 #include "debug.h"
+#include "trace-event.h"
 
 static struct {
        bool sample_id_all;
@@ -162,6 +163,8 @@ void perf_evsel__init(struct perf_evsel *evsel,
        evsel->idx         = idx;
        evsel->attr        = *attr;
        evsel->leader      = evsel;
+       evsel->unit        = "";
+       evsel->scale       = 1.0;
        INIT_LIST_HEAD(&evsel->node);
        hists__init(&evsel->hists);
        evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
@@ -178,47 +181,6 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
        return evsel;
 }
 
-struct event_format *event_format__new(const char *sys, const char *name)
-{
-       int fd, n;
-       char *filename;
-       void *bf = NULL, *nbf;
-       size_t size = 0, alloc_size = 0;
-       struct event_format *format = NULL;
-
-       if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
-               goto out;
-
-       fd = open(filename, O_RDONLY);
-       if (fd < 0)
-               goto out_free_filename;
-
-       do {
-               if (size == alloc_size) {
-                       alloc_size += BUFSIZ;
-                       nbf = realloc(bf, alloc_size);
-                       if (nbf == NULL)
-                               goto out_free_bf;
-                       bf = nbf;
-               }
-
-               n = read(fd, bf + size, alloc_size - size);
-               if (n < 0)
-                       goto out_free_bf;
-               size += n;
-       } while (n > 0);
-
-       pevent_parse_format(&format, bf, size, sys);
-
-out_free_bf:
-       free(bf);
-       close(fd);
-out_free_filename:
-       free(filename);
-out:
-       return format;
-}
-
 struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
 {
        struct perf_evsel *evsel = zalloc(sizeof(*evsel));
@@ -233,7 +195,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
                if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
                        goto out_free;
 
-               evsel->tp_format = event_format__new(sys, name);
+               evsel->tp_format = trace_event__tp_format(sys, name);
                if (evsel->tp_format == NULL)
                        goto out_free;
 
@@ -246,7 +208,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
        return evsel;
 
 out_free:
-       free(evsel->name);
+       zfree(&evsel->name);
        free(evsel);
        return NULL;
 }
@@ -566,12 +528,12 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
  *     enable/disable events specifically, as there's no
  *     initial traced exec call.
  */
-void perf_evsel__config(struct perf_evsel *evsel,
-                       struct perf_record_opts *opts)
+void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
 {
        struct perf_evsel *leader = evsel->leader;
        struct perf_event_attr *attr = &evsel->attr;
        int track = !evsel->idx; /* only the first counter needs these */
+       bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
 
        attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
        attr->inherit       = !opts->no_inherit;
@@ -645,7 +607,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
                }
        }
 
-       if (target__has_cpu(&opts->target) || opts->target.force_per_cpu)
+       if (target__has_cpu(&opts->target))
                perf_evsel__set_sample_bit(evsel, CPU);
 
        if (opts->period)
@@ -653,7 +615,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
 
        if (!perf_missing_features.sample_id_all &&
            (opts->sample_time || !opts->no_inherit ||
-            target__has_cpu(&opts->target) || opts->target.force_per_cpu))
+            target__has_cpu(&opts->target) || per_cpu))
                perf_evsel__set_sample_bit(evsel, TIME);
 
        if (opts->raw_samples) {
@@ -665,7 +627,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
        if (opts->sample_address)
                perf_evsel__set_sample_bit(evsel, DATA_SRC);
 
-       if (opts->no_delay) {
+       if (opts->no_buffering) {
                attr->watermark = 0;
                attr->wakeup_events = 1;
        }
@@ -696,7 +658,8 @@ void perf_evsel__config(struct perf_evsel *evsel,
         * Setting enable_on_exec for independent events and
         * group leaders for traced executed by perf.
         */
-       if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel))
+       if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) &&
+               !opts->initial_delay)
                attr->enable_on_exec = 1;
 }
 
@@ -788,8 +751,7 @@ void perf_evsel__free_id(struct perf_evsel *evsel)
 {
        xyarray__delete(evsel->sample_id);
        evsel->sample_id = NULL;
-       free(evsel->id);
-       evsel->id = NULL;
+       zfree(&evsel->id);
 }
 
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -805,7 +767,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 
 void perf_evsel__free_counts(struct perf_evsel *evsel)
 {
-       free(evsel->counts);
+       zfree(&evsel->counts);
 }
 
 void perf_evsel__exit(struct perf_evsel *evsel)
@@ -819,10 +781,10 @@ void perf_evsel__delete(struct perf_evsel *evsel)
 {
        perf_evsel__exit(evsel);
        close_cgroup(evsel->cgrp);
-       free(evsel->group_name);
+       zfree(&evsel->group_name);
        if (evsel->tp_format)
                pevent_free_format(evsel->tp_format);
-       free(evsel->name);
+       zfree(&evsel->name);
        free(evsel);
 }
 
@@ -1998,8 +1960,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
                evsel->attr.type   = PERF_TYPE_SOFTWARE;
                evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK;
 
-               free(evsel->name);
-               evsel->name = NULL;
+               zfree(&evsel->name);
                return true;
        }
 
index 1ea7c92e6e3365aebbedbed37ae728e9473dbab5..f1b325665aae8201b9696b2c3c5a6a64e009ffb7 100644 (file)
@@ -68,6 +68,8 @@ struct perf_evsel {
        u32                     ids;
        struct hists            hists;
        char                    *name;
+       double                  scale;
+       const char              *unit;
        struct event_format     *tp_format;
        union {
                void            *priv;
@@ -94,7 +96,7 @@ struct perf_evsel {
 struct cpu_map;
 struct thread_map;
 struct perf_evlist;
-struct perf_record_opts;
+struct record_opts;
 
 struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
 
@@ -118,7 +120,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);
 void perf_evsel__delete(struct perf_evsel *evsel);
 
 void perf_evsel__config(struct perf_evsel *evsel,
-                       struct perf_record_opts *opts);
+                       struct record_opts *opts);
 
 int __perf_evsel__sample_size(u64 sample_type);
 void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -138,6 +140,7 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
                                            char *bf, size_t size);
 const char *perf_evsel__name(struct perf_evsel *evsel);
+
 const char *perf_evsel__group_name(struct perf_evsel *evsel);
 int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
 
index 369c03648f8846d3da12bf96a938f6e76485fbed..bb3e0ede61835ff249a6c5766daa279d2ab77f6a 100644 (file)
@@ -177,7 +177,7 @@ perf_header__set_cmdline(int argc, const char **argv)
                        continue;               \
                else
 
-static int write_buildid(char *name, size_t name_len, u8 *build_id,
+static int write_buildid(const char *name, size_t name_len, u8 *build_id,
                         pid_t pid, u16 misc, int fd)
 {
        int err;
@@ -209,7 +209,7 @@ static int __dsos__write_buildid_table(struct list_head *head,
 
        dsos__for_each_with_build_id(pos, head) {
                int err;
-               char  *name;
+               const char *name;
                size_t name_len;
 
                if (!pos->hit)
@@ -387,7 +387,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
 {
        bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
        bool is_vdso = is_vdso_map(dso->short_name);
-       char *name = dso->long_name;
+       const char *name = dso->long_name;
        char nm[PATH_MAX];
 
        if (dso__is_kcore(dso)) {
@@ -643,8 +643,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
        if (ret < 0)
                return ret;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
-
+       evlist__for_each(evlist, evsel) {
                ret = do_write(fd, &evsel->attr, sz);
                if (ret < 0)
                        return ret;
@@ -800,10 +799,10 @@ static void free_cpu_topo(struct cpu_topo *tp)
                return;
 
        for (i = 0 ; i < tp->core_sib; i++)
-               free(tp->core_siblings[i]);
+               zfree(&tp->core_siblings[i]);
 
        for (i = 0 ; i < tp->thread_sib; i++)
-               free(tp->thread_siblings[i]);
+               zfree(&tp->thread_siblings[i]);
 
        free(tp);
 }
@@ -1092,7 +1091,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
        if (ret < 0)
                return ret;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (perf_evsel__is_group_leader(evsel) &&
                    evsel->nr_members > 1) {
                        const char *name = evsel->group_name ?: "{anon_group}";
@@ -1232,10 +1231,8 @@ static void free_event_desc(struct perf_evsel *events)
                return;
 
        for (evsel = events; evsel->attr.size; evsel++) {
-               if (evsel->name)
-                       free(evsel->name);
-               if (evsel->id)
-                       free(evsel->id);
+               zfree(&evsel->name);
+               zfree(&evsel->id);
        }
 
        free(events);
@@ -1326,8 +1323,7 @@ read_event_desc(struct perf_header *ph, int fd)
                }
        }
 out:
-       if (buf)
-               free(buf);
+       free(buf);
        return events;
 error:
        if (events)
@@ -1490,7 +1486,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
 
        session = container_of(ph, struct perf_session, header);
 
-       list_for_each_entry(evsel, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, evsel) {
                if (perf_evsel__is_group_leader(evsel) &&
                    evsel->nr_members > 1) {
                        fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
@@ -1709,7 +1705,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
                          struct perf_header *ph, int fd,
                          void *data __maybe_unused)
 {
-       size_t ret;
+       ssize_t ret;
        u32 nr;
 
        ret = readn(fd, &nr, sizeof(nr));
@@ -1753,7 +1749,7 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused,
                             void *data __maybe_unused)
 {
        uint64_t mem;
-       size_t ret;
+       ssize_t ret;
 
        ret = readn(fd, &mem, sizeof(mem));
        if (ret != sizeof(mem))
@@ -1771,7 +1767,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (evsel->idx == idx)
                        return evsel;
        }
@@ -1822,7 +1818,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,
                           struct perf_header *ph, int fd,
                           void *data __maybe_unused)
 {
-       size_t ret;
+       ssize_t ret;
        char *str;
        u32 nr, i;
        struct strbuf sb;
@@ -1858,7 +1854,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
                                struct perf_header *ph, int fd,
                                void *data __maybe_unused)
 {
-       size_t ret;
+       ssize_t ret;
        u32 nr, i;
        char *str;
        struct strbuf sb;
@@ -1914,7 +1910,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
                                 struct perf_header *ph, int fd,
                                 void *data __maybe_unused)
 {
-       size_t ret;
+       ssize_t ret;
        u32 nr, node, i;
        char *str;
        uint64_t mem_total, mem_free;
@@ -1974,7 +1970,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
                                struct perf_header *ph, int fd,
                                void *data __maybe_unused)
 {
-       size_t ret;
+       ssize_t ret;
        char *name;
        u32 pmu_num;
        u32 type;
@@ -2074,12 +2070,14 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
        session->evlist->nr_groups = nr_groups;
 
        i = nr = 0;
-       list_for_each_entry(evsel, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, evsel) {
                if (evsel->idx == (int) desc[i].leader_idx) {
                        evsel->leader = evsel;
                        /* {anon_group} is a dummy name */
-                       if (strcmp(desc[i].name, "{anon_group}"))
+                       if (strcmp(desc[i].name, "{anon_group}")) {
                                evsel->group_name = desc[i].name;
+                               desc[i].name = NULL;
+                       }
                        evsel->nr_members = desc[i].nr_members;
 
                        if (i >= nr_groups || nr > 0) {
@@ -2105,8 +2103,8 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
 
        ret = 0;
 out_free:
-       while ((int) --i >= 0)
-               free(desc[i].name);
+       for (i = 0; i < nr_groups; i++)
+               zfree(&desc[i].name);
        free(desc);
 
        return ret;
@@ -2299,7 +2297,7 @@ int perf_session__write_header(struct perf_session *session,
 
        lseek(fd, sizeof(f_header), SEEK_SET);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(session->evlist, evsel) {
                evsel->id_offset = lseek(fd, 0, SEEK_CUR);
                err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
                if (err < 0) {
@@ -2310,7 +2308,7 @@ int perf_session__write_header(struct perf_session *session,
 
        attr_offset = lseek(fd, 0, SEEK_CUR);
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                f_attr = (struct perf_file_attr){
                        .attr = evsel->attr,
                        .ids  = {
@@ -2325,7 +2323,8 @@ int perf_session__write_header(struct perf_session *session,
                }
        }
 
-       header->data_offset = lseek(fd, 0, SEEK_CUR);
+       if (!header->data_offset)
+               header->data_offset = lseek(fd, 0, SEEK_CUR);
        header->feat_offset = header->data_offset + header->data_size;
 
        if (at_exit) {
@@ -2532,7 +2531,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
 int perf_file_header__read(struct perf_file_header *header,
                           struct perf_header *ph, int fd)
 {
-       int ret;
+       ssize_t ret;
 
        lseek(fd, 0, SEEK_SET);
 
@@ -2626,7 +2625,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
                                       struct perf_header *ph, int fd,
                                       bool repipe)
 {
-       int ret;
+       ssize_t ret;
 
        ret = readn(fd, header, sizeof(*header));
        if (ret <= 0)
@@ -2667,7 +2666,7 @@ static int read_attr(int fd, struct perf_header *ph,
        struct perf_event_attr *attr = &f_attr->attr;
        size_t sz, left;
        size_t our_sz = sizeof(f_attr->attr);
-       int ret;
+       ssize_t ret;
 
        memset(f_attr, 0, sizeof(*f_attr));
 
@@ -2742,7 +2741,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
 {
        struct perf_evsel *pos;
 
-       list_for_each_entry(pos, &evlist->entries, node) {
+       evlist__for_each(evlist, pos) {
                if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
                    perf_evsel__prepare_tracepoint_event(pos, pevent))
                        return -1;
@@ -2832,11 +2831,11 @@ int perf_session__read_header(struct perf_session *session)
 
        symbol_conf.nr_events = nr_attrs;
 
-       perf_header__process_sections(header, fd, &session->pevent,
+       perf_header__process_sections(header, fd, &session->tevent,
                                      perf_file_section__process);
 
        if (perf_evlist__prepare_tracepoint_events(session->evlist,
-                                                  session->pevent))
+                                                  session->tevent.pevent))
                goto out_delete_evlist;
 
        return 0;
@@ -2890,7 +2889,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
        struct perf_evsel *evsel;
        int err = 0;
 
-       list_for_each_entry(evsel, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, evsel) {
                err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
                                                  evsel->id, process);
                if (err) {
@@ -3001,7 +3000,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
        lseek(fd, offset + sizeof(struct tracing_data_event),
              SEEK_SET);
 
-       size_read = trace_report(fd, &session->pevent,
+       size_read = trace_report(fd, &session->tevent,
                                 session->repipe);
        padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
 
@@ -3023,7 +3022,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
        }
 
        perf_evlist__prepare_tracepoint_events(session->evlist,
-                                              session->pevent);
+                                              session->tevent.pevent);
 
        return size_read + padding;
 }
index 307c9aed972ed0d6403fe58da4d9edae4109abdf..a2d047bdf4efab50837d04afd3a896bc482cf66f 100644 (file)
@@ -77,16 +77,16 @@ struct perf_session_env {
        unsigned long long      total_mem;
 
        int                     nr_cmdline;
-       char                    *cmdline;
        int                     nr_sibling_cores;
-       char                    *sibling_cores;
        int                     nr_sibling_threads;
-       char                    *sibling_threads;
        int                     nr_numa_nodes;
-       char                    *numa_nodes;
        int                     nr_pmu_mappings;
-       char                    *pmu_mappings;
        int                     nr_groups;
+       char                    *cmdline;
+       char                    *sibling_cores;
+       char                    *sibling_threads;
+       char                    *numa_nodes;
+       char                    *pmu_mappings;
 };
 
 struct perf_header {
index 8b1f6e891b8a8f3857bbf98e97b7f1f9c84f9987..86c37c472263568bdc1cfe24458653c535da9a87 100644 (file)
@@ -22,8 +22,8 @@ static void clean_cmdnames(struct cmdnames *cmds)
        unsigned int i;
 
        for (i = 0; i < cmds->cnt; ++i)
-               free(cmds->names[i]);
-       free(cmds->names);
+               zfree(&cmds->names[i]);
+       zfree(&cmds->names);
        cmds->cnt = 0;
        cmds->alloc = 0;
 }
@@ -263,9 +263,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
 
        for (i = 0; i < old->cnt; i++)
                cmds->names[cmds->cnt++] = old->names[i];
-       free(old->names);
+       zfree(&old->names);
        old->cnt = 0;
-       old->names = NULL;
 }
 
 const char *help_unknown_cmd(const char *cmd)
index 822903eaa201f3ec81648206eaf3c2f3ae2710c0..e4e6249b87d4eef1cd89d3df1aa3da022b550f84 100644 (file)
@@ -1,4 +1,3 @@
-#include "annotate.h"
 #include "util.h"
 #include "build-id.h"
 #include "hist.h"
@@ -182,21 +181,21 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows)
        }
 }
 
-static void hist_entry__add_cpumode_period(struct hist_entry *he,
-                                          unsigned int cpumode, u64 period)
+static void he_stat__add_cpumode_period(struct he_stat *he_stat,
+                                       unsigned int cpumode, u64 period)
 {
        switch (cpumode) {
        case PERF_RECORD_MISC_KERNEL:
-               he->stat.period_sys += period;
+               he_stat->period_sys += period;
                break;
        case PERF_RECORD_MISC_USER:
-               he->stat.period_us += period;
+               he_stat->period_us += period;
                break;
        case PERF_RECORD_MISC_GUEST_KERNEL:
-               he->stat.period_guest_sys += period;
+               he_stat->period_guest_sys += period;
                break;
        case PERF_RECORD_MISC_GUEST_USER:
-               he->stat.period_guest_us += period;
+               he_stat->period_guest_us += period;
                break;
        default:
                break;
@@ -223,10 +222,10 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
        dest->weight            += src->weight;
 }
 
-static void hist_entry__decay(struct hist_entry *he)
+static void he_stat__decay(struct he_stat *he_stat)
 {
-       he->stat.period = (he->stat.period * 7) / 8;
-       he->stat.nr_events = (he->stat.nr_events * 7) / 8;
+       he_stat->period = (he_stat->period * 7) / 8;
+       he_stat->nr_events = (he_stat->nr_events * 7) / 8;
        /* XXX need decay for weight too? */
 }
 
@@ -237,7 +236,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
        if (prev_period == 0)
                return true;
 
-       hist_entry__decay(he);
+       he_stat__decay(&he->stat);
 
        if (!he->filtered)
                hists->stats.total_period -= prev_period - he->stat.period;
@@ -342,15 +341,15 @@ static u8 symbol__parent_filter(const struct symbol *parent)
 }
 
 static struct hist_entry *add_hist_entry(struct hists *hists,
-                                     struct hist_entry *entry,
-                                     struct addr_location *al,
-                                     u64 period,
-                                     u64 weight)
+                                        struct hist_entry *entry,
+                                        struct addr_location *al)
 {
        struct rb_node **p;
        struct rb_node *parent = NULL;
        struct hist_entry *he;
        int64_t cmp;
+       u64 period = entry->stat.period;
+       u64 weight = entry->stat.weight;
 
        p = &hists->entries_in->rb_node;
 
@@ -373,7 +372,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
                         * This mem info was allocated from machine__resolve_mem
                         * and will not be used anymore.
                         */
-                       free(entry->mem_info);
+                       zfree(&entry->mem_info);
 
                        /* If the map of an existing hist_entry has
                         * become out-of-date due to an exec() or
@@ -403,7 +402,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
        rb_link_node(&he->rb_node_in, parent, p);
        rb_insert_color(&he->rb_node_in, hists->entries_in);
 out:
-       hist_entry__add_cpumode_period(he, al->cpumode, period);
+       he_stat__add_cpumode_period(&he->stat, al->cpumode, period);
        return he;
 }
 
@@ -437,7 +436,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
                .transaction = transaction,
        };
 
-       return add_hist_entry(hists, &entry, al, period, weight);
+       return add_hist_entry(hists, &entry, al);
 }
 
 int64_t
@@ -476,8 +475,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
 
 void hist_entry__free(struct hist_entry *he)
 {
-       free(he->branch_info);
-       free(he->mem_info);
+       zfree(&he->branch_info);
+       zfree(&he->mem_info);
        free_srcline(he->srcline);
        free(he);
 }
@@ -807,16 +806,6 @@ void hists__filter_by_symbol(struct hists *hists)
        }
 }
 
-int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
-{
-       return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
-}
-
-int hist_entry__annotate(struct hist_entry *he, size_t privsize)
-{
-       return symbol__annotate(he->ms.sym, he->ms.map, privsize);
-}
-
 void events_stats__inc(struct events_stats *stats, u32 type)
 {
        ++stats->nr_events[0];
index b621347a1585db4a469b8a08d10acb107406c20f..a59743fa3ef73d3aeb8c5c832a32aa2e04773a4c 100644 (file)
@@ -111,9 +111,6 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
 size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                      int max_cols, float min_pcnt, FILE *fp);
 
-int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
-int hist_entry__annotate(struct hist_entry *he, size_t privsize);
-
 void hists__filter_by_dso(struct hists *hists);
 void hists__filter_by_thread(struct hists *hists);
 void hists__filter_by_symbol(struct hists *hists);
index 84cdb072ac83975670c477fa180980ae61425bda..ded74590b92feaabd36f50b89baa77494514fd54 100644 (file)
@@ -9,6 +9,7 @@
 #include "strlist.h"
 #include "thread.h"
 #include <stdbool.h>
+#include <symbol/kallsyms.h>
 #include "unwind.h"
 
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
@@ -26,6 +27,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
        machine->pid = pid;
 
        machine->symbol_filter = NULL;
+       machine->id_hdr_size = 0;
 
        machine->root_dir = strdup(root_dir);
        if (machine->root_dir == NULL)
@@ -101,8 +103,7 @@ void machine__exit(struct machine *machine)
        map_groups__exit(&machine->kmaps);
        dsos__delete(&machine->user_dsos);
        dsos__delete(&machine->kernel_dsos);
-       free(machine->root_dir);
-       machine->root_dir = NULL;
+       zfree(&machine->root_dir);
 }
 
 void machine__delete(struct machine *machine)
@@ -502,15 +503,11 @@ static u64 machine__get_kernel_start_addr(struct machine *machine)
        char path[PATH_MAX];
        struct process_args args;
 
-       if (machine__is_host(machine)) {
-               filename = "/proc/kallsyms";
-       } else {
-               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 (machine__is_default_guest(machine))
+               filename = (char *)symbol_conf.default_guest_kallsyms;
+       else {
+               sprintf(path, "%s/proc/kallsyms", machine->root_dir);
+               filename = path;
        }
 
        if (symbol__restricted_filename(filename, "/proc/kallsyms"))
@@ -565,11 +562,10 @@ void machine__destroy_kernel_maps(struct machine *machine)
                         * on one of them.
                         */
                        if (type == MAP__FUNCTION) {
-                               free((char *)kmap->ref_reloc_sym->name);
-                               kmap->ref_reloc_sym->name = NULL;
-                               free(kmap->ref_reloc_sym);
-                       }
-                       kmap->ref_reloc_sym = NULL;
+                               zfree((char **)&kmap->ref_reloc_sym->name);
+                               zfree(&kmap->ref_reloc_sym);
+                       } else
+                               kmap->ref_reloc_sym = NULL;
                }
 
                map__delete(machine->vmlinux_maps[type]);
@@ -767,8 +763,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
                                ret = -1;
                                goto out;
                        }
-                       dso__set_long_name(map->dso, long_name);
-                       map->dso->lname_alloc = 1;
+                       dso__set_long_name(map->dso, long_name, true);
                        dso__kernel_module_get_build_id(map->dso, "");
                }
        }
@@ -939,8 +934,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
                if (name == NULL)
                        goto out_problem;
 
-               map->dso->short_name = name;
-               map->dso->sname_alloc = 1;
+               dso__set_short_name(map->dso, name, true);
                map->end = map->start + event->mmap.len;
        } else if (is_kernel_mmap) {
                const char *symbol_name = (event->mmap.filename +
@@ -1320,8 +1314,6 @@ static int machine__resolve_callchain_sample(struct machine *machine,
                                *root_al = al;
                                callchain_cursor_reset(&callchain_cursor);
                        }
-                       if (!symbol_conf.use_callchain)
-                               break;
                }
 
                err = callchain_cursor_append(&callchain_cursor,
index ef5bc913ca7a9fdda7946401e55f9b0295dddfb6..9b9bd719aa197d0a240809834109581a57d810b2 100644 (file)
@@ -11,6 +11,7 @@
 #include "strlist.h"
 #include "vdso.h"
 #include "build-id.h"
+#include "util.h"
 #include <linux/string.h>
 
 const char *map_type__name[MAP__NR_TYPES] = {
@@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
        return fprintf(fp, "%s", dsoname);
 }
 
+int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
+                        FILE *fp)
+{
+       char *srcline;
+       int ret = 0;
+
+       if (map && map->dso) {
+               srcline = get_srcline(map->dso,
+                                     map__rip_2objdump(map, addr));
+               if (srcline != SRCLINE_UNKNOWN)
+                       ret = fprintf(fp, "%s%s", prefix, srcline);
+               free_srcline(srcline);
+       }
+       return ret;
+}
+
 /**
  * map__rip_2objdump - convert symbol start address to objdump address.
  * @map: memory map
index e4e259c3ba167d77836e67d85c63e6d110f61550..18068c6b71c19df77b0d61a60aeb47ef508a0492 100644 (file)
@@ -103,6 +103,8 @@ struct map *map__clone(struct map *map);
 int map__overlap(struct map *l, struct map *r);
 size_t map__fprintf(struct map *map, FILE *fp);
 size_t map__fprintf_dsoname(struct map *map, FILE *fp);
+int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
+                        FILE *fp);
 
 int map__load(struct map *map, symbol_filter_t filter);
 struct symbol *map__find_symbol(struct map *map,
index 6de6f89c2a6175c96570055f57ccbb83cc8c58b5..a7f1b6a91fdd56b699fcac7f0b0adbaedd7e0a92 100644 (file)
@@ -10,7 +10,7 @@
 #include "symbol.h"
 #include "cache.h"
 #include "header.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include "parse-events-bison.h"
 #define YY_EXTRA_TYPE int
 #include "parse-events-flex.h"
@@ -204,7 +204,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
                                }
                                path->name = malloc(MAX_EVENT_LENGTH);
                                if (!path->name) {
-                                       free(path->system);
+                                       zfree(&path->system);
                                        free(path);
                                        return NULL;
                                }
@@ -236,8 +236,8 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name)
        path->name = strdup(str+1);
 
        if (path->system == NULL || path->name == NULL) {
-               free(path->system);
-               free(path->name);
+               zfree(&path->system);
+               zfree(&path->name);
                free(path);
                path = NULL;
        }
@@ -269,9 +269,10 @@ const char *event_type(int type)
 
 
 
-static int __add_event(struct list_head *list, int *idx,
-                      struct perf_event_attr *attr,
-                      char *name, struct cpu_map *cpus)
+static struct perf_evsel *
+__add_event(struct list_head *list, int *idx,
+           struct perf_event_attr *attr,
+           char *name, struct cpu_map *cpus)
 {
        struct perf_evsel *evsel;
 
@@ -279,19 +280,19 @@ static int __add_event(struct list_head *list, int *idx,
 
        evsel = perf_evsel__new_idx(attr, (*idx)++);
        if (!evsel)
-               return -ENOMEM;
+               return NULL;
 
        evsel->cpus = cpus;
        if (name)
                evsel->name = strdup(name);
        list_add_tail(&evsel->node, list);
-       return 0;
+       return evsel;
 }
 
 static int add_event(struct list_head *list, int *idx,
                     struct perf_event_attr *attr, char *name)
 {
-       return __add_event(list, idx, attr, name, NULL);
+       return __add_event(list, idx, attr, name, NULL) ? 0 : -ENOMEM;
 }
 
 static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -633,6 +634,9 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
 {
        struct perf_event_attr attr;
        struct perf_pmu *pmu;
+       struct perf_evsel *evsel;
+       char *unit;
+       double scale;
 
        pmu = perf_pmu__find(name);
        if (!pmu)
@@ -640,7 +644,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
 
        memset(&attr, 0, sizeof(attr));
 
-       if (perf_pmu__check_alias(pmu, head_config))
+       if (perf_pmu__check_alias(pmu, head_config, &unit, &scale))
                return -EINVAL;
 
        /*
@@ -652,8 +656,14 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
        if (perf_pmu__config(pmu, &attr, head_config))
                return -EINVAL;
 
-       return __add_event(list, idx, &attr, pmu_event_name(head_config),
-                          pmu->cpus);
+       evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
+                           pmu->cpus);
+       if (evsel) {
+               evsel->unit = unit;
+               evsel->scale = scale;
+       }
+
+       return evsel ? 0 : -ENOMEM;
 }
 
 int parse_events__modifier_group(struct list_head *list,
@@ -810,8 +820,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
        if (!add && get_event_modifier(&mod, str, NULL))
                return -EINVAL;
 
-       list_for_each_entry(evsel, list, node) {
-
+       __evlist__for_each(list, evsel) {
                if (add && get_event_modifier(&mod, str, evsel))
                        return -EINVAL;
 
@@ -835,7 +844,7 @@ int parse_events_name(struct list_head *list, char *name)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, list, node) {
+       __evlist__for_each(list, evsel) {
                if (!evsel->name)
                        evsel->name = strdup(name);
        }
@@ -907,7 +916,7 @@ int parse_events_terms(struct list_head *terms, const char *str)
        ret = parse_events__scanner(str, &data, PE_START_TERMS);
        if (!ret) {
                list_splice(data.terms, terms);
-               free(data.terms);
+               zfree(&data.terms);
                return 0;
        }
 
index 31f404a032a90499e5d366123f3185972edf3b49..d22e3f8017dc429a67458bc18457a6de7cd9f778 100644 (file)
@@ -78,6 +78,8 @@ static int get_value(struct parse_opt_ctx_t *p,
 
        case OPTION_BOOLEAN:
                *(bool *)opt->value = unset ? false : true;
+               if (opt->set)
+                       *(bool *)opt->set = true;
                return 0;
 
        case OPTION_INCR:
@@ -224,6 +226,24 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
                        return 0;
                }
                if (!rest) {
+                       if (!prefixcmp(options->long_name, "no-")) {
+                               /*
+                                * The long name itself starts with "no-", so
+                                * accept the option without "no-" so that users
+                                * do not have to enter "no-no-" to get the
+                                * negation.
+                                */
+                               rest = skip_prefix(arg, options->long_name + 3);
+                               if (rest) {
+                                       flags |= OPT_UNSET;
+                                       goto match;
+                               }
+                               /* Abbreviated case */
+                               if (!prefixcmp(options->long_name + 3, arg)) {
+                                       flags |= OPT_UNSET;
+                                       goto is_abbreviated;
+                               }
+                       }
                        /* abbreviated? */
                        if (!strncmp(options->long_name, arg, arg_end - arg)) {
 is_abbreviated:
@@ -259,6 +279,7 @@ is_abbreviated:
                        if (!rest)
                                continue;
                }
+match:
                if (*rest) {
                        if (*rest != '=')
                                continue;
index b0241e28eaf7dd7b81469e22416e8f1e16e26c63..cbf0149cf221783aea2aeafd8643900b80e6765d 100644 (file)
@@ -82,6 +82,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
  *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
  *   the value when met.
  *   CALLBACKS can use it like they want.
+ *
+ * `set`::
+ *   whether an option was set by the user
  */
 struct option {
        enum parse_opt_type type;
@@ -94,6 +97,7 @@ struct option {
        int flags;
        parse_opt_cb *callback;
        intptr_t defval;
+       bool *set;
 };
 
 #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
@@ -103,6 +107,10 @@ struct option {
 #define OPT_GROUP(h)                { .type = OPTION_GROUP, .help = (h) }
 #define OPT_BIT(s, l, v, h, b)      { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
 #define OPT_BOOLEAN(s, l, v, h)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
+#define OPT_BOOLEAN_SET(s, l, v, os, h) \
+       { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
+       .value = check_vtype(v, bool *), .help = (h), \
+       .set = check_vtype(os, bool *)}
 #define OPT_INCR(s, l, v, h)        { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
 #define OPT_SET_UINT(s, l, v, h, i)  { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) }
 #define OPT_SET_PTR(s, l, v, h, p)  { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
index c232d8dd410bf6483ba8fcd850380bbd562f03ee..d9cab4d271924a41e98658a3d28808b06546b80f 100644 (file)
@@ -1,19 +1,23 @@
 #include <linux/list.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <dirent.h>
 #include "fs.h"
+#include <locale.h>
 #include "util.h"
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
 
+#define UNIT_MAX_LEN   31 /* max length for event unit name */
+
 struct perf_pmu_alias {
        char *name;
        struct list_head terms;
        struct list_head list;
+       char unit[UNIT_MAX_LEN+1];
+       double scale;
 };
 
 struct perf_pmu_format {
@@ -94,7 +98,80 @@ static int pmu_format(const char *name, struct list_head *format)
        return 0;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
+static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
+{
+       struct stat st;
+       ssize_t sret;
+       char scale[128];
+       int fd, ret = -1;
+       char path[PATH_MAX];
+       char *lc;
+
+       snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       if (fstat(fd, &st) < 0)
+               goto error;
+
+       sret = read(fd, scale, sizeof(scale)-1);
+       if (sret < 0)
+               goto error;
+
+       scale[sret] = '\0';
+       /*
+        * save current locale
+        */
+       lc = setlocale(LC_NUMERIC, NULL);
+
+       /*
+        * force to C locale to ensure kernel
+        * scale string is converted correctly.
+        * kernel uses default C locale.
+        */
+       setlocale(LC_NUMERIC, "C");
+
+       alias->scale = strtod(scale, NULL);
+
+       /* restore locale */
+       setlocale(LC_NUMERIC, lc);
+
+       ret = 0;
+error:
+       close(fd);
+       return ret;
+}
+
+static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
+{
+       char path[PATH_MAX];
+       ssize_t sret;
+       int fd;
+
+       snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+               sret = read(fd, alias->unit, UNIT_MAX_LEN);
+       if (sret < 0)
+               goto error;
+
+       close(fd);
+
+       alias->unit[sret] = '\0';
+
+       return 0;
+error:
+       close(fd);
+       alias->unit[0] = '\0';
+       return -1;
+}
+
+static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
 {
        struct perf_pmu_alias *alias;
        char buf[256];
@@ -110,6 +187,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&alias->terms);
+       alias->scale = 1.0;
+       alias->unit[0] = '\0';
+
        ret = parse_events_terms(&alias->terms, buf);
        if (ret) {
                free(alias);
@@ -117,7 +197,14 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
        }
 
        alias->name = strdup(name);
+       /*
+        * load unit name and scale if available
+        */
+       perf_pmu__parse_unit(alias, dir, name);
+       perf_pmu__parse_scale(alias, dir, name);
+
        list_add_tail(&alias->list, list);
+
        return 0;
 }
 
@@ -129,6 +216,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 {
        struct dirent *evt_ent;
        DIR *event_dir;
+       size_t len;
        int ret = 0;
 
        event_dir = opendir(dir);
@@ -143,13 +231,24 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
                if (!strcmp(name, ".") || !strcmp(name, ".."))
                        continue;
 
+               /*
+                * skip .unit and .scale info files
+                * parsed in perf_pmu__new_alias()
+                */
+               len = strlen(name);
+               if (len > 5 && !strcmp(name + len - 5, ".unit"))
+                       continue;
+               if (len > 6 && !strcmp(name + len - 6, ".scale"))
+                       continue;
+
                snprintf(path, PATH_MAX, "%s/%s", dir, name);
 
                ret = -EINVAL;
                file = fopen(path, "r");
                if (!file)
                        break;
-               ret = perf_pmu__new_alias(head, name, file);
+
+               ret = perf_pmu__new_alias(head, dir, name, file);
                fclose(file);
        }
 
@@ -406,7 +505,7 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
 
 /*
  * Setup one of config[12] attr members based on the
- * user input data - temr parameter.
+ * user input data - term parameter.
  */
 static int pmu_config_term(struct list_head *formats,
                           struct perf_event_attr *attr,
@@ -508,16 +607,42 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
        return NULL;
 }
 
+
+static int check_unit_scale(struct perf_pmu_alias *alias,
+                           char **unit, double *scale)
+{
+       /*
+        * Only one term in event definition can
+        * define unit and scale, fail if there's
+        * more than one.
+        */
+       if ((*unit && alias->unit) ||
+           (*scale && alias->scale))
+               return -EINVAL;
+
+       if (alias->unit)
+               *unit = alias->unit;
+
+       if (alias->scale)
+               *scale = alias->scale;
+
+       return 0;
+}
+
 /*
  * Find alias in the terms list and replace it with the terms
  * defined for the alias
  */
-int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
+                         char **unit, double *scale)
 {
        struct parse_events_term *term, *h;
        struct perf_pmu_alias *alias;
        int ret;
 
+       *unit   = NULL;
+       *scale  = 0;
+
        list_for_each_entry_safe(term, h, head_terms, list) {
                alias = pmu_find_alias(pmu, term);
                if (!alias)
@@ -525,6 +650,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
                ret = pmu_alias_terms(alias, &term->list);
                if (ret)
                        return ret;
+
+               ret = check_unit_scale(alias, unit, scale);
+               if (ret)
+                       return ret;
+
                list_del(&term->list);
                free(term);
        }
@@ -625,7 +755,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
                        continue;
                }
                printf("  %-50s [Kernel PMU event]\n", aliases[j]);
-               free(aliases[j]);
+               zfree(&aliases[j]);
                printed++;
        }
        if (printed)
index 1179b26f244a31280e5454787a51a8f01ff9ac2e..9183380e203851b8fb12f0bcee499b61dcda0f58 100644 (file)
@@ -28,7 +28,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 int perf_pmu__config_terms(struct list_head *formats,
                           struct perf_event_attr *attr,
                           struct list_head *head_terms);
-int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
+                         char **unit, double *scale);
 struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
                                  struct list_head *head_terms);
 int perf_pmu_wrap(void);
index 9c6989ca2bea0242edcfed3f75803dd4e923068d..a8a9b6cd93a8f080a968f1cd05e7f80bb0df0ca6 100644 (file)
@@ -40,7 +40,7 @@
 #include "color.h"
 #include "symbol.h"
 #include "thread.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include "trace-event.h"       /* For __maybe_unused */
 #include "probe-event.h"
 #include "probe-finder.h"
@@ -72,6 +72,7 @@ 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;
 
 /* Initialize symbol maps and path of vmlinux/modules */
@@ -154,7 +155,7 @@ static struct dso *kernel_get_module_dso(const char *module)
 
        vmlinux_name = symbol_conf.vmlinux_name;
        if (vmlinux_name) {
-               if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
+               if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0)
                        return NULL;
        } else {
                if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
@@ -186,6 +187,37 @@ static int init_user_exec(void)
        return ret;
 }
 
+static int convert_exec_to_group(const char *exec, char **result)
+{
+       char *ptr1, *ptr2, *exec_copy;
+       char buf[64];
+       int ret;
+
+       exec_copy = strdup(exec);
+       if (!exec_copy)
+               return -ENOMEM;
+
+       ptr1 = basename(exec_copy);
+       if (!ptr1) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ptr2 = strpbrk(ptr1, "-._");
+       if (ptr2)
+               *ptr2 = '\0';
+       ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
+       if (ret < 0)
+               goto out;
+
+       *result = strdup(buf);
+       ret = *result ? 0 : -ENOMEM;
+
+out:
+       free(exec_copy);
+       return ret;
+}
+
 static int convert_to_perf_probe_point(struct probe_trace_point *tp,
                                        struct perf_probe_point *pp)
 {
@@ -261,6 +293,68 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
        return 0;
 }
 
+static int get_text_start_address(const char *exec, unsigned long *address)
+{
+       Elf *elf;
+       GElf_Ehdr ehdr;
+       GElf_Shdr shdr;
+       int fd, ret = -ENOENT;
+
+       fd = open(exec, O_RDONLY);
+       if (fd < 0)
+               return -errno;
+
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+       if (elf == NULL)
+               return -EINVAL;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL)
+               goto out;
+
+       if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL))
+               goto out;
+
+       *address = shdr.sh_addr - shdr.sh_offset;
+       ret = 0;
+out:
+       elf_end(elf);
+       return ret;
+}
+
+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];
+
+       if (!exec)
+               return 0;
+
+       ret = get_text_start_address(exec, &stext);
+       if (ret < 0)
+               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;
+               tevs[i].point.module = strdup(exec);
+               tevs[i].point.symbol = strdup(buf);
+               if (!tevs[i].point.symbol || !tevs[i].point.module) {
+                       ret = -ENOMEM;
+                       break;
+               }
+               tevs[i].uprobes = true;
+       }
+
+       return ret;
+}
+
 static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
                                            int ntevs, const char *module)
 {
@@ -290,12 +384,18 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
                }
        }
 
-       if (tmp)
-               free(tmp);
-
+       free(tmp);
        return ret;
 }
 
+static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
+{
+       int i;
+
+       for (i = 0; i < ntevs; i++)
+               clear_probe_trace_event(tevs + i);
+}
+
 /* Try to find perf_probe_event with debuginfo */
 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
                                          struct probe_trace_event **tevs,
@@ -305,15 +405,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
        struct debuginfo *dinfo;
        int ntevs, ret = 0;
 
-       if (pev->uprobes) {
-               if (need_dwarf) {
-                       pr_warning("Debuginfo-analysis is not yet supported"
-                                       " with -x/--exec option.\n");
-                       return -ENOSYS;
-               }
-               return convert_name_to_addr(pev, target);
-       }
-
        dinfo = open_debuginfo(target);
 
        if (!dinfo) {
@@ -332,9 +423,18 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 
        if (ntevs > 0) {        /* Succeeded to find trace events */
                pr_debug("find %d probe_trace_events.\n", ntevs);
-               if (target)
-                       ret = add_module_to_probe_trace_events(*tevs, ntevs,
-                                                              target);
+               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);
+               }
+               if (ret < 0) {
+                       clear_probe_trace_events(*tevs, ntevs);
+                       zfree(tevs);
+               }
                return ret < 0 ? ret : ntevs;
        }
 
@@ -401,15 +501,13 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
                case EFAULT:
                        raw_path = strchr(++raw_path, '/');
                        if (!raw_path) {
-                               free(*new_path);
-                               *new_path = NULL;
+                               zfree(new_path);
                                return -ENOENT;
                        }
                        continue;
 
                default:
-                       free(*new_path);
-                       *new_path = NULL;
+                       zfree(new_path);
                        return -errno;
                }
        }
@@ -580,7 +678,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
                 */
                fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
                        vl->point.offset);
-               free(vl->point.symbol);
+               zfree(&vl->point.symbol);
                nvars = 0;
                if (vl->vars) {
                        strlist__for_each(node, vl->vars) {
@@ -647,16 +745,14 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 
 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
                                struct probe_trace_event **tevs __maybe_unused,
-                               int max_tevs __maybe_unused, const char *target)
+                               int max_tevs __maybe_unused,
+                               const char *target __maybe_unused)
 {
        if (perf_probe_event_need_dwarf(pev)) {
                pr_warning("Debuginfo-analysis is not supported.\n");
                return -ENOSYS;
        }
 
-       if (pev->uprobes)
-               return convert_name_to_addr(pev, target);
-
        return 0;
 }
 
@@ -678,6 +774,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
 }
 #endif
 
+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);
+       }
+       memset(lr, 0, sizeof(*lr));
+}
+
+void line_range__init(struct line_range *lr)
+{
+       memset(lr, 0, sizeof(*lr));
+       INIT_LIST_HEAD(&lr->line_list);
+}
+
 static int parse_line_num(char **ptr, int *val, const char *what)
 {
        const char *start = *ptr;
@@ -1278,8 +1396,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
 error:
        pr_debug("Failed to synthesize perf probe point: %s\n",
                 strerror(-ret));
-       if (buf)
-               free(buf);
+       free(buf);
        return NULL;
 }
 
@@ -1480,34 +1597,25 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
        struct perf_probe_arg_field *field, *next;
        int i;
 
-       if (pev->event)
-               free(pev->event);
-       if (pev->group)
-               free(pev->group);
-       if (pp->file)
-               free(pp->file);
-       if (pp->function)
-               free(pp->function);
-       if (pp->lazy_line)
-               free(pp->lazy_line);
+       free(pev->event);
+       free(pev->group);
+       free(pp->file);
+       free(pp->function);
+       free(pp->lazy_line);
+
        for (i = 0; i < pev->nargs; i++) {
-               if (pev->args[i].name)
-                       free(pev->args[i].name);
-               if (pev->args[i].var)
-                       free(pev->args[i].var);
-               if (pev->args[i].type)
-                       free(pev->args[i].type);
+               free(pev->args[i].name);
+               free(pev->args[i].var);
+               free(pev->args[i].type);
                field = pev->args[i].field;
                while (field) {
                        next = field->next;
-                       if (field->name)
-                               free(field->name);
+                       zfree(&field->name);
                        free(field);
                        field = next;
                }
        }
-       if (pev->args)
-               free(pev->args);
+       free(pev->args);
        memset(pev, 0, sizeof(*pev));
 }
 
@@ -1516,21 +1624,14 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
        struct probe_trace_arg_ref *ref, *next;
        int i;
 
-       if (tev->event)
-               free(tev->event);
-       if (tev->group)
-               free(tev->group);
-       if (tev->point.symbol)
-               free(tev->point.symbol);
-       if (tev->point.module)
-               free(tev->point.module);
+       free(tev->event);
+       free(tev->group);
+       free(tev->point.symbol);
+       free(tev->point.module);
        for (i = 0; i < tev->nargs; i++) {
-               if (tev->args[i].name)
-                       free(tev->args[i].name);
-               if (tev->args[i].value)
-                       free(tev->args[i].value);
-               if (tev->args[i].type)
-                       free(tev->args[i].type);
+               free(tev->args[i].name);
+               free(tev->args[i].value);
+               free(tev->args[i].type);
                ref = tev->args[i].ref;
                while (ref) {
                        next = ref->next;
@@ -1538,8 +1639,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
                        ref = next;
                }
        }
-       if (tev->args)
-               free(tev->args);
+       free(tev->args);
        memset(tev, 0, sizeof(*tev));
 }
 
@@ -1913,14 +2013,29 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
                                          int max_tevs, const char *target)
 {
        struct symbol *sym;
-       int ret = 0, i;
+       int ret, i;
        struct probe_trace_event *tev;
 
+       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;
+               }
+       }
+
        /* 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;
+       }
+
        /* Allocate trace event buffer */
        tev = *tevs = zalloc(sizeof(struct probe_trace_event));
        if (tev == NULL)
@@ -2056,7 +2171,7 @@ end:
        for (i = 0; i < npevs; i++) {
                for (j = 0; j < pkgs[i].ntevs; j++)
                        clear_probe_trace_event(&pkgs[i].tevs[j]);
-               free(pkgs[i].tevs);
+               zfree(&pkgs[i].tevs);
        }
        free(pkgs);
 
@@ -2281,7 +2396,7 @@ 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, *name = NULL;
+       char *function = NULL;
        int ret = -EINVAL;
        unsigned long long vaddr = 0;
 
@@ -2297,12 +2412,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
                goto out;
        }
 
-       name = realpath(exec, NULL);
-       if (!name) {
-               pr_warning("Cannot find realpath for %s.\n", exec);
-               goto out;
-       }
-       map = dso__new_map(name);
+       map = dso__new_map(exec);
        if (!map) {
                pr_warning("Cannot find appropriate DSO for %s.\n", exec);
                goto out;
@@ -2367,7 +2477,5 @@ out:
        }
        if (function)
                free(function);
-       if (name)
-               free(name);
        return ret;
 }
index f9f3de8b4220b9c4989016f212192cb48cd83aeb..fcaf7273e85a35f41ac465c2f343ec07cbd0f1a4 100644 (file)
@@ -12,6 +12,7 @@ struct probe_trace_point {
        char            *symbol;        /* Base symbol */
        char            *module;        /* Module name */
        unsigned long   offset;         /* Offset from symbol */
+       unsigned long   address;        /* Actual address of the trace point */
        bool            retprobe;       /* Return probe flag */
 };
 
@@ -119,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev);
 /* Command string to line-range */
 extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
 
+/* Release line range members */
+extern void line_range__clear(struct line_range *lr);
+
+/* Initialize line range */
+extern void line_range__init(struct line_range *lr);
+
 /* Internal use: Return kernel/module path */
 extern const char *kernel_get_module_path(const char *module);
 
index ffb657ffd327b1779b328f4546f4d45c0784e243..061edb162b5ba03f9b4f883543faa5c0f27e371d 100644 (file)
@@ -226,10 +226,8 @@ struct debuginfo *debuginfo__new(const char *path)
        if (!dbg)
                return NULL;
 
-       if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
-               free(dbg);
-               dbg = NULL;
-       }
+       if (debuginfo__init_offline_dwarf(dbg, path) < 0)
+               zfree(&dbg);
 
        return dbg;
 }
@@ -241,10 +239,8 @@ struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
        if (!dbg)
                return NULL;
 
-       if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
-               free(dbg);
-               dbg = NULL;
-       }
+       if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0)
+               zfree(&dbg);
 
        return dbg;
 }
@@ -729,6 +725,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
                return -ENOENT;
        }
        tp->offset = (unsigned long)(paddr - sym.st_value);
+       tp->address = (unsigned long)paddr;
        tp->symbol = strdup(symbol);
        if (!tp->symbol)
                return -ENOMEM;
@@ -1301,8 +1298,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
 
        ret = debuginfo__find_probes(dbg, &tf.pf);
        if (ret < 0) {
-               free(*tevs);
-               *tevs = NULL;
+               zfree(tevs);
                return ret;
        }
 
@@ -1413,13 +1409,10 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
        if (ret < 0) {
                /* Free vlist for error */
                while (af.nvls--) {
-                       if (af.vls[af.nvls].point.symbol)
-                               free(af.vls[af.nvls].point.symbol);
-                       if (af.vls[af.nvls].vars)
-                               strlist__delete(af.vls[af.nvls].vars);
+                       zfree(&af.vls[af.nvls].point.symbol);
+                       strlist__delete(af.vls[af.nvls].vars);
                }
-               free(af.vls);
-               *vls = NULL;
+               zfree(vls);
                return ret;
        }
 
@@ -1523,10 +1516,7 @@ post:
        if (fname) {
                ppt->file = strdup(fname);
                if (ppt->file == NULL) {
-                       if (ppt->function) {
-                               free(ppt->function);
-                               ppt->function = NULL;
-                       }
+                       zfree(&ppt->function);
                        ret = -ENOMEM;
                        goto end;
                }
@@ -1580,8 +1570,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
                else
                        ret = 0;        /* Lines are not found */
        else {
-               free(lf->lr->path);
-               lf->lr->path = NULL;
+               zfree(&lf->lr->path);
        }
        return ret;
 }
index 239036fb2b2c0b08b9352dcbce368904917d2521..595bfc73d2ed28cf14feee7daf73c76d92527223 100644 (file)
@@ -18,4 +18,5 @@ util/cgroup.c
 util/rblist.c
 util/strlist.c
 util/fs.c
+util/trace-event.c
 ../../lib/rbtree.c
index 4bf8ace7f5116a3b7536ba9c13592bb4f8e7a7e1..122669c18ff45db82311cc1c6b243416b98b7256 100644 (file)
@@ -908,9 +908,10 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
        if (i >= pevlist->evlist.nr_entries)
                return NULL;
 
-       list_for_each_entry(pos, &pevlist->evlist.entries, node)
+       evlist__for_each(&pevlist->evlist, pos) {
                if (i-- == 0)
                        break;
+       }
 
        return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
 }
index c8845b107f6085cfacb907fce862c2e76dc6db5b..373762501dadced6c476235ad8170a5241e72801 100644 (file)
@@ -74,8 +74,7 @@ bool perf_can_sample_identifier(void)
        return perf_probe_api(perf_probe_sample_identifier);
 }
 
-void perf_evlist__config(struct perf_evlist *evlist,
-                       struct perf_record_opts *opts)
+void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
 {
        struct perf_evsel *evsel;
        bool use_sample_identifier = false;
@@ -90,19 +89,19 @@ void perf_evlist__config(struct perf_evlist *evlist,
        if (evlist->cpus->map[0] < 0)
                opts->no_inherit = true;
 
-       list_for_each_entry(evsel, &evlist->entries, node)
+       evlist__for_each(evlist, evsel)
                perf_evsel__config(evsel, opts);
 
        if (evlist->nr_entries > 1) {
                struct perf_evsel *first = perf_evlist__first(evlist);
 
-               list_for_each_entry(evsel, &evlist->entries, node) {
+               evlist__for_each(evlist, evsel) {
                        if (evsel->attr.sample_type == first->attr.sample_type)
                                continue;
                        use_sample_identifier = perf_can_sample_identifier();
                        break;
                }
-               list_for_each_entry(evsel, &evlist->entries, node)
+               evlist__for_each(evlist, evsel)
                        perf_evsel__set_sample_id(evsel, use_sample_identifier);
        }
 
@@ -123,7 +122,7 @@ static int get_max_rate(unsigned int *rate)
        return filename__read_int(path, (int *) rate);
 }
 
-static int perf_record_opts__config_freq(struct perf_record_opts *opts)
+static int record_opts__config_freq(struct record_opts *opts)
 {
        bool user_freq = opts->user_freq != UINT_MAX;
        unsigned int max_rate;
@@ -173,7 +172,44 @@ static int perf_record_opts__config_freq(struct perf_record_opts *opts)
        return 0;
 }
 
-int perf_record_opts__config(struct perf_record_opts *opts)
+int record_opts__config(struct record_opts *opts)
 {
-       return perf_record_opts__config_freq(opts);
+       return record_opts__config_freq(opts);
+}
+
+bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
+{
+       struct perf_evlist *temp_evlist;
+       struct perf_evsel *evsel;
+       int err, fd, cpu;
+       bool ret = false;
+
+       temp_evlist = perf_evlist__new();
+       if (!temp_evlist)
+               return false;
+
+       err = parse_events(temp_evlist, str);
+       if (err)
+               goto out_delete;
+
+       evsel = perf_evlist__last(temp_evlist);
+
+       if (!evlist || cpu_map__empty(evlist->cpus)) {
+               struct cpu_map *cpus = cpu_map__new(NULL);
+
+               cpu =  cpus ? cpus->map[0] : 0;
+               cpu_map__delete(cpus);
+       } else {
+               cpu = evlist->cpus->map[0];
+       }
+
+       fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
+       if (fd >= 0) {
+               close(fd);
+               ret = true;
+       }
+
+out_delete:
+       perf_evlist__delete(temp_evlist);
+       return ret;
 }
index d5e5969f6fea4fce43974a748f3069e869ab9fca..e108207c5de0448be37775877889b223ea157634 100644 (file)
@@ -194,8 +194,7 @@ static void define_event_symbols(struct event_format *event,
                zero_flag_atom = 0;
                break;
        case PRINT_FIELD:
-               if (cur_field_name)
-                       free(cur_field_name);
+               free(cur_field_name);
                cur_field_name = strdup(args->field.name);
                break;
        case PRINT_FLAGS:
@@ -257,12 +256,9 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
        return event;
 }
 
-static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
-                                   struct perf_sample *sample,
+static void perl_process_tracepoint(struct perf_sample *sample,
                                    struct perf_evsel *evsel,
-                                   struct machine *machine __maybe_unused,
-                                   struct thread *thread,
-                                       struct addr_location *al)
+                                   struct thread *thread)
 {
        struct format_field *field;
        static char handler[256];
@@ -349,10 +345,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
 
 static void perl_process_event_generic(union perf_event *event,
                                       struct perf_sample *sample,
-                                      struct perf_evsel *evsel,
-                                      struct machine *machine __maybe_unused,
-                                      struct thread *thread __maybe_unused,
-                                          struct addr_location *al __maybe_unused)
+                                      struct perf_evsel *evsel)
 {
        dSP;
 
@@ -377,12 +370,11 @@ static void perl_process_event_generic(union perf_event *event,
 static void perl_process_event(union perf_event *event,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
-                              struct machine *machine,
                               struct thread *thread,
-                                  struct addr_location *al)
+                              struct addr_location *al __maybe_unused)
 {
-       perl_process_tracepoint(event, sample, evsel, machine, thread, al);
-       perl_process_event_generic(event, sample, evsel, machine, thread, al);
+       perl_process_tracepoint(sample, evsel, thread);
+       perl_process_event_generic(event, sample, evsel);
 }
 
 static void run_start_sub(void)
index 53c20e7fd90037ce46dc1c53d20e99264d66c47a..cd9774df3750e8164f0ba1825a0a64bdbd12041e 100644 (file)
@@ -161,8 +161,7 @@ static void define_event_symbols(struct event_format *event,
                zero_flag_atom = 0;
                break;
        case PRINT_FIELD:
-               if (cur_field_name)
-                       free(cur_field_name);
+               free(cur_field_name);
                cur_field_name = strdup(args->field.name);
                break;
        case PRINT_FLAGS:
@@ -231,13 +230,10 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
        return event;
 }
 
-static void python_process_tracepoint(union perf_event *perf_event
-                                     __maybe_unused,
-                                struct perf_sample *sample,
-                                struct perf_evsel *evsel,
-                                struct machine *machine __maybe_unused,
-                                struct thread *thread,
-                                struct addr_location *al)
+static void python_process_tracepoint(struct perf_sample *sample,
+                                     struct perf_evsel *evsel,
+                                     struct thread *thread,
+                                     struct addr_location *al)
 {
        PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
        static char handler_name[256];
@@ -351,11 +347,8 @@ static void python_process_tracepoint(union perf_event *perf_event
        Py_DECREF(t);
 }
 
-static void python_process_general_event(union perf_event *perf_event
-                                        __maybe_unused,
-                                        struct perf_sample *sample,
+static void python_process_general_event(struct perf_sample *sample,
                                         struct perf_evsel *evsel,
-                                        struct machine *machine __maybe_unused,
                                         struct thread *thread,
                                         struct addr_location *al)
 {
@@ -411,22 +404,19 @@ exit:
        Py_DECREF(t);
 }
 
-static void python_process_event(union perf_event *perf_event,
+static void python_process_event(union perf_event *event __maybe_unused,
                                 struct perf_sample *sample,
                                 struct perf_evsel *evsel,
-                                struct machine *machine,
                                 struct thread *thread,
                                 struct addr_location *al)
 {
        switch (evsel->attr.type) {
        case PERF_TYPE_TRACEPOINT:
-               python_process_tracepoint(perf_event, sample, evsel,
-                                         machine, thread, al);
+               python_process_tracepoint(sample, evsel, thread, al);
                break;
        /* Reserve for future process_hw/sw/raw APIs */
        default:
-               python_process_general_event(perf_event, sample, evsel,
-                                            machine, thread, al);
+               python_process_general_event(sample, evsel, thread, al);
        }
 }
 
index f36d24a024453f6e2777d1bc4cfbb10fb9a3cf4a..7acc03e8f3b2eabaf7bdb5620ea463ba6cacabb5 100644 (file)
@@ -132,18 +132,18 @@ static void perf_session__delete_threads(struct perf_session *session)
 
 static void perf_session_env__delete(struct perf_session_env *env)
 {
-       free(env->hostname);
-       free(env->os_release);
-       free(env->version);
-       free(env->arch);
-       free(env->cpu_desc);
-       free(env->cpuid);
+       zfree(&env->hostname);
+       zfree(&env->os_release);
+       zfree(&env->version);
+       zfree(&env->arch);
+       zfree(&env->cpu_desc);
+       zfree(&env->cpuid);
 
-       free(env->cmdline);
-       free(env->sibling_cores);
-       free(env->sibling_threads);
-       free(env->numa_nodes);
-       free(env->pmu_mappings);
+       zfree(&env->cmdline);
+       zfree(&env->sibling_cores);
+       zfree(&env->sibling_threads);
+       zfree(&env->numa_nodes);
+       zfree(&env->pmu_mappings);
 }
 
 void perf_session__delete(struct perf_session *session)
@@ -247,27 +247,6 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
        }
 }
  
-void mem_bswap_32(void *src, int byte_size)
-{
-       u32 *m = src;
-       while (byte_size > 0) {
-               *m = bswap_32(*m);
-               byte_size -= sizeof(u32);
-               ++m;
-       }
-}
-
-void mem_bswap_64(void *src, int byte_size)
-{
-       u64 *m = src;
-
-       while (byte_size > 0) {
-               *m = bswap_64(*m);
-               byte_size -= sizeof(u64);
-               ++m;
-       }
-}
-
 static void swap_sample_id_all(union perf_event *event, void *data)
 {
        void *end = (void *) event + event->header.size;
@@ -851,6 +830,7 @@ static struct machine *
                                               struct perf_sample *sample)
 {
        const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+       struct machine *machine;
 
        if (perf_guest &&
            ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
@@ -863,7 +843,11 @@ static struct machine *
                else
                        pid = sample->pid;
 
-               return perf_session__findnew_machine(session, pid);
+               machine = perf_session__find_machine(session, pid);
+               if (!machine)
+                       machine = perf_session__findnew_machine(session,
+                                               DEFAULT_GUEST_KERNEL_ID);
+               return machine;
        }
 
        return &session->machines.host;
@@ -1158,7 +1142,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session,
        void *buf = NULL;
        int skip = 0;
        u64 head;
-       int err;
+       ssize_t err;
        void *p;
 
        perf_tool__fill_defaults(tool);
@@ -1400,7 +1384,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
 {
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, evsel) {
                if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
                        return true;
        }
@@ -1458,7 +1442,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
 
        ret += events_stats__fprintf(&session->stats, fp);
 
-       list_for_each_entry(pos, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, pos) {
                ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
                ret += events_stats__fprintf(&pos->hists.stats, fp);
        }
@@ -1480,35 +1464,30 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 {
        struct perf_evsel *pos;
 
-       list_for_each_entry(pos, &session->evlist->entries, node) {
+       evlist__for_each(session->evlist, pos) {
                if (pos->attr.type == type)
                        return pos;
        }
        return NULL;
 }
 
-void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
-                         struct perf_sample *sample, struct machine *machine,
+void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
+                         struct addr_location *al,
                          unsigned int print_opts, unsigned int stack_depth)
 {
-       struct addr_location al;
        struct callchain_cursor_node *node;
        int print_ip = print_opts & PRINT_IP_OPT_IP;
        int print_sym = print_opts & PRINT_IP_OPT_SYM;
        int print_dso = print_opts & PRINT_IP_OPT_DSO;
        int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
        int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
+       int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
        char s = print_oneline ? ' ' : '\t';
 
-       if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
-               error("problem processing %d event, skipping it.\n",
-                       event->header.type);
-               return;
-       }
-
        if (symbol_conf.use_callchain && sample->callchain) {
+               struct addr_location node_al;
 
-               if (machine__resolve_callchain(machine, evsel, al.thread,
+               if (machine__resolve_callchain(al->machine, evsel, al->thread,
                                               sample, NULL, NULL,
                                               PERF_MAX_STACK_DEPTH) != 0) {
                        if (verbose)
@@ -1517,20 +1496,31 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
                }
                callchain_cursor_commit(&callchain_cursor);
 
+               if (print_symoffset)
+                       node_al = *al;
+
                while (stack_depth) {
+                       u64 addr = 0;
+
                        node = callchain_cursor_current(&callchain_cursor);
                        if (!node)
                                break;
 
+                       if (node->sym && node->sym->ignore)
+                               goto next;
+
                        if (print_ip)
                                printf("%c%16" PRIx64, s, node->ip);
 
+                       if (node->map)
+                               addr = node->map->map_ip(node->map, node->ip);
+
                        if (print_sym) {
                                printf(" ");
                                if (print_symoffset) {
-                                       al.addr = node->ip;
-                                       al.map  = node->map;
-                                       symbol__fprintf_symname_offs(node->sym, &al, stdout);
+                                       node_al.addr = addr;
+                                       node_al.map  = node->map;
+                                       symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
                                } else
                                        symbol__fprintf_symname(node->sym, stdout);
                        }
@@ -1541,32 +1531,42 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
                                printf(")");
                        }
 
+                       if (print_srcline)
+                               map__fprintf_srcline(node->map, addr, "\n  ",
+                                                    stdout);
+
                        if (!print_oneline)
                                printf("\n");
 
-                       callchain_cursor_advance(&callchain_cursor);
-
                        stack_depth--;
+next:
+                       callchain_cursor_advance(&callchain_cursor);
                }
 
        } else {
+               if (al->sym && al->sym->ignore)
+                       return;
+
                if (print_ip)
                        printf("%16" PRIx64, sample->ip);
 
                if (print_sym) {
                        printf(" ");
                        if (print_symoffset)
-                               symbol__fprintf_symname_offs(al.sym, &al,
+                               symbol__fprintf_symname_offs(al->sym, al,
                                                             stdout);
                        else
-                               symbol__fprintf_symname(al.sym, stdout);
+                               symbol__fprintf_symname(al->sym, stdout);
                }
 
                if (print_dso) {
                        printf(" (");
-                       map__fprintf_dsoname(al.map, stdout);
+                       map__fprintf_dsoname(al->map, stdout);
                        printf(")");
                }
+
+               if (print_srcline)
+                       map__fprintf_srcline(al->map, al->addr, "\n  ", stdout);
        }
 }
 
index 50f640958f0f8aec87c7f5b3ef7346ad27363542..3140f8ae6148b4cc4c9716b0db33a51b68fa6672 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __PERF_SESSION_H
 #define __PERF_SESSION_H
 
+#include "trace-event.h"
 #include "hist.h"
 #include "event.h"
 #include "header.h"
@@ -32,7 +33,7 @@ struct perf_session {
        struct perf_header      header;
        struct machines         machines;
        struct perf_evlist      *evlist;
-       struct pevent           *pevent;
+       struct trace_event      tevent;
        struct events_stats     stats;
        bool                    repipe;
        struct ordered_samples  ordered_samples;
@@ -44,6 +45,7 @@ struct perf_session {
 #define PRINT_IP_OPT_DSO               (1<<2)
 #define PRINT_IP_OPT_SYMOFFSET (1<<3)
 #define PRINT_IP_OPT_ONELINE   (1<<4)
+#define PRINT_IP_OPT_SRCLINE   (1<<5)
 
 struct perf_tool;
 
@@ -72,8 +74,6 @@ int perf_session__resolve_callchain(struct perf_session *session,
 
 bool perf_session__has_traces(struct perf_session *session, const char *msg);
 
-void mem_bswap_64(void *src, int byte_size);
-void mem_bswap_32(void *src, int byte_size);
 void perf_event__attr_swap(struct perf_event_attr *attr);
 
 int perf_session__create_kernel_maps(struct perf_session *session);
@@ -105,8 +105,8 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
                                            unsigned int type);
 
-void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
-                         struct perf_sample *sample, struct machine *machine,
+void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
+                         struct addr_location *al,
                          unsigned int print_opts, unsigned int stack_depth);
 
 int perf_session__cpu_bitmap(struct perf_session *session,
index 58ea5ca6c255143fcbc6a40d78c043e0c4ed1b4e..d0aee4b9dfd482ea36c5a50c73e97c1ff9738a95 100644 (file)
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
 build_lib = getenv('PYTHON_EXTBUILD_LIB')
 build_tmp = getenv('PYTHON_EXTBUILD_TMP')
 libtraceevent = getenv('LIBTRACEEVENT')
-liblk = getenv('LIBLK')
+libapikfs = getenv('LIBAPIKFS')
 
 ext_sources = [f.strip() for f in file('util/python-ext-sources')
                                if len(f.strip()) > 0 and f[0] != '#']
@@ -34,7 +34,7 @@ perf = Extension('perf',
                  sources = ext_sources,
                  include_dirs = ['util/include'],
                  extra_compile_args = cflags,
-                 extra_objects = [libtraceevent, liblk],
+                 extra_objects = [libtraceevent, libapikfs],
                  )
 
 setup(name='perf',
index 8b0bb1f4494a539ab563153ac7953bb4bc94b69b..635cd8f8b22ed14463fe4f7fd9357f9e663da41f 100644 (file)
@@ -13,6 +13,7 @@ int           have_ignore_callees = 0;
 int            sort__need_collapse = 0;
 int            sort__has_parent = 0;
 int            sort__has_sym = 0;
+int            sort__has_dso = 0;
 enum sort_mode sort__mode = SORT_MODE__NORMAL;
 
 enum sort_type sort__first_dimension;
@@ -161,6 +162,11 @@ struct sort_entry sort_dso = {
 
 /* --sort symbol */
 
+static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
+{
+       return (int64_t)(right_ip - left_ip);
+}
+
 static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
 {
        u64 ip_l, ip_r;
@@ -183,15 +189,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
        int64_t ret;
 
        if (!left->ms.sym && !right->ms.sym)
-               return right->level - left->level;
+               return _sort__addr_cmp(left->ip, right->ip);
 
        /*
         * comparing symbol address alone is not enough since it's a
         * relative address within a dso.
         */
-       ret = sort__dso_cmp(left, right);
-       if (ret != 0)
-               return ret;
+       if (!sort__has_dso) {
+               ret = sort__dso_cmp(left, right);
+               if (ret != 0)
+                       return ret;
+       }
 
        return _sort__sym_cmp(left->ms.sym, right->ms.sym);
 }
@@ -372,7 +380,7 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
        struct addr_map_symbol *from_r = &right->branch_info->from;
 
        if (!from_l->sym && !from_r->sym)
-               return right->level - left->level;
+               return _sort__addr_cmp(from_l->addr, from_r->addr);
 
        return _sort__sym_cmp(from_l->sym, from_r->sym);
 }
@@ -384,7 +392,7 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
        struct addr_map_symbol *to_r = &right->branch_info->to;
 
        if (!to_l->sym && !to_r->sym)
-               return right->level - left->level;
+               return _sort__addr_cmp(to_l->addr, to_r->addr);
 
        return _sort__sym_cmp(to_l->sym, to_r->sym);
 }
@@ -1056,6 +1064,8 @@ int sort_dimension__add(const char *tok)
                        sort__has_parent = 1;
                } else if (sd->entry == &sort_sym) {
                        sort__has_sym = 1;
+               } else if (sd->entry == &sort_dso) {
+                       sort__has_dso = 1;
                }
 
                __sort_dimension__add(sd, i);
index d11aefbc4b8dcb6f8d0592897776f9717bdb7133..f3e4bc5fe5d214444594193197509fe161bf7104 100644 (file)
@@ -129,7 +129,7 @@ static struct a2l_data *addr2line_init(const char *path)
 
 out:
        if (a2l) {
-               free((void *)a2l->input);
+               zfree((char **)&a2l->input);
                free(a2l);
        }
        bfd_close(abfd);
@@ -140,24 +140,30 @@ static void addr2line_cleanup(struct a2l_data *a2l)
 {
        if (a2l->abfd)
                bfd_close(a2l->abfd);
-       free((void *)a2l->input);
-       free(a2l->syms);
+       zfree((char **)&a2l->input);
+       zfree(&a2l->syms);
        free(a2l);
 }
 
 static int addr2line(const char *dso_name, unsigned long addr,
-                    char **file, unsigned int *line)
+                    char **file, unsigned int *line, struct dso *dso)
 {
        int ret = 0;
-       struct a2l_data *a2l;
+       struct a2l_data *a2l = dso->a2l;
+
+       if (!a2l) {
+               dso->a2l = addr2line_init(dso_name);
+               a2l = dso->a2l;
+       }
 
-       a2l = addr2line_init(dso_name);
        if (a2l == NULL) {
                pr_warning("addr2line_init failed for %s\n", dso_name);
                return 0;
        }
 
        a2l->addr = addr;
+       a2l->found = false;
+
        bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
 
        if (a2l->found && a2l->filename) {
@@ -168,14 +174,26 @@ static int addr2line(const char *dso_name, unsigned long addr,
                        ret = 1;
        }
 
-       addr2line_cleanup(a2l);
        return ret;
 }
 
+void dso__free_a2l(struct dso *dso)
+{
+       struct a2l_data *a2l = dso->a2l;
+
+       if (!a2l)
+               return;
+
+       addr2line_cleanup(a2l);
+
+       dso->a2l = NULL;
+}
+
 #else /* HAVE_LIBBFD_SUPPORT */
 
 static int addr2line(const char *dso_name, unsigned long addr,
-                    char **file, unsigned int *line_nr)
+                    char **file, unsigned int *line_nr,
+                    struct dso *dso __maybe_unused)
 {
        FILE *fp;
        char cmd[PATH_MAX];
@@ -219,42 +237,58 @@ out:
        pclose(fp);
        return ret;
 }
+
+void dso__free_a2l(struct dso *dso __maybe_unused)
+{
+}
+
 #endif /* HAVE_LIBBFD_SUPPORT */
 
+/*
+ * Number of addr2line failures (without success) before disabling it for that
+ * dso.
+ */
+#define A2L_FAIL_LIMIT 123
+
 char *get_srcline(struct dso *dso, unsigned long addr)
 {
        char *file = NULL;
        unsigned line = 0;
        char *srcline;
-       char *dso_name = dso->long_name;
-       size_t size;
+       const char *dso_name;
 
        if (!dso->has_srcline)
                return SRCLINE_UNKNOWN;
 
+       if (dso->symsrc_filename)
+               dso_name = dso->symsrc_filename;
+       else
+               dso_name = dso->long_name;
+
        if (dso_name[0] == '[')
                goto out;
 
        if (!strncmp(dso_name, "/tmp/perf-", 10))
                goto out;
 
-       if (!addr2line(dso_name, addr, &file, &line))
+       if (!addr2line(dso_name, addr, &file, &line, dso))
                goto out;
 
-       /* just calculate actual length */
-       size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
+       if (asprintf(&srcline, "%s:%u", file, line) < 0) {
+               free(file);
+               goto out;
+       }
 
-       srcline = malloc(size);
-       if (srcline)
-               snprintf(srcline, size, "%s:%u", file, line);
-       else
-               srcline = SRCLINE_UNKNOWN;
+       dso->a2l_fails = 0;
 
        free(file);
        return srcline;
 
 out:
-       dso->has_srcline = 0;
+       if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) {
+               dso->has_srcline = 0;
+               dso__free_a2l(dso);
+       }
        return SRCLINE_UNKNOWN;
 }
 
index cfa906882e2ceb2ed138fb4fd996474324f4d6c3..4abe23550c73808b16586ac4121bcde244a7fba8 100644 (file)
@@ -28,7 +28,7 @@ void strbuf_init(struct strbuf *sb, ssize_t hint)
 void strbuf_release(struct strbuf *sb)
 {
        if (sb->alloc) {
-               free(sb->buf);
+               zfree(&sb->buf);
                strbuf_init(sb, 0);
        }
 }
index 3edd0538161f3556f49ca1e10b1f3a1edd2e6468..79a757a2a15c22db5eec8494d662071cde57a12e 100644 (file)
@@ -14,7 +14,7 @@ static void strfilter_node__delete(struct strfilter_node *node)
 {
        if (node) {
                if (node->p && !is_operator(*node->p))
-                       free((char *)node->p);
+                       zfree((char **)&node->p);
                strfilter_node__delete(node->l);
                strfilter_node__delete(node->r);
                free(node);
index f0b0c008c5075005b562a2a5a2e938dd2644ea51..2553e5b55b8996175220d8fc16cfb403161f35b7 100644 (file)
@@ -128,7 +128,7 @@ void argv_free(char **argv)
 {
        char **p;
        for (p = argv; *p; p++)
-               free(*p);
+               zfree(p);
 
        free(argv);
 }
index eabdce0a2daa0a0a2c5c882529617322ce6e8852..71f9d102b96fc4aa9a94176151008083e275199f 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include "strlist.h"
+#include "util.h"
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -38,7 +39,7 @@ out_delete:
 static void str_node__delete(struct str_node *snode, bool dupstr)
 {
        if (dupstr)
-               free((void *)snode->s);
+               zfree((char **)&snode->s);
        free(snode);
 }
 
index 96c866045d60d2a17f4d969ed5e3a0a3c00933fc..43262b83c5411894f3dff3244782b6bd8bfe580d 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <linux/bitops.h>
 
+#include "perf.h"
 #include "svghelper.h"
+#include "util.h"
+#include "cpumap.h"
 
 static u64 first_time, last_time;
 static u64 turbo_frequency, max_freq;
@@ -28,6 +32,8 @@ static u64 turbo_frequency, max_freq;
 #define SLOT_HEIGHT 25.0
 
 int svg_page_width = 1000;
+u64 svg_highlight;
+const char *svg_highlight_name;
 
 #define MIN_TEXT_SIZE 0.01
 
@@ -39,9 +45,14 @@ static double cpu2slot(int cpu)
        return 2 * cpu + 1;
 }
 
+static int *topology_map;
+
 static double cpu2y(int cpu)
 {
-       return cpu2slot(cpu) * SLOT_MULT;
+       if (topology_map)
+               return cpu2slot(topology_map[cpu]) * SLOT_MULT;
+       else
+               return cpu2slot(cpu) * SLOT_MULT;
 }
 
 static double time2pixels(u64 __time)
@@ -95,6 +106,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
 
        total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
        fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
+       fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
        fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
 
        fprintf(svgfile, "<defs>\n  <style type=\"text/css\">\n    <![CDATA[\n");
@@ -103,6 +115,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
        fprintf(svgfile, "      rect.process  { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.sample   { fill:rgb(  0,  0,255); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
+       fprintf(svgfile, "      rect.sample_hi{ fill:rgb(255,128,  0); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.blocked  { fill:rgb(255,  0,  0); fill-opacity:0.5; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.waiting  { fill:rgb(224,214,  0); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
        fprintf(svgfile, "      rect.WAITING  { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
@@ -128,14 +141,42 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type)
                time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
 }
 
-void svg_sample(int Yslot, int cpu, u64 start, u64 end)
+static char *time_to_string(u64 duration);
+void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
+{
+       if (!svgfile)
+               return;
+
+       fprintf(svgfile, "<g>\n");
+       fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu,
+               time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace);
+       svg_box(Yslot, start, end, "blocked");
+       fprintf(svgfile, "</g>\n");
+}
+
+void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
 {
        double text_size;
+       const char *type;
+
        if (!svgfile)
                return;
 
-       fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n",
-               time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT);
+       if (svg_highlight && end - start > svg_highlight)
+               type = "sample_hi";
+       else
+               type = "sample";
+       fprintf(svgfile, "<g>\n");
+
+       fprintf(svgfile, "<title>#%d running %s</title>\n",
+               cpu, time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
+       fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
+               time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT,
+               type);
 
        text_size = (time2pixels(end)-time2pixels(start));
        if (cpu > 9)
@@ -148,6 +189,7 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end)
                fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
                        time2pixels(start), Yslot *  SLOT_MULT + SLOT_HEIGHT - 1, text_size,  cpu + 1);
 
+       fprintf(svgfile, "</g>\n");
 }
 
 static char *time_to_string(u64 duration)
@@ -168,7 +210,7 @@ static char *time_to_string(u64 duration)
        return text;
 }
 
-void svg_waiting(int Yslot, u64 start, u64 end)
+void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
 {
        char *text;
        const char *style;
@@ -192,6 +234,9 @@ void svg_waiting(int Yslot, u64 start, u64 end)
        font_size = round_text_size(font_size);
 
        fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
+       fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace);
        fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
                time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
        if (font_size > MIN_TEXT_SIZE)
@@ -242,28 +287,42 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
        max_freq = __max_freq;
        turbo_frequency = __turbo_freq;
 
+       fprintf(svgfile, "<g>\n");
+
        fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n",
                time2pixels(first_time),
                time2pixels(last_time)-time2pixels(first_time),
                cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
 
-       sprintf(cpu_string, "CPU %i", (int)cpu+1);
+       sprintf(cpu_string, "CPU %i", (int)cpu);
        fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
                10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
 
        fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
                10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
+
+       fprintf(svgfile, "</g>\n");
 }
 
-void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name)
+void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace)
 {
        double width;
+       const char *type;
 
        if (!svgfile)
                return;
 
+       if (svg_highlight && end - start >= svg_highlight)
+               type = "sample_hi";
+       else if (svg_highlight_name && strstr(name, svg_highlight_name))
+               type = "sample_hi";
+       else
+               type = "sample";
 
        fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
+       fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
        fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
                time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
        width = time2pixels(end)-time2pixels(start);
@@ -288,6 +347,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
                return;
 
 
+       fprintf(svgfile, "<g>\n");
+
        if (type > 6)
                type = 6;
        sprintf(style, "c%i", type);
@@ -306,6 +367,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
        if (width > MIN_TEXT_SIZE)
                fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
                        time2pixels(start), cpu2y(cpu)+width, width, type);
+
+       fprintf(svgfile, "</g>\n");
 }
 
 static char *HzToHuman(unsigned long hz)
@@ -339,6 +402,8 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
+
        if (max_freq)
                height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
        height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
@@ -347,10 +412,11 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
        fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
                time2pixels(start), height+0.9, HzToHuman(freq));
 
+       fprintf(svgfile, "</g>\n");
 }
 
 
-void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2)
+void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace)
 {
        double height;
 
@@ -358,6 +424,15 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
                return;
 
 
+       fprintf(svgfile, "<g>\n");
+
+       fprintf(svgfile, "<title>%s wakes up %s</title>\n",
+               desc1 ? desc1 : "?",
+               desc2 ? desc2 : "?");
+
+       if (backtrace)
+               fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
+
        if (row1 < row2) {
                if (row1) {
                        fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
@@ -395,9 +470,11 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
        if (row1)
                fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(32,255,32)\"/>\n",
                        time2pixels(start), height);
+
+       fprintf(svgfile, "</g>\n");
 }
 
-void svg_wakeline(u64 start, int row1, int row2)
+void svg_wakeline(u64 start, int row1, int row2, const char *backtrace)
 {
        double height;
 
@@ -405,6 +482,11 @@ void svg_wakeline(u64 start, int row1, int row2)
                return;
 
 
+       fprintf(svgfile, "<g>\n");
+
+       if (backtrace)
+               fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
+
        if (row1 < row2)
                fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
                        time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT,  time2pixels(start), row2 * SLOT_MULT);
@@ -417,17 +499,28 @@ void svg_wakeline(u64 start, int row1, int row2)
                height += SLOT_HEIGHT;
        fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(32,255,32)\"/>\n",
                        time2pixels(start), height);
+
+       fprintf(svgfile, "</g>\n");
 }
 
-void svg_interrupt(u64 start, int row)
+void svg_interrupt(u64 start, int row, const char *backtrace)
 {
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
+
+       fprintf(svgfile, "<title>Wakeup from interrupt</title>\n");
+
+       if (backtrace)
+               fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
+
        fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(255,128,128)\"/>\n",
                        time2pixels(start), row * SLOT_MULT);
        fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(255,128,128)\"/>\n",
                        time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
+
+       fprintf(svgfile, "</g>\n");
 }
 
 void svg_text(int Yslot, u64 start, const char *text)
@@ -455,6 +548,7 @@ void svg_legenda(void)
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
        svg_legenda_box(0,      "Running", "sample");
        svg_legenda_box(100,    "Idle","c1");
        svg_legenda_box(200,    "Deeper Idle", "c3");
@@ -462,6 +556,7 @@ void svg_legenda(void)
        svg_legenda_box(550,    "Sleeping", "process2");
        svg_legenda_box(650,    "Waiting for cpu", "waiting");
        svg_legenda_box(800,    "Blocked on IO", "blocked");
+       fprintf(svgfile, "</g>\n");
 }
 
 void svg_time_grid(void)
@@ -499,3 +594,123 @@ void svg_close(void)
                svgfile = NULL;
        }
 }
+
+#define cpumask_bits(maskp) ((maskp)->bits)
+typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
+
+struct topology {
+       cpumask_t *sib_core;
+       int sib_core_nr;
+       cpumask_t *sib_thr;
+       int sib_thr_nr;
+};
+
+static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos)
+{
+       int i;
+       int thr;
+
+       for (i = 0; i < t->sib_thr_nr; i++) {
+               if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i])))
+                       continue;
+
+               for_each_set_bit(thr,
+                                cpumask_bits(&t->sib_thr[i]),
+                                MAX_NR_CPUS)
+                       if (map[thr] == -1)
+                               map[thr] = (*pos)++;
+       }
+}
+
+static void scan_core_topology(int *map, struct topology *t)
+{
+       int pos = 0;
+       int i;
+       int cpu;
+
+       for (i = 0; i < t->sib_core_nr; i++)
+               for_each_set_bit(cpu,
+                                cpumask_bits(&t->sib_core[i]),
+                                MAX_NR_CPUS)
+                       scan_thread_topology(map, t, cpu, &pos);
+}
+
+static int str_to_bitmap(char *s, cpumask_t *b)
+{
+       int i;
+       int ret = 0;
+       struct cpu_map *m;
+       int c;
+
+       m = cpu_map__new(s);
+       if (!m)
+               return -1;
+
+       for (i = 0; i < m->nr; i++) {
+               c = m->map[i];
+               if (c >= MAX_NR_CPUS) {
+                       ret = -1;
+                       break;
+               }
+
+               set_bit(c, cpumask_bits(b));
+       }
+
+       cpu_map__delete(m);
+
+       return ret;
+}
+
+int svg_build_topology_map(char *sib_core, int sib_core_nr,
+                          char *sib_thr, int sib_thr_nr)
+{
+       int i;
+       struct topology t;
+
+       t.sib_core_nr = sib_core_nr;
+       t.sib_thr_nr = sib_thr_nr;
+       t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t));
+       t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t));
+
+       if (!t.sib_core || !t.sib_thr) {
+               fprintf(stderr, "topology: no memory\n");
+               goto exit;
+       }
+
+       for (i = 0; i < sib_core_nr; i++) {
+               if (str_to_bitmap(sib_core, &t.sib_core[i])) {
+                       fprintf(stderr, "topology: can't parse siblings map\n");
+                       goto exit;
+               }
+
+               sib_core += strlen(sib_core) + 1;
+       }
+
+       for (i = 0; i < sib_thr_nr; i++) {
+               if (str_to_bitmap(sib_thr, &t.sib_thr[i])) {
+                       fprintf(stderr, "topology: can't parse siblings map\n");
+                       goto exit;
+               }
+
+               sib_thr += strlen(sib_thr) + 1;
+       }
+
+       topology_map = malloc(sizeof(int) * MAX_NR_CPUS);
+       if (!topology_map) {
+               fprintf(stderr, "topology: no memory\n");
+               goto exit;
+       }
+
+       for (i = 0; i < MAX_NR_CPUS; i++)
+               topology_map[i] = -1;
+
+       scan_core_topology(topology_map, &t);
+
+       return 0;
+
+exit:
+       zfree(&t.sib_core);
+       zfree(&t.sib_thr);
+
+       return -1;
+}
index e0781989cc31f5d1dd004dc66c22a584d371189d..f7b4d6e699ea8d987dd461c108038b713bc6b958 100644 (file)
@@ -5,24 +5,29 @@
 
 extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
 extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
-extern void svg_sample(int Yslot, int cpu, u64 start, u64 end);
-extern void svg_waiting(int Yslot, u64 start, u64 end);
+extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
+extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
+extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
 extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
 
 
-extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name);
+extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace);
 extern void svg_cstate(int cpu, u64 start, u64 end, int type);
 extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
 
 
 extern void svg_time_grid(void);
 extern void svg_legenda(void);
-extern void svg_wakeline(u64 start, int row1, int row2);
-extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
-extern void svg_interrupt(u64 start, int row);
+extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace);
+extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace);
+extern void svg_interrupt(u64 start, int row, const char *backtrace);
 extern void svg_text(int Yslot, u64 start, const char *text);
 extern void svg_close(void);
+extern int svg_build_topology_map(char *sib_core, int sib_core_nr,
+                                 char *sib_thr, int sib_thr_nr);
 
 extern int svg_page_width;
+extern u64 svg_highlight;
+extern const char *svg_highlight_name;
 
 #endif /* __PERF_SVGHELPER_H */
index eed0b96302af189fa4b7c75f73ef538b8493336e..759456728703bf1471fcfb1ad600e687d8947033 100644 (file)
@@ -6,6 +6,7 @@
 #include <inttypes.h>
 
 #include "symbol.h"
+#include <symbol/kallsyms.h>
 #include "debug.h"
 
 #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
@@ -135,9 +136,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
        return -1;
 }
 
-static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
-                                   GElf_Shdr *shp, const char *name,
-                                   size_t *idx)
+Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
+                            GElf_Shdr *shp, const char *name, size_t *idx)
 {
        Elf_Scn *sec = NULL;
        size_t cnt = 1;
@@ -553,7 +553,7 @@ bool symsrc__has_symtab(struct symsrc *ss)
 
 void symsrc__destroy(struct symsrc *ss)
 {
-       free(ss->name);
+       zfree(&ss->name);
        elf_end(ss->elf);
        close(ss->fd);
 }
index 2d2dd0532b5a971e588086c0605ae0d6ed4080df..bd15f490d04fe5ea83607d761b65bcdfca09cbbe 100644 (file)
@@ -1,4 +1,5 @@
 #include "symbol.h"
+#include "util.h"
 
 #include <stdio.h>
 #include <fcntl.h>
@@ -253,6 +254,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
        if (!ss->name)
                goto out_close;
 
+       ss->fd = fd;
        ss->type = type;
 
        return 0;
@@ -274,7 +276,7 @@ bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
 
 void symsrc__destroy(struct symsrc *ss)
 {
-       free(ss->name);
+       zfree(&ss->name);
        close(ss->fd);
 }
 
index c0c36965fff0f0060b2f2a077edc17c569648bf2..39ce9adbaaf0bef120e0903e72ad1e98f8114527 100644 (file)
 
 #include <elf.h>
 #include <limits.h>
+#include <symbol/kallsyms.h>
 #include <sys/utsname.h>
 
-#ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 256
-#endif
-
 static int dso__load_kernel_sym(struct dso *dso, struct map *map,
                                symbol_filter_t filter);
 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -446,62 +443,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
        return ret;
 }
 
-int kallsyms__parse(const char *filename, void *arg,
-                   int (*process_symbol)(void *arg, const char *name,
-                                         char type, u64 start))
-{
-       char *line = NULL;
-       size_t n;
-       int err = -1;
-       FILE *file = fopen(filename, "r");
-
-       if (file == NULL)
-               goto out_failure;
-
-       err = 0;
-
-       while (!feof(file)) {
-               u64 start;
-               int line_len, len;
-               char symbol_type;
-               char *symbol_name;
-
-               line_len = getline(&line, &n, file);
-               if (line_len < 0 || !line)
-                       break;
-
-               line[--line_len] = '\0'; /* \n */
-
-               len = hex2u64(line, &start);
-
-               len++;
-               if (len + 2 >= line_len)
-                       continue;
-
-               symbol_type = line[len];
-               len += 2;
-               symbol_name = line + len;
-               len = line_len - len;
-
-               if (len >= KSYM_NAME_LEN) {
-                       err = -1;
-                       break;
-               }
-
-               err = process_symbol(arg, symbol_name,
-                                    symbol_type, start);
-               if (err)
-                       break;
-       }
-
-       free(line);
-       fclose(file);
-       return err;
-
-out_failure:
-       return -1;
-}
-
 int modules__parse(const char *filename, void *arg,
                   int (*process_module)(void *arg, const char *name,
                                         u64 start))
@@ -565,12 +506,34 @@ struct process_kallsyms_args {
        struct dso *dso;
 };
 
-static u8 kallsyms2elf_type(char type)
+bool symbol__is_idle(struct symbol *sym)
 {
-       if (type == 'W')
-               return STB_WEAK;
+       const char * const idle_symbols[] = {
+               "cpu_idle",
+               "intel_idle",
+               "default_idle",
+               "native_safe_halt",
+               "enter_idle",
+               "exit_idle",
+               "mwait_idle",
+               "mwait_idle_with_hints",
+               "poll_idle",
+               "ppc64_runlatch_off",
+               "pseries_dedicated_idle_sleep",
+               NULL
+       };
+
+       int i;
+
+       if (!sym)
+               return false;
+
+       for (i = 0; idle_symbols[i]; i++) {
+               if (!strcmp(idle_symbols[i], sym->name))
+                       return true;
+       }
 
-       return isupper(type) ? STB_GLOBAL : STB_LOCAL;
+       return false;
 }
 
 static int map__process_kallsym_symbol(void *arg, const char *name,
@@ -833,7 +796,7 @@ static void delete_modules(struct rb_root *modules)
                mi = rb_entry(next, struct module_info, rb_node);
                next = rb_next(&mi->rb_node);
                rb_erase(&mi->rb_node, modules);
-               free(mi->name);
+               zfree(&mi->name);
                free(mi);
        }
 }
@@ -1126,10 +1089,10 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
         * dso__data_read_addr().
         */
        if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
-               dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE;
+               dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE;
        else
-               dso->data_type = DSO_BINARY_TYPE__KCORE;
-       dso__set_long_name(dso, strdup(kcore_filename));
+               dso->binary_type = DSO_BINARY_TYPE__KCORE;
+       dso__set_long_name(dso, strdup(kcore_filename), true);
 
        close(fd);
 
@@ -1295,8 +1258,8 @@ 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__binary_type_file(dso, symtab_type,
-                                         root_dir, name, PATH_MAX))
+               if (dso__read_binary_type_filename(dso, symtab_type,
+                                                  root_dir, name, PATH_MAX))
                        continue;
 
                /* Name is now the name of the next image to try */
@@ -1306,6 +1269,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
                if (!syms_ss && symsrc__has_symtab(ss)) {
                        syms_ss = ss;
                        next_slot = true;
+                       if (!dso->symsrc_filename)
+                               dso->symsrc_filename = strdup(name);
                }
 
                if (!runtime_ss && symsrc__possibly_runtime(ss)) {
@@ -1376,7 +1341,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
 }
 
 int dso__load_vmlinux(struct dso *dso, struct map *map,
-                     const char *vmlinux, symbol_filter_t filter)
+                     const char *vmlinux, bool vmlinux_allocated,
+                     symbol_filter_t filter)
 {
        int err = -1;
        struct symsrc ss;
@@ -1402,10 +1368,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
 
        if (err > 0) {
                if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
-                       dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
+                       dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
                else
-                       dso->data_type = DSO_BINARY_TYPE__VMLINUX;
-               dso__set_long_name(dso, (char *)vmlinux);
+                       dso->binary_type = DSO_BINARY_TYPE__VMLINUX;
+               dso__set_long_name(dso, vmlinux, vmlinux_allocated);
                dso__set_loaded(dso, map->type);
                pr_debug("Using %s for symbols\n", symfs_vmlinux);
        }
@@ -1424,21 +1390,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
 
        filename = dso__build_id_filename(dso, NULL, 0);
        if (filename != NULL) {
-               err = dso__load_vmlinux(dso, map, filename, filter);
-               if (err > 0) {
-                       dso->lname_alloc = 1;
+               err = dso__load_vmlinux(dso, map, filename, true, filter);
+               if (err > 0)
                        goto out;
-               }
                free(filename);
        }
 
        for (i = 0; i < vmlinux_path__nr_entries; ++i) {
-               err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter);
-               if (err > 0) {
-                       dso__set_long_name(dso, strdup(vmlinux_path[i]));
-                       dso->lname_alloc = 1;
+               err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
+               if (err > 0)
                        break;
-               }
        }
 out:
        return err;
@@ -1496,14 +1457,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 
        build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
 
+       scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
+                 sbuild_id);
+
        /* Use /proc/kallsyms if possible */
        if (is_host) {
                DIR *d;
                int fd;
 
                /* If no cached kcore go with /proc/kallsyms */
-               scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
-                         buildid_dir, sbuild_id);
                d = opendir(path);
                if (!d)
                        goto proc_kallsyms;
@@ -1528,6 +1490,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
                goto proc_kallsyms;
        }
 
+       /* Find kallsyms in build-id cache with kcore */
+       if (!find_matching_kcore(map, path, sizeof(path)))
+               return strdup(path);
+
        scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
                  buildid_dir, sbuild_id);
 
@@ -1570,15 +1536,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
        }
 
        if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
-               err = dso__load_vmlinux(dso, map,
-                                       symbol_conf.vmlinux_name, filter);
-               if (err > 0) {
-                       dso__set_long_name(dso,
-                                          strdup(symbol_conf.vmlinux_name));
-                       dso->lname_alloc = 1;
-                       return err;
-               }
-               return err;
+               return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name,
+                                        false, filter);
        }
 
        if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
@@ -1604,7 +1563,7 @@ do_kallsyms:
        free(kallsyms_allocated_filename);
 
        if (err > 0 && !dso__is_kcore(dso)) {
-               dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
+               dso__set_long_name(dso, "[kernel.kallsyms]", false);
                map__fixup_start(map);
                map__fixup_end(map);
        }
@@ -1634,7 +1593,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
                 */
                if (symbol_conf.default_guest_vmlinux_name != NULL) {
                        err = dso__load_vmlinux(dso, map,
-                               symbol_conf.default_guest_vmlinux_name, filter);
+                                               symbol_conf.default_guest_vmlinux_name,
+                                               false, filter);
                        return err;
                }
 
@@ -1651,7 +1611,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
                pr_debug("Using %s for symbols\n", kallsyms_filename);
        if (err > 0 && !dso__is_kcore(dso)) {
                machine__mmap_name(machine, path, sizeof(path));
-               dso__set_long_name(dso, strdup(path));
+               dso__set_long_name(dso, strdup(path), true);
                map__fixup_start(map);
                map__fixup_end(map);
        }
@@ -1661,13 +1621,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
 
 static void vmlinux_path__exit(void)
 {
-       while (--vmlinux_path__nr_entries >= 0) {
-               free(vmlinux_path[vmlinux_path__nr_entries]);
-               vmlinux_path[vmlinux_path__nr_entries] = NULL;
-       }
+       while (--vmlinux_path__nr_entries >= 0)
+               zfree(&vmlinux_path[vmlinux_path__nr_entries]);
 
-       free(vmlinux_path);
-       vmlinux_path = NULL;
+       zfree(&vmlinux_path);
 }
 
 static int vmlinux_path__init(void)
@@ -1719,7 +1676,7 @@ out_fail:
        return -1;
 }
 
-static int setup_list(struct strlist **list, const char *list_str,
+int setup_list(struct strlist **list, const char *list_str,
                      const char *list_name)
 {
        if (list_str == NULL)
index 07de8fea2f48dbc346124539e7393307b839051a..fffe2888a1c7c123d6e7de3f11eb74dfd4f4ebf8 100644 (file)
@@ -52,6 +52,11 @@ static inline char *bfd_demangle(void __maybe_unused *v,
 # define PERF_ELF_C_READ_MMAP ELF_C_READ
 #endif
 
+#ifdef HAVE_LIBELF_SUPPORT
+extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
+                               GElf_Shdr *shp, const char *name, size_t *idx);
+#endif
+
 #ifndef DMGL_PARAMS
 #define DMGL_PARAMS      (1 << 0)       /* Include function args */
 #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
@@ -164,6 +169,7 @@ struct mem_info {
 };
 
 struct addr_location {
+       struct machine *machine;
        struct thread *thread;
        struct map    *map;
        struct symbol *sym;
@@ -206,7 +212,8 @@ bool symsrc__possibly_runtime(struct symsrc *ss);
 
 int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
 int dso__load_vmlinux(struct dso *dso, struct map *map,
-                     const char *vmlinux, symbol_filter_t filter);
+                     const char *vmlinux, bool vmlinux_allocated,
+                     symbol_filter_t filter);
 int dso__load_vmlinux_path(struct dso *dso, struct map *map,
                           symbol_filter_t filter);
 int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
@@ -220,9 +227,6 @@ 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);
-int kallsyms__parse(const char *filename, void *arg,
-                   int (*process_symbol)(void *arg, const char *name,
-                                         char type, u64 start));
 int modules__parse(const char *filename, void *arg,
                   int (*process_module)(void *arg, const char *name,
                                         u64 start));
@@ -240,6 +244,7 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 bool symbol__restricted_filename(const char *filename,
                                 const char *restricted_filename);
+bool symbol__is_idle(struct symbol *sym);
 
 int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
                  struct symsrc *runtime_ss, symbol_filter_t filter,
@@ -273,4 +278,7 @@ void kcore_extract__delete(struct kcore_extract *kce);
 int kcore_copy(const char *from_dir, const char *to_dir);
 int compare_proc_modules(const char *from, const char *to);
 
+int setup_list(struct strlist **list, const char *list_str,
+              const char *list_name);
+
 #endif /* __PERF_SYMBOL */
index 3c778a07b7cc78de8d92ec188e9bb446c40798bd..e74c5963dc7a9db7038e4ad3f5f7de1ed490f20f 100644 (file)
@@ -55,6 +55,13 @@ enum target_errno target__validate(struct target *target)
                        ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
        }
 
+       /* THREAD and SYSTEM/CPU are mutually exclusive */
+       if (target->per_thread && (target->system_wide || target->cpu_list)) {
+               target->per_thread = false;
+               if (ret == TARGET_ERRNO__SUCCESS)
+                       ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
+       }
+
        return ret;
 }
 
@@ -100,6 +107,7 @@ static const char *target__error_str[] = {
        "UID switch overriding CPU",
        "PID/TID switch overriding SYSTEM",
        "UID switch overriding SYSTEM",
+       "SYSTEM/CPU switch overriding PER-THREAD",
        "Invalid User: %s",
        "Problems obtaining information for user %s",
 };
@@ -131,7 +139,8 @@ int target__strerror(struct target *target, int errnum,
        msg = target__error_str[idx];
 
        switch (errnum) {
-       case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM:
+       case TARGET_ERRNO__PID_OVERRIDE_CPU ...
+            TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
                snprintf(buf, buflen, "%s", msg);
                break;
 
index 2d0c506908926f6fce822adc45a39e76911edd10..7381b1ca4041f2975f5d4e7e26f25809601704b2 100644 (file)
@@ -12,7 +12,8 @@ struct target {
        uid_t        uid;
        bool         system_wide;
        bool         uses_mmap;
-       bool         force_per_cpu;
+       bool         default_per_cpu;
+       bool         per_thread;
 };
 
 enum target_errno {
@@ -33,6 +34,7 @@ enum target_errno {
        TARGET_ERRNO__UID_OVERRIDE_CPU,
        TARGET_ERRNO__PID_OVERRIDE_SYSTEM,
        TARGET_ERRNO__UID_OVERRIDE_SYSTEM,
+       TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD,
 
        /* for target__parse_uid() */
        TARGET_ERRNO__INVALID_UID,
@@ -61,4 +63,17 @@ static inline bool target__none(struct target *target)
        return !target__has_task(target) && !target__has_cpu(target);
 }
 
+static inline bool target__uses_dummy_map(struct target *target)
+{
+       bool use_dummy = false;
+
+       if (target->default_per_cpu)
+               use_dummy = target->per_thread ? true : false;
+       else if (target__has_task(target) ||
+                (!target__has_cpu(target) && !target->uses_mmap))
+               use_dummy = true;
+
+       return use_dummy;
+}
+
 #endif /* _PERF_TARGET_H */
index cd8e2f59271969f410daf28afdf93523699f475c..0358882c89108723616c4eca0431fed0aa6be200 100644 (file)
@@ -66,18 +66,20 @@ struct comm *thread__comm(const struct thread *thread)
 int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
 {
        struct comm *new, *curr = thread__comm(thread);
+       int err;
 
        /* Override latest entry if it had no specific time coverage */
        if (!curr->start) {
-               comm__override(curr, str, timestamp);
-               return 0;
+               err = comm__override(curr, str, timestamp);
+               if (err)
+                       return err;
+       } else {
+               new = comm__new(str, timestamp);
+               if (!new)
+                       return -ENOMEM;
+               list_add(&new->list, &thread->comm_list);
        }
 
-       new = comm__new(str, timestamp);
-       if (!new)
-               return -ENOMEM;
-
-       list_add(&new->list, &thread->comm_list);
        thread->comm_set = true;
 
        return 0;
@@ -127,7 +129,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
                if (!comm)
                        return -ENOMEM;
                err = thread__set_comm(thread, comm, timestamp);
-               if (!err)
+               if (err)
                        return err;
                thread->comm_set = true;
        }
index 897c1b2a750a278c8cecf000c892d5f6bba8f0af..5b856bf942e11fa9691c28551a88b53b4ac3d5f2 100644 (file)
@@ -6,6 +6,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include "symbol.h"
+#include <strlist.h>
 
 struct thread {
        union {
@@ -66,4 +67,15 @@ static inline void thread__set_priv(struct thread *thread, void *p)
 {
        thread->priv = p;
 }
+
+static inline bool thread__is_filtered(struct thread *thread)
+{
+       if (symbol_conf.comm_list &&
+           !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) {
+               return true;
+       }
+
+       return false;
+}
+
 #endif /* __PERF_THREAD_H */
index 9b5f856cc28096b865d1c34c12073a23e5eb5a9c..5d32159121058cbd3e63a26f1fefbe8584224f7e 100644 (file)
@@ -9,6 +9,7 @@
 #include "strlist.h"
 #include <string.h>
 #include "thread_map.h"
+#include "util.h"
 
 /* Skip "." and ".." directories */
 static int filter(const struct dirent *dir)
@@ -40,7 +41,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
        }
 
        for (i=0; i<items; i++)
-               free(namelist[i]);
+               zfree(&namelist[i]);
        free(namelist);
 
        return threads;
@@ -117,7 +118,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
                        threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
 
                for (i = 0; i < items; i++)
-                       free(namelist[i]);
+                       zfree(&namelist[i]);
                free(namelist);
 
                threads->nr += items;
@@ -134,12 +135,11 @@ out_free_threads:
 
 out_free_namelist:
        for (i = 0; i < items; i++)
-               free(namelist[i]);
+               zfree(&namelist[i]);
        free(namelist);
 
 out_free_closedir:
-       free(threads);
-       threads = NULL;
+       zfree(&threads);
        goto out_closedir;
 }
 
@@ -194,7 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 
                for (i = 0; i < items; i++) {
                        threads->map[j++] = atoi(namelist[i]->d_name);
-                       free(namelist[i]);
+                       zfree(&namelist[i]);
                }
                threads->nr = total_tasks;
                free(namelist);
@@ -206,12 +206,11 @@ out:
 
 out_free_namelist:
        for (i = 0; i < items; i++)
-               free(namelist[i]);
+               zfree(&namelist[i]);
        free(namelist);
 
 out_free_threads:
-       free(threads);
-       threads = NULL;
+       zfree(&threads);
        goto out;
 }
 
@@ -262,8 +261,7 @@ out:
        return threads;
 
 out_free_threads:
-       free(threads);
-       threads = NULL;
+       zfree(&threads);
        goto out;
 }
 
index ce793c7dd23c6ec68347a00fe9859fc364a8f176..8e517def925b5ba64041ca2a4820f410f06dd0ec 100644 (file)
@@ -26,7 +26,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
        float samples_per_sec;
        float ksamples_per_sec;
        float esamples_percent;
-       struct perf_record_opts *opts = &top->record_opts;
+       struct record_opts *opts = &top->record_opts;
        struct target *target = &opts->target;
        size_t ret = 0;
 
index 88cfeaff600b334390842e725b9a7f792b0fd9af..dab14d0ad3d0093d4682bab9a0c4769e3949ca55 100644 (file)
@@ -14,7 +14,7 @@ struct perf_session;
 struct perf_top {
        struct perf_tool   tool;
        struct perf_evlist *evlist;
-       struct perf_record_opts record_opts;
+       struct record_opts record_opts;
        /*
         * Symbols will be added here in perf_event__process_sample and will
         * get out after decayed.
index f3c9e551bd353f39cd68bf52ec4c1c4ea6892a2f..7e6fcfe8b43853da45767687f4eb9d6e1453f6c1 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "../perf.h"
 #include "trace-event.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include "evsel.h"
 
 #define VERSION "0.5"
@@ -397,8 +397,8 @@ put_tracepoints_path(struct tracepoint_path *tps)
                struct tracepoint_path *t = tps;
 
                tps = tps->next;
-               free(t->name);
-               free(t->system);
+               zfree(&t->name);
+               zfree(&t->system);
                free(t);
        }
 }
@@ -562,10 +562,8 @@ out:
                output_fd = fd;
        }
 
-       if (err) {
-               free(tdata);
-               tdata = NULL;
-       }
+       if (err)
+               zfree(&tdata);
 
        put_tracepoints_path(tps);
        return tdata;
index 6681f71f2f95e329ddc5eba636d05ce67d3591ee..e0d6d07f68485167f2b05260fd932a288b42eec9 100644 (file)
 #include "util.h"
 #include "trace-event.h"
 
-struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
-{
-       struct pevent *pevent = pevent_alloc();
-
-       if (pevent != NULL) {
-               pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
-               pevent_set_file_bigendian(pevent, file_bigendian);
-               pevent_set_host_bigendian(pevent, host_bigendian);
-       }
-
-       return pevent;
-}
-
 static int get_common_field(struct scripting_context *context,
                            int *offset, int *size, const char *type)
 {
index f2112270c663d1c09f201272b7d348e5f6cf220d..e113e180c48f77398637a3b04771563412e3c0ee 100644 (file)
@@ -343,7 +343,7 @@ static int read_event_files(struct pevent *pevent)
        return 0;
 }
 
-ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
+ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
 {
        char buf[BUFSIZ];
        char test[] = { 23, 8, 68 };
@@ -356,11 +356,9 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
        int host_bigendian;
        int file_long_size;
        int file_page_size;
-       struct pevent *pevent;
+       struct pevent *pevent = NULL;
        int err;
 
-       *ppevent = NULL;
-
        repipe = __repipe;
        input_fd = fd;
 
@@ -390,12 +388,17 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
        file_bigendian = buf[0];
        host_bigendian = bigendian();
 
-       pevent = read_trace_init(file_bigendian, host_bigendian);
-       if (pevent == NULL) {
-               pr_debug("read_trace_init failed");
+       if (trace_event__init(tevent)) {
+               pr_debug("trace_event__init failed");
                goto out;
        }
 
+       pevent = tevent->pevent;
+
+       pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+       pevent_set_file_bigendian(pevent, file_bigendian);
+       pevent_set_host_bigendian(pevent, host_bigendian);
+
        if (do_read(buf, 1) < 0)
                goto out;
        file_long_size = buf[0];
@@ -432,11 +435,10 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
                pevent_print_printk(pevent);
        }
 
-       *ppevent = pevent;
        pevent = NULL;
 
 out:
        if (pevent)
-               pevent_free(pevent);
+               trace_event__cleanup(tevent);
        return size;
 }
index 95199e4eea978c3961a86e5e2439e61b6a3ef8a1..57aaccc1692e616ee0f257c90472272541f7d5b3 100644 (file)
@@ -38,9 +38,8 @@ static int stop_script_unsupported(void)
 static void process_event_unsupported(union perf_event *event __maybe_unused,
                                      struct perf_sample *sample __maybe_unused,
                                      struct perf_evsel *evsel __maybe_unused,
-                                     struct machine *machine __maybe_unused,
                                      struct thread *thread __maybe_unused,
-                                         struct addr_location *al __maybe_unused)
+                                     struct addr_location *al __maybe_unused)
 {
 }
 
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
new file mode 100644 (file)
index 0000000..6322d37
--- /dev/null
@@ -0,0 +1,82 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/kernel.h>
+#include <traceevent/event-parse.h>
+#include "trace-event.h"
+#include "util.h"
+
+/*
+ * global trace_event object used by trace_event__tp_format
+ *
+ * TODO There's no cleanup call for this. Add some sort of
+ * __exit function support and call trace_event__cleanup
+ * there.
+ */
+static struct trace_event tevent;
+
+int trace_event__init(struct trace_event *t)
+{
+       struct pevent *pevent = pevent_alloc();
+
+       if (pevent) {
+               t->plugin_list = traceevent_load_plugins(pevent);
+               t->pevent  = pevent;
+       }
+
+       return pevent ? 0 : -1;
+}
+
+void trace_event__cleanup(struct trace_event *t)
+{
+       traceevent_unload_plugins(t->plugin_list, t->pevent);
+       pevent_free(t->pevent);
+}
+
+static struct event_format*
+tp_format(const char *sys, const char *name)
+{
+       struct pevent *pevent = tevent.pevent;
+       struct event_format *event = NULL;
+       char path[PATH_MAX];
+       size_t size;
+       char *data;
+
+       scnprintf(path, PATH_MAX, "%s/%s/%s/format",
+                 tracing_events_path, sys, name);
+
+       if (filename__read_str(path, &data, &size))
+               return NULL;
+
+       pevent_parse_format(pevent, &event, data, size, sys);
+
+       free(data);
+       return event;
+}
+
+struct event_format*
+trace_event__tp_format(const char *sys, const char *name)
+{
+       static bool initialized;
+
+       if (!initialized) {
+               int be = traceevent_host_bigendian();
+               struct pevent *pevent;
+
+               if (trace_event__init(&tevent))
+                       return NULL;
+
+               pevent = tevent.pevent;
+               pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+               pevent_set_file_bigendian(pevent, be);
+               pevent_set_host_bigendian(pevent, be);
+               initialized = true;
+       }
+
+       return tp_format(sys, name);
+}
index 04df63114109604403f2f57a84ed03ec0b765707..7b6d68688327a75286eb3ab1a77fea15bb74ffb8 100644 (file)
@@ -3,17 +3,26 @@
 
 #include <traceevent/event-parse.h>
 #include "parse-events.h"
-#include "session.h"
 
 struct machine;
 struct perf_sample;
 union perf_event;
 struct perf_tool;
 struct thread;
+struct plugin_list;
+
+struct trace_event {
+       struct pevent           *pevent;
+       struct plugin_list      *plugin_list;
+};
+
+int trace_event__init(struct trace_event *t);
+void trace_event__cleanup(struct trace_event *t);
+struct event_format*
+trace_event__tp_format(const char *sys, const char *name);
 
 int bigendian(void);
 
-struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
 void event_format__print(struct event_format *event,
                         int cpu, void *data, int size);
 
@@ -27,7 +36,7 @@ raw_field_value(struct event_format *event, const char *name, void *data);
 void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
 void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
 
-ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
+ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
 
 struct event_format *trace_find_next_event(struct pevent *pevent,
                                           struct event_format *event);
@@ -59,7 +68,6 @@ struct scripting_ops {
        void (*process_event) (union perf_event *event,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
-                              struct machine *machine,
                               struct thread *thread,
                                   struct addr_location *al);
        int (*generate_script) (struct pevent *pevent, const char *outfile);
index 0efd5393de85ea33775198f25045cfa00a612247..742f23bf35ff7fabaae020100ebe3d359191a3da 100644 (file)
@@ -28,6 +28,7 @@
 #include "session.h"
 #include "perf_regs.h"
 #include "unwind.h"
+#include "symbol.h"
 #include "util.h"
 
 extern int
@@ -158,23 +159,6 @@ static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
        __v;                                                    \
        })
 
-static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
-                                   GElf_Shdr *shp, const char *name)
-{
-       Elf_Scn *sec = NULL;
-
-       while ((sec = elf_nextscn(elf, sec)) != NULL) {
-               char *str;
-
-               gelf_getshdr(sec, shp);
-               str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
-               if (!strcmp(name, str))
-                       break;
-       }
-
-       return sec;
-}
-
 static u64 elf_section_offset(int fd, const char *name)
 {
        Elf *elf;
@@ -190,7 +174,7 @@ static u64 elf_section_offset(int fd, const char *name)
                if (gelf_getehdr(elf, &ehdr) == NULL)
                        break;
 
-               if (!elf_section_by_name(elf, &ehdr, &shdr, name))
+               if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
                        break;
 
                offset = shdr.sh_offset;
@@ -340,10 +324,10 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
        /* Check the .debug_frame section for unwinding info */
        if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
                memset(&di, 0, sizeof(di));
-               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);
+               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
 
index 28a0a89c1f739749a59c8b80aa3d3b37d8f4000f..42ad667bb317570e6f22216598181d1e2a8c9798 100644 (file)
@@ -1,11 +1,17 @@
 #include "../perf.h"
 #include "util.h"
+#include "fs.h"
 #include <sys/mman.h>
 #ifdef HAVE_BACKTRACE_SUPPORT
 #include <execinfo.h>
 #endif
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <byteswap.h>
+#include <linux/kernel.h>
 
 /*
  * XXX We need to find a better place for these things...
@@ -151,21 +157,40 @@ unsigned long convert_unit(unsigned long value, char *unit)
        return value;
 }
 
-int readn(int fd, void *buf, size_t n)
+static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
 {
        void *buf_start = buf;
+       size_t left = n;
 
-       while (n) {
-               int ret = read(fd, buf, n);
+       while (left) {
+               ssize_t ret = is_read ? read(fd, buf, left) :
+                                       write(fd, buf, left);
 
                if (ret <= 0)
                        return ret;
 
-               n -= ret;
-               buf += ret;
+               left -= ret;
+               buf  += ret;
        }
 
-       return buf - buf_start;
+       BUG_ON((size_t)(buf - buf_start) != n);
+       return n;
+}
+
+/*
+ * Read exactly 'n' bytes or return an error.
+ */
+ssize_t readn(int fd, void *buf, size_t n)
+{
+       return ion(true, fd, buf, n);
+}
+
+/*
+ * Write exactly 'n' bytes or return an error.
+ */
+ssize_t writen(int fd, void *buf, size_t n)
+{
+       return ion(false, fd, buf, n);
 }
 
 size_t hex_width(u64 v)
@@ -413,3 +438,102 @@ int filename__read_int(const char *filename, int *value)
        close(fd);
        return err;
 }
+
+int filename__read_str(const char *filename, char **buf, size_t *sizep)
+{
+       size_t size = 0, alloc_size = 0;
+       void *bf = NULL, *nbf;
+       int fd, n, err = 0;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0)
+               return -errno;
+
+       do {
+               if (size == alloc_size) {
+                       alloc_size += BUFSIZ;
+                       nbf = realloc(bf, alloc_size);
+                       if (!nbf) {
+                               err = -ENOMEM;
+                               break;
+                       }
+
+                       bf = nbf;
+               }
+
+               n = read(fd, bf + size, alloc_size - size);
+               if (n < 0) {
+                       if (size) {
+                               pr_warning("read failed %d: %s\n",
+                                          errno, strerror(errno));
+                               err = 0;
+                       } else
+                               err = -errno;
+
+                       break;
+               }
+
+               size += n;
+       } while (n > 0);
+
+       if (!err) {
+               *sizep = size;
+               *buf   = bf;
+       } else
+               free(bf);
+
+       close(fd);
+       return err;
+}
+
+const char *get_filename_for_perf_kvm(void)
+{
+       const char *filename;
+
+       if (perf_host && !perf_guest)
+               filename = strdup("perf.data.host");
+       else if (!perf_host && perf_guest)
+               filename = strdup("perf.data.guest");
+       else
+               filename = strdup("perf.data.kvm");
+
+       return filename;
+}
+
+int perf_event_paranoid(void)
+{
+       char path[PATH_MAX];
+       const char *procfs = procfs__mountpoint();
+       int value;
+
+       if (!procfs)
+               return INT_MAX;
+
+       scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
+
+       if (filename__read_int(path, &value))
+               return INT_MAX;
+
+       return value;
+}
+
+void mem_bswap_32(void *src, int byte_size)
+{
+       u32 *m = src;
+       while (byte_size > 0) {
+               *m = bswap_32(*m);
+               byte_size -= sizeof(u32);
+               ++m;
+       }
+}
+
+void mem_bswap_64(void *src, int byte_size)
+{
+       u64 *m = src;
+
+       while (byte_size > 0) {
+               *m = bswap_64(*m);
+               byte_size -= sizeof(u64);
+               ++m;
+       }
+}
index c8f362daba8755f5b054d70c90f52211f6d8ccc8..6995d66f225c786a7a90ee3e6884f628474f7cec 100644 (file)
@@ -71,8 +71,9 @@
 #include <linux/magic.h>
 #include "types.h"
 #include <sys/ttydefaults.h>
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 #include <termios.h>
+#include <linux/bitops.h>
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
@@ -185,6 +186,8 @@ static inline void *zalloc(size_t size)
        return calloc(1, size);
 }
 
+#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+
 static inline int has_extension(const char *filename, const char *ext)
 {
        size_t len = strlen(filename);
@@ -253,7 +256,8 @@ bool strlazymatch(const char *str, const char *pat);
 int strtailcmp(const char *s1, const char *s2);
 char *strxfrchar(char *s, char from, char to);
 unsigned long convert_unit(unsigned long value, char *unit);
-int readn(int fd, void *buf, size_t size);
+ssize_t readn(int fd, void *buf, size_t n);
+ssize_t writen(int fd, void *buf, size_t n);
 
 struct perf_event_attr;
 
@@ -280,6 +284,17 @@ static inline unsigned next_pow2(unsigned x)
        return 1ULL << (32 - __builtin_clz(x - 1));
 }
 
+static inline unsigned long next_pow2_l(unsigned long x)
+{
+#if BITS_PER_LONG == 64
+       if (x <= (1UL << 31))
+               return next_pow2(x);
+       return (unsigned long)next_pow2(x >> 32) << 32;
+#else
+       return next_pow2(x);
+#endif
+}
+
 size_t hex_width(u64 v);
 int hex2u64(const char *ptr, u64 *val);
 
@@ -307,4 +322,11 @@ char *get_srcline(struct dso *dso, unsigned long addr);
 void free_srcline(char *srcline);
 
 int filename__read_int(const char *filename, int *value);
+int filename__read_str(const char *filename, char **buf, size_t *sizep);
+int perf_event_paranoid(void);
+
+void mem_bswap_64(void *src, int byte_size);
+void mem_bswap_32(void *src, int byte_size);
+
+const char *get_filename_for_perf_kvm(void);
 #endif /* GIT_COMPAT_UTIL_H */
index 697c8b4e59cc0cc4b906a73e0207364d4960854e..0fb3c1fcd3e62d0a1b26c032c0128ded5ef84035 100644 (file)
@@ -31,14 +31,14 @@ void perf_read_values_destroy(struct perf_read_values *values)
                return;
 
        for (i = 0; i < values->threads; i++)
-               free(values->value[i]);
-       free(values->value);
-       free(values->pid);
-       free(values->tid);
-       free(values->counterrawid);
+               zfree(&values->value[i]);
+       zfree(&values->value);
+       zfree(&values->pid);
+       zfree(&values->tid);
+       zfree(&values->counterrawid);
        for (i = 0; i < values->counters; i++)
-               free(values->countername[i]);
-       free(values->countername);
+               zfree(&values->countername[i]);
+       zfree(&values->countername);
 }
 
 static void perf_read_values__enlarge_threads(struct perf_read_values *values)
index 39159822d58f8a895b8703486339085439ec7c72..0ddb3b8a89ecff40fc2626ec5937d2c1bb62a2ca 100644 (file)
@@ -103,7 +103,7 @@ struct dso *vdso__dso_findnew(struct list_head *head)
                dso = dso__new(VDSO__MAP_NAME);
                if (dso != NULL) {
                        dsos__add(head, dso);
-                       dso__set_long_name(dso, file);
+                       dso__set_long_name(dso, file, false);
                }
        }
 
index dc4de37621117f7dc6fe8d47669e761063c9eed0..bcf1d2f0b791337169ee54ffce946619006015ae 100644 (file)
@@ -18,9 +18,9 @@
 #include "helpers/bitmask.h"
 
 static struct option set_opts[] = {
-       { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
-       { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
-       { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
+       { .name = "perf-bias",  .has_arg = required_argument,   .flag = NULL,   .val = 'b'},
+       { .name = "sched-mc",   .has_arg = required_argument,   .flag = NULL,   .val = 'm'},
+       { .name = "sched-smt",  .has_arg = required_argument,   .flag = NULL,   .val = 's'},
        { },
 };
 
index ee76544deecb4138c7fdd2fee2ef4b410d39e5cc..8abbef164b4eeaf5fff90118f201dce07539ed81 100644 (file)
@@ -61,6 +61,7 @@ QUIET_SUBDIR1  =
 ifneq ($(findstring $(MAKEFLAGS),s),s)
   ifneq ($(V),1)
        QUIET_CC       = @echo '  CC       '$@;
+       QUIET_CC_FPIC  = @echo '  CC FPIC  '$@;
        QUIET_AR       = @echo '  AR       '$@;
        QUIET_LINK     = @echo '  LINK     '$@;
        QUIET_MKDIR    = @echo '  MKDIR    '$@;
@@ -76,5 +77,8 @@ ifneq ($(findstring $(MAKEFLAGS),s),s)
                +@echo         '  DESCEND  '$(1); \
                mkdir -p $(OUTPUT)$(1) && \
                $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
+
+       QUIET_CLEAN    = @printf '  CLEAN    %s\n' $1;
+       QUIET_INSTALL  = @printf '  INSTALL  %s\n' $1;
   endif
 endif
index 999eab1bc64fb579be929ccbbe5363d0c23a96c5..40631569a0fd6633d99c566b927096f5769ed34f 100755 (executable)
@@ -18,6 +18,7 @@ $| = 1;
 my %opt;
 my %repeat_tests;
 my %repeats;
+my %evals;
 
 #default opts
 my %default = (
@@ -25,6 +26,7 @@ my %default = (
     "TEST_TYPE"                        => "build",
     "BUILD_TYPE"               => "randconfig",
     "MAKE_CMD"                 => "make",
+    "CLOSE_CONSOLE_SIGNAL"     => "INT",
     "TIMEOUT"                  => 120,
     "TMP_DIR"                  => "/tmp/ktest/\${MACHINE}",
     "SLEEP_TIME"               => 60,  # sleep time between tests
@@ -39,6 +41,7 @@ my %default = (
     "CLEAR_LOG"                        => 0,
     "BISECT_MANUAL"            => 0,
     "BISECT_SKIP"              => 1,
+    "BISECT_TRIES"             => 1,
     "MIN_CONFIG_TYPE"          => "boot",
     "SUCCESS_LINE"             => "login:",
     "DETECT_TRIPLE_FAULT"      => 1,
@@ -137,6 +140,7 @@ my $bisect_bad_commit = "";
 my $reverse_bisect;
 my $bisect_manual;
 my $bisect_skip;
+my $bisect_tries;
 my $config_bisect_good;
 my $bisect_ret_good;
 my $bisect_ret_bad;
@@ -163,6 +167,7 @@ my $timeout;
 my $booted_timeout;
 my $detect_triplefault;
 my $console;
+my $close_console_signal;
 my $reboot_success_line;
 my $success_line;
 my $stop_after_success;
@@ -273,6 +278,7 @@ my %option_map = (
     "IGNORE_ERRORS"            => \$ignore_errors,
     "BISECT_MANUAL"            => \$bisect_manual,
     "BISECT_SKIP"              => \$bisect_skip,
+    "BISECT_TRIES"             => \$bisect_tries,
     "CONFIG_BISECT_GOOD"       => \$config_bisect_good,
     "BISECT_RET_GOOD"          => \$bisect_ret_good,
     "BISECT_RET_BAD"           => \$bisect_ret_bad,
@@ -285,6 +291,7 @@ my %option_map = (
     "TIMEOUT"                  => \$timeout,
     "BOOTED_TIMEOUT"           => \$booted_timeout,
     "CONSOLE"                  => \$console,
+    "CLOSE_CONSOLE_SIGNAL"     => \$close_console_signal,
     "DETECT_TRIPLE_FAULT"      => \$detect_triplefault,
     "SUCCESS_LINE"             => \$success_line,
     "REBOOT_SUCCESS_LINE"      => \$reboot_success_line,
@@ -445,6 +452,27 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
 EOF
     ;
 
+sub _logit {
+    if (defined($opt{"LOG_FILE"})) {
+       open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
+       print OUT @_;
+       close(OUT);
+    }
+}
+
+sub logit {
+    if (defined($opt{"LOG_FILE"})) {
+       _logit @_;
+    } else {
+       print @_;
+    }
+}
+
+sub doprint {
+    print @_;
+    _logit @_;
+}
+
 sub read_prompt {
     my ($cancel, $prompt) = @_;
 
@@ -662,6 +690,22 @@ sub set_value {
     }
 }
 
+sub set_eval {
+    my ($lvalue, $rvalue, $name) = @_;
+
+    my $prvalue = process_variables($rvalue);
+    my $arr;
+
+    if (defined($evals{$lvalue})) {
+       $arr = $evals{$lvalue};
+    } else {
+       $arr = [];
+       $evals{$lvalue} = $arr;
+    }
+
+    push @{$arr}, $rvalue;
+}
+
 sub set_variable {
     my ($lvalue, $rvalue) = @_;
 
@@ -947,6 +991,20 @@ sub __read_config {
                $test_case = 1;
            }
 
+       } elsif (/^\s*([A-Z_\[\]\d]+)\s*=~\s*(.*?)\s*$/) {
+
+           next if ($skip);
+
+           my $lvalue = $1;
+           my $rvalue = $2;
+
+           if ($default || $lvalue =~ /\[\d+\]$/) {
+               set_eval($lvalue, $rvalue, $name);
+           } else {
+               my $val = "$lvalue\[$test_num\]";
+               set_eval($val, $rvalue, $name);
+           }
+
        } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
 
            next if ($skip);
@@ -1126,6 +1184,10 @@ sub __eval_option {
        } elsif (defined($opt{$var})) {
            $o = $opt{$var};
            $retval = "$retval$o";
+       } elsif ($var eq "KERNEL_VERSION" && defined($make)) {
+           # special option KERNEL_VERSION uses kernel version
+           get_version();
+           $retval = "$retval$version";
        } else {
            $retval = "$retval\$\{$var\}";
        }
@@ -1140,6 +1202,33 @@ sub __eval_option {
     return $retval;
 }
 
+sub process_evals {
+    my ($name, $option, $i) = @_;
+
+    my $option_name = "$name\[$i\]";
+    my $ev;
+
+    my $old_option = $option;
+
+    if (defined($evals{$option_name})) {
+       $ev = $evals{$option_name};
+    } elsif (defined($evals{$name})) {
+       $ev = $evals{$name};
+    } else {
+       return $option;
+    }
+
+    for my $e (@{$ev}) {
+       eval "\$option =~ $e";
+    }
+
+    if ($option ne $old_option) {
+       doprint("$name changed from '$old_option' to '$option'\n");
+    }
+
+    return $option;
+}
+
 sub eval_option {
     my ($name, $option, $i) = @_;
 
@@ -1160,28 +1249,9 @@ sub eval_option {
        $option = __eval_option($name, $option, $i);
     }
 
-    return $option;
-}
+    $option = process_evals($name, $option, $i);
 
-sub _logit {
-    if (defined($opt{"LOG_FILE"})) {
-       open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
-       print OUT @_;
-       close(OUT);
-    }
-}
-
-sub logit {
-    if (defined($opt{"LOG_FILE"})) {
-       _logit @_;
-    } else {
-       print @_;
-    }
-}
-
-sub doprint {
-    print @_;
-    _logit @_;
+    return $option;
 }
 
 sub run_command;
@@ -1296,7 +1366,7 @@ sub close_console {
     my ($fp, $pid) = @_;
 
     doprint "kill child process $pid\n";
-    kill 2, $pid;
+    kill $close_console_signal, $pid;
 
     print "closing!\n";
     close($fp);
@@ -2517,12 +2587,29 @@ sub run_bisect {
        $buildtype = "useconfig:$minconfig";
     }
 
-    my $ret = run_bisect_test $type, $buildtype;
+    # If the user sets bisect_tries to less than 1, then no tries
+    # is a success.
+    my $ret = 1;
 
-    if ($bisect_manual) {
+    # Still let the user manually decide that though.
+    if ($bisect_tries < 1 && $bisect_manual) {
        $ret = answer_bisect;
     }
 
+    for (my $i = 0; $i < $bisect_tries; $i++) {
+       if ($bisect_tries > 1) {
+           my $t = $i + 1;
+           doprint("Running bisect trial $t of $bisect_tries:\n");
+       }
+       $ret = run_bisect_test $type, $buildtype;
+
+       if ($bisect_manual) {
+           $ret = answer_bisect;
+       }
+
+       last if (!$ret);
+    }
+
     # Are we looking for where it worked, not failed?
     if ($reverse_bisect && $ret >= 0) {
        $ret = !$ret;
@@ -3916,6 +4003,18 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     my $makecmd = set_test_option("MAKE_CMD", $i);
 
+    $outputdir = set_test_option("OUTPUT_DIR", $i);
+    $builddir = set_test_option("BUILD_DIR", $i);
+
+    chdir $builddir || die "can't change directory to $builddir";
+
+    if (!-d $outputdir) {
+       mkpath($outputdir) or
+           die "can't create $outputdir";
+    }
+
+    $make = "$makecmd O=$outputdir";
+
     # Load all the options into their mapped variable names
     foreach my $opt (keys %option_map) {
        ${$option_map{$opt}} = set_test_option($opt, $i);
@@ -3940,13 +4039,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        $start_minconfig = $minconfig;
     }
 
-    chdir $builddir || die "can't change directory to $builddir";
-
-    foreach my $dir ($tmpdir, $outputdir) {
-       if (!-d $dir) {
-           mkpath($dir) or
-               die "can't create $dir";
-       }
+    if (!-d $tmpdir) {
+       mkpath($tmpdir) or
+           die "can't create $tmpdir";
     }
 
     $ENV{"SSH_USER"} = $ssh_user;
@@ -3955,7 +4050,6 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $buildlog = "$tmpdir/buildlog-$machine";
     $testlog = "$tmpdir/testlog-$machine";
     $dmesg = "$tmpdir/dmesg-$machine";
-    $make = "$makecmd O=$outputdir";
     $output_config = "$outputdir/.config";
 
     if (!$buildonly) {
index 0a290fb4cd5e746b278001719c4e2e518106b83b..172eec4517fb9792e172a9a8c60348f31115f400 100644 (file)
 # For a virtual machine with guest name "Guest".
 #CONSOLE =  virsh console Guest
 
+# Signal to send to kill console.
+# ktest.pl will create a child process to monitor the console.
+# When the console is finished, ktest will kill the child process
+# with this signal.
+# (default INT)
+#CLOSE_CONSOLE_SIGNAL = HUP
+
 # Required version ending to differentiate the test
 # from other linux builds on the system.
 #LOCALVERSION = -test
 #   BISECT_BAD with BISECT_CHECK = good or
 #   BISECT_CHECK = bad, respectively.
 #
+# BISECT_TRIES = 5 (optional, default 1)
+#
+#   For those cases that it takes several tries to hit a bug,
+#   the BISECT_TRIES is useful. It is the number of times the
+#   test is ran before it says the kernel is good. The first failure
+#   will stop trying and mark the current SHA1 as bad.
+#
+#   Note, as with all race bugs, there's no guarantee that if
+#   it succeeds, it is really a good bisect. But it helps in case
+#   the bug is some what reliable.
+#
+#   You can set BISECT_TRIES to zero, and all tests will be considered
+#   good, unless you also set BISECT_MANUAL.
+#
 # BISECT_RET_GOOD = 0 (optional, default undefined)
 #
 #   In case the specificed test returns something other than just
diff --git a/tools/testing/selftests/rcutorture/.gitignore b/tools/testing/selftests/rcutorture/.gitignore
new file mode 100644 (file)
index 0000000..05838f6
--- /dev/null
@@ -0,0 +1,6 @@
+initrd
+linux-2.6
+b[0-9]*
+rcu-test-image
+res
+*.swp
diff --git a/tools/testing/selftests/rcutorture/bin/config2frag.sh b/tools/testing/selftests/rcutorture/bin/config2frag.sh
new file mode 100644 (file)
index 0000000..9f9ffcd
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Usage: sh config2frag.sh < .config > configfrag
+#
+# Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the
+# resulting file becomes a legitimate Kconfig fragment.
+#
+# This 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>
+
+LANG=C sed -e 's/^# CONFIG_\([a-zA-Z0-9_]*\) is not set$/CONFIG_\1=n/'
diff --git a/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh b/tools/testing/selftests/rcutorture/bin/configNR_CPUS.sh
new file mode 100755 (executable)
index 0000000..43540f1
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+# Extract the number of CPUs expected from the specified Kconfig-file
+# fragment by checking CONFIG_SMP and CONFIG_NR_CPUS.  If the specified
+# file gives no clue, base the number on the number of idle CPUs on
+# the system.
+#
+# Usage: configNR_CPUS.sh config-frag
+#
+# This 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>
+
+cf=$1
+if test ! -r $cf
+then
+       echo Unreadable config fragment $cf 1>&2
+       exit -1
+fi
+if grep -q '^CONFIG_SMP=n$' $cf
+then
+       echo 1
+       exit 0
+fi
+if grep -q '^CONFIG_NR_CPUS=' $cf
+then
+       grep '^CONFIG_NR_CPUS=' $cf | 
+               sed -e 's/^CONFIG_NR_CPUS=\([0-9]*\).*$/\1/'
+       exit 0
+fi
+cpus2use.sh
diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh
new file mode 100755 (executable)
index 0000000..d686537
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Usage: sh configcheck.sh .config .config-template
+#
+# This 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>
+
+T=/tmp/abat-chk-config.sh.$$
+trap 'rm -rf $T' 0
+mkdir $T
+
+cat $1 > $T/.config
+
+cat $2 | sed -e 's/\(.*\)=n/# \1 is not set/' -e 's/^#CHECK#//' |
+awk    '
+BEGIN  {
+               print "if grep -q \"" $0 "\" < '"$T/.config"'";
+               print "then";
+               print "\t:";
+               print "else";
+               if ($1 == "#") {
+                       print "\tif grep -q \"" $2 "\" < '"$T/.config"'";
+                       print "\tthen";
+                       print "\t\tif test \"$firsttime\" = \"\""
+                       print "\t\tthen"
+                       print "\t\t\tfirsttime=1"
+                       print "\t\tfi"
+                       print "\t\techo \":" $2 ": improperly set\"";
+                       print "\telse";
+                       print "\t\t:";
+                       print "\tfi";
+               } else {
+                       print "\tif test \"$firsttime\" = \"\""
+                       print "\tthen"
+                       print "\t\tfirsttime=1"
+                       print "\tfi"
+                       print "\techo \":" $0 ": improperly set\"";
+               }
+               print "fi";
+       }' | sh
diff --git a/tools/testing/selftests/rcutorture/bin/configinit.sh b/tools/testing/selftests/rcutorture/bin/configinit.sh
new file mode 100755 (executable)
index 0000000..a1be6e6
--- /dev/null
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# sh configinit.sh config-spec-file [ build output dir ]
+#
+# Create a .config file from the spec file.  Run from the kernel source tree.
+# Exits with 0 if all went well, with 1 if all went well but the config
+# did not match, and some other number for other failures.
+#
+# The first argument is the .config specification file, which contains
+# desired settings, for example, "CONFIG_NO_HZ=y".  For best results,
+# this should be a full pathname.
+#
+# The second argument is a optional path to a build output directory,
+# for example, "O=/tmp/foo".  If this argument is omitted, the .config
+# file will be generated directly in the current directory.
+#
+# This 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>
+
+T=/tmp/configinit.sh.$$
+trap 'rm -rf $T' 0
+mkdir $T
+
+# Capture config spec file.
+
+c=$1
+buildloc=$2
+builddir=
+if test -n $buildloc
+then
+       if echo $buildloc | grep -q '^O='
+       then
+               builddir=`echo $buildloc | sed -e 's/^O=//'`
+               if test ! -d $builddir
+               then
+                       mkdir $builddir
+               fi
+       else
+               echo Bad build directory: \"$builddir\"
+               exit 2
+       fi
+fi
+
+sed -e 's/^\(CONFIG[0-9A-Z_]*\)=.*$/grep -v "^# \1" |/' < $c > $T/u.sh
+sed -e 's/^\(CONFIG[0-9A-Z_]*=\).*$/grep -v \1 |/' < $c >> $T/u.sh
+grep '^grep' < $T/u.sh > $T/upd.sh
+echo "cat - $c" >> $T/upd.sh
+make mrproper
+make $buildloc distclean > $builddir/Make.distclean 2>&1
+make $buildloc defconfig > $builddir/Make.defconfig.out 2>&1
+mv $builddir/.config $builddir/.config.sav
+sh $T/upd.sh < $builddir/.config.sav > $builddir/.config
+cp $builddir/.config $builddir/.config.new
+yes '' | make $buildloc oldconfig > $builddir/Make.modconfig.out 2>&1
+
+# verify new config matches specification.
+configcheck.sh $builddir/.config $c
+
+exit 0
diff --git a/tools/testing/selftests/rcutorture/bin/cpus2use.sh b/tools/testing/selftests/rcutorture/bin/cpus2use.sh
new file mode 100755 (executable)
index 0000000..abe14b7
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Get an estimate of how CPU-hoggy to be.
+#
+# Usage: cpus2use.sh
+#
+# This 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>
+
+ncpus=`grep '^processor' /proc/cpuinfo | wc -l`
+idlecpus=`mpstat | tail -1 | \
+       awk -v ncpus=$ncpus '{ print ncpus * ($7 + $12) / 100 }'`
+awk -v ncpus=$ncpus -v idlecpus=$idlecpus < /dev/null '
+BEGIN {
+       cpus2use = idlecpus;
+       if (cpus2use < 1)
+               cpus2use = 1;
+       if (cpus2use < ncpus / 10)
+               cpus2use = ncpus / 10;
+       if (cpus2use == int(cpus2use))
+               cpus2use = int(cpus2use)
+       else
+               cpus2use = int(cpus2use) + 1
+       print cpus2use;
+}'
+
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
new file mode 100644 (file)
index 0000000..587561d
--- /dev/null
@@ -0,0 +1,198 @@
+#!/bin/bash
+#
+# 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>
+
+# bootparam_hotplug_cpu bootparam-string
+#
+# Returns 1 if the specified boot-parameter string tells rcutorture to
+# test CPU-hotplug operations.
+bootparam_hotplug_cpu () {
+       echo "$1" | grep -q "rcutorture\.onoff_"
+}
+
+# checkarg --argname argtype $# arg mustmatch cannotmatch
+#
+# Checks the specified argument "arg" against the mustmatch and cannotmatch
+# patterns.
+checkarg () {
+       if test $3 -le 1
+       then
+               echo $1 needs argument $2 matching \"$5\"
+               usage
+       fi
+       if echo "$4" | grep -q -e "$5"
+       then
+               :
+       else
+               echo $1 $2 \"$4\" must match \"$5\"
+               usage
+       fi
+       if echo "$4" | grep -q -e "$6"
+       then
+               echo $1 $2 \"$4\" must not match \"$6\"
+               usage
+       fi
+}
+
+# configfrag_boot_params bootparam-string config-fragment-file
+#
+# Adds boot parameters from the .boot file, if any.
+configfrag_boot_params () {
+       if test -r "$2.boot"
+       then
+               echo $1 `grep -v '^#' "$2.boot" | tr '\012' ' '`
+       else
+               echo $1
+       fi
+}
+
+# configfrag_hotplug_cpu config-fragment-file
+#
+# Returns 1 if the config fragment specifies hotplug CPU.
+configfrag_hotplug_cpu () {
+       if test ! -r "$1"
+       then
+               echo Unreadable config fragment "$1" 1>&2
+               exit -1
+       fi
+       grep -q '^CONFIG_HOTPLUG_CPU=y$' "$1"
+}
+
+# identify_qemu builddir
+#
+# Returns our best guess as to which qemu command is appropriate for
+# the kernel at hand.  Override with the RCU_QEMU_CMD environment variable.
+identify_qemu () {
+       local u="`file "$1"`"
+       if test -n "$RCU_QEMU_CMD"
+       then
+               echo $RCU_QEMU_CMD
+       elif echo $u | grep -q x86-64
+       then
+               echo qemu-system-x86_64
+       elif echo $u | grep -q "Intel 80386"
+       then
+               echo qemu-system-i386
+       elif uname -a | grep -q ppc64
+       then
+               echo qemu-system-ppc64
+       else
+               echo Cannot figure out what qemu command to use! 1>&2
+               # Usually this will be one of /usr/bin/qemu-system-*
+               # Use RCU_QEMU_CMD environment variable or appropriate
+               # argument to top-level script.
+               exit 1
+       fi
+}
+
+# identify_qemu_append qemu-cmd
+#
+# Output arguments for the qemu "-append" string based on CPU type
+# and the RCU_QEMU_INTERACTIVE environment variable.
+identify_qemu_append () {
+       case "$1" in
+       qemu-system-x86_64|qemu-system-i386)
+               echo noapic selinux=0 initcall_debug debug
+               ;;
+       esac
+       if test -n "$RCU_QEMU_INTERACTIVE"
+       then
+               echo root=/dev/sda
+       else
+               echo console=ttyS0
+       fi
+}
+
+# identify_qemu_args qemu-cmd serial-file
+#
+# Output arguments for qemu arguments based on the RCU_QEMU_MAC
+# and RCU_QEMU_INTERACTIVE environment variables.
+identify_qemu_args () {
+       case "$1" in
+       qemu-system-x86_64|qemu-system-i386)
+               ;;
+       qemu-system-ppc64)
+               echo -enable-kvm -M pseries -cpu POWER7 -nodefaults
+               echo -device spapr-vscsi
+               if test -n "$RCU_QEMU_INTERACTIVE" -a -n "$RCU_QEMU_MAC"
+               then
+                       echo -device spapr-vlan,netdev=net0,mac=$RCU_QEMU_MAC
+                       echo -netdev bridge,br=br0,id=net0
+               elif test -n "$RCU_QEMU_INTERACTIVE"
+               then
+                       echo -net nic -net user
+               fi
+               ;;
+       esac
+       if test -n "$RCU_QEMU_INTERACTIVE"
+       then
+               echo -monitor stdio -serial pty -S
+       else
+               echo -serial file:$2
+       fi
+}
+
+# identify_qemu_vcpus
+#
+# Returns the number of virtual CPUs available to the aggregate of the
+# guest OSes.
+identify_qemu_vcpus () {
+       lscpu | grep '^CPU(s):' | sed -e 's/CPU(s)://'
+}
+
+# print_bug
+#
+# Prints "BUG: " in red followed by remaining arguments
+print_bug () {
+       printf '\033[031mBUG: \033[m'
+       echo $*
+}
+
+# print_warning
+#
+# Prints "WARNING: " in yellow followed by remaining arguments
+print_warning () {
+       printf '\033[033mWARNING: \033[m'
+       echo $*
+}
+
+# specify_qemu_cpus qemu-cmd qemu-args #cpus
+#
+# Appends a string containing "-smp XXX" to qemu-args, unless the incoming
+# qemu-args already contains "-smp".
+specify_qemu_cpus () {
+       local nt;
+
+       if echo $2 | grep -q -e -smp
+       then
+               echo $2
+       else
+               case "$1" in
+               qemu-system-x86_64|qemu-system-i386)
+                       echo $2 -smp $3
+                       ;;
+               qemu-system-ppc64)
+                       nt="`lscpu | grep '^NUMA node0' | sed -e 's/^[^,]*,\([0-9]*\),.*$/\1/'`"
+                       echo $2 -smp cores=`expr \( $3 + $nt - 1 \) / $nt`,threads=$nt
+                       ;;
+               esac
+       fi
+}
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
new file mode 100755 (executable)
index 0000000..197901e
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Build a kvm-ready Linux kernel from the tree in the current directory.
+#
+# Usage: sh kvm-build.sh config-template build-dir more-configs
+#
+# This 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>
+
+config_template=${1}
+if test -z "$config_template" -o ! -f "$config_template" -o ! -r "$config_template"
+then
+       echo "kvm-build.sh :$config_template: Not a readable file"
+       exit 1
+fi
+builddir=${2}
+if test -z "$builddir" -o ! -d "$builddir" -o ! -w "$builddir"
+then
+       echo "kvm-build.sh :$builddir: Not a writable directory, cannot build into it"
+       exit 1
+fi
+moreconfigs=${3}
+if test -z "$moreconfigs" -o ! -r "$moreconfigs"
+then
+       echo "kvm-build.sh :$moreconfigs: Not a readable file"
+       exit 1
+fi
+
+T=/tmp/test-linux.sh.$$
+trap 'rm -rf $T' 0
+mkdir $T
+
+cat ${config_template} | grep -v CONFIG_RCU_TORTURE_TEST > $T/config
+cat << ___EOF___ >> $T/config
+CONFIG_INITRAMFS_SOURCE="$RCU_INITRD"
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_CONSOLE=y
+___EOF___
+cat $moreconfigs >> $T/config
+
+configinit.sh $T/config O=$builddir
+retval=$?
+if test $retval -gt 1
+then
+       exit 2
+fi
+ncpus=`cpus2use.sh`
+make O=$builddir -j$ncpus $RCU_KMAKE_ARG > $builddir/Make.out 2>&1
+retval=$?
+if test $retval -ne 0 || grep "rcu[^/]*": < $builddir/Make.out | egrep -q "Stop|Error|error:|warning:" || egrep -q "Stop|Error|error:" < $builddir/Make.out
+then
+       echo Kernel build error
+       egrep "Stop|Error|error:|warning:" < $builddir/Make.out
+       echo Run aborted.
+       exit 3
+fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
new file mode 100755 (executable)
index 0000000..baef09f
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+#
+# Given the results directories for previous KVM runs of rcutorture,
+# check the build and console output for errors.  Given a directory
+# containing results directories, this recursively checks them all.
+#
+# Usage: sh kvm-recheck.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, 2011
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
+for rd in "$@"
+do
+       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
+               configcheck.sh $i/.config $i/ConfigFragment
+               parse-build.sh $i/Make.out $configfile
+               parse-rcutorture.sh $i/console.log $configfile
+               parse-console.sh $i/console.log $configfile
+               if test -r $i/Warnings
+               then
+                       cat $i/Warnings
+               fi
+       done
+done
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-rcu.sh
new file mode 100755 (executable)
index 0000000..151b237
--- /dev/null
@@ -0,0 +1,192 @@
+#!/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.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
new file mode 100644 (file)
index 0000000..1b7923b
--- /dev/null
@@ -0,0 +1,210 @@
+#!/bin/bash
+#
+# Run a series of 14 tests under KVM.  These are not particularly
+# well-selected or well-tuned, but are the current set.  Run from the
+# top level of the source tree.
+#
+# Edit the definitions below to set the locations of the various directories,
+# as well as the test duration.
+#
+# Usage: sh kvm.sh [ options ]
+#
+# This 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>
+
+scriptname=$0
+args="$*"
+
+dur=30
+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
+resdir=""
+configs=""
+ds=`date +%Y.%m.%d-%H:%M:%S`
+kversion=""
+
+. functions.sh
+
+usage () {
+       echo "Usage: $scriptname optional arguments:"
+       echo "       --bootargs kernel-boot-arguments"
+       echo "       --builddir absolute-pathname"
+       echo "       --buildonly"
+       echo "       --configs \"config-file list\""
+       echo "       --datestamp string"
+       echo "       --duration minutes"
+       echo "       --interactive"
+       echo "       --kmake-arg kernel-make-arguments"
+       echo "       --kversion vN.NN"
+       echo "       --mac nn:nn:nn:nn:nn:nn"
+       echo "       --no-initrd"
+       echo "       --qemu-args qemu-system-..."
+       echo "       --qemu-cmd qemu-system-..."
+       echo "       --results absolute-pathname"
+       echo "       --relbuilddir relative-pathname"
+       exit 1
+}
+
+while test $# -gt 0
+do
+       case "$1" in
+       --bootargs)
+               checkarg --bootargs "(list of kernel boot arguments)" "$#" "$2" '.*' '^--'
+               RCU_BOOTARGS="$2"
+               shift
+               ;;
+       --builddir)
+               checkarg --builddir "(absolute pathname)" "$#" "$2" '^/' '^error'
+               builddir=$2
+               gotbuilddir=1
+               shift
+               ;;
+       --buildonly)
+               RCU_BUILDONLY=1; export RCU_BUILDONLY
+               ;;
+       --configs)
+               checkarg --configs "(list of config files)" "$#" "$2" '^[^/]*$' '^--'
+               configs="$2"
+               shift
+               ;;
+       --datestamp)
+               checkarg --datestamp "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
+               ds=$2
+               shift
+               ;;
+       --duration)
+               checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
+               dur=$2
+               shift
+               ;;
+       --interactive)
+               RCU_QEMU_INTERACTIVE=1; export RCU_QEMU_INTERACTIVE
+               ;;
+       --kmake-arg)
+               checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
+               RCU_KMAKE_ARG="$2"; export RCU_KMAKE_ARG
+               shift
+               ;;
+       --kversion)
+               checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error'
+               kversion=$2
+               shift
+               ;;
+       --mac)
+               checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error
+               RCU_QEMU_MAC=$2; export RCU_QEMU_MAC
+               shift
+               ;;
+       --no-initrd)
+               RCU_INITRD=""; export RCU_INITRD
+               ;;
+       --qemu-args)
+               checkarg --qemu-args "-qemu args" $# "$2" '^-' '^error'
+               RCU_QEMU_ARG="$2"
+               shift
+               ;;
+       --qemu-cmd)
+               checkarg --qemu-cmd "(qemu-system-...)" $# "$2" 'qemu-system-' '^--'
+               RCU_QEMU_CMD="$2"; export RCU_QEMU_CMD
+               shift
+               ;;
+       --relbuilddir)
+               checkarg --relbuilddir "(relative pathname)" "$#" "$2" '^[^/]*$' '^--'
+               relbuilddir=$2
+               gotrelbuilddir=1
+               builddir=${KVM}/${relbuilddir}
+               shift
+               ;;
+       --results)
+               checkarg --results "(absolute pathname)" "$#" "$2" '^/' '^error'
+               resdir=$2
+               shift
+               ;;
+       *)
+               echo Unknown argument $1
+               usage
+               ;;
+       esac
+       shift
+done
+
+CONFIGFRAG=${KVM}/configs; export CONFIGFRAG
+KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
+
+if test -z "$configs"
+then
+       configs="`cat $CONFIGFRAG/$kversion/CFLIST`"
+fi
+
+if test -z "$resdir"
+then
+       resdir=$KVM/res
+       if ! test -e $resdir
+       then
+               mkdir $resdir || :
+       fi
+else
+       if ! test -e $resdir
+       then
+               mkdir -p "$resdir" || :
+       fi
+fi
+mkdir $resdir/$ds
+touch $resdir/$ds/log
+echo $scriptname $args >> $resdir/$ds/log
+
+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 || :
+fi
+
+for CF in $configs
+do
+       # Running TREE01 multiple times creates TREE01, TREE01.2, TREE01.3, ...
+       rd=$resdir/$ds/$CF
+       if test -d "${rd}"
+       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
+       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
+# 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 " --- `date` Test summary:"
+kvm-recheck.sh $resdir/$ds
diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh
new file mode 100755 (executable)
index 0000000..5432309
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Check the build output from an rcutorture run for goodness.
+# The "file" is a pathname on the local system, and "title" is
+# a text string for error-message purposes.
+#
+# The file must contain kernel build output.
+#
+# Usage:
+#      sh parse-build.sh file title
+#
+# This 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>
+
+T=$1
+title=$2
+
+. functions.sh
+
+if grep -q CC < $T
+then
+       :
+else
+       print_bug $title no build
+       exit 1
+fi
+
+if grep -q "error:" < $T
+then
+       print_bug $title build errors:
+       grep "error:" < $T
+       exit 2
+fi
+exit 0
+
+if egrep -q "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T
+then
+       print_warning $title build errors:
+       egrep "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T
+       exit 2
+fi
+exit 0
diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh
new file mode 100755 (executable)
index 0000000..4185d4c
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Check the console output from an rcutorture run for oopses.
+# The "file" is a pathname on the local system, and "title" is
+# a text string for error-message purposes.
+#
+# Usage:
+#      sh parse-console.sh file title
+#
+# This 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>
+
+T=/tmp/abat-chk-badness.sh.$$
+trap 'rm -f $T' 0
+
+file="$1"
+title="$2"
+
+. functions.sh
+
+egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T
+if test -s $T
+then
+       print_warning Assertion failure in $file $title
+       cat $T
+fi
diff --git a/tools/testing/selftests/rcutorture/bin/parse-rcutorture.sh b/tools/testing/selftests/rcutorture/bin/parse-rcutorture.sh
new file mode 100755 (executable)
index 0000000..dd0a275
--- /dev/null
@@ -0,0 +1,106 @@
+#!/bin/sh
+#
+# Check the console output from an rcutorture run for goodness.
+# The "file" is a pathname on the local system, and "title" is
+# a text string for error-message purposes.
+#
+# The file must contain rcutorture output, but can be interspersed
+# with other dmesg text.
+#
+# Usage:
+#      sh parse-rcutorture.sh file title
+#
+# This 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>
+
+T=/tmp/parse-rcutorture.sh.$$
+file="$1"
+title="$2"
+
+trap 'rm -f $T.seq' 0
+
+. functions.sh
+
+# check for presence of rcutorture.txt file
+
+if test -f "$file" -a -r "$file"
+then
+       :
+else
+       echo $title unreadable rcutorture.txt file: $file
+       exit 1
+fi
+
+# check for abject failure
+
+if grep -q FAILURE $file || grep -q -e '-torture.*!!!' $file
+then
+       nerrs=`grep --binary-files=text '!!!' $file | tail -1 | awk '{for (i=NF-8;i<=NF;i++) sum+=$i; } END {print sum}'`
+       print_bug $title FAILURE, $nerrs instances
+       echo "   " $url
+       exit
+fi
+
+grep --binary-files=text 'torture:.*ver:' $file | grep --binary-files=text -v '(null)' | sed -e 's/^(initramfs)[^]]*] //' -e 's/^\[[^]]*] //' |
+awk '
+BEGIN  {
+       ver = 0;
+       badseq = 0;
+       }
+
+       {
+       if (!badseq && ($5 + 0 != $5 || $5 <= ver)) {
+               badseqno1 = ver;
+               badseqno2 = $5;
+               badseqnr = NR;
+               badseq = 1;
+       }
+       ver = $5
+       }
+
+END    {
+       if (badseq) {
+               if (badseqno1 == badseqno2 && badseqno2 == ver)
+                       print "RCU GP HANG at " ver " rcutorture stat " badseqnr;
+               else
+                       print "BAD SEQ " badseqno1 ":" badseqno2 " last:" ver " RCU version " badseqnr;
+       }
+       }' > $T.seq
+
+if grep -q SUCCESS $file
+then
+       if test -s $T.seq
+       then
+               print_warning $title $title `cat $T.seq`
+               echo "   " $file
+               exit 2
+       fi
+else
+       if grep -q RCU_HOTPLUG $file
+       then
+               print_warning HOTPLUG FAILURES $title `cat $T.seq`
+               echo "   " $file
+               exit 3
+       fi
+       echo $title no success message, `grep --binary-files=text 'ver:' $file | wc -l` successful RCU version messages
+       if test -s $T.seq
+       then
+               print_warning $title `cat $T.seq`
+       fi
+       exit 2
+fi
diff --git a/tools/testing/selftests/rcutorture/configs/CFLIST b/tools/testing/selftests/rcutorture/configs/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/SRCU-N b/tools/testing/selftests/rcutorture/configs/SRCU-N
new file mode 100644 (file)
index 0000000..10a0e27
--- /dev/null
@@ -0,0 +1,8 @@
+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
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/SRCU-P b/tools/testing/selftests/rcutorture/configs/SRCU-P
new file mode 100644 (file)
index 0000000..6650e00
--- /dev/null
@@ -0,0 +1,8 @@
+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
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/TINY01 b/tools/testing/selftests/rcutorture/configs/TINY01
new file mode 100644 (file)
index 0000000..0c2823f
--- /dev/null
@@ -0,0 +1,13 @@
+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
new file mode 100644 (file)
index 0000000..e5072d7
--- /dev/null
@@ -0,0 +1,13 @@
+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
new file mode 100644 (file)
index 0000000..141119a
--- /dev/null
@@ -0,0 +1,23 @@
+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
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/TREE02 b/tools/testing/selftests/rcutorture/configs/TREE02
new file mode 100644 (file)
index 0000000..2d4d096
--- /dev/null
@@ -0,0 +1,26 @@
+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
new file mode 100644 (file)
index 0000000..a47de5b
--- /dev/null
@@ -0,0 +1,23 @@
+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
new file mode 100644 (file)
index 0000000..8d839b8
--- /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=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
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/TREE05 b/tools/testing/selftests/rcutorture/configs/TREE05
new file mode 100644 (file)
index 0000000..b5ba72e
--- /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=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
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/TREE06 b/tools/testing/selftests/rcutorture/configs/TREE06
new file mode 100644 (file)
index 0000000..7c95ab4
--- /dev/null
@@ -0,0 +1,26 @@
+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
new file mode 100644 (file)
index 0000000..1467404
--- /dev/null
@@ -0,0 +1,24 @@
+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
new file mode 100644 (file)
index 0000000..7d097a6
--- /dev/null
@@ -0,0 +1,26 @@
+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
new file mode 100644 (file)
index 0000000..442c4e4
--- /dev/null
@@ -0,0 +1,26 @@
+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
new file mode 100644 (file)
index 0000000..0d1ec0d
--- /dev/null
@@ -0,0 +1,21 @@
+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/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/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/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/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/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/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/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/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/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/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/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v0.0/ver_functions.sh
new file mode 100644 (file)
index 0000000..e805253
--- /dev/null
@@ -0,0 +1,35 @@
+#!/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
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/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/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/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/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/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/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
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/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
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/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/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/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/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/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/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/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/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/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/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/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/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/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/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/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v3.3/ver_functions.sh
new file mode 100644 (file)
index 0000000..c37432f
--- /dev/null
@@ -0,0 +1,41 @@
+#!/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
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/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/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/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/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/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/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/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/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/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/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/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/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/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/v3.5/ver_functions.sh
new file mode 100644 (file)
index 0000000..6a5f13a
--- /dev/null
@@ -0,0 +1,46 @@
+#!/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
new file mode 100644 (file)
index 0000000..5e40ead
--- /dev/null
@@ -0,0 +1,46 @@
+#!/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/TINY_RCU.txt b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
new file mode 100644 (file)
index 0000000..28db67b
--- /dev/null
@@ -0,0 +1,40 @@
+This document gives a brief rationale for the TINY_RCU test cases.
+
+
+Kconfig Parameters:
+
+CONFIG_DEBUG_LOCK_ALLOC -- Do all three and none of the three.
+CONFIG_PREEMPT_COUNT
+CONFIG_RCU_TRACE
+
+The theory here is that randconfig testing will hit the other six possible
+combinations of these parameters.
+
+
+Kconfig Parameters Ignored:
+
+CONFIG_DEBUG_OBJECTS_RCU_HEAD
+CONFIG_PROVE_RCU
+
+       In common code tested by TREE_RCU test cases.
+
+CONFIG_NO_HZ_FULL_SYSIDLE
+CONFIG_RCU_NOCB_CPU
+CONFIG_RCU_USER_QS
+
+       Meaningless for TINY_RCU.
+
+CONFIG_RCU_STALL_COMMON
+CONFIG_RCU_TORTURE_TEST
+
+       Redundant with CONFIG_RCU_TRACE.
+
+CONFIG_HOTPLUG_CPU
+CONFIG_PREEMPT
+CONFIG_PREEMPT_RCU
+CONFIG_SMP
+CONFIG_TINY_RCU
+CONFIG_TREE_PREEMPT_RCU
+CONFIG_TREE_RCU
+
+       All forced by CONFIG_TINY_RCU.
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.
diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt
new file mode 100644 (file)
index 0000000..49d134c
--- /dev/null
@@ -0,0 +1,90 @@
+This document describes one way to create the initrd directory hierarchy
+in order to allow an initrd to be built into your kernel.  The trick
+here is to steal the initrd file used on your Linux laptop, Ubuntu in
+this case.  There are probably much better ways of doing this.
+
+That said, here are the commands:
+
+------------------------------------------------------------------------
+zcat /initrd.img > /tmp/initrd.img.zcat
+mkdir initrd
+cd initrd
+cpio -id < /tmp/initrd.img.zcat
+------------------------------------------------------------------------
+
+Interestingly enough, if you are running rcutorture, you don't really
+need userspace in many cases.  Running without userspace has the
+advantage of allowing you to test your kernel independently of the
+distro in place, the root-filesystem layout, and so on.  To make this
+happen, put the following script in the initrd's tree's "/init" file,
+with 0755 mode.
+
+------------------------------------------------------------------------
+#!/bin/sh
+
+[ -d /dev ] || mkdir -m 0755 /dev
+[ -d /root ] || mkdir -m 0700 /root
+[ -d /sys ] || mkdir /sys
+[ -d /proc ] || mkdir /proc
+[ -d /tmp ] || mkdir /tmp
+mkdir -p /var/lock
+mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
+mount -t proc -o nodev,noexec,nosuid proc /proc
+# Some things don't work properly without /etc/mtab.
+ln -sf /proc/mounts /etc/mtab
+
+# Note that this only becomes /dev on the real filesystem if udev's scripts
+# are used; which they will be, but it's worth pointing out
+if ! mount -t devtmpfs -o mode=0755 udev /dev; then
+       echo "W: devtmpfs not available, falling back to tmpfs for /dev"
+       mount -t tmpfs -o mode=0755 udev /dev
+       [ -e /dev/console ] || mknod --mode=600 /dev/console c 5 1
+       [ -e /dev/kmsg ] || mknod --mode=644 /dev/kmsg c 1 11
+       [ -e /dev/null ] || mknod --mode=666 /dev/null c 1 3
+fi
+
+mkdir /dev/pts
+mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
+mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run
+mkdir /run/initramfs
+# compatibility symlink for the pre-oneiric locations
+ln -s /run/initramfs /dev/.initramfs
+
+# Export relevant variables
+export ROOT=
+export ROOTDELAY=
+export ROOTFLAGS=
+export ROOTFSTYPE=
+export IP=
+export BOOT=
+export BOOTIF=
+export UBIMTD=
+export break=
+export init=/sbin/init
+export quiet=n
+export readonly=y
+export rootmnt=/root
+export debug=
+export panic=
+export blacklist=
+export resume=
+export resume_offset=
+export recovery=
+
+for i in /sys/devices/system/cpu/cpu*/online
+do
+       case $i in
+       '/sys/devices/system/cpu/cpu0/online')
+               ;;
+       '/sys/devices/system/cpu/cpu*/online')
+               ;;
+       *)
+               echo 1 > $i
+               ;;
+       esac
+done
+
+while :
+do
+       sleep 10
+done
diff --git a/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt b/tools/testing/selftests/rcutorture/doc/rcu-test-image.txt
new file mode 100644 (file)
index 0000000..66efb59
--- /dev/null
@@ -0,0 +1,42 @@
+This document describes one way to created the rcu-test-image file
+that contains the filesystem used by the guest-OS kernel.  There are
+probably much better ways of doing this, and this filesystem could no
+doubt be smaller.  It is probably also possible to simply download
+an appropriate image from any number of places.
+
+That said, here are the commands:
+
+------------------------------------------------------------------------
+dd if=/dev/zero of=rcu-test-image bs=400M count=1
+mkfs.ext3 ./rcu-test-image
+sudo mount -o loop ./rcu-test-image /mnt
+
+# Replace "precise" below with your favorite Ubuntu release.
+# Empirical evidence says this image will work for 64-bit, but...
+# Note that debootstrap does take a few minutes to run.  Or longer.
+sudo debootstrap --verbose --arch i386 precise /mnt http://archive.ubuntu.com/ubuntu
+cat << '___EOF___' | sudo dd of=/mnt/etc/fstab
+# UNCONFIGURED FSTAB FOR BASE SYSTEM
+#
+/dev/vda        /               ext3    defaults        1 1
+dev             /dev            tmpfs   rw              0 0
+tmpfs           /dev/shm        tmpfs   defaults        0 0
+devpts          /dev/pts        devpts  gid=5,mode=620  0 0
+sysfs           /sys            sysfs   defaults        0 0
+proc            /proc           proc    defaults        0 0
+___EOF___
+sudo umount /mnt
+------------------------------------------------------------------------
+
+
+References:
+
+       http://sripathikodi.blogspot.com/2010/02/creating-kvm-bootable-fedora-system.html
+       https://help.ubuntu.com/community/KVM/CreateGuests
+       https://help.ubuntu.com/community/JeOSVMBuilder
+       http://wiki.libvirt.org/page/UbuntuKVMWalkthrough
+       http://www.moe.co.uk/2011/01/07/pci_add_option_rom-failed-to-find-romfile-pxe-rtl8139-bin/ -- "apt-get install kvm-pxe"
+       http://www.landley.net/writing/rootfs-howto.html
+       http://en.wikipedia.org/wiki/Initrd
+       http://en.wikipedia.org/wiki/Cpio
+       http://wiki.libvirt.org/page/UbuntuKVMWalkthrough
index 396d6c44e9d738d8cf85a0ce20317b001c573212..acf2165c04e64f8b15e844b787de9f59c324b199 100644 (file)
@@ -3,11 +3,12 @@
 CC = $(CROSS_COMPILE)gcc
 PTHREAD_LIBS = -lpthread
 WARNINGS = -Wall -Wextra
-CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) -I../include
+CFLAGS = $(WARNINGS) -g -I../include
+LDFLAGS = $(PTHREAD_LIBS)
 
 all: testusb ffs-test
 %: %.c
-       $(CC) $(CFLAGS) -o $@ $^
+       $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
 
 clean:
        $(RM) testusb ffs-test
index 24e9ddd93fa45e664b432cf49d43dde672d5e251..3d907dacf2ac85c4e9d17a5dec1808859c27f5f5 100644 (file)
@@ -2,21 +2,21 @@
 #
 TARGETS=page-types slabinfo
 
-LK_DIR = ../lib/lk
-LIBLK = $(LK_DIR)/liblk.a
+LIB_DIR = ../lib/api
+LIBS = $(LIB_DIR)/libapikfs.a
 
 CC = $(CROSS_COMPILE)gcc
 CFLAGS = -Wall -Wextra -I../lib/
-LDFLAGS = $(LIBLK)
+LDFLAGS = $(LIBS)
 
-$(TARGETS): liblk
+$(TARGETS): $(LIBS)
 
-liblk:
-       make -C $(LK_DIR)
+$(LIBS):
+       make -C $(LIB_DIR)
 
 %: %.c
        $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
 
 clean:
        $(RM) page-types slabinfo
-       make -C ../lib/lk clean
+       make -C $(LIB_DIR) clean
index d5e9d6d185c82f7ff087b51a54300421508edeca..f9be24d9efacbde91935eb5d981c57d5548a9afa 100644 (file)
@@ -36,7 +36,7 @@
 #include <sys/statfs.h>
 #include "../../include/uapi/linux/magic.h"
 #include "../../include/uapi/linux/kernel-page-flags.h"
-#include <lk/debugfs.h>
+#include <api/fs/debugfs.h>
 
 #ifndef MAX_PATH
 # define MAX_PATH 256
index a0aa84b5941ac96aabae48b03d80278052ce8929..4f588bc941861b10f7d5dccf9305941c8d3cc218 100644 (file)
@@ -1898,6 +1898,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
        int r;
        struct kvm_vcpu *vcpu, *v;
 
+       if (id >= KVM_MAX_VCPUS)
+               return -EINVAL;
+
        vcpu = kvm_arch_vcpu_create(kvm, id);
        if (IS_ERR(vcpu))
                return PTR_ERR(vcpu);